Android模拟器学framework和driver之传感器篇1(linux sensor driver)

对于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

#include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/input-polldev.h> #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);这也没啥好说的,大家愿意的话可以再后面在添上这个driver module的作者和出处,传扬千里,哈哈,我就不了,本人比较谦虚。这边最主要的应该就是temperature_device_driver这个变量这是一个platform_driver结构体,在驱动注册的时候必须把这个结构体传进去,我们的platform设备模型就是通过这个结构体找到相应的device,然后把driver和device绑定在一起,这边涉及到linux 设备驱动模型,这边我也不做详细的分析了,想要了解的话可以自己学习,个人觉得如果是做linux驱动的话了解linux 设备驱动模型是很重要的,这可以让我们站在一个比较高的层次上去写代码。

OK,不扯了看下这个结构体:

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

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函数:

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,接下来就是一些事件的处理,看如下代码:

#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 # 大家可以看到我这边cat出name就是自己写进去的那个名字,初步测试驱动ok接下来下一篇中给大家介绍下编译生成一个tool来测试驱动功能。








AndroidSensor移植的总结     Sensor作为Android系统的一个输入设备,对Android设备来说是必不可少的。Sensor主要报告G-Sensor、LightsSensor、ProximitySensor、TemperatureSensor等。由于各个Sensor的移植大同小异。本文就主要对G-SensorLightSensor进行说明。Sensor的移植主要包括三部分的工作:Linux Kernel中相关设备的驱动开发Android中HAL中相关库的开发以及Android中应用层中测试程序的开发。一、Linux K 阅读详情

相关推荐

【信息科与工程】【数据中心】第三十五 云计算数据中心的科知识04

编号科(课程)核心知识点在云计算/云存储/云网络/云安全/云MaaS中的作用代表教材/资料/论文 + 数方程式列表工业界应用D1421​云原生数据库:TiDB​HTAP(混合事务/分析处理)、分布式SQL、水平扩展、强一致(Raft)、自动故障恢复、与MySQL兼容、TiFlash列式引擎提供弹性扩展的分布式数据库;支撑高并发在线交易与实时分析教材:《TiDB in Action》PingCAP(2020) 论文:《TiDB: A Raft-based HTAP Database》(2017)

weixin_49199313的博客 206

linux iio子系统

//============================================================================\\ || 系            统:WindowsXP & Ubuntu14.04       || || 工            具:Source Insight 3.5       || || 作

疯狂三极管的博客 2万+

sensor driver习笔记

以前听前辈讲过一部分,现在通过阅读高通文档又补充了一部分内容,在此记录,防止遗忘。也分享给需要的朋友们。

qq_42261630的博客 1044

linux输入设备驱动程序

输入设备是与系统交互的设备,这些设备包括按钮、键盘、触摸屏、鼠标等。他们的工作方式是发送事件、输入内核在系统上捕获传播。

Icewaver的专栏 462

select实现延时函数

select实现延时函数

1484

Android模拟器frameworkdriver传感器Android HAL)

前面,带着大家一起写了一个temperature sensor驱动,已经一个测试tool来测试这个驱动,基本功能已经ok,若还有问题的可以参考前面2文章,在这里我们要在HAL层中添加我们的设备,来跟framework中的代码连接起来。 在开始摆代码之前我觉得有必要啰嗦几句,HAL层我个人觉得是个比较重要的东西,虽然这边现在还不是很成熟,还不是很规范,但是google还是做了很大力气针对H

wantianpei的专栏 1720

android hal 光线传感器,Android模拟器frameworkdriver传感器3(Android HAL)

当前位置:操作系统 > 安卓/Android >>Android模拟器frameworkdriver传感器3(Android HAL)前面,带着大家一起写了一个temperature sensor驱动,已经一个测试tool来测试这个驱动,基本功能已经ok,若还有问题的可以参考前面2文章,在这里我们要在HAL层中添加我们的设备,来跟framework中的代码连接起来。在...

weixin_39885067的博客 469

