新增LED設備--從上層到底層理解安卓架構之HAL篇
硬件抽象層介紹
+
1)不是所有的硬件設備都有標準的Linux內核接口,通過HAL層封裝了一套固定的向上接口,可以使得上層的開發(fā)邏輯更清晰簡單。HAL框架是固定的,開發(fā)人員只需要按照框架開發(fā)即可,無需關注與上層的交互上,將精力放在HAL層本身的實現(xiàn)上即可。
2)從商業(yè)角度,硬件廠商可以把一些核心的算法、調試參數(shù)、實現(xiàn)邏輯等放在HAL層而不是kenel層,kenel層只是簡單與硬件做數(shù)據(jù)交互。這樣的好處是可以不用遵Linux的GPL開源協(xié)議,保護自身的商業(yè)機密。
Hal架構圖
模塊類型結構體hw_module_t,設備類型結構體hw_device_t,
兩個結構體的詳細內容可以參考源碼路徑:/hardware/libhardware/include/hardware/hardware.h。HAL層開發(fā)主要工作是建立好自定義的結構體,并實現(xiàn)hw_device_t的內部的幾個關鍵函數(shù)。
頭文件hardware/libhardware/include/hardware/testled_hal.h
struct testled_module_t {struct hw_module_t common;};struct testled_device_t {struct hw_device_t common;int (*open)(void);int (*control)(int on);};
頭文件內申明了led的兩個關鍵結構體testled_module_t和testled_device_t,結構體的實現(xiàn)在c文件中。
2)c文件 hardware/libhardware/modules/testled/testled_hal.c
//日志的標簽
static int fd;int testled_hal_dev_close(struct hw_device_t *device){if(device != NULL){struct testled_device_t *temp = (struct testled_device_t *)device;free(temp);}close(fd);return 0;}int testled_hal_open_dev(void){ALOGD("--%s--", __func__);fd = open("/dev/test-led", O_RDWR);if(fd < 0){ALOGE("open failed : %s", strerror(errno));return fd;}return 0;}int testled_hal_control_dev(int on){ALOGD("--%s--", __func__);int ret;switch(on){case 0:ret = ioctl(fd, LED1CTRL_ON_CMD,0);break;case 1:ret = ioctl(fd, LED1CTRL_OFF_CMD,0);break;case 2:ret = ioctl(fd, LED2CTRL_ON_CMD,0);break;case 3:ret = ioctl(fd, LED2CTRL_OFF_CMD,0);break;default:break;}if(ret < 0){ALOGE("control failed : %s", strerror(errno));return ret;}return 0;}int testled_hal_module_open(const struct hw_module_t *module, const char *id,struct hw_device_t **device){ALOGD("--%s--", __func__);struct testled_device_t *led_dev = NULL;led_dev = (struct testled_device_t *)malloc(sizeof(struct testled_device_t));if (led_dev == NULL){ALOGE("malloc failed");return -1;}ALOGD("malloc success");//初始化device對象led_dev->common.tag = HARDWARE_DEVICE_TAG;led_dev->common.version = 1;led_dev->common.module = module;led_dev->common.close = testled_hal_dev_close;led_dev->open = testled_hal_open_dev;led_dev->control = testled_hal_control_dev;
//將當前的led_dev傳遞給jni層
= (struct hw_device_t *)led_dev;return 0;}struct testled_device_t testled_hal_methods = {open : testled_hal_module_open,};struct testled_module_t HAL_MODULE_INFO_SYM = {common : {tag : HARDWARE_MODULE_TAG,version_major : 1,version_minor : 0,id : LED_HAL_MODULE_ID,name : "testled hal module",methods : &testled_hal_methods,},};
主要實現(xiàn)了hal結構體中的close,open,control函數(shù),并將函數(shù)傳給結led_dev構體。
common.close = testled_hal_dev_close;led_dev->open = testled_hal_open_dev;control = testled_hal_control_dev;
Android.mk hardware/libhardware/modules/testled/Android.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := testled_hal.defaultLOCAL_MODULE_RELATIVE_PATH := hwLOCAL_SRC_FILES := testled_hal.cLOCAL_SHARED_LIBRARIES := liblog libcutilsLOCAL_MODULE_TAGS := optionalinclude $(BUILD_SHARED_LIBRARY)
將c文件編譯成模塊
hardware/libhardware/modules/Android.mk內加入testled
三、編譯
模塊編譯
mmm hardware/libhardware/modules/ testled
在out/target/product/nanopc-t4/system/lib/hw/ 目錄下生生成test_led_hal.default.so
全部編譯后,test_led_hal.default.so在設備的/system/lib/hw路徑下,android frameworks中的JNI調用led設備時,通過一系列轉換就會調用到這個庫內部的函數(shù),從而調動掉底層的led驅動。
掃碼關注我們
看更多嵌入式案例
喜歡本篇內容請給我們點個再看
免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!





