Android 驅動開發系列三
阿新 • • 發佈:2019-01-26
寫blog的時候,發現跳章了,HAL硬體抽象層都沒有寫就到JNI了,這裡補回來。
1、新增HAL標頭檔案
進入到 android-4.0.4_r1.2/hardware/libhardware/include/hardware 目錄,建立 ttt.h 檔案:
- [email protected]:~/workspace/android-4.0.4_r1.2/hardware/libhardware/include/hardware# gedit ttt.h
檔案內容如下:
- #ifndef ANDROID_TTT_INTERFACE_H
-
#define ANDROID_TTT_INTERFACE_H
- #include <hardware/hardware.h>
- __BEGIN_DECLS
- // 定義模組ID
- #define HELLO_HARDWARE_MODULE_ID "ttt"
- // 硬體模組結構體
- struct ttt_module_t{
- struct hw_module_t common;
- };
- // hardware interface struct
- struct ttt_device_t{
- struct hw_device_t common;
- int fd;
-
int(*set_val)(struct ttt_device_t* dev,
- int(*get_val)(struct ttt_device_t* dev, int* val);
- };
- __END_DECLS
- #endif
這裡按照Android硬體抽象層規範的要求,分別定義模組ID、模組結構體以及硬體介面結構體。
2、實現HAL
進入android-4.0.4_r1.2/hardware/libhardware/modules 目錄,建立 ttt 目錄:
-
[email protected]:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules# mkdir ttt
進入到新建立的ttt目錄下面,並建立 ttt.c 檔案:
- [email protected]:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules/ttt# gedit ttt.c
其內容如下:
- #define LOG_TAG "TTTStub"
- #include <hardware/hardware.h>
- #include <hardware/ttt.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <cutils/log.h>
- #include <cutils/atomic.h>
- #define DEVICE_NAME "/dev/ttt"
- #define MODULE_NAME "TTT"
- #define MODULE_AUTHOR "[email protected]"
- // open/close device interface
- staticint ttt_device_open(conststruct hw_module_t* module, constchar* name, struct hw_device_t** device);
- staticint ttt_device_close(struct hw_device_t* device);
- // device interfaces
- staticint ttt_set_val(struct ttt_device_t* dev, int val);
- staticint ttt_get_val(struct ttt_device_t* dev, int* val);
- // module methods
- staticstruct hw_module_methods_t ttt_module_methods = {
- open: ttt_device_open
- };
- // module variables
- conststruct ttt_module_t HAL_MODULE_INFO_SYM = {
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 0,
- id: HELLO_HARDWARE_MODULE_ID,
- name: MODULE_NAME,
- author: MODULE_AUTHOR,
- methods: &ttt_module_methods,
- }
- };
- // * device set value interface
- staticint ttt_set_val(struct ttt_device_t* dev, int val)
- {
- LOGI("TTT Stub: set value %d to device.", val);
- write(dev->fd, &val, sizeof(val));
- return 0;
- }
- // * device get value interface
- staticint ttt_get_val(struct ttt_device_t* dev, int* val)
- {
- if(!val){
- LOGE("TTT Stub: error val pointer.");
- return -EFAULT;
- }
- read(dev->fd, val, sizeof(*val));
- LOGI("TTT Stub: get value %d from device.", *val);
- return 0;
- }
- // * close device interface
- staticint ttt_device_close(struct hw_device_t* device)
- {
- struct ttt_device_t* ttt_device = (struct ttt_device_t*)device;
- if(ttt_device){
- close(ttt_device->fd);
- free(ttt_device);
- }
- return 0;
- }
- // * open device interface
- staticint ttt_device_open(conststruct hw_module_t* module, constchar* name, struct hw_device_t** device)
- {
- struct ttt_device_t* dev;
- dev = (struct ttt_device_t*)malloc( sizeof(struct ttt_device_t) );
- if(!dev){
- LOGE("TTT stub: failed to alloc space");
- return -EFAULT;
- }
- memset(dev, 0, sizeof(struct ttt_device_t));
- dev->common.tag = HARDWARE_DEVICE_TAG;
- dev->common.version = 0;
- dev->common.module = (hw_module_t*)module;
- dev->common.close = ttt_device_close;
- dev->set_val = ttt_set_val;
- dev->get_val = ttt_get_val;
- if( (dev->fd = open(DEVICE_NAME, O_RDWR)) == -1){
- LOGE("TTT Stub: failed to open /dev/ttt -- %s.", strerror(errno));
- free(dev);
- return -EFAULT;
- }
- *device = &(dev->common);
- LOGI("TTT Stub: open /dev/ttt successfully.");
- return 0;
- }
在該目錄下建立對應的Android.mk檔案:
- [email protected]:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules/ttt# gedit Android.mk
其內容如下:
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE_TAGS := optional
- LOCAL_PRELINK_MODULE := false
- LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
- LOCAL_SHARED_LIBRARIES := liblog
- LOCAL_SRC_FILES := ttt.c
- LOCAL_MODULE := ttt.default
- 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 檔案:
- [email protected]:~/workspace/android-4.0.4_r1.2/system/core/rootdir# gedit ueventd.rc
在裡面新增一句:
- /dev/ttt 0666 root root
4、開始編譯
執行命令如下:
- [email protected]:~/workspace/android-4.0.4_r1.2# mmm hardware/libhardware/modules/ttt
- ============================================
- PLATFORM_VERSION_CODENAME=REL
- PLATFORM_VERSION=4.0.4
- TARGET_PRODUCT=full_smdkv210
- TARGET_BUILD_VARIANT=eng
- TARGET_BUILD_TYPE=release
- TARGET_BUILD_APPS=
- TARGET_ARCH=arm
- TARGET_ARCH_VARIANT=armv7-a-neon
- HOST_ARCH=x86
- HOST_OS=linux
- HOST_BUILD_TYPE=release
- BUILD_ID=IMM76I
- ============================================
- make:進入目錄'/home/brantyou/workspace/android-4.0.4_r1.2'
- target thumb C: ttt.default <= hardware/libhardware/modules/ttt/ttt.c
- target SharedLib: ttt.default (out/target/product/smdkv210/obj/SHARED_LIBRARIES/ttt.default_intermediates/LINKED/ttt.default.so)
- target Symbolic: ttt.default (out/target/product/smdkv210/symbols/system/lib/hw/ttt.default.so)
- target Strip: ttt.default (out/target/product/smdkv210/obj/lib/ttt.default.so)
- Install: out/target/product/smdkv210/system/lib/hw/ttt.default.so
- make:離開目錄“/home/brantyou/workspace/android-4.0.4_r1.2”
- [email protected]:~/workspace/android-4.0.4_r1.2#
重新打包system.img: