standalone: update gun support
[pcsx_rearmed.git] / frontend / pl_gun_ts.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2011
3  *
4  * This work is licensed under the terms of any of these licenses
5  * (at your option):
6  *  - GNU GPL, version 2 or later.
7  *  - GNU LGPL, version 2.1 or later.
8  * See the COPYING file in the top-level directory.
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <dlfcn.h>
14 #include <tslib.h>
15 #include "plugin_lib.h"
16 #include "pl_gun_ts.h"
17 #include "menu.h"
18
19 #ifdef MAEMO
20 #define N900_TSMAX_X 4096
21 #define N900_TSOFFSET_X 0
22 #define N900_TSMAX_Y 4096
23 #define N900_TSOFFSET_Y 0
24 #endif
25
26 static int gun_x, gun_y, gun_in;
27 static int ts_multiplier_x, ts_multiplier_y, ts_offs_x, ts_offs_y;
28 static int (*pts_read)(struct tsdev *dev, struct ts_sample *sample, int nr);
29 static int (*pts_fd)(struct tsdev *dev);
30
31 #define limit(v, min, max) \
32         if (v < min) v = min; \
33         else if (v > max) v = max
34
35 int pl_gun_ts_update_raw(struct tsdev *ts, int *x, int *y, int *p)
36 {
37         struct ts_sample sample;
38         int sx = 0, sy = 0, sp = 0, updated = 0;
39
40         if (ts != NULL) {
41                 while (pts_read(ts, &sample, 1) > 0) {
42                         sx = sample.x;
43 #ifdef MAEMO
44                         sy = N900_TSMAX_Y - sample.y;
45 #else
46                         sy = sample.y;
47 #endif
48                         sp = sample.pressure;
49                         updated = 1;
50                 }
51
52                 if (updated) {
53                         gun_x = (sx - ts_offs_x) * ts_multiplier_x >> 10;
54                         gun_y = (sy - ts_offs_y) * ts_multiplier_y >> 10;
55                         limit(gun_x, 0, 1023);
56                         limit(gun_y, 0, 1023);
57                         if (sp)
58                                 gun_in |= 1;
59                         else
60                                 gun_in &= ~1;
61                 }
62         }
63
64         if (updated) {
65                 if (x) *x = sx;
66                 if (y) *y = sy;
67                 if (p) *p = sp;
68                 return 1;
69         }
70
71         return 0;
72 }
73
74 /* returns x, y in range 0..1023 (normalized to visible layer) */
75 void pl_gun_ts_update(struct tsdev *ts, int *x, int *y, int *in)
76 {
77         pl_gun_ts_update_raw(ts, NULL, NULL, NULL);
78
79         *x = gun_x;
80         *y = gun_y;
81         *in = gun_in;
82 }
83
84 void pl_set_gun_rect(int x, int y, int w, int h)
85 {
86         ts_offs_x = x;
87         ts_offs_y = y;
88         ts_multiplier_x = (1<<20) / w;
89         ts_multiplier_y = (1<<20) / h;
90 }
91
92 int pl_gun_ts_get_fd(struct tsdev *ts)
93 {
94         if (ts != NULL && pts_fd != NULL)
95                 return pts_fd(ts);
96
97         return -1;
98 }
99
100 struct tsdev *pl_gun_ts_init(void)
101 {
102         struct tsdev *(*pts_open)(const char *dev_name, int nonblock) = NULL;
103         int (*pts_config)(struct tsdev *) = NULL;
104         int (*pts_close)(struct tsdev *) = NULL;
105         const char *tsdevname;
106         struct tsdev *ts;
107         void *ltsh;
108
109 #ifdef MAEMO
110         tsdevname = "/dev/input/ts";
111 #else
112         tsdevname = getenv("TSLIB_TSDEVICE");
113         if (tsdevname == NULL)
114                 tsdevname = "/dev/input/touchscreen0";
115 #endif
116
117         // avoid hard dep on tslib
118         ltsh = dlopen("/usr/lib/libts-1.0.so.0", RTLD_NOW|RTLD_GLOBAL);
119         if (ltsh == NULL)
120                 ltsh = dlopen("/usr/lib/libts-0.0.so.0", RTLD_NOW|RTLD_GLOBAL);
121         if (ltsh == NULL)
122                 ltsh = dlopen("/lib/libts-0.0.so.0", RTLD_NOW|RTLD_GLOBAL);
123         if (ltsh == NULL) {
124                 fprintf(stderr, "%s\n", dlerror());
125                 goto fail;
126         }
127
128         pts_open = dlsym(ltsh, "ts_open");
129         pts_config = dlsym(ltsh, "ts_config");
130         pts_read = dlsym(ltsh, "ts_read");
131         pts_fd = dlsym(ltsh, "ts_fd");
132         pts_close = dlsym(ltsh, "ts_close");
133         if (pts_open == NULL || pts_config == NULL || pts_read == NULL
134             || pts_fd == NULL || pts_close == NULL) {
135                 fprintf(stderr, "%s\n", dlerror());
136                 goto fail_dlsym;
137         }
138
139         ts = pts_open(tsdevname, 1);
140         if (ts == NULL){
141                 printf("Failed pts_open, check permission on %s\n", tsdevname);
142                 goto fail_open;
143         }
144         if (pts_config(ts) != 0){
145                 printf("Failed pts_config\n");
146                 goto fail_config;
147         }
148
149         // FIXME: we should be able to get this somewhere
150         // the problem is this doesn't always match resolution due to different display modes
151 #ifdef MAEMO
152         pl_set_gun_rect(N900_TSOFFSET_X, N900_TSOFFSET_Y, N900_TSMAX_X, N900_TSMAX_Y);
153 #else
154 #ifdef __ARM_ARCH_7A__
155         pl_set_gun_rect(0, 0, 800, 480);
156 #else
157         pl_set_gun_rect(0, 0, 320, 240);
158 #endif
159 #endif
160         printf("Touchscreen configured, device=%s\n", tsdevname);
161         return ts;
162
163 fail_config:
164         pts_close(ts);
165 fail_open:
166 fail_dlsym:
167         dlclose(ltsh);
168         ltsh = NULL;
169 fail:
170         fprintf(stderr, "Could not open touchscreen\n");
171         return NULL;
172 }
173