= "/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
pthread_mutex_init(&g_lock, NULL);
}
+#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)
{
}
}
+#ifdef LED_NOTIFICATION
+static int write_str(char const *path, char const *str)
+{
+ int fd;
+ static int already_warned = 0;
+
+ ALOGV("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) {
+ ALOGE("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)
{
+ (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:
+ ALOGI("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;
+
+ ALOGV("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)
set_light_battery(struct light_device_t* dev,
struct light_state_t const* state)
{
- return 0;
+ int res = 0;
+
+#ifdef LED_NOTIFICATION
+ ALOGD("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
+ ALOGD("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