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