转载自:http://blog.csdn.net/myarrow/article/details/7175204

参考文献:

http://blog.csdn.net/luoshengyang/article/details/6573809

http://blog.csdn.net/hongtao_liu/article/details/6060734

建议阅读本文时先浏览以上两篇文章,本文是对上两篇文章在HAL对上层接口话题的一个总结.

1 什么是HAL

HAL的全称是Hardware Abstraction Layer,即硬件抽象层.其架构图如下:

Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚。思路是把控制硬件的动作都放到了Android HAL中,而linux driver仅仅完成一些简单的数据交互作用,甚至把硬件寄存器空间直接映射到user space。而Android是基于Aparch的license,因此硬件厂商可以只提供二进制代码,所以说Android只是一个开放的平台,并不是一个开源的平台。也许也正是因为Android不遵从GPL,所以Greg Kroah-Hartman才在2.6.33内核将Andorid驱动从linux中删除。GPL和硬件厂商目前还是有着无法弥合的裂痕。Android想要把这个问题处理好也是不容易的。

总结下来,Android HAL存在的原因主要有:

1. 并不是所有的硬件设备都有标准的linux kernel的接口

2. KERNEL DRIVER涉及到GPL的版权。某些设备制造商并不原因公开硬件驱动,所以才去用HAL方式绕过GPL。

3. 针对某些硬件,Android有一些特殊的需求.

2 与接口相关的几个结构体

首先来看三个与HAL对上层接口有关的几个结构体:

view plain copy to clipboard
  1. structhw_module_t;//模块类型
  2. structhw_module_methods_t;//模块方法
  3. structhw_device_t;//设备类型,向上提供接口
这几个数据结构是在Android工作目录/hardware/libhardware/include/hardware/hardware.h文件中定义.

3 解释

一般来说,在写HAL相关代码时都得包含这个hardware.h头文件,所以有必要先了解一下这个头文件中的内容.

