1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/*
* (C) Gražvydas "notaz" Ignotas, 2011
*
* This work is licensed under the terms of any of these licenses
* (at your option):
* - GNU GPL, version 2 or later.
* - GNU LGPL, version 2.1 or later.
* See the COPYING file in the top-level directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <tslib.h>
#include "plugin_lib.h"
#include "pl_gun_ts.h"
#include "menu.h"
#include "../plugins/dfinput/main.h"
static int gun_x, gun_y, gun_in;
static int ts_multiplier_x, ts_multiplier_y, ts_offs_x, ts_offs_y;
int (*pts_read)(struct tsdev *dev, struct ts_sample *sample, int nr);
int (*pts_fd)(struct tsdev *dev);
#define limit(v, min, max) \
if (v < min) v = min; \
else if (v > max) v = max
void pl_gun_ts_update(struct tsdev *ts, int *x, int *y, int *in)
{
struct ts_sample sample;
int sx = 0, sy = 0, sp = 0, updated = 0;
if (ts != NULL) {
while (pts_read(ts, &sample, 1) > 0) {
sx = sample.x;
sy = sample.y;
sp = sample.pressure;
updated = 1;
}
if (updated) {
gun_x = (sx - ts_offs_x) * ts_multiplier_x >> 10;
gun_y = (sy - ts_offs_y) * ts_multiplier_y >> 10;
limit(gun_x, 0, 1023);
limit(gun_y, 0, 1023);
if (sp && !(g_opts & OPT_TSGUN_NOTRIGGER))
gun_in |= GUNIN_TRIGGER;
else
gun_in &= ~GUNIN_TRIGGER;
}
}
*x = gun_x;
*y = gun_y;
*in = gun_in | in_state_gun;
}
void pl_set_gun_rect(int x, int y, int w, int h)
{
ts_offs_x = x;
ts_offs_y = y;
ts_multiplier_x = (1<<20) / w;
ts_multiplier_y = (1<<20) / h;
}
struct tsdev *pl_gun_ts_init(void)
{
struct tsdev *(*pts_open)(const char *dev_name, int nonblock) = NULL;
int (*pts_config)(struct tsdev *) = NULL;
int (*pts_close)(struct tsdev *) = NULL;
const char *tsdevname;
struct tsdev *ts;
void *ltsh;
tsdevname = getenv("TSLIB_TSDEVICE");
if (tsdevname == NULL)
tsdevname = "/dev/input/touchscreen0";
// avoid hard dep on tslib
ltsh = dlopen("/usr/lib/libts-1.0.so.0", RTLD_NOW|RTLD_GLOBAL);
if (ltsh == NULL)
ltsh = dlopen("/usr/lib/libts-0.0.so.0", RTLD_NOW|RTLD_GLOBAL);
if (ltsh == NULL) {
fprintf(stderr, "%s\n", dlerror());
goto fail;
}
pts_open = dlsym(ltsh, "ts_open");
pts_config = dlsym(ltsh, "ts_config");
pts_read = dlsym(ltsh, "ts_read");
pts_fd = dlsym(ltsh, "ts_fd");
pts_close = dlsym(ltsh, "ts_close");
if (pts_open == NULL || pts_config == NULL || pts_read == NULL
|| pts_fd == NULL || pts_close == NULL) {
fprintf(stderr, "%s\n", dlerror());
goto fail_dlsym;
}
ts = pts_open(tsdevname, 1);
if (ts == NULL)
goto fail_open;
if (pts_config(ts) != 0)
goto fail_config;
// FIXME: we should be able to get this somewhere
// the problem is this doesn't always match resolution due to different display modes
#ifdef __ARM_ARCH_7A__
pl_set_gun_rect(0, 0, 800, 480);
#else
pl_set_gun_rect(0, 0, 320, 240);
#endif
return ts;
fail_config:
pts_close(ts);
fail_open:
fail_dlsym:
dlclose(ltsh);
ltsh = NULL;
fail:
fprintf(stderr, "Could not open touchscreen\n");
return NULL;
}
|