change paths
[pandora-misc.git] / op_test_inputs.c
1 /*
2  * Copyright (c) 2010, GraÅžvydas Ignotas
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the organization nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 #define _GNU_SOURCE
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <sys/mman.h>
34 #include <unistd.h>
35 #include <linux/input.h>
36 #include <tslib.h>
37
38 #include "font.c"
39
40 typedef struct {
41         int x, y;
42         int code;
43         int active;
44         const char *name;
45 } key_item;
46
47 static key_item key_items[] =
48 {
49         {  66,  26, KEY_1, 0, "1" },
50         { 133,  26, KEY_2, 0, "2" },
51         { 200,  26, KEY_3, 0, "3" },
52         { 266,  26, KEY_4, 0, "4" },
53         { 333,  26, KEY_5, 0, "5" },
54         { 400,  26, KEY_6, 0, "6" },
55         { 466,  26, KEY_7, 0, "7" },
56         { 533,  26, KEY_8, 0, "8" },
57         { 600,  26, KEY_9, 0, "9" },
58         { 666,  26, KEY_0, 0, "0" },
59         { 733,  26, KEY_BACKSPACE, 0, "DEL" },
60         //
61         {  10,  55, KEY_RIGHTSHIFT,0, "L" },
62         {  10,  75, KEY_KPPLUS,    0, "L2" },
63         { 758,  55, KEY_RIGHTCTRL, 0, "R" },
64         { 758,  75, KEY_KPMINUS,   0, "R2" },
65         {  10, 220, KEY_POWER,     0, "POWER" },
66         {  10, 240, KEY_COFFEE,    0, "HOLD" },
67         //
68         { 130,  94, KEY_UP,     0, "U" },
69         {  80, 163, KEY_LEFT,   0, "L" },
70         { 180, 163, KEY_RIGHT,  0, "R" },
71         { 130, 232, KEY_DOWN,   0, "D" },
72         { 376,  94, KEY_LEFTALT,0, "ALT" },
73         { 368, 163, KEY_LEFTCTRL,0,"CTRL" },
74         { 368, 232, KEY_MENU,   0, "MENU" },
75         { 700,  94, KEY_PAGEUP, 0, "1" },
76         { 650, 163, KEY_HOME,   0, "4" },
77         { 750, 163, KEY_END,    0, "2" },
78         { 700, 232, KEY_PAGEDOWN,0, "3" },
79         //
80         {  92, 300, KEY_Q,      0, "Q" },
81         { 158, 300, KEY_W,      0, "W" },
82         { 225, 300, KEY_E,      0, "E" },
83         { 292, 300, KEY_R,      0, "R" },
84         { 358, 300, KEY_T,      0, "T" },
85         { 425, 300, KEY_Y,      0, "Y" },
86         { 492, 300, KEY_U,      0, "U" },
87         { 558, 300, KEY_I,      0, "I" },
88         { 625, 300, KEY_O,      0, "O" },
89         { 692, 300, KEY_P,      0, "P" },
90         //
91         {  30, 369, KEY_LEFTSHIFT, 0, "SHIFT" },
92         { 133, 369, KEY_A,      0, "A" },
93         { 200, 369, KEY_S,      0, "S" },
94         { 266, 369, KEY_D,      0, "D" },
95         { 333, 369, KEY_F,      0, "F" },
96         { 400, 369, KEY_G,      0, "G" },
97         { 466, 369, KEY_H,      0, "H" },
98         { 533, 369, KEY_J,      0, "J" },
99         { 600, 369, KEY_K,      0, "K" },
100         { 666, 369, KEY_L,      0, "L" },
101         { 710, 369, KEY_ENTER,  0, "ENTER" },
102         //
103         {  25, 437, KEY_COMMA,  0, "," },
104         {  92, 437, KEY_DOT,    0, "." },
105         { 158, 437, KEY_Z,      0, "Z" },
106         { 225, 437, KEY_X,      0, "X" },
107         { 292, 437, KEY_C,      0, "C" },
108         { 358, 437, KEY_V,      0, "V" },
109         { 425, 437, KEY_B,      0, "B" },
110         { 492, 437, KEY_N,      0, "N" },
111         { 558, 437, KEY_M,      0, "M" },
112         { 625, 437, KEY_SPACE,  0, "SPACE" },
113         { 758, 437, KEY_FN,     0, "Fn" },
114 };
115
116 #define KI_COUNT (sizeof(key_items) / sizeof(key_items[0]))
117
118 static int ts_old_x = 0, ts_old_y = 0;
119 static int lid_closed = 0;
120
121 static void draw_ts_cross(unsigned short *fb, unsigned short col, int x, int y)
122 {
123         int i, x1, y1;
124
125         if (y >= 0 && y < 480)
126                 for (x1 = x - 5, i = 0; i < 11; i++, x1++)
127                         if (x1 >= 0 && x1 < 800) fb[y * 800 + x1] = col;
128         
129         if (x >= 0 && x < 800)
130                 for (y1 = y - 5, i = 0; i < 11; i++, y1++)
131                         if (y1 >= 0 && y1 < 480) fb[y1 * 800 + x] = col;
132         
133         ts_old_x = x;
134         ts_old_y = y;
135 }
136
137 static void text_out16(unsigned short *fb, int x, int y, unsigned short col, const char *text)
138 {
139         int i,l;
140
141         fb = fb + x + y*800;
142
143         for (i = 0; i < strlen(text); i++)
144         {
145                 for (l=0;l<8;l++)
146                 {
147                         #define pix(fdmask,add) \
148                                 if (fontdata8x8[((text[i])*8)+l]&fdmask) \
149                                         fb[l*2*800+add]=fb[l*2*800+add+1]=fb[l*2*800+800+add]=fb[l*2*800+800+add+1]=col
150                         pix(0x80,  0);
151                         pix(0x40,  2);
152                         pix(0x20,  4);
153                         pix(0x10,  6);
154                         pix(0x08,  8);
155                         pix(0x04, 10);
156                         pix(0x02, 12);
157                         pix(0x01, 14);
158                         #undef pix
159                 }
160                 fb += 8*2;
161         }
162 }
163
164 static void text_out16_small(unsigned short *fb, int x, int y, unsigned short col, const char *text)
165 {
166         int i,l;
167
168         fb = fb + x + y*800;
169
170         for (i = 0; i < strlen(text); i++)
171         {
172                 for (l=0;l<8;l++)
173                 {
174                         #define pix(fdmask,add) \
175                                 if (fontdata8x8[((text[i])*8)+l]&fdmask) \
176                                         fb[l*800+add]=fb[l*800+800+add]=col
177                         pix(0x80,  0);
178                         pix(0x40,  1);
179                         pix(0x20,  2);
180                         pix(0x10,  3);
181                         pix(0x08,  4);
182                         pix(0x04,  5);
183                         pix(0x02,  6);
184                         pix(0x01,  7);
185                         #undef pix
186                 }
187                 fb += 8;
188         }
189 }
190
191 static void redraw_nubs(unsigned short *fb, int x1, int y1, int x2, int y2)
192 {
193         char buff[32];
194         int y;
195
196         fb += 90*800;
197
198         // clear areas
199         for (y = 0; y < 140; y++) {
200                 memset(fb + 800*y + 200, 0, (64+8)*2*2);
201                 memset(fb + 800*y + 450, 0, (64+8)*2*2);
202         }
203
204         text_out16(fb + 200, 32*2 + x1/8, 32*2 + y1/8, 0x001f, "@");
205         text_out16(fb + 450, 32*2 + x2/8, 32*2 + y2/8, 0x001f, "@");
206
207         snprintf(buff, sizeof(buff), "%2i, %2i", x1/8, y1/8);
208         text_out16_small(fb, 245, 130, 0x7bef, buff);
209         snprintf(buff, sizeof(buff), "%2i, %2i", x2/8, y2/8);
210         text_out16_small(fb, 495, 130, 0x7bef, buff);
211 }
212
213 static void redraw_keys_lid(unsigned short *fb)
214 {
215         const key_item *key;
216         int i;
217
218         for (i = 0; i < KI_COUNT; i++)
219         {
220                 key = &key_items[i];
221
222                 text_out16(fb, key->x, key->y,
223                         key->active ? 0x07e0 : 0x7bef, key->name);
224         }
225
226         text_out16(fb, 10, 260, lid_closed ? 0x07e0 : 0x7bef, "LID");
227 }
228
229 static void setkey(int code, int val)
230 {
231         key_item *key = NULL;
232         int i;
233
234         for (i = 0; i < KI_COUNT; i++)
235         {
236                 if (key_items[i].code == code)
237                 {
238                         key = &key_items[i];
239                         break;
240                 }
241         }
242
243         if (key == NULL)
244         {
245                 printf("%c unexpected key? (%i)\n", val ? '+' : '-', code);
246         }
247         else
248         {
249                 key->active = val;
250                 printf("%c %s\n", val ? '+' : '-', key->name);
251         }
252 }
253
254 enum {
255         DEV_PWRBTN,
256         DEV_KEYPAD,
257         DEV_BUTTONS,
258         DEV_TS,
259         DEV_LNUB,
260         DEV_RNUB,
261         DEVS_TOTAL
262 };
263
264 int main(int argc, char *argv[])
265 {
266         unsigned short *screen;
267         int fbdev, ifd[DEVS_TOTAL] = { -1, -1, -1, -1, -1, -1 };
268         int i, id, imaxfd = 0, ts_x = 0, ts_y = 0;
269         int nubx[2] = {0,0}, nuby[2] = {0,0};
270         int pressed_l = 0, pressed_r = 0;
271         struct tsdev *ts = NULL;
272
273         fbdev = open("/dev/fb0", O_RDWR);
274         if (fbdev == -1)
275         {
276                 perror("open(\"/dev/fb0\") failed");
277                 return 1;
278         }
279
280         screen = mmap(0, 800*480*2, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev, 0);
281         if (screen == MAP_FAILED)
282         {
283                 perror("mmap(fbptr) failed");
284                 return 1;
285         }
286
287         memset(screen, 0, 800*480*2);
288
289         for (id = 0; ; id++)
290         {
291                 char fname[64];
292                 char name[256] = { 0, };
293                 int fd;
294
295                 snprintf(fname, sizeof(fname), "/dev/input/event%i", id);
296                 fd = open(fname, O_RDONLY);
297                 if (fd == -1)
298                 {
299                         break;
300                 }
301
302                 ioctl(fd, EVIOCGNAME(sizeof(name)), name);
303
304                 if (strcasestr(name, "pwrbutton") != NULL)
305                 {
306                         ifd[DEV_PWRBTN] = fd;
307                 }
308                 else if (strcasestr(name, "keypad") != NULL)
309                 {
310                         ifd[DEV_KEYPAD] = fd;
311                 }
312                 else if (strcmp(name, "gpio-keys") == 0)
313                 {
314                         ifd[DEV_BUTTONS] = fd;
315                 }
316                 else if (strcasestr(name, "touchscreen") != NULL)
317                 {
318                         close(fd);
319                         ts = ts_open(fname, 0);
320                         if (ts == NULL)
321                         {
322                                 perror("ts_open");
323                                 goto end;
324                         }
325                         if (ts_config(ts))
326                         {
327                                 perror("ts_config");
328                                 goto end;
329                         }
330                         ifd[DEV_TS] = ts_fd(ts);
331                 }
332                 else if (strcmp(name, "vsense66") == 0)
333                 {
334                         ifd[DEV_LNUB] = fd;
335                 }
336                 else if (strcmp(name, "vsense67") == 0)
337                 {
338                         ifd[DEV_RNUB] = fd;
339                 }
340                 else
341                 {
342                         printf("skipping \"%s\"\n", name);
343                         close(fd);
344                         continue;
345                 }
346                 if (imaxfd < fd) imaxfd = fd;
347         }
348
349         if (ifd[DEV_PWRBTN]  == -1) printf("Warning: couldn't find pwrbutton device\n");
350         if (ifd[DEV_KEYPAD]  == -1) printf("Warning: couldn't find keypad device\n");
351         if (ifd[DEV_BUTTONS] == -1) printf("Warning: couldn't find button device\n");
352         if (ifd[DEV_TS]      == -1) printf("Warning: couldn't find touchscreen device\n");
353         if (ifd[DEV_LNUB]    == -1) printf("Warning: couldn't find nub1 device\n");
354         if (ifd[DEV_RNUB]    == -1) printf("Warning: couldn't find nub2 device\n");
355
356         text_out16_small(screen, 320, 3, 0x7bef, "Press L+R to exit");
357
358         while (!pressed_l || !pressed_r)
359         {
360                 struct input_event ev[64];
361                 int fd = -1, rd, which, ret;
362                 fd_set fdset;
363
364                 draw_ts_cross(screen, 0x0000, ts_old_x, ts_old_y);
365                 redraw_keys_lid(screen);
366                 redraw_nubs(screen, nubx[0], nuby[0], nubx[1], nuby[1]);
367                 draw_ts_cross(screen, 0xf800, ts_x, ts_y);
368
369                 FD_ZERO(&fdset);
370                 for (i = 0; i < DEVS_TOTAL; i++)
371                         if (ifd[i] != -1)
372                                 FD_SET(ifd[i], &fdset);
373
374                 ret = select(imaxfd + 1, &fdset, NULL, NULL, NULL);
375                 if (ret == -1)
376                 {
377                         perror("select");
378                         break;
379                 }
380
381                 for (i = 0; i < DEVS_TOTAL; i++)
382                         if (ifd[i] != -1 && FD_ISSET(ifd[i], &fdset))
383                                 fd = ifd[i];
384
385                 /* touch event? */
386                 if (fd == ifd[DEV_TS])
387                 {
388                         struct ts_sample samp;
389
390                         ret = ts_read(ts, &samp, 1);
391                         if (ret < 0) {
392                                 perror("ts_read");
393                                 break;
394                         }
395
396                         if (ret != 1)
397                                 continue;
398
399                         ts_x = samp.x; ts_y = samp.y;
400                         //printf("ts: %6d %6d %6d\n", samp.x, samp.y, samp.pressure);
401                         continue;
402                 }
403
404                 /* buttons or keypad */
405                 rd = read(fd, ev, sizeof(ev));
406                 if (rd < (int) sizeof(ev[0])) {
407                         perror("\nevtest: error reading");
408                         break;
409                 }
410
411                 for (i = 0; i < rd / sizeof(ev[0]); i++)
412                 {
413                         switch (ev[i].type) {
414                         case EV_SYN:
415                                 break;
416                         case EV_KEY:
417                                 setkey(ev[i].code, ev[i].value);
418                                 if (ev[i].code == KEY_RIGHTSHIFT)
419                                         pressed_l = !!ev[i].value;
420                                 if (ev[i].code == KEY_RIGHTCTRL)
421                                         pressed_r = !!ev[i].value;
422                                 break;
423                         case EV_ABS:
424                                 which = (fd == ifd[DEV_LNUB]) ? 0 : 1;
425                                 if (ev[i].code == ABS_X)
426                                         nubx[which] = ev[i].value;
427                                 else if (ev[i].code == ABS_Y)
428                                         nuby[which] = ev[i].value;
429                                 else
430                                         printf("unexpected EV_ABS code: %i\n", ev[i].code);
431                                 break;
432                         case EV_SW:
433                                 if (ev[i].code == SW_LID)
434                                         lid_closed = ev[i].value;
435                                 else
436                                         printf("unexpected EV_SW code: %i\n", ev[i].code);
437                                 break;
438                         case EV_MSC:
439                                 if (ev[i].code == MSC_SCAN)
440                                         break;
441                                 /* fallthrough */
442                         default:
443                                 printf("unexpected event: type %i, code %d\n", ev[i].type, ev[i].code);
444                                 break;
445                         }
446                 }
447         }
448
449
450 end:
451         if (ts != NULL)
452                 ts_close(ts);
453         for (i = 0; i < DEVS_TOTAL; i++)
454                 if (i != DEV_TS && ifd[i] != -1)
455                         close(ifd[i]);
456         munmap(screen, 800*480*2);
457         close(fbdev);
458         return 0;
459 }
460