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