对于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 plaincopy
  1. #include <linux/module.h>
  2. #include <linux/platform_device.h>
  3. #include <linux/slab.h>
  4. #include <linux/input-polldev.h>
  5. #include "../iio.h"
  6. #define POLL_INTERVAL   2000    //set poll time
  7. struct temperature_drvdata {
  8. struct iio_dev *indio_dev;
  9. struct input_polled_dev *poll_input;
  10. //....reserved
  11. };

相信大家看到了这个头文件就差不多知道驱动是怎么写的了吧,我选用的是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函数:

[html] view plaincopy
  1. <span style="color:#cc33cc;"><strong>static int __init temperature_init(void)
  2. {
  3. printk(KERN_INFO "temperature init...\n");
  4. return platform_driver_register(&temperature_device_driver);
  5. }
  6. static void __exit temperature_exit(void)
  7. {
  8. platform_driver_unregister(&temperature_device_driver);
  9. }
  10. module_init(temperature_init);
  11. module_exit(temperature_exit);</strong></span>
[html] view plaincopy
  1. 这也没啥好说的,大家愿意的话可以再后面在添上这个driver module的作者和出处,传扬千里,哈哈,我就不了,本人比较谦虚。

这边最主要的应该就是temperature_device_driver这个变量这是一个platform_driver结构体,在驱动注册的时候必须把这个结构体传进去,我们的platform设备模型就是通过这个结构体找到相应的device,然后把driver和device绑定在一起,这边涉及到linux 设备驱动模型,这边我也不做详细的分析了,想要了解的话可以自己学习,个人觉得如果是做linux驱动的话了解linux 设备驱动模型是很重要的,这可以让我们站在一个比较高的层次上去写代码。

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

[cpp] view plaincopy
  1. <span style="background-color: rgb(255, 255, 255);"><span style="color:#cc33cc;">static struct platform_driver temperature_device_driver = {
  2. .probe      =   temperature_probe,
  3. //  .remove     =   __devexit_p(temperature_remove),
  4. .driver     = {
  5. .name = "android-temperature",
  6. .owner= THIS_MODULE,
  7. },
  8. };</span></span>

这边就是定义了probe和remove,真实的设备的话还有会suspend,resume,early_suspend,late_resume等回调函数,在适当的时间会回调到这些函数(犀利的读者可能看到了这边remove我没有去实现,哈哈,我比较懒,不过大家要有一个良好的习惯,不要学我)。但是在这边注册了platform的驱动,是去找哪的platform设备呢?当然是我们自己要去实现啦,通常device端我们都会在板级的文件中去定义,我们这里是:

/common/arch/arm/mach-goldfish/board-goldfish.c

[cpp] view plaincopy
  1. <strong><span style="color:#cc33cc;">struct platform_device android_temperature_device = {
  2. .name="android-temperature",
  3. .id=-1,
  4. };
  5. </span></strong>
  6. static void __init goldfish_init(void)
  7. {
  8. platform_device_register(&goldfish_pdev_bus_device);
  9. <span style="color:#cc33cc;"><strong>   platform_device_register(&android_temperature_device);</strong></span>
  10. }

大家注意。这边的name和driver中platform_driver中name用该一样,不然他们怎么可以绑定在一起呢,不然他们怎么会找到对方呢,有缘千里来相会嘛,对不?

OK,当我们的driver找到了device的时候会执行probe回调函数,也就是这里的temperature_probe函数,好,我们来看一下这个probe函数:

