Chinaunix首页 | 论坛 | 博客
  • 博客访问: 353353
  • 博文数量: 197
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 303
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-02 14:21
文章分类

全部博文(197)

文章存档

2014年(89)

2013年(108)

我的朋友

分类: 嵌入式

2013-11-14 16:56:22

准备在S5PV210的android系统中实现GPS功能,程序已经写好了,也可以编译出gps.s5pc110.so的库,但是不知道上层怎么调用这个库,在GPS相关的Android.mk中也没有找到,很是纳闷。通过分析hardware module才知道是怎么回事,之前并没有详细的了解hardware module,现在简单的分析一下。

HAL层的hardware module主要实现文件为:
hardware/libhardware/hareware.c
hardware/libhardware/include/hardware/hardware.h

重要的结构体:
  1. typedef struct hw_device_t {
  2.     uint32_t tag; /** tag must be initialized to HARDWARE_DEVICE_TAG */ 标识符
  3.     uint32_t version; /** version number for hw_device_t */             版本号
  4.     struct hw_module_t* module; /** reference to the module this device belongs to */   该硬件属于哪个module
  5.     uint32_t reserved[12]; /** padding reserved for future use */
  6.     int (*close)(struct hw_device_t* device); /** Close this device */  关闭设备操作
  7. } hw_device_t;
表示一个硬件设备,存储了各种硬件设备的公共属性和方法

  1. typedef struct hw_module_t {
  2.     uint32_t tag; /** tag must be initialized to HARDWARE_MODULE_TAG */ 标识符
  3.     uint16_t version_major; /** major version number for the module */ 主版本号
  4.     uint16_t version_minor; /** minor version number of the module */ 次版本号
  5.     const char *id; /** Identifier of module */                    id,决定了库的文件名
  6.     const char *name; /** Name of this module */                    模块的名字
  7.     const char *author; /** Author/owner/implementor of the module */   模块作者
  8.     struct hw_module_methods_t* methods; /** Modules methods */         模块的操作方法
  9.     void* dso; /** module's dso */
  10.     uint32_t reserved[32-7]; /** padding to 128 bytes, reserved for future use */
  11. } hw_module_t;
描述一个硬件模块

  1. typedef struct hw_module_methods_t {
  2.     int (*open)(const struct hw_module_t* module, const char* id,
  3.             struct hw_device_t** device);
  4. } hw_module_methods_t;
定义了操作设备的方法,只有一个open函数

hareware.c分析:
  1. /** Base path of the hal modules */ 指定硬件模块库存放的路径
  2. #define HAL_LIBRARY_PATH1 "/system/lib/hw"
  3. #define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

下面这个用于搜索不同的库文件名:
  1. /**
  2.  * There are a set of variant filename for modules. The form of the filename
  3.  * is ".variant.so" so for the led module the Dream variants
  4.  * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:
  5.  *
  6.  * led.trout.so
  7.  * led.msm7k.so
  8.  * led.ARMV6.so
  9.  * led.default.so
  10.  */

  11. static const char *variant_keys[] = {
  12.     "ro.hardware",
  13.     "ro.product.board",
  14.     "ro.board.platform",
  15.     "ro.arch"
  16. };
库的名称要根据实际的product或board指定
在210平台GPS模块库的文件名可以为:
gps.s5pc110.so
gps.ARMV7.so
gps.default.so

hw_get_module函数作用是在系统中查找模块的库文件
根据硬件模块的id参数和指定的查找路径,配合product,board等变量,最终指定到一个so库文件
  1. int hw_get_module(const char *id, const struct hw_module_t **module)
---------------------------------------------------------------------------------
  1.     /* Loop through the configuration variants looking for a module */
  2.     for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
  3.         if (i < HAL_VARIANT_KEYS_COUNT) {
  4.             if (property_get(variant_keys[i], prop, NULL) == 0) {
  5.                 continue;
  6.             }
  7.             snprintf(path, sizeof(path), "%s/%s.%s.so",       //system/lib/hw/*.*.so
  8.                     HAL_LIBRARY_PATH1, id, prop);
  9.             if (access(path, R_OK) == 0) break;

  10.             snprintf(path, sizeof(path), "%s/%s.%s.so",
  11.                      HAL_LIBRARY_PATH2, id, prop);
  12.             if (access(path, R_OK) == 0) break;
  13.         } else {
  14.             snprintf(path, sizeof(path), "%s/%s.default.so",    //如果没查到硬件属性,使用默认的库文件名system/lib/hw/*.default.so
  15.                      HAL_LIBRARY_PATH1, id);
  16.             if (access(path, R_OK) == 0) break;
  17.         }
  18.     }

创建GPS modules分析:

下面这段话很重要,说明了如何构建一个模块
  1. /**
  2.  * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
  3.  * and the fields of this data structure must begin with hw_module_t
  4.  * followed by module specific information.
  5.  */

可以说这是andorid中标准的构建模块的写法
  1. const struct hw_module_t HAL_MODULE_INFO_SYM = {
  2.     .tag = HARDWARE_MODULE_TAG,
  3.     .version_major = 1,
  4.     .version_minor = 0,
  5.     .id = GPS_HARDWARE_MODULE_ID,
  6.     .name = "XC-GPS Module",
  7.     .author = "",
  8.     .methods = &hw_module_methods,
  9. };

通过分析hw_get_module函数我们知道,id是用来指定模块库文件名的,给GPS_HARDWARE_MODULE_ID赋值
#define GPS_HARDWARE_MODULE_ID  "gps"
实际上GPS_HARDWARE_MODULE_ID并不是在代码中这样定义的,可能是在某个编译脚本里,我暂时还没找到

指定methods:
  1. static struct hw_module_methods_t hw_module_methods = {
  2.     .open = open_gps
  3. };
只有一个open_gps函数,当模块加载时就会执行open_gps:
  1. static int open_gps(const struct hw_module_t* module, char const* name,
  2.                     struct hw_device_t** device)
  3. {
  4.     struct gps_device_t *gps_device = malloc(sizeof(struct gps_device_t));
  5.     if (gps_device)
  6.     {
  7.         memset(gps_device, 0, sizeof(*gps_device));
  8.         gps_device->common.tag = HARDWARE_DEVICE_TAG;
  9.         gps_device->common.version = 0;
  10.         gps_device->common.module = (struct hw_module_t*)module;
  11.         gps_device->get_gps_interface = gps_get_hardware_interface;

  12.         *device = (struct hw_device_t*)gps_device;

  13.         return 0;
  14.     }

  15.     return 1;
  16. }

每个硬件设备都应该有一个类似xxxx_device_t的结构体,里面包含了hw_device_t
gps的设备结构体定义如下:
  1. struct gps_device_t {
  2.     struct hw_device_t common;
  3.     const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
  4. };
在open函数中给这个模块所包含的hw_device_t赋值

get_gps_interface函数用来得到GPS的操作接口
  1. const GpsInterface* gps_get_hardware_interface(struct gps_device_t* dev)
  2. {
  3.     return &_GpsInterface;
  4. }

接下来,程序的主体部分就是实现_GpsInterface里面所定义的所有操作

HAL层的模块是由具体的上一层JNI来调用,关于怎么调用的,下一篇分析GPS module时再说,我也不是很清楚,再整理一下



阅读(1107) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~