因为项目中用到的LED灯与安卓原生的不太一样,需要对驱动进行适配,修改驱动接口文件。
注:本贴只示例了修改LED灯驱动接口文件
目标文件位置:vendor/xxx/open-source/libs/liblights/lights.c
修改的一些注释
#define LOG_TAG "LIGHTS" #include <cutils/log.h> #include <stdint.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <pthread.h> #include <sys/ioctl.h> #include <sys/types.h> #include <hardware/lights.h> static pthread_once_t g_init = PTHREAD_ONCE_INIT; static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; //结构体:LED对应的文件节点路径和句柄 struct led_prop { const char *filename; int fd; }; //结构体:每个LED可操作的节点,根据使用的LED灯设备来进行定义 struct led { struct led_prop brightness; //亮度 struct led_prop delay_on; //闪烁时熄灭时长 struct led_prop delay_off; //闪烁时点亮时长 struct led_prop triggers; //闪烁时的亮度 }; //定义所有的LED灯,这里只用了三个 enum { RED_LED, //红色LED灯 GREEN_LED, //绿色LED灯 LCD_BACKLIGHT, //LCD背光灯 BUTTONS_LED, //按键背光灯 NUM_LEDS, }; //定义LED文件节点,一定要根据LED驱动程序指定的路径进行填写 struct led leds[NUM_LEDS] = { [RED_LED] = { .brightness = { "/sys/class/leds/red/brightness", 0}, //正常亮度 .delay_on = { "/sys/class/leds/red/delay_on", 0}, //LED闪烁熄灭时长 .delay_off = { "/sys/class/leds/red/delay_off", 0}, //LED闪烁点亮时长 .triggers = { "/sys/class/leds/red/triggers", 0}, //LED闪烁时的亮度 }, [GREEN_LED] = { .brightness = { "/sys/class/leds/green/brightness", 0}, .delay_on = { "/sys/class/leds/green/delay_on", 0}, .delay_off = { "/sys/class/leds/green/delay_off", 0}, .triggers = { "/sys/class/leds/green/triggers", 0}, }, [LCD_BACKLIGHT] = { .brightness = { "/sys/class/backlight/sprd_backlight/brightness", -1}, }, [BUTTONS_LED] = { .brightness = {"/sys/class/leds/keyboard-backlight/brightness", -1}, }, }; void init_g_lock(void) { pthread_mutex_init(&g_lock, NULL); } //初始化所有节点,即打开节点文件获得句柄 void init_globals(void) { int i; for (i = 0; i < NUM_LEDS; ++i) { init_prop(&leds[i].brightness); init_prop(&leds[i].delay_on); init_prop(&leds[i].delay_off); init_prop(&leds[i].triggers); } } //初始化一个节点 static int init_prop(struct led_prop *prop) { int fd; prop->fd = -1; if (!prop->filename) return 0; //打开文件 fd = open(prop->filename, O_RDWR); if (fd < 0) { ALOGE("init_prop: %s cannot be opened (%s)\n", prop->filename, strerror(errno)); return -errno; } //获得句柄 prop->fd = fd; return 0; } //写数据到指定文件,是实际对LED节点进行写操作的方法 static int write_int(struct led_prop *prop, int value) { int fd; static int already_warned; already_warned = 0; ALOGE("file:%s, func:%s, path=%s, value=%d\n", __FILE__, __func__, prop->filename, value); // fd = open(path, O_RDWR); fd = open(prop->filename, O_RDWR); if (fd >= 0) { char buffer[20]; int bytes = sprintf(buffer, "%d\n", value); int amt = write(fd, buffer, bytes); close(fd); return amt == -1 ? -errno : 0; } else { if (already_warned == 0) { ALOGE("file:%s, func:%s, failed to open %s,fd = %d\n", __FILE__, __func__, prop->filename,fd); already_warned = 1; } return -errno; } } //RGB颜色转化为亮度值,其实就是取出颜色值 static int rgb_to_brightness(struct light_state_t const *state) { int color = state->color & 0x00ffffff; return ((77*((color>>16) & 0x00ff)) + (150*((color>>8) & 0x00ff)) + (29*(color & 0x00ff))) >> 8; } //设置背光灯亮度 static int set_light_backlight(struct light_device_t *dev, struct light_state_t const *state) { int err = 0; int brightness = rgb_to_brightness(state); ALOGD("file:%s, func:%s, brightness=%d\n", __FILE__, __func__, brightness); if(NULL==leds[LCD_BACKLIGHT].brightness.filename) { ALOGE("file:%s, func:%s, unsupported light!\n", __FILE__, __func__); return -EINVAL; } pthread_mutex_lock(&g_lock); err = write_int(&leds[LCD_BACKLIGHT].brightness, brightness); pthread_mutex_unlock(&g_lock); return err; } //判断LED灯是否被点亮,颜色值也代表了亮度0-255 static int is_lit(struct light_state_t const* state) { return state->color & 0x00ffffff;//返回颜色值 } //设置按键背光 static int set_light_keyboard(struct light_device_t* dev, struct light_state_t const* state) { int err = 0; int on = is_lit(state); ALOGD("file:%s, func:%s, on=%d\n", __FILE__, __func__, on); if(NULL==LIGHT_KEYBOARD) { ALOGE("file:%s, func:%s, unsupported light!\n", __FILE__, __func__); return -EINVAL; } pthread_mutex_lock(&g_lock); err = write_int(LIGHT_KEYBOARD, on?255:0); pthread_mutex_unlock(&g_lock); return err; } //关闭LED灯 static int close_lights(struct light_device_t *dev) { int i; ALOGV("file:%s, func:%s\n", __FILE__, __func__); for (i = 0; i < NUM_LEDS; ++i) { close_prop(&leds[i].brightness); close_prop(&leds[i].delay_on); close_prop(&leds[i].delay_off); close_prop(&leds[i].triggers); } if (dev) free(dev); return 0; } // 设置彩色LED灯,因为只用到了红灯和绿灯,所以只设置了两种灯 static int set_lights(struct light_device_t* dev, struct light_state_t const* state) { int len; int value; unsigned int colorRGB; unsigned int colorR; unsigned int colorG; unsigned int colorB; unsigned int brightness, delay_on,delay_off,triggers; colorRGB = state->color & 0xFFFFFF; if (colorRGB == 0xFFFFFF) { /* white */ colorRGB = 0x0; } colorR = (colorRGB >> 16) & 0x00ff; colorG = (colorRGB >> 8) & 0x00ff; colorB = colorRGB & 0x00ff; ALOGD("file:%s, func:%s, colorR=%d,colorG=%d,colorB=%d\n", __FILE__, __func__, colorR,colorG,colorB); ALOGD("file:%s, func:%s, state->flashMode=%d\n", __FILE__, __func__, state->flashMode); pthread_mutex_lock(&g_lock); //设置闪烁模式 switch (state->flashMode) { case LIGHT_FLASH_HARDWARE: case LIGHT_FLASH_TIMED: delay_on = state->flashOnMS; delay_off = state->flashOffMS; break; case LIGHT_FLASH_NONE: default: delay_on = 0; delay_off = 0; break; ALOGD("set_led_state colorRGB=%08X, unknown mode %d\n", colorRGB, state->flashMode); } if(delay_on > 0 && delay_off > 0){ if (colorR) { //注意要先设置delay_on和delay_off,再设置triggers triggers = colorR; //颜色值即代表亮度值 write_int(&leds[RED_LED].delay_on, delay_on); write_int(&leds[RED_LED].delay_off, delay_on); write_int(&leds[RED_LED].triggers, triggers); } else { /*off*/ write_int(&leds[RED_LED].triggers, 0); write_int(&leds[RED_LED].brightness, 0); } if (colorG) { triggers = colorG; write_int(&leds[GREEN_LED].delay_on, delay_on); write_int(&leds[GREEN_LED].delay_off, delay_on); write_int(&leds[GREEN_LED].triggers, triggers); } else { /*off*/ write_int(&leds[GREEN_LED].triggers, 0); write_int(&leds[GREEN_LED].brightness, 0); } } else{ if (colorR) { brightness = colorR; write_int(&leds[RED_LED].brightness, brightness); } else { /*off*/ write_int(&leds[RED_LED].brightness, 0); write_int(&leds[RED_LED].triggers, 0); write_int(&leds[RED_LED].delay_on, 0); write_int(&leds[RED_LED].delay_off, 0); } if (colorG) { brightness = colorG; write_int(&leds[GREEN_LED].brightness, brightness); } else { /*off*/ write_int(&leds[GREEN_LED].brightness, 0); write_int(&leds[GREEN_LED].triggers, 0); write_int(&leds[GREEN_LED].delay_on, 0); write_int(&leds[GREEN_LED].delay_off, 0); } } pthread_mutex_unlock(&g_lock); return 0; } //设置通知LED指示灯,其实调用了set_lights static int set_light_leds_notifications(struct light_device_t *dev, struct light_state_t const *state) { ALOGE("file:%s, func:%s, light!\n", __FILE__, __func__); set_lights(dev, state); return -EINVAL; } //设置警示灯,也调用了set_lights static int set_light_leds_attention(struct light_device_t *dev, struct light_state_t const *state) { ALOGE("file:%s, func:%s, light!\n", __FILE__, __func__); set_lights(dev, state); return -EINVAL; } //打开LED灯 static int open_lights(const struct hw_module_t *module, char const *name, struct hw_device_t **device) { int (*set_light)(struct light_device_t *dev, struct light_state_t const *state); ALOGV("file:%s, func:%s name=%s\n", __FILE__, __func__, name); //根据LED灯的ID值,为函数指针set_light设置不同的函数 if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) //背光灯 set_light = set_light_backlight; else if (0 == strcmp(LIGHT_ID_KEYBOARD, name))//键盘灯 set_light = set_light_keyboard; else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))//绿色LED灯 set_light = set_light_leds_notifications; else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) //红色LED灯 set_light = set_light_leds_attention; else if (0 == strcmp(LIGHT_ID_BATTERY,name)) //绿色LED灯 set_light = set_light_leds_notifications; else return -EINVAL; pthread_once(&g_init, init_g_lock); // pthread_once(&g_init, init_globals); struct light_device_t *dev = malloc(sizeof(struct light_device_t)); memset(dev, 0, sizeof(*dev)); //设置一些其它信息 dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0; dev->common.module = (struct hw_module_t *)module; dev->common.close = (int (*)(struct hw_device_t *))close_lights; dev->set_light = set_light; *device = (struct hw_device_t *)dev; return 0; } static struct hw_module_methods_t lights_module_methods = { .open = open_lights, }; /* * The lights Module */ struct hw_module_t HAL_MODULE_INFO_SYM = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = LIGHTS_HARDWARE_MODULE_ID, .name = "lights Module", .author = "Google, Inc.", .methods = &lights_module_methods, }; //关闭节点 static void close_prop(struct led_prop *prop) { int fd; if (prop->fd > 0) close(prop->fd); //关闭文件 return; }