[cpp] view plaincopy
  1. <strong><span style="color:#cc33cc;">static int temperature_probe(struct platform_device *pdev)
  2. {
  3. struct temperature_drvdata *ddata;
  4. struct input_dev *idev;
  5. int err=0;
  6. printk(KERN_INFO "%s\n",__FUNCTION__);
  7. ddata=kzalloc(sizeof(struct temperature_drvdata),GFP_KERNEL);
  8. if(!ddata) {
  9. printk(KERN_INFO "failed to allocate memory...\n");
  10. err=-ENOMEM;
  11. goto exit;
  12. }
  13. //----for iio device
  14. ddata->indio_dev=iio_allocate_device();
  15. if(!ddata->indio_dev){
  16. printk(KERN_INFO "error to allocate iio device memory....\n");
  17. goto exit_iio_alloc;
  18. }
  19. ddata->indio_dev->attrs = &temperature_attr_group;
  20. ddata->indio_dev->dev.parent = &pdev->dev;
  21. ddata->indio_dev->dev_data = (void *)(ddata);
  22. ddata->indio_dev->driver_module = THIS_MODULE;
  23. ddata->indio_dev->modes = INDIO_DIRECT_MODE;
  24. err = iio_device_register(ddata->indio_dev);
  25. if(err){
  26. printk(KERN_INFO "iio device register failed....\n");
  27. goto exit_iio_reg;
  28. }
  29. //-----for input device
  30. ddata->poll_input=input_allocate_polled_device();
  31. if(!(ddata->poll_input)){
  32. err=-ENOMEM;
  33. printk(KERN_INFO "input poll allocate failed...\n");
  34. goto exit_iio_reg;
  35. }
  36. ddata->poll_input->poll=temperature_dev_poll;
  37. ddata->poll_input->poll_interval = POLL_INTERVAL;
  38. idev=ddata->poll_input->input;
  39. idev->name = "Android Temperature Sensor";
  40. idev->phys = "temperature-sensor/input0";
  41. idev->dev.parent=&pdev->dev;
  42. idev->id.bustype=BUS_HOST;
  43. idev->id.vendor=0x1234;
  44. idev->id.product=0x0123;
  45. idev->id.version=0x0012;
  46. __set_bit(EV_ABS,idev->evbit);
  47. __set_bit(ABS_PRESSURE,idev->absbit);
  48. __set_bit(EV_SYN,idev->evbit);
  49. input_set_abs_params(idev,ABS_PRESSURE,0,65535,0,0);
  50. err=input_register_polled_device(ddata->poll_input);
  51. if(err){
  52. printk(KERN_INFO "input register poll device failed....\n");
  53. goto err_reg_poll;
  54. }
  55. platform_set_drvdata(pdev,ddata);
  56. return 0;
  57. err_reg_poll:
  58. input_free_polled_device(ddata->poll_input);
  59. exit_iio_reg:
  60. iio_free_device(ddata->indio_dev);
  61. exit_iio_alloc:
  62. kfree(ddata);
  63. exit:
  64. return err;
  65. }</span></strong>

这边做的都是一些初始化的事情,我们这边首先给我们的机构体分配内存,然后给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 plaincopy
  1. <span style="color:#cc33cc;"><strong>#include "android-temperature.h"
  2. static ssize_t temperature_show_name(struct device *dev,
  3. struct device_attribute *attr, char *buf)
  4. {
  5. return sprintf(buf, "%s\n", "android-temperature sensor");
  6. }
  7. static IIO_DEVICE_ATTR(name, S_IRUGO, temperature_show_name, NULL,0);
  8. static struct attribute *temperature_attributes[] = {
  9. &iio_dev_attr_name.dev_attr.attr,
  10. NULL
  11. };
  12. static const struct attribute_group temperature_attr_group = {
  13. .attrs = temperature_attributes,
  14. };
  15. static int tempValue;
  16. static void temperature_dev_poll(struct input_polled_dev *dev)
  17. {
  18. printk(KERN_INFO "Current Temperature: %d\n",tempValue);
  19. if((tempValue++)==100)
  20. tempValue=0;
  21. input_event(dev->input,EV_ABS,ABS_PRESSURE,tempValue);
  22. input_sync(dev->input);
  23. }</strong></span>

这里我们上报的数据就是这个tempValue,会每隔一段时间自增1,直到100再回到0,。

OK,驱动介绍完,接下来就可以把驱动编译进goldfish里面,然后运行模拟器,使用adb进入:

[html] view plaincopy
  1. <strong><span style="color:#cc33cc;">root@jay:/home/jay/android/common# adb shell
  2. # cd sys/bus/iio/devices/
  3. # ls
  4. device0
  5. device1
  6. device2
  7. # cd device2
  8. # ls
  9. uevent
  10. subsystem
  11. power
  12. name
  13. # cat name
  14. android-temperature sensor
  15. # </span></strong>

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

