summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsbrissen <sbrissen@Hotmail.com>2012-05-25 09:40:54 -0400
committersbrissen <sbrissen@Hotmail.com>2012-05-25 09:51:10 -0400
commit5e44bae46772acc5dbfa3160118cf3a2807e4738 (patch)
treec03f0ff12a60783f6c9cf31add530b2820af2b7a
parent9eb34160302dbf64076da9397a25e047c22e062f (diff)
downloadandroid_hardware_samsung-5e44bae46772acc5dbfa3160118cf3a2807e4738.tar.gz
android_hardware_samsung-5e44bae46772acc5dbfa3160118cf3a2807e4738.tar.bz2
android_hardware_samsung-5e44bae46772acc5dbfa3160118cf3a2807e4738.zip
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
-rw-r--r--exynos4/exynos4210/liblights/Android.mk4
-rw-r--r--exynos4/exynos4210/liblights/lights.c154
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, &notifications_red)) >= 0)
+ res = set_led(BLUE_LED_DIR, &battery_blue, &notifications_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(&notifications_red, &notifications_blue, state);
+
+ if ((res = set_led(RED_LED_DIR, &battery_red, &notifications_red)) >= 0)
+ res = set_led(BLUE_LED_DIR, &battery_blue, &notifications_blue);
+
+ pthread_mutex_unlock(&g_lock);
+#endif // LED_NOTIFICATION
+
+ return res;
}
static int