2018茶学 博士 招聘:Android模拟器学framework和driver之传感器篇1(linux sensor driver)
来源:百度文库 编辑:中财网 时间:2024/05/04 09:22:23
对于android模拟器开发环境的搭建这里我就不多说了,网上google下一大堆,还有就是android 模拟器的kernel使用的是goldfish的kernel,可以使用git得到源码,然后就可以编译了,大家还是可以参考罗老师的博客。。。
在这里我准备编写一个温度传感器的虚拟driver,之前写过g-sensor和light sensor,所以不想写了,换个新鲜的,其实驱动架构都是一样的,OK 分化不多说,下面就介绍一下这个驱动。
在这里,我比较偷懒的使用了linux的一个iio子系统,这是一个不成熟的子系统,所以被放到源码陌路下面的/drvers/staging中,对于这个子系统,我也只是粗略的看过它的驱动模型,好吧^0^,不过个人觉得这个子系统还是蛮简单使用的,而却里面的api不是很多,相信大家随便分析下就能搞懂了。
OK,首先是头文件
/common/drivers/staging/iio/temperature/android-temperature.h
[cpp] view plaincopyprint?#include
#include
#include
#include
#include "../iio.h"
#define POLL_INTERVAL 2000 //set poll time
struct temperature_drvdata {
struct iio_dev *indio_dev;
struct input_polled_dev *poll_input;
//....reserved
};
#include
#include
#include
#include
#include "../iio.h"
#define POLL_INTERVAL 2000 //set poll time
struct temperature_drvdata {
struct iio_dev *indio_dev;
struct input_polled_dev *poll_input;
//....reserved
};
相信大家看到了这个头文件就差不多知道驱动是怎么写的了吧,我选用的是platform device driver,driver layer向user space传送数据时通过input sybsystem传送的,这也是android sensor驱动比较主流的做法,还有一些做法是直接往自己创建的sysfs中写数据,这也是一中比较简单的做法,事件的触控方式我选用的是poll方式,因为这里我写的驱动是一个虚拟的设备,一般出发方式会选用中断触发,而我这个驱动选择每隔一段时间往user space上报数据,时间间隔就是这里的POLL_INTERVAL这个宏设定的。
说了这么多都没有看到驱动的代码真不好意思,下面来分析下驱动的代码。
/common/drivers/staging/iio/temperature/android-temperature.c
首先是init和exit函数:
static int __init temperature_init(void)
{
printk(KERN_INFO "temperature init...\n");
return platform_driver_register(&temperature_device_driver);
}
static void __exit temperature_exit(void)
{
platform_driver_unregister(&temperature_device_driver);
}
module_init(temperature_init);
module_exit(temperature_exit);
static int __init temperature_init(void)
{
printk(KERN_INFO "temperature init...\n");
return platform_driver_register(&temperature_device_driver);
}
static void __exit temperature_exit(void)
{
platform_driver_unregister(&temperature_device_driver);
}
module_init(temperature_init);
module_exit(temperature_exit);这也没啥好说的,大家愿意的话可以再后面在添上这个driver module的作者和出处,传扬千里,哈哈,我就不了,本人比较谦虚。
这也没啥好说的,大家愿意的话可以再后面在添上这个driver module的作者和出处,传扬千里,哈哈,我就不了,本人比较谦虚。这边最主要的应该就是temperature_device_driver这个变量这是一个platform_driver结构体,在驱动注册的时候必须把这个结构体传进去,我们的platform设备模型就是通过这个结构体找到相应的device,然后把driver和device绑定在一起,这边涉及到linux 设备驱动模型,这边我也不做详细的分析了,想要了解的话可以自己学习,个人觉得如果是做linux驱动的话了解linux 设备驱动模型是很重要的,这可以让我们站在一个比较高的层次上去写代码。
OK,不扯了看下这个结构体:
[cpp] view plaincopyprint?static struct platform_driver temperature_device_driver = {
.probe = temperature_probe,
// .remove = __devexit_p(temperature_remove),
.driver = {
.name = "android-temperature",
.owner= THIS_MODULE,
},
};
static struct platform_driver temperature_device_driver = {
.probe = temperature_probe,
// .remove = __devexit_p(temperature_remove),
.driver = {
.name = "android-temperature",
.owner= THIS_MODULE,
},
};
这边就是定义了probe和remove,真实的设备的话还有会suspend,resume,early_suspend,late_resume等回调函数,在适当的时间会回调到这些函数(犀利的读者可能看到了这边remove我没有去实现,哈哈,我比较懒,不过大家要有一个良好的习惯,不要学我)。但是在这边注册了platform的驱动,是去找哪的platform设备呢?当然是我们自己要去实现啦,通常device端我们都会在板级的文件中去定义,我们这里是:
/common/arch/arm/mach-goldfish/board-goldfish.c
[cpp] view plaincopyprint?struct platform_device android_temperature_device = {
.name="android-temperature",
.id=-1,
};
static void __init goldfish_init(void)
{
platform_device_register(&goldfish_pdev_bus_device);
platform_device_register(&android_temperature_device);
}
struct platform_device android_temperature_device = {
.name="android-temperature",
.id=-1,
};
static void __init goldfish_init(void)
{
platform_device_register(&goldfish_pdev_bus_device);
platform_device_register(&android_temperature_device);
}大家注意。这边的name和driver中platform_driver中name用该一样,不然他们怎么可以绑定在一起呢,不然他们怎么会找到对方呢,有缘千里来相会嘛,对不?
OK,当我们的driver找到了device的时候会执行probe回调函数,也就是这里的temperature_probe函数,好,我们来看一下这个probe函数:
[cpp] view plaincopyprint?static int temperature_probe(struct platform_device *pdev)
{
struct temperature_drvdata *ddata;
struct input_dev *idev;
int err=0;
printk(KERN_INFO "%s\n",__FUNCTION__);
ddata=kzalloc(sizeof(struct temperature_drvdata),GFP_KERNEL);
if(!ddata) {
printk(KERN_INFO "failed to allocate memory...\n");
err=-ENOMEM;
goto exit;
}
//----for iio device
ddata->indio_dev=iio_allocate_device();
if(!ddata->indio_dev){
printk(KERN_INFO "error to allocate iio device memory....\n");
goto exit_iio_alloc;
}
ddata->indio_dev->attrs = &temperature_attr_group;
ddata->indio_dev->dev.parent = &pdev->dev;
ddata->indio_dev->dev_data = (void *)(ddata);
ddata->indio_dev->driver_module = THIS_MODULE;
ddata->indio_dev->modes = INDIO_DIRECT_MODE;
err = iio_device_register(ddata->indio_dev);
if(err){
printk(KERN_INFO "iio device register failed....\n");
goto exit_iio_reg;
}
//-----for input device
ddata->poll_input=input_allocate_polled_device();
if(!(ddata->poll_input)){
err=-ENOMEM;
printk(KERN_INFO "input poll allocate failed...\n");
goto exit_iio_reg;
}
ddata->poll_input->poll=temperature_dev_poll;
ddata->poll_input->poll_interval = POLL_INTERVAL;
idev=ddata->poll_input->input;
idev->name = "Android Temperature Sensor";
idev->phys = "temperature-sensor/input0";
idev->dev.parent=&pdev->dev;
idev->id.bustype=BUS_HOST;
idev->id.vendor=0x1234;
idev->id.product=0x0123;
idev->id.version=0x0012;
__set_bit(EV_ABS,idev->evbit);
__set_bit(ABS_PRESSURE,idev->absbit);
__set_bit(EV_SYN,idev->evbit);
input_set_abs_params(idev,ABS_PRESSURE,0,65535,0,0);
err=input_register_polled_device(ddata->poll_input);
if(err){
printk(KERN_INFO "input register poll device failed....\n");
goto err_reg_poll;
}
platform_set_drvdata(pdev,ddata);
return 0;
err_reg_poll:
input_free_polled_device(ddata->poll_input);
exit_iio_reg:
iio_free_device(ddata->indio_dev);
exit_iio_alloc:
kfree(ddata);
exit:
return err;
}
static int temperature_probe(struct platform_device *pdev)
{
struct temperature_drvdata *ddata;
struct input_dev *idev;
int err=0;
printk(KERN_INFO "%s\n",__FUNCTION__);
ddata=kzalloc(sizeof(struct temperature_drvdata),GFP_KERNEL);
if(!ddata) {
printk(KERN_INFO "failed to allocate memory...\n");
err=-ENOMEM;
goto exit;
}
//----for iio device
ddata->indio_dev=iio_allocate_device();
if(!ddata->indio_dev){
printk(KERN_INFO "error to allocate iio device memory....\n");
goto exit_iio_alloc;
}
ddata->indio_dev->attrs = &temperature_attr_group;
ddata->indio_dev->dev.parent = &pdev->dev;
ddata->indio_dev->dev_data = (void *)(ddata);
ddata->indio_dev->driver_module = THIS_MODULE;
ddata->indio_dev->modes = INDIO_DIRECT_MODE;
err = iio_device_register(ddata->indio_dev);
if(err){
printk(KERN_INFO "iio device register failed....\n");
goto exit_iio_reg;
}
//-----for input device
ddata->poll_input=input_allocate_polled_device();
if(!(ddata->poll_input)){
err=-ENOMEM;
printk(KERN_INFO "input poll allocate failed...\n");
goto exit_iio_reg;
}
ddata->poll_input->poll=temperature_dev_poll;
ddata->poll_input->poll_interval = POLL_INTERVAL;
idev=ddata->poll_input->input;
idev->name = "Android Temperature Sensor";
idev->phys = "temperature-sensor/input0";
idev->dev.parent=&pdev->dev;
idev->id.bustype=BUS_HOST;
idev->id.vendor=0x1234;
idev->id.product=0x0123;
idev->id.version=0x0012;
__set_bit(EV_ABS,idev->evbit);
__set_bit(ABS_PRESSURE,idev->absbit);
__set_bit(EV_SYN,idev->evbit);
input_set_abs_params(idev,ABS_PRESSURE,0,65535,0,0);
err=input_register_polled_device(ddata->poll_input);
if(err){
printk(KERN_INFO "input register poll device failed....\n");
goto err_reg_poll;
}
platform_set_drvdata(pdev,ddata);
return 0;
err_reg_poll:
input_free_polled_device(ddata->poll_input);
exit_iio_reg:
iio_free_device(ddata->indio_dev);
exit_iio_alloc:
kfree(ddata);
exit:
return err;
}
这边做的都是一些初始化的事情,我们这边首先给我们的机构体分配内存,然后给iio device分配空间,然后注册iio device,然后注册input_polled_device这里可以参考input)poll的源码,主要就是内嵌了一个工作队列来poll数据,这里不多说读者可以自行去分析。
这里最重要的有2点我提一下,首先就是我们poll数据的回调函数被挂在ddata->poll_input->poll=temperature_dev_poll;参考源码这个回调函数是什么时候被执行的呢,其实input_polled_dev还有几个回调函数,其中有一个open和close函数,当user space去open input下面的这个event的时候poll回调函数就会一直执行,时间间隔为我们定义的interval这个参数。还有一点就是iio 设备驱动上面挂的文件系统就是ddata->indio_dev->attrs = &temperature_attr_group;用法很简单吧,这边我只是注册了一个name的文件节点,user space可以去读写这个节点,一般我们写驱动的时候可以用这个文件节点来开关我们的设备。
OK,接下来就是一些事件的处理,看如下代码:
[cpp] view plaincopyprint?#include "android-temperature.h"
static ssize_t temperature_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", "android-temperature sensor");
}
static IIO_DEVICE_ATTR(name, S_IRUGO, temperature_show_name, NULL,0);
static struct attribute *temperature_attributes[] = {
&iio_dev_attr_name.dev_attr.attr,
NULL
};
static const struct attribute_group temperature_attr_group = {
.attrs = temperature_attributes,
};
static int tempValue;
static void temperature_dev_poll(struct input_polled_dev *dev)
{
printk(KERN_INFO "Current Temperature: %d\n",tempValue);
if((tempValue++)==100)
tempValue=0;
input_event(dev->input,EV_ABS,ABS_PRESSURE,tempValue);
input_sync(dev->input);
}
#include "android-temperature.h"
static ssize_t temperature_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", "android-temperature sensor");
}
static IIO_DEVICE_ATTR(name, S_IRUGO, temperature_show_name, NULL,0);
static struct attribute *temperature_attributes[] = {
&iio_dev_attr_name.dev_attr.attr,
NULL
};
static const struct attribute_group temperature_attr_group = {
.attrs = temperature_attributes,
};
static int tempValue;
static void temperature_dev_poll(struct input_polled_dev *dev)
{
printk(KERN_INFO "Current Temperature: %d\n",tempValue);
if((tempValue++)==100)
tempValue=0;
input_event(dev->input,EV_ABS,ABS_PRESSURE,tempValue);
input_sync(dev->input);
}
这里我们上报的数据就是这个tempValue,会每隔一段时间自增1,直到100再回到0,。
OK,驱动介绍完,接下来就可以把驱动编译进goldfish里面,然后运行模拟器,使用adb进入:
root@jay:/home/jay/android/common# adb shell
# cd sys/bus/iio/devices/
# ls
device0
device1
device2
# cd device2
# ls
uevent
subsystem
power
name
# cat name
android-temperature sensor
#
root@jay:/home/jay/android/common# adb shell
# cd sys/bus/iio/devices/
# ls
device0
device1
device2
# cd device2
# ls
uevent
subsystem
power
name
# cat name
android-temperature sensor
#
大家可以看到我这边cat出name就是自己写进去的那个名字,初步测试驱动ok接下来下一篇中给大家介绍下编译生成一个tool来测试驱动功能。
在这里我准备编写一个温度传感器的虚拟driver,之前写过g-sensor和light sensor,所以不想写了,换个新鲜的,其实驱动架构都是一样的,OK 分化不多说,下面就介绍一下这个驱动。
在这里,我比较偷懒的使用了linux的一个iio子系统,这是一个不成熟的子系统,所以被放到源码陌路下面的/drvers/staging中,对于这个子系统,我也只是粗略的看过它的驱动模型,好吧^0^,不过个人觉得这个子系统还是蛮简单使用的,而却里面的api不是很多,相信大家随便分析下就能搞懂了。
OK,首先是头文件
/common/drivers/staging/iio/temperature/android-temperature.h
[cpp] view plaincopyprint?#include
#include
#include
#include
#include "../iio.h"
#define POLL_INTERVAL 2000 //set poll time
struct temperature_drvdata {
struct iio_dev *indio_dev;
struct input_polled_dev *poll_input;
//....reserved
};
#include
#include
#include
#include
#include "../iio.h"
#define POLL_INTERVAL 2000 //set poll time
struct temperature_drvdata {
struct iio_dev *indio_dev;
struct input_polled_dev *poll_input;
//....reserved
};
相信大家看到了这个头文件就差不多知道驱动是怎么写的了吧,我选用的是platform device driver,driver layer向user space传送数据时通过input sybsystem传送的,这也是android sensor驱动比较主流的做法,还有一些做法是直接往自己创建的sysfs中写数据,这也是一中比较简单的做法,事件的触控方式我选用的是poll方式,因为这里我写的驱动是一个虚拟的设备,一般出发方式会选用中断触发,而我这个驱动选择每隔一段时间往user space上报数据,时间间隔就是这里的POLL_INTERVAL这个宏设定的。
说了这么多都没有看到驱动的代码真不好意思,下面来分析下驱动的代码。
/common/drivers/staging/iio/temperature/android-temperature.c
首先是init和exit函数:
static int __init temperature_init(void)
{
printk(KERN_INFO "temperature init...\n");
return platform_driver_register(&temperature_device_driver);
}
static void __exit temperature_exit(void)
{
platform_driver_unregister(&temperature_device_driver);
}
module_init(temperature_init);
module_exit(temperature_exit);
static int __init temperature_init(void)
{
printk(KERN_INFO "temperature init...\n");
return platform_driver_register(&temperature_device_driver);
}
static void __exit temperature_exit(void)
{
platform_driver_unregister(&temperature_device_driver);
}
module_init(temperature_init);
module_exit(temperature_exit);这也没啥好说的,大家愿意的话可以再后面在添上这个driver module的作者和出处,传扬千里,哈哈,我就不了,本人比较谦虚。
这也没啥好说的,大家愿意的话可以再后面在添上这个driver module的作者和出处,传扬千里,哈哈,我就不了,本人比较谦虚。这边最主要的应该就是temperature_device_driver这个变量这是一个platform_driver结构体,在驱动注册的时候必须把这个结构体传进去,我们的platform设备模型就是通过这个结构体找到相应的device,然后把driver和device绑定在一起,这边涉及到linux 设备驱动模型,这边我也不做详细的分析了,想要了解的话可以自己学习,个人觉得如果是做linux驱动的话了解linux 设备驱动模型是很重要的,这可以让我们站在一个比较高的层次上去写代码。
OK,不扯了看下这个结构体:
[cpp] view plaincopyprint?static struct platform_driver temperature_device_driver = {
.probe = temperature_probe,
// .remove = __devexit_p(temperature_remove),
.driver = {
.name = "android-temperature",
.owner= THIS_MODULE,
},
};
static struct platform_driver temperature_device_driver = {
.probe = temperature_probe,
// .remove = __devexit_p(temperature_remove),
.driver = {
.name = "android-temperature",
.owner= THIS_MODULE,
},
};
这边就是定义了probe和remove,真实的设备的话还有会suspend,resume,early_suspend,late_resume等回调函数,在适当的时间会回调到这些函数(犀利的读者可能看到了这边remove我没有去实现,哈哈,我比较懒,不过大家要有一个良好的习惯,不要学我)。但是在这边注册了platform的驱动,是去找哪的platform设备呢?当然是我们自己要去实现啦,通常device端我们都会在板级的文件中去定义,我们这里是:
/common/arch/arm/mach-goldfish/board-goldfish.c
[cpp] view plaincopyprint?struct platform_device android_temperature_device = {
.name="android-temperature",
.id=-1,
};
static void __init goldfish_init(void)
{
platform_device_register(&goldfish_pdev_bus_device);
platform_device_register(&android_temperature_device);
}
struct platform_device android_temperature_device = {
.name="android-temperature",
.id=-1,
};
static void __init goldfish_init(void)
{
platform_device_register(&goldfish_pdev_bus_device);
platform_device_register(&android_temperature_device);
}大家注意。这边的name和driver中platform_driver中name用该一样,不然他们怎么可以绑定在一起呢,不然他们怎么会找到对方呢,有缘千里来相会嘛,对不?
OK,当我们的driver找到了device的时候会执行probe回调函数,也就是这里的temperature_probe函数,好,我们来看一下这个probe函数:
[cpp] view plaincopyprint?static int temperature_probe(struct platform_device *pdev)
{
struct temperature_drvdata *ddata;
struct input_dev *idev;
int err=0;
printk(KERN_INFO "%s\n",__FUNCTION__);
ddata=kzalloc(sizeof(struct temperature_drvdata),GFP_KERNEL);
if(!ddata) {
printk(KERN_INFO "failed to allocate memory...\n");
err=-ENOMEM;
goto exit;
}
//----for iio device
ddata->indio_dev=iio_allocate_device();
if(!ddata->indio_dev){
printk(KERN_INFO "error to allocate iio device memory....\n");
goto exit_iio_alloc;
}
ddata->indio_dev->attrs = &temperature_attr_group;
ddata->indio_dev->dev.parent = &pdev->dev;
ddata->indio_dev->dev_data = (void *)(ddata);
ddata->indio_dev->driver_module = THIS_MODULE;
ddata->indio_dev->modes = INDIO_DIRECT_MODE;
err = iio_device_register(ddata->indio_dev);
if(err){
printk(KERN_INFO "iio device register failed....\n");
goto exit_iio_reg;
}
//-----for input device
ddata->poll_input=input_allocate_polled_device();
if(!(ddata->poll_input)){
err=-ENOMEM;
printk(KERN_INFO "input poll allocate failed...\n");
goto exit_iio_reg;
}
ddata->poll_input->poll=temperature_dev_poll;
ddata->poll_input->poll_interval = POLL_INTERVAL;
idev=ddata->poll_input->input;
idev->name = "Android Temperature Sensor";
idev->phys = "temperature-sensor/input0";
idev->dev.parent=&pdev->dev;
idev->id.bustype=BUS_HOST;
idev->id.vendor=0x1234;
idev->id.product=0x0123;
idev->id.version=0x0012;
__set_bit(EV_ABS,idev->evbit);
__set_bit(ABS_PRESSURE,idev->absbit);
__set_bit(EV_SYN,idev->evbit);
input_set_abs_params(idev,ABS_PRESSURE,0,65535,0,0);
err=input_register_polled_device(ddata->poll_input);
if(err){
printk(KERN_INFO "input register poll device failed....\n");
goto err_reg_poll;
}
platform_set_drvdata(pdev,ddata);
return 0;
err_reg_poll:
input_free_polled_device(ddata->poll_input);
exit_iio_reg:
iio_free_device(ddata->indio_dev);
exit_iio_alloc:
kfree(ddata);
exit:
return err;
}
static int temperature_probe(struct platform_device *pdev)
{
struct temperature_drvdata *ddata;
struct input_dev *idev;
int err=0;
printk(KERN_INFO "%s\n",__FUNCTION__);
ddata=kzalloc(sizeof(struct temperature_drvdata),GFP_KERNEL);
if(!ddata) {
printk(KERN_INFO "failed to allocate memory...\n");
err=-ENOMEM;
goto exit;
}
//----for iio device
ddata->indio_dev=iio_allocate_device();
if(!ddata->indio_dev){
printk(KERN_INFO "error to allocate iio device memory....\n");
goto exit_iio_alloc;
}
ddata->indio_dev->attrs = &temperature_attr_group;
ddata->indio_dev->dev.parent = &pdev->dev;
ddata->indio_dev->dev_data = (void *)(ddata);
ddata->indio_dev->driver_module = THIS_MODULE;
ddata->indio_dev->modes = INDIO_DIRECT_MODE;
err = iio_device_register(ddata->indio_dev);
if(err){
printk(KERN_INFO "iio device register failed....\n");
goto exit_iio_reg;
}
//-----for input device
ddata->poll_input=input_allocate_polled_device();
if(!(ddata->poll_input)){
err=-ENOMEM;
printk(KERN_INFO "input poll allocate failed...\n");
goto exit_iio_reg;
}
ddata->poll_input->poll=temperature_dev_poll;
ddata->poll_input->poll_interval = POLL_INTERVAL;
idev=ddata->poll_input->input;
idev->name = "Android Temperature Sensor";
idev->phys = "temperature-sensor/input0";
idev->dev.parent=&pdev->dev;
idev->id.bustype=BUS_HOST;
idev->id.vendor=0x1234;
idev->id.product=0x0123;
idev->id.version=0x0012;
__set_bit(EV_ABS,idev->evbit);
__set_bit(ABS_PRESSURE,idev->absbit);
__set_bit(EV_SYN,idev->evbit);
input_set_abs_params(idev,ABS_PRESSURE,0,65535,0,0);
err=input_register_polled_device(ddata->poll_input);
if(err){
printk(KERN_INFO "input register poll device failed....\n");
goto err_reg_poll;
}
platform_set_drvdata(pdev,ddata);
return 0;
err_reg_poll:
input_free_polled_device(ddata->poll_input);
exit_iio_reg:
iio_free_device(ddata->indio_dev);
exit_iio_alloc:
kfree(ddata);
exit:
return err;
}
这边做的都是一些初始化的事情,我们这边首先给我们的机构体分配内存,然后给iio device分配空间,然后注册iio device,然后注册input_polled_device这里可以参考input)poll的源码,主要就是内嵌了一个工作队列来poll数据,这里不多说读者可以自行去分析。
这里最重要的有2点我提一下,首先就是我们poll数据的回调函数被挂在ddata->poll_input->poll=temperature_dev_poll;参考源码这个回调函数是什么时候被执行的呢,其实input_polled_dev还有几个回调函数,其中有一个open和close函数,当user space去open input下面的这个event的时候poll回调函数就会一直执行,时间间隔为我们定义的interval这个参数。还有一点就是iio 设备驱动上面挂的文件系统就是ddata->indio_dev->attrs = &temperature_attr_group;用法很简单吧,这边我只是注册了一个name的文件节点,user space可以去读写这个节点,一般我们写驱动的时候可以用这个文件节点来开关我们的设备。
OK,接下来就是一些事件的处理,看如下代码:
[cpp] view plaincopyprint?#include "android-temperature.h"
static ssize_t temperature_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", "android-temperature sensor");
}
static IIO_DEVICE_ATTR(name, S_IRUGO, temperature_show_name, NULL,0);
static struct attribute *temperature_attributes[] = {
&iio_dev_attr_name.dev_attr.attr,
NULL
};
static const struct attribute_group temperature_attr_group = {
.attrs = temperature_attributes,
};
static int tempValue;
static void temperature_dev_poll(struct input_polled_dev *dev)
{
printk(KERN_INFO "Current Temperature: %d\n",tempValue);
if((tempValue++)==100)
tempValue=0;
input_event(dev->input,EV_ABS,ABS_PRESSURE,tempValue);
input_sync(dev->input);
}
#include "android-temperature.h"
static ssize_t temperature_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", "android-temperature sensor");
}
static IIO_DEVICE_ATTR(name, S_IRUGO, temperature_show_name, NULL,0);
static struct attribute *temperature_attributes[] = {
&iio_dev_attr_name.dev_attr.attr,
NULL
};
static const struct attribute_group temperature_attr_group = {
.attrs = temperature_attributes,
};
static int tempValue;
static void temperature_dev_poll(struct input_polled_dev *dev)
{
printk(KERN_INFO "Current Temperature: %d\n",tempValue);
if((tempValue++)==100)
tempValue=0;
input_event(dev->input,EV_ABS,ABS_PRESSURE,tempValue);
input_sync(dev->input);
}
这里我们上报的数据就是这个tempValue,会每隔一段时间自增1,直到100再回到0,。
OK,驱动介绍完,接下来就可以把驱动编译进goldfish里面,然后运行模拟器,使用adb进入:
root@jay:/home/jay/android/common# adb shell
# cd sys/bus/iio/devices/
# ls
device0
device1
device2
# cd device2
# ls
uevent
subsystem
power
name
# cat name
android-temperature sensor
#
root@jay:/home/jay/android/common# adb shell
# cd sys/bus/iio/devices/
# ls
device0
device1
device2
# cd device2
# ls
uevent
subsystem
power
name
# cat name
android-temperature sensor
#
大家可以看到我这边cat出name就是自己写进去的那个名字,初步测试驱动ok接下来下一篇中给大家介绍下编译生成一个tool来测试驱动功能。
paranoid android中文歌词
radiohead 的 Paranoid Android 中文翻译
framework是什么
net framework
NET Framework
模拟器!!
模拟器!!!!!!!!!!!!!!
模拟器!!!!!!!!!
模拟器!!!
NET Framework是什么软件
装不上!Microsoft .NET Framework
.net framework 问题?
Microsoft .NET Framework sdk
Microsoft .NET Framework sdk
有关.net framework的
micosoft .net framework是什么?
micosoft .net framework是什么?
.net framework是什么?
.net framework哪有啊
.net framework哪有啊
.net Framework环境下载
如何安装.NET framework
Framework是什么呀
什么是.net framework ?