1. 程式人生 > >Android 驅動開發系列三

Android 驅動開發系列三

寫blog的時候,發現跳章了,HAL硬體抽象層都沒有寫就到JNI了,這裡補回來。

1、新增HAL標頭檔案

進入到 android-4.0.4_r1.2/hardware/libhardware/include/hardware 目錄,建立 ttt.h 檔案:

  1. [email protected]:~/workspace/android-4.0.4_r1.2/hardware/libhardware/include/hardware# gedit ttt.h  

檔案內容如下:

  1. #ifndef ANDROID_TTT_INTERFACE_H
  2. #define ANDROID_TTT_INTERFACE_H
  3. #include <hardware/hardware.h>
  4. __BEGIN_DECLS  
  5. // 定義模組ID
  6. #define HELLO_HARDWARE_MODULE_ID    "ttt"
  7. // 硬體模組結構體
  8. struct ttt_module_t{  
  9.     struct hw_module_t common;  
  10. };  
  11. // hardware interface struct
  12. struct ttt_device_t{  
  13.     struct hw_device_t common;  
  14.     int fd;  
  15.     int(*set_val)(struct ttt_device_t* dev, 
    int val);  
  16.     int(*get_val)(struct ttt_device_t* dev, int* val);  
  17. };  
  18. __END_DECLS  
  19. #endif

這裡按照Android硬體抽象層規範的要求,分別定義模組ID、模組結構體以及硬體介面結構體。

2、實現HAL

進入android-4.0.4_r1.2/hardware/libhardware/modules 目錄,建立 ttt 目錄:

  1. [email protected]:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules# mkdir ttt  

進入到新建立的ttt目錄下面,並建立 ttt.c 檔案:

  1. [email protected]:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules/ttt# gedit ttt.c  

其內容如下:

  1. #define LOG_TAG     "TTTStub"
  2. #include <hardware/hardware.h>
  3. #include <hardware/ttt.h>
  4. #include <fcntl.h>
  5. #include <errno.h>
  6. #include <cutils/log.h>
  7. #include <cutils/atomic.h>
  8. #define DEVICE_NAME "/dev/ttt"
  9. #define MODULE_NAME "TTT"
  10. #define MODULE_AUTHOR   "[email protected]"
  11. // open/close device interface
  12. staticint ttt_device_open(conststruct hw_module_t* module, constchar* name, struct hw_device_t** device);  
  13. staticint ttt_device_close(struct hw_device_t* device);  
  14. // device interfaces
  15. staticint ttt_set_val(struct ttt_device_t* dev, int val);  
  16. staticint ttt_get_val(struct ttt_device_t* dev, int* val);  
  17. // module methods
  18. staticstruct hw_module_methods_t ttt_module_methods = {  
  19.     open: ttt_device_open  
  20. };  
  21. // module variables
  22. conststruct ttt_module_t HAL_MODULE_INFO_SYM = {  
  23.     common: {  
  24.         tag: HARDWARE_MODULE_TAG,  
  25.         version_major: 1,  
  26.         version_minor: 0,  
  27.         id: HELLO_HARDWARE_MODULE_ID,  
  28.         name: MODULE_NAME,  
  29.         author: MODULE_AUTHOR,  
  30.         methods: &ttt_module_methods,  
  31.     }  
  32. };  
  33. // * device set value interface
  34. staticint ttt_set_val(struct ttt_device_t* dev, int val)  
  35. {  
  36.     LOGI("TTT Stub: set value %d to device.", val);  
  37.     write(dev->fd, &val, sizeof(val));  
  38.     return 0;  
  39. }  
  40. // * device get value interface
  41. staticint ttt_get_val(struct ttt_device_t* dev, int* val)  
  42. {  
  43.     if(!val){  
  44.         LOGE("TTT Stub: error val pointer.");  
  45.         return -EFAULT;  
  46.     }  
  47.     read(dev->fd, val, sizeof(*val));  
  48.     LOGI("TTT Stub: get value %d from device.", *val);  
  49.     return 0;  
  50. }  
  51. // * close device interface
  52. staticint ttt_device_close(struct hw_device_t* device)  
  53. {  
  54.     struct ttt_device_t* ttt_device = (struct ttt_device_t*)device;  
  55.     if(ttt_device){  
  56.         close(ttt_device->fd);  
  57.         free(ttt_device);  
  58.     }  
  59.     return 0;  
  60. }  
  61. // * open device interface
  62. staticint ttt_device_open(conststruct hw_module_t* module, constchar* name, struct hw_device_t** device)  
  63. {  
  64.     struct ttt_device_t* dev;  
  65.     dev = (struct ttt_device_t*)malloc( sizeof(struct ttt_device_t) );  
  66.     if(!dev){  
  67.         LOGE("TTT stub: failed to alloc space");  
  68.         return -EFAULT;  
  69.     }  
  70.     memset(dev, 0, sizeof(struct ttt_device_t));  
  71.     dev->common.tag = HARDWARE_DEVICE_TAG;  
  72.     dev->common.version = 0;  
  73.     dev->common.module = (hw_module_t*)module;  
  74.     dev->common.close = ttt_device_close;  
  75.     dev->set_val = ttt_set_val;  
  76.     dev->get_val = ttt_get_val;  
  77.     if( (dev->fd = open(DEVICE_NAME, O_RDWR)) == -1){  
  78.         LOGE("TTT Stub: failed to open /dev/ttt -- %s.", strerror(errno));  
  79.         free(dev);  
  80.         return -EFAULT;  
  81.     }  
  82.     *device = &(dev->common);  
  83.     LOGI("TTT Stub: open /dev/ttt successfully.");  
  84.     return 0;  
  85. }  


