blob: de706726de6e47eaa559697377f8321f2882a9e8 [file] [log] [blame]
codeworkxf1be2fe2012-03-24 17:38:29 +01001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 * Copyright (C) 2011 The CyanogenMod Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19#define LOG_TAG "lights"
20#define LOG_NDEBUG 0
21
22#include <cutils/log.h>
23
24#include <stdint.h>
25#include <string.h>
26#include <unistd.h>
27#include <errno.h>
28#include <fcntl.h>
29#include <pthread.h>
30
31#include <sys/ioctl.h>
32#include <sys/types.h>
33
34#include <hardware/lights.h>
35
36/******************************************************************************/
37
38static pthread_once_t g_init = PTHREAD_ONCE_INIT;
39static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
40static int g_enable_touchlight = -1;
41
R. Andrew Ohanaec03b1b2012-04-01 00:30:55 -070042#ifdef EXYNOS4210_TABLET
43char const*const PANEL_FILE
44 = "/sys/class/backlight/backlight/brightness";
45#else
codeworkxf1be2fe2012-03-24 17:38:29 +010046char const*const PANEL_FILE
47 = "/sys/class/backlight/panel/brightness";
48
49char const*const BUTTON_POWER
50 = "/sys/class/sec/sec_touchkey/enable_disable";
51
52char const*const BUTTON_FILE
53 = "/sys/class/sec/sec_touchkey/brightness";
R. Andrew Ohanaec03b1b2012-04-01 00:30:55 -070054#endif
codeworkxf1be2fe2012-03-24 17:38:29 +010055
56void init_globals(void)
57{
58 // init the mutex
59 pthread_mutex_init(&g_lock, NULL);
60}
61
62void
63load_settings()
64{
65 FILE* fp = fopen("/data/.disable_touchlight", "r");
66 if (!fp) {
67 g_enable_touchlight = 1;
68 } else {
69 g_enable_touchlight = (int)(fgetc(fp));
70 if (g_enable_touchlight == '1')
71 g_enable_touchlight = 1;
72 else
73 g_enable_touchlight = 0;
74
75 fclose(fp);
76 }
77}
78
79static int
80write_int(char const* path, int value)
81{
82 int fd;
83 static int already_warned = 0;
84
85 fd = open(path, O_RDWR);
86 if (fd >= 0) {
87 char buffer[20];
88 int bytes = sprintf(buffer, "%d\n", value);
89 int amt = write(fd, buffer, bytes);
90 close(fd);
91 return amt == -1 ? -errno : 0;
92 } else {
93 if (already_warned == 0) {
94 LOGE("write_int failed to open %s\n", path);
95 already_warned = 1;
96 }
97 return -errno;
98 }
99}
100
101static int
102is_lit(struct light_state_t const* state)
103{
104 return state->color & 0x00ffffff;
105}
106
107static int
108rgb_to_brightness(struct light_state_t const* state)
109{
110 int color = state->color & 0x00ffffff;
111 return ((77*((color>>16)&0x00ff))
112 + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
113}
114
115static int
116set_light_backlight(struct light_device_t* dev,
117 struct light_state_t const* state)
118{
119 load_settings();
120
121 int err = 0;
122 int brightness = rgb_to_brightness(state);
123
124 pthread_mutex_lock(&g_lock);
125 err = write_int(PANEL_FILE, brightness);
126
R. Andrew Ohanaec03b1b2012-04-01 00:30:55 -0700127#ifndef EXYNOS4210_TABLET
codeworkxf1be2fe2012-03-24 17:38:29 +0100128 if (g_enable_touchlight == -1 || g_enable_touchlight > 0)
129 err = write_int(BUTTON_FILE, brightness > 0 ? 1 : 0);
R. Andrew Ohanaec03b1b2012-04-01 00:30:55 -0700130#endif
codeworkxf1be2fe2012-03-24 17:38:29 +0100131
132 pthread_mutex_unlock(&g_lock);
133
134 return err;
135}
136
137static int
138set_light_keyboard(struct light_device_t* dev,
139 struct light_state_t const* state)
140{
141 return 0;
142}
143
144static int
145set_light_buttons(struct light_device_t* dev,
146 struct light_state_t const* state)
147{
R. Andrew Ohanaec03b1b2012-04-01 00:30:55 -0700148#ifdef EXYNOS4210_TABLET
149 return 0;
150#else
codeworkxf1be2fe2012-03-24 17:38:29 +0100151 int err = 0;
152 int on = is_lit(state);
153
154 pthread_mutex_lock(&g_lock);
155 LOGD("set_light_button on=%d\n", on ? 1 : 0);
156 err = write_int(BUTTON_FILE, on ? 1:0);
157 pthread_mutex_unlock(&g_lock);
158
159 return err;
R. Andrew Ohanaec03b1b2012-04-01 00:30:55 -0700160#endif
codeworkxf1be2fe2012-03-24 17:38:29 +0100161}
162
163static int
164set_light_battery(struct light_device_t* dev,
165 struct light_state_t const* state)
166{
167 return 0;
168}
169
170static int
171set_light_notification(struct light_device_t* dev,
172 struct light_state_t const* state)
173{
174 return 0;
175}
176
177static int
178set_light_attention(struct light_device_t* dev,
179 struct light_state_t const* state)
180{
181 return 0;
182}
183
184static int
185close_lights(struct light_device_t *dev)
186{
187 if (dev) {
188 free(dev);
189 }
190 return 0;
191}
192
193
194/******************************************************************************/
195static int open_lights(const struct hw_module_t* module, char const* name,
196 struct hw_device_t** device)
197{
198 int (*set_light)(struct light_device_t* dev,
199 struct light_state_t const* state);
200
201 if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
202 set_light = set_light_backlight;
203 }
204 else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {
205 set_light = set_light_keyboard;
206 }
207 else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
208 set_light = set_light_buttons;
209 }
210 else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {
211 set_light = set_light_battery;
212 }
213 else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
214 set_light = set_light_notification;
215 }
216 else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {
217 set_light = set_light_attention;
218 }
219 else {
220 return -EINVAL;
221 }
222
223 pthread_once(&g_init, init_globals);
224
225 struct light_device_t *dev = malloc(sizeof(struct light_device_t));
226 memset(dev, 0, sizeof(*dev));
227
228 dev->common.tag = HARDWARE_DEVICE_TAG;
229 dev->common.version = 0;
230 dev->common.module = (struct hw_module_t*)module;
231 dev->common.close = (int (*)(struct hw_device_t*))close_lights;
232 dev->set_light = set_light;
233
234 *device = (struct hw_device_t*)dev;
235 return 0;
236}
237
238
239static struct hw_module_methods_t lights_module_methods = {
240 .open = open_lights,
241};
242
243const struct hw_module_t HAL_MODULE_INFO_SYM = {
244 .tag = HARDWARE_MODULE_TAG,
245 .version_major = 1,
246 .version_minor = 0,
247 .id = LIGHTS_HARDWARE_MODULE_ID,
248 .name = "Samsung Exynos4210 Lights Module",
249 .author = "The CyanogenMod Project",
250 .methods = &lights_module_methods,
251};