HAL框架

HAL框架
当我们需要为这些设备编写HAL层代码时,必须严格按照Google定义的标准接口去实现,否则将导致设备无法在Android Framework下正常工作。

1、321架构 (包含了三个结构体和两个常量,和一个函数。)

HAL的模块接口在android\hardware\libhardware\include\hardware\hardware.h中
android\hardware\libhardware\hardware.c

模块与驱动

#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')
#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')

(1)三个结构体

/提供了非常多的模块信息需要在初始化的时候去填充,最为关键的是hw_module_methods_t里的open函数/
/主要参数id,name ,这个是唯一的,一般id与name是相同/

对于struct hw_module_t结构体的理解为,每个硬件通过hw_module_t结构体来描述,我们可以"继承"这个结构体,拓展自己的属性,但是需要注意的是,宿主结构的第一个成员必须是struct hw_module_t类型,硬件对象必须定义一个固定的名字:HMI(Hardware Module Information),每个硬件对象里面都包含了module指针,对应得结构体里面封装了open函数指针,用于打开硬件,并会返回硬件的操作方式。

typedef struct hw_module_t {
    uint32_t tag;
    uint16_t module_api_version;
    uint16_t hal_api_version;
    const char *id;
    const char *name;
    const char *author;
    struct hw_module_methods_t* module;
    void* dso;
    uint32_t reserved[32-7];
} hw_module_t;
tag:该值为module的tag,必须定义为HARDWARE_MODULE_TAG; 
module_api_version:模块中API函数接口的版本号;
hal_api_version:HAL模块接口的API版本号;
id:硬件的id号,唯一标识模块;
name:该模块的名称;
author:模块的作者;
module:指向封装有open函数指针的结构体,用于模块打开

该结构体里面封装了一个open函数指针,该函数用于实现打开一个特定的设备,打开的设备通过device二级指针进行返回。
typedef struct hw_module_methods_t { /使用在hw_module里,提供了一个open方法需要具体去实现/

    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);
} hw_module_methods_t;

对于struct hw_device_t结构体的理解为,硬件设备的操作方法,通过struct module_methods_t结构内的open函数指针将返回hw_device_t结构体指针,从而获得了该硬件设备的操作方法,我们也可以"继承"该结构体,拓展实际硬件设备的操作方式,但是需要注意的是,在宿主结构中,第一个成员必须是struct hw_device_t类型。

typedef struct hw_device_t {
    uint32_t tag;
    uint32_t version;
    struct hw_module_t* module;
    uint32_t reserved[12];
    int (*close)(struct hw_device_t* device);
} hw_device_t;
tag:设备的tag,必须定义为HARDWARE_DEVICE_TAG;
version:设备操作方式的版本号;
module:hw_module_t结构体指针,指向设备所属的硬件模块,设备操作接口与硬件模块的联系;
close:函数指针,关闭该硬件设备的方法。

(2)两个常量

#define HAL_MODULE_INFO_SYM         HMI
#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"

这两个常量与HAL模块的入口相关,在上层调用hw_get_module时,通过模块ID和对应的HMI结构体找到模块入口,
然后通过之前的open函数接口,就可以获得设备的操作接口(hw_device_t),之后就可以通过module访问模块实现的相关函数。

(3)一个函数(新版本有两个)

/通过ID获取模块相关联的信息/
int hw_get_module(const char *id, const struct hw_module_t **module);
/通过类"class_id"和实例"inst"获取与模块实例相关的模块信息/
int hw_get_module_by_class(const char *class_id, const char *inst, const struct hw_module_t **module);
当用户调用hw_get_module()函数时,将硬件的id名进行传入,那么函数将会从当前系统中注册的硬件模块里查找对应的硬件模块,并通过module二级指针进行返回。

2、hal实现方法

(1)定义一个 struct xx_hw_module_t 结构体,必须在第一个,定义一个 hw_module_t结构体的变量,还可以定义其他功能函数
(2)定义一个 struct xx_hw_module_methods_t 结构体,实现open函数
(3)定义一个 struct xx_hw_device_t 结构体,必须在第一个,定义一个 hw_device_t结构体的变量,还可以定义其他功能函数

如在hardware\libhardware\include\hardware\fd.h中framebuffer(显示器驱动)

typedef struct framebuffer_device_t {
    struct hw_device_t common;   //第一个就定义了一个hw_device_t
    。。。。。。
}

(4)定义 xx_HARDWARE_MODULE_ID 字符串变量,每个模块唯一的一个变量
(5)创建一个名字为 HAL_MODULE_INFO_SYM 的xx_hw_module_t对象

3、获取,释放Module和Device结构对象的方法(获取HAL的流程)

(1)使用hw_get_module 传入目标HAL的id
(2)根据id,拼装成路径,去寻找对应的.so文件
(3)使用dlopen加载打开对应的so文件。
(4)使用dlsyn加载符号表中的 HAL_MODULE_INFO_SYM 即对应的 xx_hw_module_t变量转换成hw_module_t指针返回。

上面四步在代码中的体现
hw_get_module 调用->hw_get_module_by_class -> 通过hw_module_exists找到对应的模块 -> 调用load-> 调用dlopen,打开这个动态链接库 -> 再调用 dlsym 通过HAL_MODULE_INFO_SYM_AS_STR 去寻找 链接库里的 HAL_MODULE_INFO_SYM-> 然后返回 hw_module_t指针

(5)根据获取到的module指针,获取 xx_hw_module_methods_t 调用 open 函数获取 hw_device_t结构体
(6)使用 hw_device_t指针调用定义的功能函数

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘭噗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值