Android模拟器frameworkdriver传感器

Android模拟器frameworkdriver传感器 Android传感器的介绍这里我就不多说了,给出一个链接,想了解的朋友可以先去了解下: http://www.ibm.com/developerworks/cn/opensource/os-android-sensor/   我这里我会带着大家一起分析android传感器部分,之前拜读过罗老师对Android HAL分

sam0535的专栏 2849

Android HAL模块开发实战:从HIDL接口到内核通信完整实现

硬件抽象层(HAL)是Android系统架构中的核心组件,它定义了硬件设备与上层框架之间的标准化接口。其核心原理是通过接口定义语言(如HIDL)实现进程间通信(IPC),将硬件具体实现细节封装在底层,为上层提供统一的访问方式。这一设计的技术价值在于实现了硬件驱动的跨平台兼容性可维护性,使得Android能够适配多样化的硬件设备。在工程实践中,HAL模块通常需要与Linux内核驱动通过sysfs文件系统或ioctl系统调用进行数据交互,完成传感器数据采集、设备控制等关键功能。本文以构建一个虚拟传感器HAL模

cuanji3287的博客 429

A33_gsensor驱动调试

lichee\tools\pack\chips\sun8iw5p1\configs\m86\sysconfig.fex里面 ;-------------------------------------------------------------------------------- ; G sensor configuration ; gs_twi_id--- TWI ID for co...

look_distance的博客 693

Linux中断,时钟延时

1 概述   ############### 由于中断服务程序的执行并不存在于进程上下文中,所以要求中断服务程序的时间要尽量短。因此, Linux在中断处理中引入了顶半部底半部分离的机制。另外,内核对时钟的处理也采用中断方式,而内核软件定时器最终依赖于时钟中断。   根据中断的来源,中断可分为内部中断外部中断 内部中断的中断源来自CPU内部(软件中断指令、溢出、除法错误等,例如,操作系...

QtHalcon 2803

Android模拟器frameworkdriver传感器6(Android 通过JNI连接驱动framework)...

之前,我们已经实现了android HAL层,在android模拟器上移植了一个虚拟的temperature sensor,我之前在模拟器上也移植了backlight,RTC等驱动,都能在应用层得到需要的数据,其实自己想点东西,给自己布置点任务还是不错的,通过模拟器也可以来linux 中的device driver,这部分在今后的博客中我会涉及到,这blog我主要是想在之前所做的东西的基础...

luotuoass 289

Linux 下 poll 详解

Linux下Poll

威桑的博客 3680

Android/Linux 全志平台摄像头sensor调试记录(一)

1 .摄像头模组型号 OV2710 + XC7021( ISP)   +H5,电压需求 ISP:          OV2710:senor 的电压AVDD DOVDD 电压为3.3V,DVDD 1.5V 。ISP 控制sensor PWDN        XC7021 I2C 地址为0x36, OV2710地址为0x6C        #define I2C_ADDRBP

lbaihao的专栏 8211

android sensor移植

sensor直接连接到应用处理器,并有linuxkernel管理。本文涉及到kernel驱动sensor HAL以及SensorService。 sensor架构 安卓提供Sensor APISensorManager,然而没有提供Sensor HALsensor驱动。 电源管理管脚功能设置在设备树中应当设置好,Sensor类用于支持一些新特性。增加了一些sensor新特性,如:

shichaog的专栏 4369

linux gsensor驱动分析【转】

本文转载自:http://blog.sina.com.cn/s/blog_89f592f501013sr2.html 本文以Bma250驱动为例子,详细介绍Gsensor设计的一个模板。 gsensor驱动在系统中的层次如下图所示: 图中包含三个部分:hardware, driver, input: nHardware:其实我们可以认为Gsensor也是一个I2C设备。...

zzb2760715357的博客 717
上一篇: live555学习笔记17-H264VideoStreamParser详解
下一篇: Android模拟器学framework和driver之传感器篇2(生成测试tool)
ai_longyu
博客等级 码龄14年 9粉丝 209原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值