转载于:https://www.cnblogs.com/zhangjie-ai-liujun/archive/2012/03/31/2426695.html

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

  1. Android模拟器学framework和driver之传感器篇3(Android HAL)

    Android模拟器学framework和driver之传感器篇3(Android HAL) 前面,带着大家一起写了一个temperature sensor的驱动,已经一个测试tool来测试这个驱动, ...

  2. Android模拟器学framework和driver之battery backlight-----5. backlight in linux

    前面介绍了battery的相关的东西,现在我们来介绍下backlight模块,背光主要是用来调节显示屏亮度的,一般背光都是用PWM控制的,调节占空比达到改变有效电压值来调节光的强弱. 背光的移植在li ...

  3. [Linux Audio Driver] Qualcomm平台音频GMS认证器件要求

    从GMS测试常见的fail项来明确其器件要求,常见的fail测试项主要是以下三个: 后面是分析,要看结论的话直接拉到文末: 一:Audio Frequency Speaker Test 此测试使用外部 ...

  4. android 4.0模拟器启动不了,Android 4.0 framework源码修改编译,模拟器运行不起来,求助...

    当前位置:编程学习 > wap >> Android 4.0 framework源码修改编译,模拟器运行不起来,求助 我下载编译了android 4.0 ICS的源码,然后能利用编译 ...

  5. Appium移动自动化测试(三)--安装Android模拟器(转)

    Appium移动自动化测试(三)--安装Android模拟器 2015-06-08 10:33 by 虫师, 30828 阅读, 9 评论, 收藏, 编辑 当Android SDK安装完成之后,并不意 ...

  6. 介绍Visual Studio的Android模拟器

    介绍Visual Studio的Android模拟器 http://blogs.msdn.com/b/visualstudioalm/archive/2014/11/12/introducing-vi ...

  7. 用Android Studio调试Framework层代码

    Android程序员不得不知的调试技巧. 本文以webview loadUrl和域名解析为例,介绍配合使用LLDB和Android Studio调试Framework代码的技巧. java 层调试 首 ...

  8. 安装Android模拟器Genymotion【Android学习入门】

    安装Android模拟器Genymotion 推荐教程:一个强大的Android模拟器Genymotion具体内容如下: 相信很多Android开发者一定受够了速度慢.体验差效率及其地下的官方模拟器了 ...

  9. eclipse 插件 ---Android 模拟器genymotion安装(整理)

    genymotion是一款号称速度最快性能最好的android模拟器,它基于Oracle VM VirtualBox.支持GPS.重力感应.光.温度等诸多传感器:支持OpenGL 3D加速:电池电 ...

最新文章

  1. canvas java 上传截图_在Vue项目中使用html2canvas生成页面截图并上传
  2. react 合并数组_React 常被忽视的细节。
  3. JavaScript递归应用与实践
  4. 超燃| 2019 中国.NET 开发者峰会视频发布
  5. DOS状态下可以安装Win XP
  6. 小米“祭出” AIoT 神器!| 技术头条
  7. 如何才能不被社会淘汰?一个程序员的七年之痒
  8. UnityShader中插值平滑曲线
  9. RGMII通信接口详述
  10. 使用Optuna进行超参数优化
  11. 群晖DSM Docker下Xware迅雷远程下载教程
  12. 数据导入与预处理实验二---json格式文件转换
  13. Windows Server 2016修改计算机名
  14. EXCEL横向表格如何调整为纵向表格?
  15. 从零开始制作游戏辅助
  16. Kindle电子书整理脚本
  17. 使用scrollTo、scrollBy、Scroller实现滚动动画
  18. google 天气rss
  19. dede image.class.php,织梦CMS中图片处理类
  20. Android自定义View绘制流程

热门文章

  1. 2022-2028年中国金融云行业市场研究及前瞻分析报告
  2. etcd 笔记(09)— 基于 etcd 实现微服务的注册与发现
  3. 2022-2028年中国钽酸锂单晶行业市场调查分析及投资发展潜力报告
  4. MYSQL局域网访问设置
  5. 用TVM在硬件平台上部署深度学习工作负载的端到端 IR 堆栈
  6. MindArmour差分隐私
  7. 如何在GPU上优化卷积
  8. CUDA运行时Runtime(三)
  9. NVIDIA安倍架构
  10. 2021年大数据Flink(十二):流批一体API Transformation