initial f200 touchscreen support
[ginge.git] / loader / host.c
1 /*
2  * GINGE - GINGE Is Not Gp2x Emulator
3  * (C) notaz, 2010-2011,2015
4  *
5  * This work is licensed under the MAME license, see COPYING file for details.
6  */
7 #define _GNU_SOURCE 1 // for plat.c
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <errno.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <linux/input.h>
17
18 #include "../common/libpicofe/input.h"
19 #include "../common/libpicofe/linux/in_evdev.h"
20 #include "../common/host_fb.h"
21
22 #include "header.h"
23 #include "realfuncs.h"
24
25 // must be affected by realfuncs.h
26 #include "../common/libpicofe/input.c"
27 #include "../common/libpicofe/linux/plat.c"
28 #include "../common/libpicofe/linux/in_evdev.c"
29
30 #ifdef PND
31 #include "host_pnd.c"
32 #elif defined(WIZ)
33 #include "host_wiz.c"
34 #endif
35
36 char **g_argv;
37 static int ts_fd = -1;
38
39 /* touscreen. Could just use tsblib, but it's LGPL... */
40 static int tsc[7];
41
42 static int host_ts_init(void)
43 {
44   static const char name_def[] = "/dev/input/touchscreen0";
45   const char *name;
46   FILE *f;
47   int ret;
48
49   f = fopen("/etc/pointercal", "r");
50   if (f == NULL) {
51     perror("fopen pointercal");
52     return -1;
53   }
54   ret = fscanf(f, "%d %d %d %d %d %d %d", &tsc[0], &tsc[1],
55                &tsc[2], &tsc[3], &tsc[4], &tsc[5], &tsc[6]);
56   fclose(f);
57   if (ret != 7) {
58     fprintf(stderr, "could not parse pointercal\n");
59     return -1;
60   }
61
62   name = getenv("TSLIB_TSDEVICE");
63   if (name == NULL)
64     name = name_def;
65   ts_fd = open(name, O_RDONLY | O_NONBLOCK);
66   if (ts_fd == -1) {
67     fprintf(stderr, "open %s", name);
68     perror("");
69     return -1;
70   }
71   return 0;
72 }
73
74 // returns ranges 0-1023
75 int host_read_ts(int *pressure, int *x1024, int *y1024)
76 {
77   static int raw_x, raw_y, raw_p;
78   struct input_event ev;
79   ssize_t ret;
80
81   if (ts_fd == -1)
82     return -1;
83
84   for (;;) {
85     errno = 0;
86     ret = read(ts_fd, &ev, sizeof(ev));
87     if (ret != sizeof(ev)) {
88       if (errno == EAGAIN)
89         break;
90       perror("ts read");
91       return -1;
92     }
93     if (ev.type == EV_ABS) {
94       switch (ev.code) {
95       case ABS_X: raw_x = ev.value; break;
96       case ABS_Y: raw_y = ev.value; break;
97       case ABS_PRESSURE: raw_p = ev.value; break;
98       }
99     }
100   }
101
102   *pressure = raw_p;
103   *x1024 = (tsc[0] * raw_x + tsc[1] * raw_y + tsc[2]) / tsc[6];
104   *y1024 = (tsc[3] * raw_x + tsc[4] * raw_y + tsc[5]) / tsc[6];
105
106   host_video_normalize_ts(x1024, y1024);
107
108   return 0;
109 }
110
111 int host_init(void)
112 {
113   in_init();
114   host_init_input();
115   in_probe();
116   host_ts_init();
117
118   return 0;
119 }
120
121 int host_read_btns(void)
122 {
123   int actions[IN_BINDTYPE_COUNT] = { 0, };
124
125   in_update(actions);
126   host_actions(actions);
127
128   return actions[IN_BINDTYPE_PLAYER12];
129 }
130
131 void host_forced_exit(int status)
132 {
133   // exit() might not be enough because loader and app data is out of sync,
134   // and other threads (which are really processes on this old glibc used)
135   // might not exit properly.
136   char cmd[64];
137
138   printf("forced exit...\n");
139
140   if (g_argv != NULL) {
141     snprintf(cmd, sizeof(cmd), "killall %s", g_argv[0]);
142     system(cmd);
143     usleep(300000);
144     snprintf(cmd, sizeof(cmd), "killall -9 %s", g_argv[0]);
145     system(cmd);
146   }
147   exit(status);
148 }
149
150 // vim:shiftwidth=2:expandtab