在該目錄下建立對應的Android.mk檔案:

  1. [email protected]:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules/ttt# gedit Android.mk  

其內容如下:

  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_MODULE_TAGS := optional  
  4. LOCAL_PRELINK_MODULE := false
  5. LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw  
  6. LOCAL_SHARED_LIBRARIES := liblog  
  7. LOCAL_SRC_FILES := ttt.c  
  8. LOCAL_MODULE := ttt.default
  9. include $(BUILD_SHARED_LIBRARY)  


3、新增許可權

由於裝置檔案是在核心驅動裡面通過 device_create 建立的,而 device_create 建立的裝置檔案預設只有 root 使用者

可讀寫,而 ttt_device_open 一般是由上層APP來呼叫的,這些 APP 一般不具有 root 許可權,這時候就有可能導致開啟裝置檔案失敗,提示類似於:

Permission denied.

解決辦法是類似 linux 的udev 規則,

進入到 android-4.0.4_r1.2/system/core/rootdir 目錄,開啟 uenentd.rc 檔案:

  1. [email protected]:~/workspace/android-4.0.4_r1.2/system/core/rootdir# gedit ueventd.rc  

在裡面新增一句:

  1. /dev/ttt                  0666   root       root  



4、開始編譯


執行命令如下:

  1. [email protected]:~/workspace/android-4.0.4_r1.2# mmm hardware/libhardware/modules/ttt  
  2. ============================================  
  3. PLATFORM_VERSION_CODENAME=REL  
  4. PLATFORM_VERSION=4.0.4  
  5. TARGET_PRODUCT=full_smdkv210  
  6. TARGET_BUILD_VARIANT=eng  
  7. TARGET_BUILD_TYPE=release  
  8. TARGET_BUILD_APPS=  
  9. TARGET_ARCH=arm  
  10. TARGET_ARCH_VARIANT=armv7-a-neon  
  11. HOST_ARCH=x86  
  12. HOST_OS=linux  
  13. HOST_BUILD_TYPE=release  
  14. BUILD_ID=IMM76I  
  15. ============================================  
  16. make:進入目錄'/home/brantyou/workspace/android-4.0.4_r1.2'
  17. target thumb C: ttt.default <= hardware/libhardware/modules/ttt/ttt.c  
  18. target SharedLib: ttt.default (out/target/product/smdkv210/obj/SHARED_LIBRARIES/ttt.default_intermediates/LINKED/ttt.default.so)  
  19. target Symbolic: ttt.default (out/target/product/smdkv210/symbols/system/lib/hw/ttt.default.so)  
  20. target Strip: ttt.default (out/target/product/smdkv210/obj/lib/ttt.default.so)  
  21. Install: out/target/product/smdkv210/system/lib/hw/ttt.default.so  
  22. make:離開目錄“/home/brantyou/workspace/android-4.0.4_r1.2”  
  23. [email protected]:~/workspace/android-4.0.4_r1.2#   

重新打包system.img:

  1. [email