blob: 06bb5f88faf64742702d82f395a276c59bf30aae [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
42char const*const PANEL_FILE
43 = "/sys/class/backlight/panel/brightness";
44
45char const*const BUTTON_POWER
46 = "/sys/class/sec/sec_touchkey/enable_disable";
47
48char const*const BUTTON_FILE
49 = "/sys/class/sec/sec_touchkey/brightness";
50
51void init_globals(void)
52{
53 // init the mutex
54 pthread_mutex_init(&g_lock, NULL);
55}
56
57void
58load_settings()
59{
60 FILE* fp = fopen("/data/.disable_touchlight", "r");
61 if (!fp) {
62 g_enable_touchlight = 1;
63 } else {
64 g_enable_touchlight = (int)(fgetc(fp));
65 if (g_enable_touchlight == '1')
66 g_enable_touchlight = 1;
67 else
68 g_enable_touchlight = 0;
69
70 fclose(fp);
71 }
72}
73
74static int
75write_int(char const* path, int value)
76{
77 int fd;
78 static int already_warned = 0;
79
80 fd = open(path, O_RDWR);
81 if (fd >= 0) {
82 char buffer[20];
83 int bytes = sprintf(buffer, "%d\n", value);
84 int amt = write(fd, buffer, bytes);
85 close(fd);
86 return amt == -1 ? -errno : 0;
87 } else {
88 if (already_warned == 0) {
89 LOGE("write_int failed to open %s\n", path);
90 already_warned = 1;
91 }
92 return -errno;
93 }
94}
95
96static int
97is_lit(struct light_state_t const* state)
98{
99 return state->color & 0x00ffffff;
100}
101
102static int
103rgb_to_brightness(struct light_state_t const* state)
104{
105 int color = state->color & 0x00ffffff;
106 return ((77*((color>>16)&0x00ff))
107 + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
108}
109
110static int
111set_light_backlight(struct light_device_t* dev,
112 struct light_state_t const* state)
113{
114 load_settings();
115
116 int err = 0;
117 int brightness = rgb_to_brightness(state);
118
119 pthread_mutex_lock(&g_lock);
120 err = write_int(PANEL_FILE, brightness);
121
122 if (g_enable_touchlight == -1 || g_enable_touchlight > 0)
123 err = write_int(BUTTON_FILE, brightness > 0 ? 1 : 0);
124
125 pthread_mutex_unlock(&g_lock);
126
127 return err;
128}
129
130static int
131set_light_keyboard(struct light_device_t* dev,
132 struct light_state_t const* state)
133{
134 return 0;
135}
136
137static int
138set_light_buttons(struct light_device_t* dev,
139 struct light_state_t const* state)
140{
141 int err = 0;
142 int on = is_lit(state);
143
144 pthread_mutex_lock(&g_lock);
145 LOGD("set_light_button on=%d\n", on ? 1 : 0);
146 err = write_int(BUTTON_FILE, on ? 1:0);
147 pthread_mutex_unlock(&g_lock);
148
149 return err;
150}
151
152static int
153set_light_battery(struct light_device_t* dev,
154 struct light_state_t const* state)
155{
156 return 0;
157}
158
159static int
160set_light_notification(struct light_device_t* dev,
161 struct light_state_t const* state)
162{
163 return 0;
164}
165
166static int
167set_light_attention(struct light_device_t* dev,
168 struct light_state_t const* state)
169{
170 return 0;
171}
172
173static int
174close_lights(struct light_device_t *dev)
175{
176 if (dev) {
177 free(dev);
178 }
179 return 0;
180}
181
182
183/******************************************************************************/
184static int open_lights(const struct hw_module_t* module, char const* name,
185 struct hw_device_t** device)
186{
187 int (*set_light)(struct light_device_t* dev,
188 struct light_state_t const* state);
189
190 if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
191 set_light = set_light_backlight;
192 }
193 else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {
194 set_light = set_light_keyboard;
195 }
196 else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
197 set_light = set_light_buttons;
198 }
199 else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {
200 set_light = set_light_battery;
201 }
202 else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
203 set_light = set_light_notification;
204 }
205 else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {
206 set_light = set_light_attention;
207 }
208 else {
209 return -EINVAL;
210 }
211
212 pthread_once(&g_init, init_globals);
213
214 struct light_device_t *dev = malloc(sizeof(struct light_device_t));
215 memset(dev, 0, sizeof(*dev));
216
217 dev->common.tag = HARDWARE_DEVICE_TAG;
218 dev->common.version = 0;
219 dev->common.module = (struct hw_module_t*)module;
220 dev->common.close = (int (*)(struct hw_device_t*))close_lights;
221 dev->set_light = set_light;
222
223 *device = (struct hw_device_t*)dev;
224 return 0;
225}
226
227
228static struct hw_module_methods_t lights_module_methods = {
229 .open = open_lights,
230};
231
232const struct hw_module_t HAL_MODULE_INFO_SYM = {
233 .tag = HARDWARE_MODULE_TAG,
234 .version_major = 1,
235 .version_minor = 0,
236 .id = LIGHTS_HARDWARE_MODULE_ID,
237 .name = "Samsung Exynos4210 Lights Module",
238 .author = "The CyanogenMod Project",
239 .methods = &lights_module_methods,
240};