每種硬體都對應了一個HAL模組,實現HAL,需要滿足HAL的相關規則,規則定義在原始碼hardward目錄下,標頭檔案hardward.h,C檔案hardward.c。
1、重要結構體:
hardward.h中定義了三個重要的結構體:
struct hw_module_t; struct hw_module_methods_t; struct hw_device_t;
a、結構體hw_module_t代表hal模組 ,hal模組需自定義一個結構體,並且該struct包含hw_module_t結構體,且模組的tag必須為HARDWARE_MODULE_TAG,表示hal模組的結構體。
b、結構體hw_module_methods_t代表模組的操作方法列表,它內部只有一個函式指標open,用來開啟該模組下的裝置
c、結構體hw_device_t代表該模組下的裝置,hal模組需要自定義一個結構體,且必須包含 hw_device_t。
d、最後這個模組定義好之後還必須匯出符號HAL_MODULE_INFO_SYM,指向這個模組,HAL_MODULE_INFO_SYM定義在hardware.h中值為“HMI”
2、上層如何與hal進行通訊:
透過HAL_MODULE_INFO_SYM,google hal與qcom hal部分進行繫結,上層也透過HAL_MODULE_INFO_SYM獲取到hal層的相關介面,獲取到hal模組使用hw_get_module函式。
3、實現加減的簡單hal實現
在hardware/libhardware/include/hardware目錄下建立lethe.h:
在該標頭檔案中我們自定義裝置結構體,在該裝置結構體中宣告add和subtract函式。
#include <stdint.h> #include <stdbool.h> #include <sys/cdefs.h> #include <sys/types.h> #include <cutils/native_handle.h> #include <hardware/hardware.h> #include <hardware/gralloc.h> // hal模組名 #define LETHE_HARDWARE_MODULE_ID "lethe" // hal版本號 #define LETHE_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(0, 1) #define HARDWARE_LETHE "lethe" // 自定義hal模組結構體 typedef struct lethe_module { struct hw_module_t common; // 第一個變數必須為hw_module_t } lethe_module_t; // 自定義hal裝置結構體 typedef struct lethe_device { struct hw_device_t common; // 加法函式 int (*add)(const struct lethe_device *dev, int a, int b, int *total); // 減法函式 int (*subtract)(const struct lethe_device *dev, int a, int b, int *total); } lethe_device_t; static inline int lethe_open_test(const struct hw_module_t *module, lethe_device_t **device) { return module->methods->open(module, HARDWARE_LETHE, (struct hw_device_t **)device); }
在hardware/libhardware目錄下新建lethe資料夾:
在lethe.c檔案中主要匯入符號HAL_MODULE_INFO_SYM,用來指向自定義模組,編寫模組相關函式介面:
#include <malloc.h> #include <stdint.h> #include <string.h> #include <log/log.h> #include <hardware/lethe.h> #include <hardware/hardware.h> static int add(const struct lethe_device *dev, int a, int b, int *total) { if (!dev) { return -1; } *total = a + b; return 0; } static int subtract(const struct lethe_device *dev, int a, int b, int *total) { if (!dev) { return -1; } *total = a - b; return 0; } static int lethe_close(hw_device_t *dev) { if(dev) { free(dev); return 0; } else { return -1; } } //開啟裝置函式 static int lethe_open(const hw_module_t* module,const char __unused *id, hw_device_t** device) { if (device == NULL) { ALOGE("NULL device on open"); return -1; } lethe_device_t *dev = malloc(sizeof(lethe_device_t)); memset(dev, 0, sizeof(lethe_device_t)); dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = LETHE_MODULE_API_VERSION_1_0; dev->common.module = (struct hw_module_t*) module; dev->common.close = lethe_close; dev->add = add; dev->subtract = subtract; *device = &(dev->common); return 0; } static struct hw_module_methods_t lethe_module_methods = { .open = lethe_open, }; //匯出符號HAL_MODULE_INFO_SYM,指向自定義模組 lethe_module_t HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = LETHE_MODULE_API_VERSION_1_0, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = LETHE_HARDWARE_MODULE_ID, .name = "lethe hal", .author = "lethe", .methods = &lethe_module_methods, }, };
編寫Android.bp檔案就可以生成自己的hal庫:
cc_library_shared { //共享庫,.so結尾 relative_install_path: "hw", proprietary: true, srcs: ["lethe.c"], header_libs: ["libhardware_headers"], shared_libs: ["liblog"], }
Lethetest.cpp用來測試hal:
#include <hardware/hardware.h> #include <hardware/lethe.h> #include <log/log.h> int main() { lethe_device_t* lethe_device = NULL; const lethe_module_t *module = NULL; // 用來獲取lethe模組 int ret = hw_get_module(LETHE_HARDWARE_MODULE_ID, (const struct hw_module_t** )&module); if (!ret) { ret = lethe_open_test((const struct hw_module_t*)module, &lethe_device); } if (ret < 0) { ALOGE("get lethe hal failed ......"); return -1; } int total = 0; lethe_device->add(lethe_device, 5, 3, &total); ALOGE("[lethe]======== add 5 + 3 = %d", total); lethe_device->add(lethe_device, 5, 3, &total); ALOGE("[lethe]======== subtract 5 - 3 = %d", total); }
執行./lethe_test進行hal測試,測試結果如下:
[lethe]======== add 5 + 3 = 8 [lethe]======== add 5 - 3 = 2