日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

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

發布時間:2023/11/27 生活经验 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

?

[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. ??
  7. #define?POLL_INTERVAL???2000????//set?poll?time??
  8. ??
  9. struct?temperature_drvdata?{??
  10. ????struct?iio_dev?*indio_dev;??
  11. ????struct?input_polled_dev?*poll_input;??
  12. ????//....reserved??
  13. };??

相信大家看到了這個頭文件就差不多知道驅動是怎么寫的了吧,我選用的是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. ??
  7. static?void?__exit?temperature_exit(void)??
  8. {??
  9. ????platform_driver_unregister(&temperature_device_driver);??
  10. }??
  11. ??
  12. module_init(temperature_init);??
  13. 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. ??
  3. ??
  4. static?ssize_t?temperature_show_name(struct?device?*dev,??
  5. ????struct?device_attribute?*attr,?char?*buf)??
  6. {?????
  7. ????return?sprintf(buf,?"%s\n",?"android-temperature?sensor");??
  8. }??
  9. ??
  10. static?IIO_DEVICE_ATTR(name,?S_IRUGO,?temperature_show_name,?NULL,0);??
  11. ??
  12. static?struct?attribute?*temperature_attributes[]?=?{??
  13. ????&iio_dev_attr_name.dev_attr.attr,??
  14. ????NULL??
  15. };??
  16. ??
  17. static?const?struct?attribute_group?temperature_attr_group?=?{??
  18. ????.attrs?=?temperature_attributes,??
  19. };??
  20. ??
  21. static?int?tempValue;??
  22. static?void?temperature_dev_poll(struct?input_polled_dev?*dev)??
  23. {??
  24. ????printk(KERN_INFO?"Current?Temperature:?%d\n",tempValue);??
  25. ????if((tempValue++)==100)??
  26. ????????tempValue=0;??
  27. ????input_event(dev->input,EV_ABS,ABS_PRESSURE,tempValue);??
  28. ????input_sync(dev->input);??
  29. }</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)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。