欢迎转载,务必注明出处:http://blog.csdn.net/wang_shuai_ww/article/details/44407641
本篇与http://blog.csdn.net/wang_shuai_ww/article/details/44305599该篇文章不同的仅仅在HAL层的.so方面,操作方法前面一篇是使用普通接口write来操作,write接口操作单个LED没有问题,当有多个LED时可能就不是那么方便了,所以本篇介绍使用unlocked_ioctl的方法。
驱动程序已经写好了unlocked_ioctl方法,这里不再对驱动程序做修改了,这里修改的仅仅是硬件抽象层HAL,硬件服务层和JNI层也不需要修改,可以兼容。
注意:现在的Linux内核已经使用unlocked_ioctl取代ioctl了,写驱动程序时就不再使用ioctl了。
修改后的源码如下:
#include <hardware/hardware.h> #include "led.h" #include <fcntl.h> #include <errno.h> #include <cutils/log.h> #include <cutils/atomic.h> // 引入log头文件 #include <android/log.h> // log标签 #define TAG "Led_Load_HAL" // 定义info信息 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG,__VA_ARGS__) // 定义debug信息 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) // 定义error信息 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) #define DEVICE_NAME "/dev/real_led" #define MODULE_NAME "led" #define MODULE_AUYHOR "[email protected]" #define LED_ON 1 #define LED_OFF 0 static int led_device_open(const struct hw_module_t *module, const char *id, struct hw_device_t **device); static int led_device_close(struct hw_device_t *device); static int led_set_on(struct led_device_t *dev, int num); static int led_set_off(struct led_device_t *dev, int num); static struct hw_module_methods_t led_module_methods = { open: led_device_open }; struct led_module_t HAL_MODULE_INFO_SYM = { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: LED_HARDWARE_MODULE_ID, name: DEVICE_NAME, author: MODULE_AUYHOR, methods: &led_module_methods, } }; static int led_device_open(const struct hw_module_t *module, const char *id, struct hw_device_t **device) { if(!strcmp(id, LED_HARDWARE_DEVICE_ID)) { struct led_device_t *dev; dev = (struct led_device_t *)malloc(sizeof(struct led_device_t)); if(!dev) { LOGE("Failed to alloc space for led_device_t"); return -EFAULT; } memset(dev, 0, sizeof(struct led_device_t)); dev->common.tag = HARDWARE_MODULE_TAG; dev->common.version = 0; dev->common.module = (hw_module_t *)module; dev->common.close = led_device_close; dev->set_on = led_set_on; dev->set_off = led_set_off; if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) { LOGE("Failed to open device file "DEVICE_NAME"-- %s.", strerror(errno)); free(dev); return -EFAULT; } *device = &(dev->common); LOGI("Open device file "DEVICE_NAME" successfully."); return 0; } return -EFAULT; } static int led_device_close(struct hw_device_t *device){ struct led_device_t *led_device = (struct led_device_t *)device; if(led_device){ close(led_device->fd); free(led_device); } return 0; } static int led_set_on(struct led_device_t *dev, int num){ if(!dev){ LOGE("Null dev pointer."); return -EFAULT; } LOGI("Set the first %d LED lights.", num); ioctl(dev->fd, LED_ON, num); return 0; } static int led_set_off(struct led_device_t *dev, int num){ if(!dev){ LOGE("Null dev pointer."); return -EFAULT; } LOGI("Set the first %d LED close.", num); ioctl(dev->fd, LED_OFF, num); return 0; }
编译,打包下载使用,具体的参考前面的方法。
这里说明,我使用的是本篇的操作方法。后面的记录也都是基于这个版本的。