view plain copy to clipboard
  1. /*
  2. *Copyright(C)2008TheAndroidOpenSourceProject
  3. *
  4. *LicensedundertheApacheLicense,Version2.0(the"License");
  5. *youmaynotusethisfileexceptincompliancewiththeLicense.
  6. *YoumayobtainacopyoftheLicenseat
  7. *
  8. *http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  11. *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  12. *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  13. *SeetheLicenseforthespecificlanguagegoverningpermissionsand
  14. *limitationsundertheLicense.
  15. */
  16. #ifndefANDROID_INCLUDE_HARDWARE_HARDWARE_H
  17. #defineANDROID_INCLUDE_HARDWARE_HARDWARE_H
  18. #include<stdint.h>
  19. #include<sys/cdefs.h>
  20. #include<cutils/native_handle.h>
  21. #include<system/graphics.h>
  22. __BEGIN_DECLS
  23. /*
  24. *Valueforthehw_module_t.tagfield
  25. */
  26. #defineMAKE_TAG_CONSTANT(A,B,C,D)(((A)<<24)|((B)<<16)|((C)<<8)|(D))
  27. #defineHARDWARE_MODULE_TAGMAKE_TAG_CONSTANT('H','W','M','T')
  28. #defineHARDWARE_DEVICE_TAGMAKE_TAG_CONSTANT('H','W','D','T')
  29. structhw_module_t;
  30. structhw_module_methods_t;
  31. structhw_device_t;
  32. /**
  33. *EveryhardwaremodulemusthaveadatastructurenamedHAL_MODULE_INFO_SYM
  34. *andthefieldsofthisdatastructuremustbeginwithhw_module_t
  35. *followedbymodulespecificinformation.
  36. */
  37. //每一个硬件模块都每必须有一个名为HAL_MODULE_INFO_SYM的数据结构变量,它的第一个成员的类型必须为hw_module_t
  38. typedefstructhw_module_t{
  39. /**tagmustbeinitializedtoHARDWARE_MODULE_TAG*/
  40. uint32_ttag;
  41. /**majorversionnumberforthemodule*/
  42. uint16_tversion_major;
  43. /**minorversionnumberofthemodule*/
  44. uint16_tversion_minor;
  45. /**Identifierofmodule*/
  46. constchar*id;
  47. /**Nameofthismodule*/
  48. constchar*name;
  49. /**Author/owner/implementorofthemodule*/
  50. constchar*author;
  51. /**Modulesmethods*/
  52. //模块方法列表,指向hw_module_methods_t*
  53. structhw_module_methods_t*methods;
  54. /**module'sdso*/
  55. void*dso;
  56. /**paddingto128bytes,reservedforfutureuse*/
  57. uint32_treserved[32-7];
  58. }hw_module_t;
  59. typedefstructhw_module_methods_t{//硬件模块方法列表的定义,这里只定义了一个open函数
  60. /**Openaspecificdevice*/
  61. int(*open)(conststructhw_module_t*module,constchar*id,//注意这个open函数明确指出第三个参数的类型为structhw_device_t**
  62. structhw_device_t**device);
  63. }hw_module_methods_t;
  64. /**
  65. *Everydevicedatastructuremustbeginwithhw_device_t
  66. *followedbymodulespecificpublicmethodsandattributes.
  67. */
  68. //每一个设备数据结构的第一个成员函数必须是hw_device_t类型,其次才是各个公共方法和属性
  69. typedefstructhw_device_t{
  70. /**tagmustbeinitializedtoHARDWARE_DEVICE_TAG*/
  71. uint32_ttag;
  72. /**versionnumberforhw_device_t*/
  73. uint32_tversion;
  74. /**referencetothemodulethisdevicebelongsto*/
  75. structhw_module_t*module;
  76. /**paddingreservedforfutureuse*/
  77. uint32_treserved[12];
  78. /**Closethisdevice*/
  79. int(*close)(structhw_device_t*device);
  80. }hw_device_t;
  81. /**
  82. *Nameofthehal_module_info
  83. */
  84. #defineHAL_MODULE_INFO_SYMHMI
  85. /**
  86. *Nameofthehal_module_infoasastring
  87. */
  88. #defineHAL_MODULE_INFO_SYM_AS_STR"HMI"
  89. /**
  90. *Getthemoduleinfoassociatedwithamodulebyid.
  91. *
  92. *@return:0==success,<0==errorand*module==NULL
  93. */
  94. inthw_get_module(constchar*id,conststructhw_module_t**module);
  95. /**
  96. *Getthemoduleinfoassociatedwithamoduleinstancebyclass'class_id'
  97. *andinstance'inst'.
  98. *
  99. *Somemodulestypesnecessitatemultipleinstances.Forexampleaudiosupports
  100. *multipleconcurrentinterfacesandthus'audio'isthemoduleclass
  101. *and'primary'or'a2dp'aremoduleinterfaces.Thisimpliesthatthefiles
  102. *providingthesemoduleswouldbenamedaudio.primary.<variant>.soand
  103. *audio.a2dp.<variant>.so
  104. *
  105. *@return:0==success,<0==errorand*module==NULL
  106. */
  107. inthw_get_module_by_class(constchar*class_id,constchar*inst,
  108. conststructhw_module_t**module);
  109. __END_DECLS
  110. #endif/*ANDROID_INCLUDE_HARDWARE_HARDWARE_H*/

由以上内容可以看出(typedef struct hw_module_t ,typedef struct hw_device_t),如果我们要写一个自定义设备的驱动的HAL层时,我们得首先自定义两个数据结构:

假设我们要做的设备名为XXX:

在头文件中定义:XXX.h

view plain copy to clipboard
  1. /*定义模块ID*/
  2. #defineXXX_HARDWARE_MODULE_ID"XXX"
  3. /*硬件模块结构体*/
  4. //见hardware.h中的hw_module_t定义的说明,xxx_module_t的第一个成员必须是hw_module_t类型,其次才是模块的一此相关信息,当然也可以不定义,
  5. //这里就没有定义模块相关信息
  6. structxxx_module_t{
  7. structhw_module_tcommon;
  8. };
  9. /*硬件接口结构体*/
  10. //见hardware.h中的hw_device_t的说明,要求自定义xxx_device_t的第一个成员必须是hw_device_t类型,其次才是其它的一些接口信息.
  11. structxxx_device_t{
  12. structhw_device_tcommon;
  13. //以下成员是HAL对上层提供的接口或一些属性
  14. intfd;
  15. int(*set_val)(structxxx_device_t*dev,intval);
  16. int(*get_val)(structxxx_device_t*dev,int*val);
  17. };
注:特别注意xxx_device_t的结构定义,这个才是HAL向上层提供接口函数的数据结构,其成员就是我们想要关心的接口函数.

接下来我们在实现文件XXX.c文件中定义一个xxx_module_t的变量:

view plain copy to clipboard
  1. /*模块实例变量*/
  2. structxxx_module_tHAL_MODULE_INFO_SYM={//变量名必须为HAL_MODULE_INFO_SYM,这是强制要求的,你要写Android的HAL就得遵循这个游戏规则,
  3. //见hardware.h中的hw_module_t的类型信息说明.它是一个宏定义:#define HAL_MODULE_INFO_SYM HMI
  4. common:{
  5. tag:HARDWARE_MODULE_TAG,
  6. version_major:1,
  7. version_minor:0,
  8. id:XXX_HARDWARE_MODULE_ID,//头文件中有定义
  9. name:MODULE_NAME,
  10. author:MODULE_AUTHOR,
  11. methods:&xxx_module_methods,//模块方法列表,在本地定义
  12. }
  13. };

注意到上面有HAL_MODULE_INFO_SYM变量的成员common中包含一个函数列表xxx_module_methods,而这个成员函数列表是在本地自定义的。那么这个成员函数列是不是就是HAL向上层提供函数的地方呢?很失望,不是在这里,前面我们已经说过了,是在xxx_device_t中定义的,这个xxx_module_methods实际上只提供了一个open函数,就相当于只提供了一个模块初始化函数.其定义如下:

view plain copy to clipboard
  1. /*模块方法表*/
  2. staticstructhw_module_methods_txxx_module_methods={
  3. open:xxx_device_open
  4. };
注意到,上边的函数列表中只列出了一个xxx_device_open函数,这个函数也是需要在本地实现的一个函数。前面说过,这个函数只相当于模块初始化函数。

那么HAL又到底是怎么将xxx_device_t中定义的接口提供到上层去的呢?

且看上面这个函数列表中唯一的一个xxx_device_open的定义:

view plain copy to clipboard
  1. staticintxxx_device_open(conststructhw_module_t*module,constchar*name,structhw_device_t**device){
  2. structxxx_device_t*dev;
  3. dev=(structhello_device_t*)malloc(sizeof(structxxx_device_t));//动态分配空间
  4. if(!dev){
  5. LOGE("HelloStub:failedtoallocspace");
  6. return-EFAULT;
  7. }
  8. memset(dev,0,sizeof(structxxx_device_t));
  9. //对dev->common的内容赋值,
  10. dev->common.tag=HARDWARE_DEVICE_TAG;
  11. dev->common.version=0;
  12. dev->common.module=(hw_module_t*)module;
  13. dev->common.close=xxx_device_close;
  14. //对dev其它成员赋值
  15. dev->set_val=xxx_set_val;
  16. dev->get_val=xxx_get_val;
  17. if((dev->fd=open(DEVICE_NAME,O_RDWR))==-1){
  18. LOGE("HelloStub:failedtoopen/dev/hello--%s.",strerror(errno));
  19. free(dev);
  20. return-EFAULT;
  21. }
  22. //输出&(dev->common),输出的并不是dev,而是&(dev->common)!(common内不是只包含了一个close接口吗?)
  23. *device=&(dev->common);
  24. LOGI("HelloStub:open/dev/hellosuccessfully.");
  25. return0;
  26. }
