12ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel/*
26e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel * Copyright (C) 2014, 2017 The  Linux Foundation. All rights reserved.
36e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel * Not a contribution
42ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * Copyright (C) 2008 The Android Open Source Project
52ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel *
62ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * Licensed under the Apache License, Version 2.0 (the "License");
72ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * you may not use this file except in compliance with the License.
82ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * You may obtain a copy of the License at
92ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel *
102ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel *      http://www.apache.org/licenses/LICENSE-2.0
112ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel *
122ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * Unless required by applicable law or agreed to in writing, software
132ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * distributed under the License is distributed on an "AS IS" BASIS,
142ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
152ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * See the License for the specific language governing permissions and
162ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * limitations under the License.
172ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel */
182ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
192ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
202ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel// #define LOG_NDEBUG 0
212ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
222ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <cutils/log.h>
2386f0be319b163d01870e0cc4c2d6489f5c5f117dNaseer Ahmed
242ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <stdint.h>
252ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <stdlib.h>
262ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <string.h>
272ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <unistd.h>
282ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <errno.h>
292ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <fcntl.h>
302ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <pthread.h>
312ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
322ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <sys/ioctl.h>
332ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <sys/types.h>
342ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
352ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#include <hardware/lights.h>
362ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
376e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel#ifndef DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS
386e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel#define DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS 0x80
396e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel#endif
406e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel
412ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel/******************************************************************************/
422ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
432ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic pthread_once_t g_init = PTHREAD_ONCE_INIT;
442ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
452ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic struct light_state_t g_notification;
462ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic struct light_state_t g_battery;
476e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudelstatic int g_last_backlight_mode = BRIGHTNESS_MODE_USER;
482ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int g_attention = 0;
492ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
502ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelchar const*const RED_LED_FILE
512ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        = "/sys/class/leds/red/brightness";
522ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
532ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelchar const*const GREEN_LED_FILE
542ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        = "/sys/class/leds/green/brightness";
552ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
562ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelchar const*const BLUE_LED_FILE
572ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        = "/sys/class/leds/blue/brightness";
582ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
592ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelchar const*const LCD_FILE
602ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        = "/sys/class/leds/lcd-backlight/brightness";
612ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
62cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudelchar const*const LCD_FILE2
63cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel        = "/sys/class/backlight/panel0-backlight/brightness";
64cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel
652ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelchar const*const BUTTON_FILE
662ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        = "/sys/class/leds/button-backlight/brightness";
672ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
682ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelchar const*const RED_BLINK_FILE
692ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        = "/sys/class/leds/red/blink";
702ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
712ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelchar const*const GREEN_BLINK_FILE
722ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        = "/sys/class/leds/green/blink";
732ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
742ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelchar const*const BLUE_BLINK_FILE
752ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        = "/sys/class/leds/blue/blink";
762ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
776e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudelchar const*const PERSISTENCE_FILE
786e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel        = "/sys/class/graphics/fb0/msm_fb_persist_mode";
796e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel
802ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel/**
812ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * device methods
822ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel */
832ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
842ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelvoid init_globals(void)
852ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
862ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    // init the mutex
872ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_init(&g_lock, NULL);
882ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
892ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
902ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
912ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelwrite_int(char const* path, int value)
922ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
932ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int fd;
942ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    static int already_warned = 0;
952ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
962ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    fd = open(path, O_RDWR);
972ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if (fd >= 0) {
982ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        char buffer[20];
992ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
1002ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        ssize_t amt = write(fd, buffer, (size_t)bytes);
1012ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        close(fd);
1022ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        return amt == -1 ? -errno : 0;
1032ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    } else {
1042ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        if (already_warned == 0) {
1052ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            ALOGE("write_int failed to open %s\n", path);
1062ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            already_warned = 1;
1072ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        }
1082ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        return -errno;
1092ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
1102ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
1112ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
1122ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
1132ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelis_lit(struct light_state_t const* state)
1142ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
1152ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return state->color & 0x00ffffff;
1162ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
1172ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
1182ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
1192ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelrgb_to_brightness(struct light_state_t const* state)
1202ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
1212ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int color = state->color & 0x00ffffff;
1222ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return ((77*((color>>16)&0x00ff))
1232ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
1242ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
1252ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
1262ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
1272ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelset_light_backlight(struct light_device_t* dev,
1282ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        struct light_state_t const* state)
1292ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
1302ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int err = 0;
1312ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int brightness = rgb_to_brightness(state);
1326e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel    unsigned int lpEnabled =
1336e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel        state->brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE;
1342ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if(!dev) {
1352ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        return -1;
1362ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
1376e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel
1382ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_lock(&g_lock);
1396e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel    // Toggle low persistence mode state
1406e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel    if ((g_last_backlight_mode != state->brightnessMode && lpEnabled) ||
1416e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel        (!lpEnabled &&
1426e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel         g_last_backlight_mode == BRIGHTNESS_MODE_LOW_PERSISTENCE)) {
1436e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel        if ((err = write_int(PERSISTENCE_FILE, lpEnabled)) != 0) {
1446e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel            ALOGE("%s: Failed to write to %s: %s\n", __FUNCTION__,
1456e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel                   PERSISTENCE_FILE, strerror(errno));
1466e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel        }
1476e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel        if (lpEnabled != 0) {
1486e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel            brightness = DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS;
1496e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel        }
1506e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel    }
1516e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel
1526e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel    g_last_backlight_mode = state->brightnessMode;
1536e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel
1546e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel    if (!err) {
155cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel        if (!access(LCD_FILE, F_OK)) {
156cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel            err = write_int(LCD_FILE, brightness);
157cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel        } else {
158cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel            err = write_int(LCD_FILE2, brightness);
159cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel        }
160cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel    }
161cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel
162cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel    pthread_mutex_unlock(&g_lock);
163cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel    return err;
164cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel}
165cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudel
166cd66324640d3290ee75bf5bf41826fbcbc55a13aThierry Strudelstatic int
1672ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelset_speaker_light_locked(struct light_device_t* dev,
1682ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        struct light_state_t const* state)
1692ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
1702ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int red, green, blue;
1712ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int blink;
1722ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int onMS, offMS;
1732ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    unsigned int colorRGB;
1742ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
1752ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if(!dev) {
1762ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        return -1;
1772ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
1782ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
1792ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    switch (state->flashMode) {
1802ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        case LIGHT_FLASH_TIMED:
1812ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            onMS = state->flashOnMS;
1822ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            offMS = state->flashOffMS;
1832ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            break;
1842ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        case LIGHT_FLASH_NONE:
1852ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        default:
1862ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            onMS = 0;
1872ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            offMS = 0;
1882ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            break;
1892ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
1902ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
1912ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    colorRGB = state->color;
1922ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
1932ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#if 0
1942ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    ALOGD("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n",
1952ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            state->flashMode, colorRGB, onMS, offMS);
1962ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel#endif
1972ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
1982ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    red = (colorRGB >> 16) & 0xFF;
1992ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    green = (colorRGB >> 8) & 0xFF;
2002ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    blue = colorRGB & 0xFF;
2012ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
2022ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if (onMS > 0 && offMS > 0) {
2032ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        /*
2042ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel         * if ON time == OFF time
2052ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel         *   use blink mode 2
2062ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel         * else
2072ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel         *   use blink mode 1
2082ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel         */
2092ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        if (onMS == offMS)
2102ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            blink = 2;
2112ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        else
2122ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            blink = 1;
2132ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    } else {
2142ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        blink = 0;
2152ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
2162ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
2172ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if (blink) {
2182ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        if (red) {
2192ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            if (write_int(RED_BLINK_FILE, blink))
2202ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel                write_int(RED_LED_FILE, 0);
22186f0be319b163d01870e0cc4c2d6489f5c5f117dNaseer Ahmed	}
2222ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        if (green) {
2232ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            if (write_int(GREEN_BLINK_FILE, blink))
2242ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel                write_int(GREEN_LED_FILE, 0);
22586f0be319b163d01870e0cc4c2d6489f5c5f117dNaseer Ahmed	}
2262ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        if (blue) {
2272ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            if (write_int(BLUE_BLINK_FILE, blink))
2282ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel                write_int(BLUE_LED_FILE, 0);
22986f0be319b163d01870e0cc4c2d6489f5c5f117dNaseer Ahmed	}
2302ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    } else {
2312ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        write_int(RED_LED_FILE, red);
2322ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        write_int(GREEN_LED_FILE, green);
2332ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        write_int(BLUE_LED_FILE, blue);
2342ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
2352ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
2362ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return 0;
2372ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
2382ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
2392ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic void
2402ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelhandle_speaker_battery_locked(struct light_device_t* dev)
2412ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
2422ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if (is_lit(&g_battery)) {
2432ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        set_speaker_light_locked(dev, &g_battery);
2442ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    } else {
2452ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        set_speaker_light_locked(dev, &g_notification);
2462ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
2472ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
2482ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
2492ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
2502ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelset_light_battery(struct light_device_t* dev,
2512ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        struct light_state_t const* state)
2522ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
2532ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_lock(&g_lock);
2542ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    g_battery = *state;
2552ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    handle_speaker_battery_locked(dev);
2562ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_unlock(&g_lock);
2572ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return 0;
2582ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
2592ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
2602ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
2612ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelset_light_notifications(struct light_device_t* dev,
2622ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        struct light_state_t const* state)
2632ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
2642ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_lock(&g_lock);
2652ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    g_notification = *state;
2662ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    handle_speaker_battery_locked(dev);
2672ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_unlock(&g_lock);
2682ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return 0;
2692ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
2702ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
2712ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
2722ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelset_light_attention(struct light_device_t* dev,
2732ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        struct light_state_t const* state)
2742ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
2752ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_lock(&g_lock);
2762ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if (state->flashMode == LIGHT_FLASH_HARDWARE) {
2772ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        g_attention = state->flashOnMS;
2782ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    } else if (state->flashMode == LIGHT_FLASH_NONE) {
2792ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        g_attention = 0;
2802ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
2812ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    handle_speaker_battery_locked(dev);
2822ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_unlock(&g_lock);
2832ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return 0;
2842ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
2852ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
2862ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
2872ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelset_light_buttons(struct light_device_t* dev,
2882ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        struct light_state_t const* state)
2892ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
2902ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int err = 0;
2912ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if(!dev) {
2922ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        return -1;
2932ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
2942ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_lock(&g_lock);
2952ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    err = write_int(BUTTON_FILE, state->color & 0xFF);
2962ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_mutex_unlock(&g_lock);
2972ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return err;
2982ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
2992ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3002ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel/** Close the lights device */
3012ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int
3022ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelclose_lights(struct light_device_t *dev)
3032ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
3042ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if (dev) {
3052ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        free(dev);
3062ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    }
3072ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return 0;
3082ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
3092ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3102ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3112ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel/******************************************************************************/
3122ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3132ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel/**
3142ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * module methods
3152ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel */
3162ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3172ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel/** Open a new instance of a lights device using name */
3182ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic int open_lights(const struct hw_module_t* module, char const* name,
3192ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        struct hw_device_t** device)
3202ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel{
3212ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    int (*set_light)(struct light_device_t* dev,
3222ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel            struct light_state_t const* state);
3232ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
32486f0be319b163d01870e0cc4c2d6489f5c5f117dNaseer Ahmed    if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
32586f0be319b163d01870e0cc4c2d6489f5c5f117dNaseer Ahmed        set_light = set_light_backlight;
32686f0be319b163d01870e0cc4c2d6489f5c5f117dNaseer Ahmed    else if (0 == strcmp(LIGHT_ID_BATTERY, name))
3272ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        set_light = set_light_battery;
3282ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
3292ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        set_light = set_light_notifications;
3302ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
3312ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        set_light = set_light_buttons;
3322ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
3332ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        set_light = set_light_attention;
3342ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    else
3352ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        return -EINVAL;
3362ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3372ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    pthread_once(&g_init, init_globals);
3382ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3392ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    struct light_device_t *dev = malloc(sizeof(struct light_device_t));
3402ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3412ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    if(!dev)
3422ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel        return -ENOMEM;
3432ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3442ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    memset(dev, 0, sizeof(*dev));
3452ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3462ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    dev->common.tag = HARDWARE_DEVICE_TAG;
3476e71b7f95e9fdc03147c5f235060dd4ed4f23b86Thierry Strudel    dev->common.version = LIGHTS_DEVICE_API_VERSION_2_0;
3482ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    dev->common.module = (struct hw_module_t*)module;
3492ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
3502ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    dev->set_light = set_light;
3512ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3522ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    *device = (struct hw_device_t*)dev;
3532ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    return 0;
3542ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel}
3552ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3562ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstatic struct hw_module_methods_t lights_module_methods = {
3572ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    .open =  open_lights,
3582ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel};
3592ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel
3602ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel/*
3612ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel * The lights Module
3622ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel */
3632ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudelstruct hw_module_t HAL_MODULE_INFO_SYM = {
3642ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    .tag = HARDWARE_MODULE_TAG,
3652ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    .version_major = 1,
3662ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    .version_minor = 0,
3672ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    .id = LIGHTS_HARDWARE_MODULE_ID,
3682ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    .name = "lights Module",
3692ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    .author = "Google, Inc.",
3702ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel    .methods = &lights_module_methods,
3712ebc25b87caae537b8cd97beb8a86a7ff5f0cdf4Thierry Strudel};
372