107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/* 2d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * Copyright (C) 2014, 2017 The Linux Foundation. All rights reserved. 3d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema * Not a contribution 407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Copyright (C) 2008 The Android Open Source Project 507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Licensed under the Apache License, Version 2.0 (the "License"); 707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * you may not use this file except in compliance with the License. 807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * You may obtain a copy of the License at 907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 1007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * http://www.apache.org/licenses/LICENSE-2.0 1107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 1207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Unless required by applicable law or agreed to in writing, software 1307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * distributed under the License is distributed on an "AS IS" BASIS, 1407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * See the License for the specific language governing permissions and 1607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * limitations under the License. 1707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 1807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 1907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 2007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani// #define LOG_NDEBUG 0 2107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 22d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include <log/log.h> 23d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include <cutils/properties.h> 2407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <stdint.h> 2507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <stdlib.h> 2607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <string.h> 2707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <unistd.h> 2807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <errno.h> 2907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <fcntl.h> 3007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <pthread.h> 3107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 3207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <sys/ioctl.h> 3307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <sys/types.h> 3407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 3507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <hardware/lights.h> 36d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#include "lights_prv.h" 37d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 38d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#ifndef DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS 39d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#define DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS 0x80 40d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema#endif 4107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 4207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/******************************************************************************/ 4307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 4407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic pthread_once_t g_init = PTHREAD_ONCE_INIT; 4507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; 4607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic struct light_state_t g_notification; 4707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic struct light_state_t g_battery; 48d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemastatic int g_last_backlight_mode = BRIGHTNESS_MODE_USER; 4907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int g_attention = 0; 50d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemastatic int g_brightness_max = 0; 5107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanichar const*const RED_LED_FILE 5307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani = "/sys/class/leds/red/brightness"; 5407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanichar const*const GREEN_LED_FILE 5607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani = "/sys/class/leds/green/brightness"; 5707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanichar const*const BLUE_LED_FILE 5907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani = "/sys/class/leds/blue/brightness"; 6007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 6107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanichar const*const LCD_FILE 6207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani = "/sys/class/leds/lcd-backlight/brightness"; 6307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 64d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemachar const*const LCD_FILE2 65d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema = "/sys/class/backlight/panel0-backlight/brightness"; 66d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 6707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanichar const*const BUTTON_FILE 6807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani = "/sys/class/leds/button-backlight/brightness"; 6907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 7007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanichar const*const RED_BLINK_FILE 7107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani = "/sys/class/leds/red/blink"; 7207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 7307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanichar const*const GREEN_BLINK_FILE 7407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani = "/sys/class/leds/green/blink"; 7507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 7607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanichar const*const BLUE_BLINK_FILE 7707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani = "/sys/class/leds/blue/blink"; 7807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 79d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemachar const*const PERSISTENCE_FILE 80d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema = "/sys/class/graphics/fb0/msm_fb_persist_mode"; 81d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 8207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/** 8307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * device methods 8407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 8507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 8607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanivoid init_globals(void) 8707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 8807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani // init the mutex 8907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_init(&g_lock, NULL); 9007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 9107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 9207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 9307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniwrite_int(char const* path, int value) 9407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 9507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int fd; 9607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani static int already_warned = 0; 9707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 9807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani fd = open(path, O_RDWR); 9907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (fd >= 0) { 10007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani char buffer[20]; 10107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value); 10207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ssize_t amt = write(fd, buffer, (size_t)bytes); 10307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani close(fd); 10407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return amt == -1 ? -errno : 0; 10507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } else { 10607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (already_warned == 0) { 10707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGE("write_int failed to open %s\n", path); 10807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani already_warned = 1; 10907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 11007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return -errno; 11107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 11207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 11307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 11407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 11507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniis_lit(struct light_state_t const* state) 11607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 11707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return state->color & 0x00ffffff; 11807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 11907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 12007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 12107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanirgb_to_brightness(struct light_state_t const* state) 12207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 12307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int color = state->color & 0x00ffffff; 12407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return ((77*((color>>16)&0x00ff)) 12507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; 12607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 12707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 12807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 12907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniset_light_backlight(struct light_device_t* dev, 13007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct light_state_t const* state) 13107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 13207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int err = 0; 13307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int brightness = rgb_to_brightness(state); 134d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema unsigned int lpEnabled = 135d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema state->brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE; 136d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if(!dev) { 137d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema return -1; 138d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 139d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 140d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema pthread_mutex_lock(&g_lock); 141d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema // Toggle low persistence mode state 142d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if ((g_last_backlight_mode != state->brightnessMode && lpEnabled) || 143d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema (!lpEnabled && 144d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema g_last_backlight_mode == BRIGHTNESS_MODE_LOW_PERSISTENCE)) { 145d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if ((err = write_int(PERSISTENCE_FILE, lpEnabled)) != 0) { 146d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema ALOGE("%s: Failed to write to %s: %s\n", __FUNCTION__, 147d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema PERSISTENCE_FILE, strerror(errno)); 148d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 149d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if (lpEnabled != 0) { 150d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema brightness = DEFAULT_LOW_PERSISTENCE_MODE_BRIGHTNESS; 151d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 152d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 153d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 154d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema g_last_backlight_mode = state->brightnessMode; 155d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 156d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if (!err) { 157d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if (!access(LCD_FILE, F_OK)) { 158d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema err = write_int(LCD_FILE, brightness); 159d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } else { 160d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema err = write_int(LCD_FILE2, brightness); 161d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 162d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 163d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 164d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema pthread_mutex_unlock(&g_lock); 165d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema return err; 166d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema} 167d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 168d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemastatic int 169d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennemaset_light_backlight_ext(struct light_device_t* dev, 170d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema struct light_state_t const* state) 171d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema{ 172d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema int err = 0; 173d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 17407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!dev) { 17507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return -1; 17607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 177d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 178d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema int brightness = state->color & 0x00ffffff; 17907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_lock(&g_lock); 180d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 181d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if (brightness >= 0 && brightness <= g_brightness_max) { 182d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema set_brightness_ext_level(brightness); 183d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 184d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 18507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_unlock(&g_lock); 186d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 18707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return err; 18807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 18907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 19007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 19107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniset_speaker_light_locked(struct light_device_t* dev, 19207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct light_state_t const* state) 19307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 19407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int red, green, blue; 19507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int blink; 19607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int onMS, offMS; 19707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani unsigned int colorRGB; 19807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 19907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!dev) { 20007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return -1; 20107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 20207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 20307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani switch (state->flashMode) { 20407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani case LIGHT_FLASH_TIMED: 20507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani onMS = state->flashOnMS; 20607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani offMS = state->flashOffMS; 20707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani break; 20807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani case LIGHT_FLASH_NONE: 20907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani default: 21007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani onMS = 0; 21107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani offMS = 0; 21207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani break; 21307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 21407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 21507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani colorRGB = state->color; 21607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 21707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#if 0 21807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ALOGD("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n", 21907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani state->flashMode, colorRGB, onMS, offMS); 22007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#endif 22107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 22207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani red = (colorRGB >> 16) & 0xFF; 22307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani green = (colorRGB >> 8) & 0xFF; 22407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani blue = colorRGB & 0xFF; 22507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 22607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (onMS > 0 && offMS > 0) { 22707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani /* 22807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * if ON time == OFF time 22907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * use blink mode 2 23007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * else 23107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * use blink mode 1 23207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 23307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (onMS == offMS) 23407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani blink = 2; 23507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani else 23607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani blink = 1; 23707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } else { 23807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani blink = 0; 23907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 24007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 24107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (blink) { 24207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (red) { 24307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (write_int(RED_BLINK_FILE, blink)) 24407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani write_int(RED_LED_FILE, 0); 245d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 24607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (green) { 24707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (write_int(GREEN_BLINK_FILE, blink)) 24807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani write_int(GREEN_LED_FILE, 0); 249d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 25007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (blue) { 25107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (write_int(BLUE_BLINK_FILE, blink)) 25207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani write_int(BLUE_LED_FILE, 0); 253d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 25407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } else { 25507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani write_int(RED_LED_FILE, red); 25607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani write_int(GREEN_LED_FILE, green); 25707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani write_int(BLUE_LED_FILE, blue); 25807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 25907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 26007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return 0; 26107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 26207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 26307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic void 26407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanihandle_speaker_battery_locked(struct light_device_t* dev) 26507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 26607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (is_lit(&g_battery)) { 26707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani set_speaker_light_locked(dev, &g_battery); 26807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } else { 26907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani set_speaker_light_locked(dev, &g_notification); 27007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 27107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 27207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 27307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 27407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniset_light_battery(struct light_device_t* dev, 27507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct light_state_t const* state) 27607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 27707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_lock(&g_lock); 27807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani g_battery = *state; 27907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani handle_speaker_battery_locked(dev); 28007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_unlock(&g_lock); 28107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return 0; 28207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 28307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 28407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 28507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniset_light_notifications(struct light_device_t* dev, 28607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct light_state_t const* state) 28707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 28807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_lock(&g_lock); 28907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani g_notification = *state; 29007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani handle_speaker_battery_locked(dev); 29107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_unlock(&g_lock); 29207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return 0; 29307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 29407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 29507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 29607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniset_light_attention(struct light_device_t* dev, 29707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct light_state_t const* state) 29807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 29907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_lock(&g_lock); 30007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (state->flashMode == LIGHT_FLASH_HARDWARE) { 30107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani g_attention = state->flashOnMS; 30207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } else if (state->flashMode == LIGHT_FLASH_NONE) { 30307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani g_attention = 0; 30407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 30507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani handle_speaker_battery_locked(dev); 30607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_unlock(&g_lock); 30707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return 0; 30807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 30907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 31007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 31107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniset_light_buttons(struct light_device_t* dev, 31207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct light_state_t const* state) 31307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 31407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int err = 0; 31507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!dev) { 31607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return -1; 31707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 31807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_lock(&g_lock); 31907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani err = write_int(BUTTON_FILE, state->color & 0xFF); 32007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_mutex_unlock(&g_lock); 32107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return err; 32207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 32307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 32407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/** Close the lights device */ 32507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int 32607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniclose_lights(struct light_device_t *dev) 32707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 32807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (dev) { 32907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani free(dev); 33007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 33107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return 0; 33207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 33307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 33407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 33507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/******************************************************************************/ 33607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 33707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/** 33807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * module methods 33907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 34007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 34107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/** Open a new instance of a lights device using name */ 34207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic int open_lights(const struct hw_module_t* module, char const* name, 34307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct hw_device_t** device) 34407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 34507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int (*set_light)(struct light_device_t* dev, 34607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct light_state_t const* state); 34707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 348d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) { 349d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema char property[PROPERTY_VALUE_MAX]; 350d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema property_get("persist.extend.brightness", property, "0"); 351d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema 352d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) || 353d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema !(strncmp(property, "true", PROPERTY_VALUE_MAX))) { 354d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema property_get("persist.display.max_brightness", property, "255"); 355d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema g_brightness_max = atoi(property); 356d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema set_brightness_ext_init(); 357d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema set_light = set_light_backlight_ext; 358d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } else 359d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema set_light = set_light_backlight; 360d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } else if (0 == strcmp(LIGHT_ID_BATTERY, name)) 36107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani set_light = set_light_battery; 36207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) 36307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani set_light = set_light_notifications; 364d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) { 365d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema if (!access(BUTTON_FILE, F_OK)) { 366d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema // enable light button when the file is present 367d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema set_light = set_light_buttons; 368d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } else { 369d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema return -EINVAL; 370d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 371d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema } 37207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) 37307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani set_light = set_light_attention; 37407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani else 37507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return -EINVAL; 37607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 37707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani pthread_once(&g_init, init_globals); 37807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 37907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct light_device_t *dev = malloc(sizeof(struct light_device_t)); 38007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 38107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if(!dev) 38207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return -ENOMEM; 38307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 38407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani memset(dev, 0, sizeof(*dev)); 38507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 38607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani dev->common.tag = HARDWARE_DEVICE_TAG; 387d39a514dd0540cf47e121775a77e9ac1b578bdb1Ben Fennema dev->common.version = LIGHTS_DEVICE_API_VERSION_2_0; 38807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani dev->common.module = (struct hw_module_t*)module; 38907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani dev->common.close = (int (*)(struct hw_device_t*))close_lights; 39007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani dev->set_light = set_light; 39107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 39207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani *device = (struct hw_device_t*)dev; 39307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return 0; 39407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 39507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 39607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistatic struct hw_module_methods_t lights_module_methods = { 39707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .open = open_lights, 39807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani}; 39907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 40007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/* 40107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * The lights Module 40207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 40307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistruct hw_module_t HAL_MODULE_INFO_SYM = { 40407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .tag = HARDWARE_MODULE_TAG, 40507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .version_major = 1, 40607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .version_minor = 0, 40707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .id = LIGHTS_HARDWARE_MODULE_ID, 40807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .name = "lights Module", 40907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .author = "Google, Inc.", 41007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .methods = &lights_module_methods, 41107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani}; 412