欢迎转载,务必注明出处: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 "wsh_sean@qq.com"
#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;
}
读者可以跟前面的代码进行对比不同。
编译,打包下载使用,具体的参考前面的方法。
这里说明,我使用的是本篇的操作方法。后面的记录也都是基于这个版本的。