经验告诉我们,一般在进行模块初始化的时候,模块的接口函数也会“注册”,上面是模块初始化函数,那么接口注册在哪?于是我们找到*device =&(dev->common);这行代码,可问题是,这样一来,返回给调用者不是&(dev->common)吗?而这个dev->common仅仅只包含了一个模块关闭接口!到底怎么回事?为什么不直接返回dev,dev下不是提供所有HAL向上层接口吗?

在回答上述问题之前,让我们先看一下这xxx_device_open函数原型,还是在hardware.h头文件中,找到下面几行代码:

view plain copy to clipboard
  1. typedefstructhw_module_methods_t{
  2. /**Openaspecificdevice*/
  3. int(*open)(conststructhw_module_t*module,constchar*id,
  4. structhw_device_t**device);
  5. }hw_module_methods_t;
这是方法列表的定义,明确要求了方法列表中有且只一个open方法,即相当于模块初始化方法,且,这个方法的第三个参数明确指明了类型是struct hw_device_t **,而不是用户自定义的xxx_device_t,这也就是解译了在open函数实现内为什么输出的是&(dev->common)而不是dev了,原来返回的类型在hardware.h中的open函数原型中明确指出只能返回hw_device_t类型.

可是,dev->common不是只包含close接口吗?做为HAL的上层,它又是怎么"看得到"HAL提供的全部接口的呢?

接下来,让我们来看看做为HAL上层,它又是怎么使用由HAL返回的dev->common的:

参考:在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口这篇文章,从中可以看到这么几行代码:

view plain copy to clipboard
  1. /*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/
  2. staticinlineinthello_device_open(consthw_module_t*module,structhello_device_t**device){
  3. returnmodule->methods->open(module,HELLO_HARDWARE_MODULE_ID,(structhw_device_t**)device);
  4. }
由此可见,返回的&(dev->common)最终会返回给struce hello_device_t **类型的输出变量device,换句话说,类型为hw_device_t的dev->common在初始化函数open返回后,会强制转化为xxx_device_t来使用,终于明白了,原来如此!另外,在hardware.h中对xxx_device_t类型有说明,要求它的 第一个成员的类型必须是 hw_device_t,原来是为了HAL上层使用时的强制转化的目的,如果xxx_device_t的第一个成员类型不是hw_device_t,那么HAL上层使用中强制转化就没有意义了,这个时候,就真的“看不到”HAL提供的接口了.


此外,在hardware.h头文件中,还有明确要求定义xxx_module_t类型时,明确要求第一个成员变量类型必须为hw_module_t,这也是为了方便找到其第一个成员变量common,进而找到本地定义的方法列表,从而调用open函数进行模块初始化.


综上所述,HAL是通过structxxx_device_t这个结构体向上层提供接口的.

即:接口包含在structxxx_device_t这个结构体内。

而具体执行是通过struct xxx_module_t HAL_MODULE_INFO_SYM这个结构体变量的函数列表成员下的open函数来返回给上层的.

更多相关文章

  1. Android开发学习之TypedArray类
  2. Android(安卓)多点触摸接口
  3. Android(安卓)SipDemo项目实现SIP协议
  4. Android应用程序安装与Launcher启动机制
  5. AIDL接口描述语言的使用
  6. Android实现QQ分享功能
  7. android备份服务流程
  8. Android(安卓)编译大全
  9. Android部分功能模块实现

随机推荐

  1. Android2.2平台上支持多camera(二)
  2. Android官方技术文档翻译——Eclilpse项
  3. android 开发 实现自动安装
  4. Android通过SystemProperties类查看系统
  5. Android JavaBinder: !!! FAILED BINDER
  6. Delphi XE5 for Android (三)
  7. android webview秒开框架
  8. ubuntu上实现Android(安卓)JNI示例
  9. 如何通过adb 设置cpu 不降频,性能优化分析
  10. Android之RemoteViews