1ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/*
2ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Copyright (C) 2008 The Android Open Source Project
3a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson * Copyright (C) 2014 The  Linux Foundation. All rights reserved.
4ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *
5ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Licensed under the Apache License, Version 2.0 (the "License");
6ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * you may not use this file except in compliance with the License.
7ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * You may obtain a copy of the License at
8ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *
9ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *      http://www.apache.org/licenses/LICENSE-2.0
10ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *
11ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Unless required by applicable law or agreed to in writing, software
12ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * distributed under the License is distributed on an "AS IS" BASIS,
13ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * See the License for the specific language governing permissions and
15ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * limitations under the License.
16ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
17ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
18ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
19ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson// #define LOG_NDEBUG 0
20ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
21ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <cutils/log.h>
22ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
23ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <stdint.h>
24ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <string.h>
25ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <unistd.h>
26ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <errno.h>
27ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <fcntl.h>
28ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <pthread.h>
29ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
30ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/ioctl.h>
31ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/types.h>
32ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
33ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <hardware/lights.h>
34ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
35ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/******************************************************************************/
36ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
37ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic pthread_once_t g_init = PTHREAD_ONCE_INIT;
38ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
39ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic struct light_state_t g_notification;
40ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic struct light_state_t g_battery;
41ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int g_attention = 0;
42ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
43ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonchar const*const RED_LED_FILE
44ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        = "/sys/class/leds/red/brightness";
45ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
46ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonchar const*const GREEN_LED_FILE
47ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        = "/sys/class/leds/green/brightness";
48ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
49ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonchar const*const BLUE_LED_FILE
50ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        = "/sys/class/leds/blue/brightness";
51ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
52ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonchar const*const LCD_FILE
53ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        = "/sys/class/leds/lcd-backlight/brightness";
54ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
55a653efede03423aa840da24634f1ec6f20796f1eSimon Wilsonchar const*const BUTTON_FILE
56a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        = "/sys/class/leds/button-backlight/brightness";
57ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
58a653efede03423aa840da24634f1ec6f20796f1eSimon Wilsonchar const*const RED_BLINK_FILE
59a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        = "/sys/class/leds/red/blink";
60ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
61a653efede03423aa840da24634f1ec6f20796f1eSimon Wilsonchar const*const GREEN_BLINK_FILE
62a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        = "/sys/class/leds/green/blink";
63ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
64a653efede03423aa840da24634f1ec6f20796f1eSimon Wilsonchar const*const BLUE_BLINK_FILE
65a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        = "/sys/class/leds/blue/blink";
66ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
67ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/**
68ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * device methods
69ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
70ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
71ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonvoid init_globals(void)
72ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
73ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // init the mutex
74ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_init(&g_lock, NULL);
75ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
76ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
77ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int
78ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonwrite_int(char const* path, int value)
79ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
80ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int fd;
81ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    static int already_warned = 0;
82ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
83ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    fd = open(path, O_RDWR);
84ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (fd >= 0) {
85ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        char buffer[20];
869caaa41be6c1f3ceb52a2748c8f13c48b8aee848Manoj Kumar AVM        int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
87a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        ssize_t amt = write(fd, buffer, (size_t)bytes);
88ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        close(fd);
89ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return amt == -1 ? -errno : 0;
90ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
91ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (already_warned == 0) {
92ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("write_int failed to open %s\n", path);
93ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            already_warned = 1;
94ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
95ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -errno;
96ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
97ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
98ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
99ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int
100ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonis_lit(struct light_state_t const* state)
101ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
102ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return state->color & 0x00ffffff;
103ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
104ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
105ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int
106ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonrgb_to_brightness(struct light_state_t const* state)
107ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
108ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int color = state->color & 0x00ffffff;
109ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return ((77*((color>>16)&0x00ff))
110ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
111ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
112ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
113ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int
114ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonset_light_backlight(struct light_device_t* dev,
115ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        struct light_state_t const* state)
116ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
117ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int err = 0;
118ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int brightness = rgb_to_brightness(state);
119a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    if(!dev) {
120a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        return -1;
121a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    }
122ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&g_lock);
123ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    err = write_int(LCD_FILE, brightness);
124ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&g_lock);
125ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return err;
126ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
127ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
128ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int
129ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonset_speaker_light_locked(struct light_device_t* dev,
130ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        struct light_state_t const* state)
131ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
132a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    int red, green, blue;
133a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    int blink;
134ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int onMS, offMS;
135ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    unsigned int colorRGB;
136ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
137a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    if(!dev) {
138a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        return -1;
139a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    }
140a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson
141ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch (state->flashMode) {
142ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case LIGHT_FLASH_TIMED:
143ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            onMS = state->flashOnMS;
144ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            offMS = state->flashOffMS;
145ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
146ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case LIGHT_FLASH_NONE:
147ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:
148ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            onMS = 0;
149ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            offMS = 0;
150ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
151ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
152ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
153ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    colorRGB = state->color;
154ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
155ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#if 0
156ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ALOGD("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n",
157ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            state->flashMode, colorRGB, onMS, offMS);
158ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#endif
159ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
160a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    red = (colorRGB >> 16) & 0xFF;
161a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    green = (colorRGB >> 8) & 0xFF;
162a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    blue = colorRGB & 0xFF;
163ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
164a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    if (onMS > 0 && offMS > 0) {
165ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        blink = 1;
166ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
167ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        blink = 0;
168ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
169ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
170ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (blink) {
171cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li        if (red) {
172cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li            if (write_int(RED_BLINK_FILE, blink))
173cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li                write_int(RED_LED_FILE, 0);
174cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li	}
175cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li        if (green) {
176cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li            if (write_int(GREEN_BLINK_FILE, blink))
177cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li                write_int(GREEN_LED_FILE, 0);
178cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li	}
179cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li        if (blue) {
180cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li            if (write_int(BLUE_BLINK_FILE, blink))
181cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li                write_int(BLUE_LED_FILE, 0);
182cbf0d5f822b638271c897338a3d29c43ce0d4e37Mao Li	}
183a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    } else {
184a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        write_int(RED_LED_FILE, red);
185a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        write_int(GREEN_LED_FILE, green);
186a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        write_int(BLUE_LED_FILE, blue);
187ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
188ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
189ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return 0;
190ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
191ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
192ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic void
193ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonhandle_speaker_battery_locked(struct light_device_t* dev)
194ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
195ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (is_lit(&g_battery)) {
196ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        set_speaker_light_locked(dev, &g_battery);
197ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
198ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        set_speaker_light_locked(dev, &g_notification);
199ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
200ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
201ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
202ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int
203db007e94420fc2efb423fa037355ea7269a982edMao Liset_light_battery(struct light_device_t* dev,
204db007e94420fc2efb423fa037355ea7269a982edMao Li        struct light_state_t const* state)
205db007e94420fc2efb423fa037355ea7269a982edMao Li{
206db007e94420fc2efb423fa037355ea7269a982edMao Li    pthread_mutex_lock(&g_lock);
207db007e94420fc2efb423fa037355ea7269a982edMao Li    g_battery = *state;
208db007e94420fc2efb423fa037355ea7269a982edMao Li    handle_speaker_battery_locked(dev);
209db007e94420fc2efb423fa037355ea7269a982edMao Li    pthread_mutex_unlock(&g_lock);
210db007e94420fc2efb423fa037355ea7269a982edMao Li    return 0;
211db007e94420fc2efb423fa037355ea7269a982edMao Li}
212db007e94420fc2efb423fa037355ea7269a982edMao Li
213db007e94420fc2efb423fa037355ea7269a982edMao Listatic int
214ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonset_light_notifications(struct light_device_t* dev,
215ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        struct light_state_t const* state)
216ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
217ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&g_lock);
218ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    g_notification = *state;
219ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    handle_speaker_battery_locked(dev);
220ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&g_lock);
221ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return 0;
222ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
223ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
224ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int
225ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonset_light_attention(struct light_device_t* dev,
226ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        struct light_state_t const* state)
227ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
228ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&g_lock);
229ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (state->flashMode == LIGHT_FLASH_HARDWARE) {
230ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        g_attention = state->flashOnMS;
231ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else if (state->flashMode == LIGHT_FLASH_NONE) {
232ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        g_attention = 0;
233ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
234ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    handle_speaker_battery_locked(dev);
235ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&g_lock);
236ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return 0;
237ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
238ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
239a653efede03423aa840da24634f1ec6f20796f1eSimon Wilsonstatic int
240a653efede03423aa840da24634f1ec6f20796f1eSimon Wilsonset_light_buttons(struct light_device_t* dev,
241a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        struct light_state_t const* state)
242a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson{
243a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    int err = 0;
244a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    if(!dev) {
245a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        return -1;
246a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    }
247a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    pthread_mutex_lock(&g_lock);
248a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    err = write_int(BUTTON_FILE, state->color & 0xFF);
249a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    pthread_mutex_unlock(&g_lock);
250a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    return err;
251a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson}
252ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
253ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** Close the lights device */
254ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int
255ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonclose_lights(struct light_device_t *dev)
256ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
257ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (dev) {
258ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        free(dev);
259ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
260ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return 0;
261ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
262ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
263ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
264ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/******************************************************************************/
265ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
266ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/**
267ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * module methods
268ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
269ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
270ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** Open a new instance of a lights device using name */
271ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int open_lights(const struct hw_module_t* module, char const* name,
272ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        struct hw_device_t** device)
273ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
274ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int (*set_light)(struct light_device_t* dev,
275ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            struct light_state_t const* state);
276ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
277ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
278ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        set_light = set_light_backlight;
279db007e94420fc2efb423fa037355ea7269a982edMao Li    else if (0 == strcmp(LIGHT_ID_BATTERY, name))
280db007e94420fc2efb423fa037355ea7269a982edMao Li        set_light = set_light_battery;
281ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
282ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        set_light = set_light_notifications;
283a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
284a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson        set_light = set_light_buttons;
285ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
286ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        set_light = set_light_attention;
287ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    else
288ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
289ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
290ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_once(&g_init, init_globals);
291ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
292ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct light_device_t *dev = malloc(sizeof(struct light_device_t));
2939caaa41be6c1f3ceb52a2748c8f13c48b8aee848Manoj Kumar AVM
2949caaa41be6c1f3ceb52a2748c8f13c48b8aee848Manoj Kumar AVM    if(!dev)
2959caaa41be6c1f3ceb52a2748c8f13c48b8aee848Manoj Kumar AVM        return -ENOMEM;
2969caaa41be6c1f3ceb52a2748c8f13c48b8aee848Manoj Kumar AVM
297ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    memset(dev, 0, sizeof(*dev));
298ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
299ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dev->common.tag = HARDWARE_DEVICE_TAG;
300ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dev->common.version = 0;
301ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dev->common.module = (struct hw_module_t*)module;
302ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
303ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dev->set_light = set_light;
304ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
305ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *device = (struct hw_device_t*)dev;
306ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return 0;
307ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
308ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
309ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic struct hw_module_methods_t lights_module_methods = {
310ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    .open =  open_lights,
311ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
312ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
313ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/*
314ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * The lights Module
315ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
316ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstruct hw_module_t HAL_MODULE_INFO_SYM = {
317ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    .tag = HARDWARE_MODULE_TAG,
318ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    .version_major = 1,
319ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    .version_minor = 0,
320ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    .id = LIGHTS_HARDWARE_MODULE_ID,
321ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    .name = "lights Module",
322ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    .author = "Google, Inc.",
323ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    .methods = &lights_module_methods,
324ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
325