summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/android/dx50/button-dx50.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/android/dx50/button-dx50.c')
-rw-r--r--firmware/target/hosted/android/dx50/button-dx50.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/firmware/target/hosted/android/dx50/button-dx50.c b/firmware/target/hosted/android/dx50/button-dx50.c
new file mode 100644
index 0000000000..5ab58ce420
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/button-dx50.c
@@ -0,0 +1,314 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2010 Thomas Martitz
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#include <stdbool.h>
24#include "button.h"
25#include "buttonmap.h"
26#include "config.h"
27#include "kernel.h"
28#include "system.h"
29#include "touchscreen.h"
30#include "powermgmt.h"
31#include "backlight.h"
32
33#include <linux/input.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <stdint.h>
38#include <dirent.h>
39#include <fcntl.h>
40#include <sys/ioctl.h>
41#include <sys/inotify.h>
42#include <sys/limits.h>
43#include <sys/poll.h>
44#include <errno.h>
45
46
47static struct pollfd *ufds;
48static char **device_names;
49static int nfds;
50
51enum {
52 PRINT_DEVICE_ERRORS = 1U << 0,
53 PRINT_DEVICE = 1U << 1,
54 PRINT_DEVICE_NAME = 1U << 2,
55 PRINT_DEVICE_INFO = 1U << 3,
56 PRINT_VERSION = 1U << 4,
57 PRINT_POSSIBLE_EVENTS = 1U << 5,
58 PRINT_INPUT_PROPS = 1U << 6,
59 PRINT_HID_DESCRIPTOR = 1U << 7,
60
61 PRINT_ALL_INFO = (1U << 8) - 1,
62
63 PRINT_LABELS = 1U << 16,
64};
65
66static int last_y, last_x;
67static int last_btns;
68
69static enum {
70 STATE_UNKNOWN,
71 STATE_UP,
72 STATE_DOWN
73} last_touch_state = STATE_UNKNOWN;
74
75
76static int open_device(const char *device, int print_flags)
77{
78 int fd;
79 struct pollfd *new_ufds;
80 char **new_device_names;
81
82 fd = open(device, O_RDWR);
83 if(fd < 0) {
84 if(print_flags & PRINT_DEVICE_ERRORS)
85 fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
86 return -1;
87 }
88
89 new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1));
90 if(new_ufds == NULL) {
91 fprintf(stderr, "out of memory\n");
92 return -1;
93 }
94 ufds = new_ufds;
95 new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1));
96 if(new_device_names == NULL) {
97 fprintf(stderr, "out of memory\n");
98 return -1;
99 }
100 device_names = new_device_names;
101
102 ufds[nfds].fd = fd;
103 ufds[nfds].events = POLLIN;
104 device_names[nfds] = strdup(device);
105 nfds++;
106
107 return 0;
108}
109
110
111
112static int scan_dir(const char *dirname, int print_flags)
113{
114 char devname[PATH_MAX];
115 char *filename;
116 DIR *dir;
117 struct dirent *de;
118 dir = opendir(dirname);
119 if(dir == NULL)
120 return -1;
121 strcpy(devname, dirname);
122 filename = devname + strlen(devname);
123 *filename++ = '/';
124 while((de = readdir(dir))) {
125 if(de->d_name[0] == '.' &&
126 (de->d_name[1] == '\0' ||
127 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
128 continue;
129 strcpy(filename, de->d_name);
130 open_device(devname, print_flags);
131 }
132 closedir(dir);
133 return 0;
134}
135
136bool _hold;
137
138bool button_hold()
139{
140 FILE *f = fopen("/sys/class/axppower/holdkey", "r");
141 char x;
142 fscanf(f, "%c", &x);
143 fclose(f);
144 _hold = !(x&STATE_UNLOCKED);
145 return _hold;
146}
147
148
149void button_init_device(void)
150{
151 int res;
152 int print_flags = 0;
153 const char *device = NULL;
154 const char *device_path = "/dev/input";
155
156 nfds = 1;
157 ufds = calloc(1, sizeof(ufds[0]));
158 ufds[0].fd = inotify_init();
159 ufds[0].events = POLLIN;
160 if(device) {
161 res = open_device(device, print_flags);
162 if(res < 0) {
163 // return 1;
164 }
165 } else {
166 res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);
167 if(res < 0) {
168 fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno));
169 // return 1;
170 }
171 res = scan_dir(device_path, print_flags);
172 if(res < 0) {
173 fprintf(stderr, "scan dir failed for %s\n", device_path);
174 // return 1;
175 }
176 }
177
178 button_hold(); //store state
179
180 set_rockbox_ready();
181}
182
183void touchscreen_enable_device(bool en)
184{
185 (void)en; /* FIXME: do something smart */
186}
187
188
189int keycode_to_button(int keyboard_key)
190{
191 switch(keyboard_key){
192 case KEYCODE_PWR:
193 return BUTTON_POWER;
194
195 case KEYCODE_PWR_LONG:
196 return BUTTON_POWER_LONG;
197
198 case KEYCODE_VOLPLUS:
199 return BUTTON_VOL_UP;
200
201 case KEYCODE_VOLMINUS:
202 return BUTTON_VOL_DOWN;
203
204 case KEYCODE_PREV:
205 return BUTTON_LEFT;
206
207 case KEYCODE_NEXT:
208 return BUTTON_RIGHT;
209
210 case KEYCODE_PLAY:
211 return BUTTON_PLAY;
212
213 case KEYCODE_HOLD:
214 button_hold(); /* store state */
215 backlight_hold_changed(_hold);
216 return BUTTON_NONE;
217
218 default:
219 return BUTTON_NONE;
220 }
221}
222
223
224int button_read_device(int *data)
225{
226 int i;
227 int res;
228 struct input_event event;
229 int read_more;
230 unsigned button = 0;
231
232 if(last_btns & BUTTON_POWER_LONG)
233 {
234 return last_btns; /* simulate repeat */
235 }
236
237 do {
238 read_more = 0;
239 poll(ufds, nfds, 10);
240 for(i = 1; i < nfds; i++) {
241 if(ufds[i].revents & POLLIN) {
242 res = read(ufds[i].fd, &event, sizeof(event));
243 if(res < (int)sizeof(event)) {
244 fprintf(stderr, "could not get event\n");
245 }
246
247 switch(event.type)
248 {
249 case 1: /* HW-Button */
250 button = keycode_to_button(event.code);
251 if (_hold) /* we have to wait for keycode_to_button() first to maybe clear hold state */
252 break;
253 if (button == BUTTON_NONE)
254 {
255 last_btns = button;
256 break;
257 }
258/* workaround for a wrong feedback, only present with DX90 */
259#if defined(DX90)
260 if (button == BUTTON_RIGHT && (last_btns & BUTTON_LEFT == BUTTON_LEFT) && !event.value)
261 {
262 button = BUTTON_LEFT;
263 }
264#endif
265 if (event.value)
266 last_btns |= button;
267 else
268 last_btns &= (~button);
269
270 break;
271
272 case 3: /* Touchscreen */
273 if(_hold)
274 break;
275
276 switch(event.code)
277 {
278 case 53: /* x -> next will be y */
279 last_x = event.value;
280 read_more = 1;
281 break;
282 case 54: /* y */
283 last_y = event.value;
284 break;
285 case 57: /* press -> next will be x */
286 if(event.value==1)
287 {
288 last_touch_state = STATE_DOWN;
289 read_more = 1;
290 }
291 else
292 last_touch_state = STATE_UP;
293 break;
294 }
295 break;
296 }
297 }
298 }
299 } while(read_more);
300
301
302 /* Get grid button/coordinates based on the current touchscreen mode
303 *
304 * Caveat: the caller seemingly depends on *data always being filled with
305 * the last known touchscreen position, so always call
306 * touchscreen_to_pixels() */
307 int touch = touchscreen_to_pixels(last_x, last_y, data);
308
309 if (last_touch_state == STATE_DOWN)
310 return last_btns | touch;
311
312 return last_btns;
313}
314