/* * Copyright (C) 2012-2014 Paul Kocialkowski * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #define LOG_TAG "gta04_lights" #include #include /* * Globals */ const char backlight_brightness[] = "/sys/class/backlight/pwm-backlight/brightness"; const char backlight_max_brightness[] = "/sys/class/backlight/pwm-backlight/max_brightness"; const char battery_red_brightness[] = "/sys/class/leds/gta04:red:power/brightness"; const char battery_red_max_brightness[] = "/sys/class/leds/gta04:red:power/max_brightness"; const char battery_green_brightness[] = "/sys/class/leds/gta04:green:power/brightness"; const char battery_green_max_brightness[] = "/sys/class/leds/gta04:green:power/max_brightness"; const char notifications_red_brightness[] = "/sys/class/leds/gta04:red:aux/brightness"; const char notifications_red_max_brightness[] = "/sys/class/leds/gta04:red:aux/max_brightness"; const char notifications_green_brightness[] = "/sys/class/leds/gta04:green:aux/brightness"; const char notifications_green_max_brightness[] = "/sys/class/leds/gta04:green:aux/max_brightness"; pthread_mutex_t lights_mutex = PTHREAD_MUTEX_INITIALIZER; /* * Sysfs */ int sysfs_value_read(const char *path) { char buffer[100]; int value; int fd = -1; int rc; if (path == NULL) return -1; fd = open(path, O_RDONLY); if (fd < 0) goto error; rc = read(fd, &buffer, sizeof(buffer)); if (rc <= 0) goto error; value = atoi(buffer); goto complete; error: value = -1; complete: if (fd >= 0) close(fd); return value; } int sysfs_value_write(const char *path, int value) { char buffer[100]; int fd = -1; int rc; if (path == NULL) return -1; fd = open(path, O_WRONLY); if (fd < 0) goto error; snprintf((char *) &buffer, sizeof(buffer), "%d\n", value); rc = write(fd, buffer, strlen(buffer)); if (rc < (int) strlen(buffer)) goto error; rc = 0; goto complete; error: rc = -1; complete: if (fd >= 0) close(fd); return rc; } /* * GTA04 Lights */ int gta04_lights_set_light_notifications(struct light_device_t *device, const struct light_state_t *state) { int red, green; int max; int rc = 0; if (state == NULL) return -EINVAL; // GTA04 only has red and green: blue is merged to green red = (state->color & 0x00ff0000) >> 16; green = (state->color & 0x0000ff00) >> 8 | (state->color & 0x000000ff); pthread_mutex_lock(&lights_mutex); // Red max max = sysfs_value_read(notifications_red_max_brightness); if (max > 0) red = (red * max) / 0xff; // Green max max = sysfs_value_read(notifications_green_max_brightness); if (max > 0) green = (green * max) / 0xff; rc |= sysfs_value_write(notifications_red_brightness, red); rc |= sysfs_value_write(notifications_green_brightness, green); pthread_mutex_unlock(&lights_mutex); return rc; } int gta04_lights_set_light_battery(struct light_device_t *device, const struct light_state_t *state) { int red, green; int max; int rc = 0; if (state == NULL) return -EINVAL; // GTA04 only has red and green: blue is merged to green red = (state->color & 0x00ff0000) >> 16; green = (state->color & 0x0000ff00) >> 8 | (state->color & 0x000000ff); pthread_mutex_lock(&lights_mutex); // Red max max = sysfs_value_read(battery_red_max_brightness); if (max > 0) red = (red * max) / 0xff; // Green max max = sysfs_value_read(battery_green_max_brightness); if (max > 0) green = (green * max) / 0xff; rc |= sysfs_value_write(battery_red_brightness, red); rc |= sysfs_value_write(battery_green_brightness, green); pthread_mutex_unlock(&lights_mutex); return rc; } int gta04_lights_set_light_backlight(struct light_device_t *device, const struct light_state_t *state) { int brightness; int color; int max; int rc; if (state == NULL) return -EINVAL; color = state->color & 0x00ffffff; brightness = ((77 * ((color >> 16) & 0xff)) + (150 * ((color >> 8) & 0xff)) + (29 * (color & 0xff))) >> 8; pthread_mutex_lock(&lights_mutex); // Brightness max max = sysfs_value_read(backlight_max_brightness); if (max > 0) brightness = (brightness * max) / 0xff; rc = sysfs_value_write(backlight_brightness, brightness); pthread_mutex_unlock(&lights_mutex); return rc; } /* * Interface */ int gta04_lights_close(struct light_device_t *device) { ALOGD("%s(%p)", __func__, device); if (device == NULL) return -EINVAL; pthread_mutex_destroy(&lights_mutex); free(device); return 0; } int gta04_lights_open(const struct hw_module_t *module, char const *light_id, struct hw_device_t **device) { struct light_device_t *light_device; int (*set_light)(struct light_device_t *light_device, const struct light_state_t *state); ALOGD("%s(%p, %s, %p)", __func__, module, light_id, device); if (module == NULL || light_id == NULL || device == NULL) return -EINVAL; if (strcmp(LIGHT_ID_BACKLIGHT, light_id) == 0) set_light = gta04_lights_set_light_backlight; else if (strcmp(LIGHT_ID_BATTERY, light_id) == 0) set_light = gta04_lights_set_light_battery; else if (strcmp(LIGHT_ID_NOTIFICATIONS, light_id) == 0) set_light = gta04_lights_set_light_notifications; else return -EINVAL; pthread_mutex_init(&lights_mutex, NULL); light_device = (struct light_device_t *) calloc(1, sizeof(struct light_device_t)); light_device->common.tag = HARDWARE_DEVICE_TAG; light_device->common.version = 0; light_device->common.module = (struct hw_module_t *) module; light_device->common.close = (int (*)(struct hw_device_t *)) gta04_lights_close; light_device->set_light = set_light; *device = (struct hw_device_t *) light_device; return 0; } struct hw_module_methods_t gta04_lights_module_methods = { .open = gta04_lights_open, }; struct hw_module_t HAL_MODULE_INFO_SYM = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = LIGHTS_HARDWARE_MODULE_ID, .name = "GTA04 Lights", .author = "Paul Kocialkowski", .methods = >a04_lights_module_methods, };