diff options
author | sbrissen <sbrissen@Hotmail.com> | 2012-05-25 09:40:54 -0400 |
---|---|---|
committer | sbrissen <sbrissen@Hotmail.com> | 2012-05-25 09:51:10 -0400 |
commit | 5e44bae46772acc5dbfa3160118cf3a2807e4738 (patch) | |
tree | c03f0ff12a60783f6c9cf31add530b2820af2b7a /exynos4/exynos4210 | |
parent | 9eb34160302dbf64076da9397a25e047c22e062f (diff) | |
download | hardware_samsung-5e44bae46772acc5dbfa3160118cf3a2807e4738.zip hardware_samsung-5e44bae46772acc5dbfa3160118cf3a2807e4738.tar.gz hardware_samsung-5e44bae46772acc5dbfa3160118cf3a2807e4738.tar.bz2 |
Add Red/Blue LED notification support
This will allow the use of the red/blue led's on the sph-d710
Uses BOARD_HAS_LED_NOTIF in boardconfig.
Change-Id: Ic217ed5b0ec673d03bb596fbde0ac725a5ca0887
Diffstat (limited to 'exynos4/exynos4210')
-rw-r--r-- | exynos4/exynos4210/liblights/Android.mk | 4 | ||||
-rw-r--r-- | exynos4/exynos4210/liblights/lights.c | 154 |
2 files changed, 156 insertions, 2 deletions
diff --git a/exynos4/exynos4210/liblights/Android.mk b/exynos4/exynos4210/liblights/Android.mk index 995bd02..fdc3882 100644 --- a/exynos4/exynos4210/liblights/Android.mk +++ b/exynos4/exynos4210/liblights/Android.mk @@ -25,6 +25,10 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog +ifeq ($(BOARD_HAS_LED_NOTIF),true) + LOCAL_CFLAGS += -DLED_NOTIFICATION +endif + LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM) LOCAL_MODULE_TAGS := optional diff --git a/exynos4/exynos4210/liblights/lights.c b/exynos4/exynos4210/liblights/lights.c index 7a15a33..c328f8b 100644 --- a/exynos4/exynos4210/liblights/lights.c +++ b/exynos4/exynos4210/liblights/lights.c @@ -50,6 +50,10 @@ char const*const BUTTON_FILE = "/sys/class/sec/sec_touchkey/brightness"; #endif +#ifdef LED_NOTIFICATION +static char const RED_LED_DIR[] = "/sys/class/leds/red"; +static char const BLUE_LED_DIR[] = "/sys/class/leds/blue"; +#endif // LED_NOTIFICATION void init_globals(void) { // init the mutex @@ -73,6 +77,12 @@ load_settings() } } +#ifdef LED_NOTIFICATION +static struct led_state { + unsigned int enabled; + int delay_on, delay_off; +} battery_red, battery_blue, notifications_red, notifications_blue; +#endif // LED_NOTIFICATION static int write_int(char const* path, int value) { @@ -95,6 +105,45 @@ write_int(char const* path, int value) } } +#ifdef LED_NOTIFICATION +static int write_str(char const *path, char const *str) +{ + int fd; + static int already_warned = 0; + + LOGV("write_str: path=\"%s\", str=\"%s\".", path, str); + fd = open(path, O_RDWR); + + if (fd >= 0) { + int amt = write(fd, str, strlen(str)); + close(fd); + return amt == -1 ? -errno : 0; + } else { + if (already_warned == 0) { + LOGE("write_str failed to open %s\n", path); + already_warned = 1; + } + return -errno; + } +} + +/* Should check for snprintf truncation, but as these functions only use + * internal paths, meh. */ +static int write_df_int(char const *dir, char const *file, int value) +{ + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/%s", dir, file); + return write_int(path, value); +} + +static int write_df_str(char const *dir, char const *file, char const *str) +{ + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/%s", dir, file); + return write_str(path, str); +} +#endif // LED_NOTIFICATION + static int is_lit(struct light_state_t const* state) { @@ -109,6 +158,75 @@ rgb_to_brightness(struct light_state_t const* state) + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; } +#ifdef LED_NOTIFICATION +static void comp_led_states(struct led_state *red, struct led_state *blue, + struct light_state_t const* state) +{ + unsigned int color = state->color; + int delay_on, delay_off; + + switch (state->flashMode) { + case LIGHT_FLASH_TIMED: + delay_on = state->flashOnMS; + delay_off = state->flashOffMS; + break; + default: + LOGI("Unsuported flashMode %d, default to NONE.", state->flashMode); + case LIGHT_FLASH_NONE: + delay_on = delay_off = 0; + break; + } + + red->enabled = !!(color >> 16 & 0xff); + red->delay_on = delay_on; + red->delay_off = delay_off; + + blue->enabled = !!(color & 0xff); + blue->delay_on = delay_on; + blue->delay_off = delay_off; + + LOGV("comp_led_states: red=(%u, %d, %d), blue=(%u, %d, %d).", + red->enabled, red->delay_on, red->delay_off, blue->enabled, + blue->delay_on, blue->delay_off); +} + +static int set_led(char const *dir, struct led_state const *battery, + struct led_state const *notifications) +{ + + struct led_state const *state = NULL; + int res; + + if (notifications->enabled) + state = notifications; + else if (battery->enabled) + state = battery; + + if (state != NULL) { + int delay_on = state->delay_on; + int delay_off = state->delay_off; + + if (delay_on > 0 && delay_off > 0) { + /* Handling of blink_count is wrong in the kernel, blinking indefinitely + * for any non-zero value. TW lights just sets it to 1. */ + if ((res = write_df_str(dir, "trigger", "notification")) < 0) return res; + if ((res = write_df_str(dir, "brightness", "255" )) < 0) return res; + if ((res = write_df_str(dir, "blink_count", "1" )) < 0) return res; + if ((res = write_df_int(dir, "delay_on", delay_on )) < 0) return res; + if ((res = write_df_int(dir, "delay_off", delay_off )) < 0) return res; + } else { + if ((res = write_df_str(dir, "trigger", "none")) < 0) return res; + if ((res = write_df_str(dir, "brightness", "255" )) < 0) return res; + } + } else { + if ((res = write_df_str(dir, "trigger", "none")) < 0) return res; + if ((res = write_df_str(dir, "brightness", "0" )) < 0) return res; + } + + return 0; +} +#endif // LED_NOTIFICATION + static int set_light_backlight(struct light_device_t* dev, struct light_state_t const* state) @@ -163,14 +281,46 @@ static int set_light_battery(struct light_device_t* dev, struct light_state_t const* state) { - return 0; + int res = 0; + +#ifdef LED_NOTIFICATION + LOGD("set_light_battery: color=%#010x, fM=%u, fOnMS=%d, fOffMs=%d.", + state->color, state->flashMode, state->flashOnMS, state->flashOffMS); + + pthread_mutex_lock(&g_lock); + + comp_led_states(&battery_red, &battery_blue, state); + + if ((res = set_led(RED_LED_DIR, &battery_red, ¬ifications_red)) >= 0) + res = set_led(BLUE_LED_DIR, &battery_blue, ¬ifications_blue); + + pthread_mutex_unlock(&g_lock); +#endif // LED_NOTIFICATION + + return res; } static int set_light_notification(struct light_device_t* dev, struct light_state_t const* state) { - return 0; + int res = 0; + +#ifdef LED_NOTIFICATION + LOGD("set_light_notification: color=%#010x, fM=%u, fOnMS=%d, fOffMs=%d.", + state->color, state->flashMode, state->flashOnMS, state->flashOffMS); + + pthread_mutex_lock(&g_lock); + + comp_led_states(¬ifications_red, ¬ifications_blue, state); + + if ((res = set_led(RED_LED_DIR, &battery_red, ¬ifications_red)) >= 0) + res = set_led(BLUE_LED_DIR, &battery_blue, ¬ifications_blue); + + pthread_mutex_unlock(&g_lock); +#endif // LED_NOTIFICATION + + return res; } static int |