hal:模板:harDWare/libharDWare/modules/overlay/
如图所示jni与hal层主要数据结构和函数调用:
然后再通过pmodule->common.methods->open函数给pdevice赋值,拿到led_hw_device_t的结构体实现。
通过拿到对应的库再调用库内部函数来拿到关键结构device。然后就可以对device进行 *** 作了。
hal的开发主要是为了保护厂家私有代码而制定的一个架构。如果不考虑是否保护则直接用jni就可以了。二、关键结构体源码:
hal:模板:harDWare/libharDWare/modules/overlay/// 模块 *** 作方法typedef struct hw_module_methods_t { /** Open a specific device */ int (*open)(const struct hw_module_t* module, const char* ID, struct hw_device_t** device);} hw_module_methods_t;typedef struct hw_module_t { /** tag must be initialized to HARDWARE_MODulE_TAG */ uint32_t tag; // 必须初始化成HARDWARE_MODulE_TAG /** major version number for the module */ uint16_t version_major; // 主版本号: 1 /** minor version number of the module */ uint16_t version_minor; // 此版本号: 0 /** IDentifIEr of module */ const char *ID; // 动态库的文件名字 /** name of this module */ const char *name; // 动态库的简单描述:自定义 /** Author/owner/implementor of the module */ const char *author; // 作者: 自定义 /** Modules methods */ struct hw_module_methods_t* methods; // 方法 /** module's dso */ voID* dso; // 一般不用 /** padding to 128 bytes, reserved for future use */ uint32_t reserved[32-7]; // 保留,一般不用} hw_module_t;// device对象typedef struct hw_device_t { /** tag must be initialized to HARDWARE_DEVICE_TAG */ uint32_t tag; //必须初始化成:HARDWARE_DEVICE_TAG /** version number for hw_device_t */ uint32_t version; // 主版本号:1 /** reference to the module this device belongs to */ struct hw_module_t* module; //指向device所在的module对象 /** padding reserved for future use */ uint32_t reserved[12]; /** Close this device */ int (*close)(struct hw_device_t* device);} hw_device_t;
分别对应上面的
1、device结构体包含device *** 作方式
struct led_hw_device_t{ struct hw_device_t common;// 必须是这样的 // 以下为扩展部分 int (*led_on)(voID); int (*led_off)(voID); };
2、给module结构体赋值;
// 必须有一个HMI变量struct led_hw_module_t HMI ={ common : { tag : HARDWARE_MODulE_TAG, version_major : 1, version_minor : 0, ID : LED_MODulE_ID, name : "led hal sample", author : "wukong",
3、给定module结构体中method的方法结构体
methods : &my_methods, }};
4、实现method方法结构体中的open方法;
struct hw_module_methods_t my_methods ={ open : led_hal_open};
三、对应的androID.mk的编写hal : AndroID.mk 的编写;LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_SHARED_liBRARIES := \ libcutils#指定目标文件应该安装到哪个路径上LOCAL_MODulE_PATH := $(TARGET_OUT_SHARED_liBRARIES)/hwLOCAL_SRC_fileS := led_hal.c#指定目标动态库文件名,要和代码中的ID保持一致,加个.default后缀LOCAL_MODulE := myled_hal.defaultLOCAL_PRElink_MODulE := falseinclude $(BUILD_SHARED_liBRARY)jni文件的编写:jni调用hal的接口:1, int hw_get_module(const char * ID,const struct hw_module_t * * module)参数1: 动态库文件名,LED_MODulE_ID参数2: 执行模块的指针返回值: 正确为02,调用module中的方法 pModule->common.methods->open();编译jni文件的AndroID.mk的编写;LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)#jni调用hal的时候,需要连接libharDWare==>(hw_get_module)LOCAL_SHARED_liBRARIES := \ libcutils \ libharDWareLOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE)LOCAL_SRC_fileS:= led_jni.cppLOCAL_MODulE:= libled_jniLOCAL_PRElink_MODulE := falseinclude $(BUILD_SHARED_liBRARY)
四、三个问题1、为什么hal.so --> /system/lib/hw是放在这个目录下?
2、为什么必须有要将moudle定义为HMI变量
3、指定目标动态库文件名,要和代码中的ID保持一致,为什么要加个.default后缀
LOCAL_MODulE := myled_hal.defaulthw_get_module(LED_MODulE_ID, (const struct hw_module_t * * )&pModule); | snprintf(path, sizeof(path), "%s/%s.default.so","/system/lib/hw", "myled_hal"); ==> "/system/lib/hw/myled_hal.default.so" if (access(path, R_OK)) // 测试文件是否存在 status = load(ID, path, module); |// load(const char *ID,const char *path, const struct hw_module_t **pHmi) handle = dlopen(path, RTLD_Now); const char *sym = "HMI"; hmi = (struct hw_module_t *)dlsym(handle, sym); *pHmi = hmi;// 必须有一个HMI变量struct led_hw_module_t HMI ={ common : { tag : HARDWARE_MODulE_TAG, version_major : 1, version_minor : 0, ID : LED_MODulE_ID, name : "led hal sample", author : "wukong", methods : &my_methods, }在hw_get_module中传ID;LED_MODulE_ID
在hw_get_module中传ID;LED_MODulE_ID
struct led_hw_module_t{ struct hw_module_t common; // 必须是这样的 // 以下为扩展部分};struct led_hw_device_t{ struct hw_device_t common;// 必须是这样的 // 以下为扩展部分 int (*led_on)(voID); int (*led_off)(voID); };
2、给module结构体赋值;
// 必须有一个HMI变量struct led_hw_module_t HMI ={ common : { tag : HARDWARE_MODulE_TAG, version_major : 1, version_minor : 0, ID : LED_MODulE_ID, name : "led hal sample", author : "wukong",
3、给定module结构体中method的方法结构体
methods : &my_methods, }};
4、实现method方法结构体中的open方法;
struct hw_module_methods_t my_methods ={ open : led_hal_open};
5、匹配module结构体指针
int led_hal_open(const struct hw_module_t* module, const char* ID, struct hw_device_t** device){ LOGD("---^_^ ---%s--\n", __FUNCTION__);
6、 构建mydevice对象
struct led_hw_device_t *mydev = NulL; mydev = (struct led_hw_device_t *)malloc(sizeof(struct led_hw_device_t)); mydev->common.tag = HARDWARE_DEVICE_TAG; mydev->common.version = 1; mydev->common.module = module; ==>这一步有什么作用?可将module结构体中的信息传递给device对象; mydev->common.close = led_hal_close; mydev->led_on = hal_led_on; mydev->led_off = hal_led_off;
7、打开设备文件 *** 作底层驱动
fd = open("/dev/led", O_RDWR); if(fd < 0) { LOGE("open : %s\n", strerror(errno)); return -1; }
8、将构建好的mydevice对象返回给device对象则device可以调用device中定义的方法;
*device = (struct hw_device_t*)mydev; return 0;}
9、具体构建device对象定义的方法;
int led_hal_close(struct hw_device_t* device){由于open方法中malloc的是led_hw_device_t结构体指针所以要释放也是对应的指针 struct led_hw_device_t *tmp; if(device != NulL) { 在这里将传进来的device还原; tmp = (struct led_hw_device_t *)device; 后free掉 free(tmp); } if(fd > 0) close(fd); return 0;}int hal_led_on(voID){ LOGD("---^_^ ---%s--\n", __FUNCTION__); int ret ; ret = ioctl(fd,LED_ON,NulL); if(ret < 0) { LOGE("ioctl : %s\n", strerror(errno)); return -1; } return 0; }int hal_led_off(voID){ LOGD("---^_^ ---%s--\n", __FUNCTION__); int ret ; ret = ioctl(fd,LED_OFF,NulL); if(ret < 0) { LOGE("ioctl : %s\n", strerror(errno)); return -1; } return 0;}
在jni层通过实现hw_get_module方法
包含相同的头文件则调用的方法也相同;这也就成了对应的关系了
ret = hw_get_module(LED_MODulE_ID, (const struct hw_module_t * * )&pModule); if(ret == 0) { LOGD("hw_get_module ok"); if(pModule != NulL) {可以理解为open之后device对象就有了匹配方法了 pModule->common.methods->open((const struct hw_module_t*)pModule, NulL, (struct hw_device_t**)&pDevice); } }
即pDevice->led_off(); pDevice->led_off(); pDevice->common.close((struct hw_device_t *)pDevice);
jni中通过module的LED_MODulE_ID定义的字符串匹配hal层的模块匹配到后再调用hal层中的open方法调用设备方法;
其中的null可传入具体的设备号,如果有多个设备的话,即一个模块中集成了多个设备;
有多个ID是否有多个open函数;
jni 中的AdroID.mk文件的编写;
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SHARED_liBRARIES := \ libcutils \ libharDWare ==>#jni调用hal的时候,需要连接libharDWare==>(hw_get_module)LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE)LOCAL_SRC_fileS:= led_jni.cppLOCAL_MODulE:= libled_jniLOCAL_PRElink_MODulE := falseinclude $(BUILD_SHARED_liBRARY)hal 文件的AndroID.mk的编写;LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_SHARED_liBRARIES := \ libcutilsLOCAL_MODulE_PATH := $(TARGET_OUT_SHARED_liBRARIES)/hwLOCAL_SRC_fileS := led_hal.cLOCAL_MODulE := myled_hal.defaultLOCAL_PRElink_MODulE := falseinclude $(BUILD_SHARED_liBRARY)
库在文件系统中的摆放;
apk--> /system/appjni.so --> /system/lib cp -raf out/target/product/fs100/system/lib/libled_jni.so /opt/fs100_root/system/libhal.so --> /system/lib/hw cp -raf out/target/product/fs100/system/lib/hw/myled_hal.default.so /opt/fs100_root/system/lib/hw
总结 以上是内存溢出为你收集整理的android hal文件的编写全部内容,希望文章能够帮你解决android hal文件的编写所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)