OSDN Git Service

init: move the init.sh execution to the post-fs stage
[android-x86/device-generic-common.git] / wacom / wacom-input.c
1 /*****************************************************************************
2  ** wacom-input.c
3  **
4  ** Copyright (C) 2011 Stefan Seidel
5  **
6  ** This program is free software; you can redistribute it and/or
7  ** modify it under the terms of the GNU General Public License
8  ** as published by the Free Software Foundation; either version 2
9  ** of the License, or (at your option) any later version.
10  **
11  ** This program is distributed in the hope that it will be useful,
12  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  ** GNU General Public License for more details.
15  **
16  ** You should have received a copy of the GNU General Public License
17  ** along with this program; if not, write to the Free Software
18  ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  **
20  **
21  ** Code inspired by wacdump.c from http://linuxwacom.sourceforge.net and
22  ** uniput-sample.c from http://thiemonge.org/getting-started-with-uinput
23  **
24  **
25  ** Version history:
26  **    0.1 - 2011-03-29 - initial support for "tpc" device
27  **    0.2 - 2011-04-13 - support command-line options for device type, node, pressure
28  **
29  ****************************************************************************/
30
31 #include "wactablet.h"
32 #include "wacserial.h"
33 #include "wacusb.h"
34
35 #include <ctype.h>
36 #include <time.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <signal.h>
44 #include <linux/input.h>
45 #include <linux/uinput.h>
46
47 #define die(str, args...) do { \
48         perror(str, ## args); \
49         exit(EXIT_FAILURE); \
50     } while(0)
51
52 int fd;
53 WACOMENGINE hEngine = NULL;
54 WACOMTABLET hTablet = NULL;
55
56 void wacom_report_event(__u16 type, __u16 code, __s32 value) {
57         struct input_event ev;
58         if (value == -1) {
59                 return;
60         }
61         memset(&ev, 0, sizeof(struct input_event));
62         ev.type = type;
63         ev.code = code;
64         ev.value = value;
65         if (write(fd, &ev, sizeof(struct input_event)) < 0)
66                 perror("error: write");
67 }
68
69 static void signal_handler(int signo) {
70         if (ioctl(fd, UI_DEV_DESTROY) < 0) {
71                 die("error: cannot destroy uinput device\n");
72         }
73         close(fd);
74         WacomCloseTablet(hTablet);
75         WacomTermEngine(hEngine);
76         exit(EXIT_SUCCESS);
77 }
78
79 int main(int argc, char** argv) {
80         const char* arg;
81         const char* devName = "tpc";
82         const char* devNode = "/dev/ttyS0";
83         struct uinput_user_dev uidev;
84         WACOMSTATE state = WACOMSTATE_INIT;
85         WACOMMODEL model = { 0 };
86         unsigned char uchBuf[64];
87         int nLength = 0;
88         int minPress = 20;
89
90         // parse arguments
91         while (*argv) {
92                 arg = *(argv++);
93
94                 /* handle options */
95                 if (arg[0] == '-') {
96                         /* device type */
97                         if (strcmp(arg, "-h") == 0) {
98                                 fprintf(
99                                                 stderr,
100                                                 "Usage: wacom-input [-t DeviceType] [-d DeviceNode] [-p PressureThreshold]\n\t-t defaults to \"tpc\"\n\t-d defaults to \"/dev/ttyS0\"\n\t-p defaults to 40\n");
101                                 exit(0);
102                                 /* device type */
103                         } else if (strcmp(arg, "-t") == 0) {
104                                 arg = *(argv++);
105                                 if (arg == NULL || arg[0] == '-') {
106                                         die("Missing device type");
107                                 }
108                                 devName = arg;
109                                 /* device node */
110                         } else if (strcmp(arg, "-d") == 0) {
111                                 arg = *(argv++);
112                                 if (arg == NULL || arg[0] == '-') {
113                                         die("Missing device node");
114                                 }
115                                 devNode = arg;
116                                 /* pressure */
117                         } else if (strcmp(arg, "-p") == 0) {
118                                 arg = *(argv++);
119                                 if (arg == NULL || (minPress = atoi(arg)) == 0) {
120                                         die("Wrong pressure threshold");
121                                 }
122                         }
123                 }
124         }
125         // end parse arguments
126
127         if (signal(SIGINT, signal_handler) == SIG_ERR) {
128                 die("error registering signal handler\n");
129         }
130
131         // connect to wacom device
132         hEngine = WacomInitEngine();
133         if (!hEngine) {
134                 close(fd);
135                 die("failed to open tablet engine");
136         }
137
138         /* open tablet */
139         model.uClass = WACOMCLASS_SERIAL;
140         model.uDevice = WacomGetDeviceFromName(devName, model.uClass);
141         hTablet = WacomOpenTablet(hEngine, devNode, &model);
142         if (!hTablet) {
143                 close(fd);
144                 WacomTermEngine(hEngine);
145                 die ("WacomOpenTablet");
146         }
147         WacomGetState(hTablet, &state);
148         // wacom device is set up properly
149
150         // set up uinput
151         fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
152         if (fd < 0) {
153                 fd = open("/dev/input/uinput", O_WRONLY | O_NONBLOCK);
154         }
155
156         if (fd < 0)
157                 die("error: opening /dev/[input/]uinput failed");
158
159         // report that we have TOUCH events ...
160         if (ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0)
161                 die("error: ioctl");
162         if (ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH) < 0)
163                 die("error: ioctl");
164
165         // and absolute x, y, pressure data
166         if (ioctl(fd, UI_SET_EVBIT, EV_ABS) < 0)
167                 die("error: ioctl");
168         if (ioctl(fd, UI_SET_ABSBIT, ABS_X) < 0)
169                 die("error: ioctl");
170         if (ioctl(fd, UI_SET_ABSBIT, ABS_Y) < 0)
171                 die("error: ioctl");
172         if (ioctl(fd, UI_SET_ABSBIT, ABS_PRESSURE) < 0)
173                 die("error: ioctl");
174
175         // this is for simulated mouse middle/right button
176         //    if(ioctl(fd, UI_SET_KEYBIT, BTN_MOUSE) < 0)
177         //        die("error: ioctl");
178         //    if(ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT) < 0)
179         //        die("error: ioctl");
180         //    if(ioctl(fd, UI_SET_KEYBIT, BTN_LEFT) < 0)
181         //        die("error: ioctl");
182
183         // register uinput device
184         memset(&uidev, 0, sizeof(uidev));
185         uidev.absmin[ABS_X] = state.values[WACOMFIELD_POSITION_X].nMin;
186         uidev.absmax[ABS_X] = state.values[WACOMFIELD_POSITION_X].nMax;
187         uidev.absmin[ABS_Y] = state.values[WACOMFIELD_POSITION_Y].nMin;
188         uidev.absmax[ABS_Y] = state.values[WACOMFIELD_POSITION_Y].nMax;
189         uidev.absmin[ABS_PRESSURE] = state.values[WACOMFIELD_PRESSURE].nMin;
190         uidev.absmax[ABS_PRESSURE] = state.values[WACOMFIELD_PRESSURE].nMax;
191         // this could be more detailed, but in the end, who cares?
192         snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "wacom-input");
193         uidev.id.bustype = BUS_RS232;
194         uidev.id.vendor = 0x056a;
195         uidev.id.product = 0xffff;
196         uidev.id.version = 1;
197
198         if (write(fd, &uidev, sizeof(uidev)) < 0)
199                 die("error: set virtual device info 1");
200
201         if (ioctl(fd, UI_DEV_CREATE) < 0)
202                 die("error: create uinput device 1");
203         // uinput is set up
204
205         while (1) {
206                 if ((nLength = WacomReadRaw(hTablet, uchBuf, sizeof(uchBuf))) < 0) {
207                         continue;
208                 }
209                 if (WacomParseData(hTablet, uchBuf, nLength, &state)) {
210                         continue;
211                 }
212                 if (!state.values[WACOMFIELD_PROXIMITY].nValue) {
213                         // no tool in proximity
214                         wacom_report_event(EV_ABS, ABS_PRESSURE, 0);
215                         wacom_report_event(EV_KEY, BTN_TOUCH, 0);
216                         //          wacom_report_event(EV_KEY, BTN_RIGHT,    0);
217                         //          wacom_report_event(EV_KEY, BTN_MIDDLE,   0);
218                         wacom_report_event(EV_SYN, SYN_REPORT, 0);
219                         continue;
220                 }
221
222                 wacom_report_event(EV_ABS, ABS_X,
223                                 state.values[WACOMFIELD_POSITION_X].nValue);
224                 wacom_report_event(EV_ABS, ABS_Y,
225                                 state.values[WACOMFIELD_POSITION_Y].nValue);
226                 wacom_report_event(EV_ABS, ABS_PRESSURE,
227                                 state.values[WACOMFIELD_PRESSURE].nValue);
228                 wacom_report_event(EV_KEY, BTN_TOUCH,
229                                 state.values[WACOMFIELD_PRESSURE].nValue > minPress);
230                 //        wacom_report_event(EV_KEY, BTN_RIGHT,    state.values[WACOMFIELD_BUTTONS].nValue == WACOMBUTTON_STYLUS);
231                 //        wacom_report_event(EV_KEY, BTN_MIDDLE,   state.values[WACOMFIELD_TOOLTYPE].nValue == WACOMTOOLTYPE_ERASER);
232                 wacom_report_event(EV_SYN, SYN_REPORT, 0);
233         }
234
235         if (ioctl(fd, UI_DEV_DESTROY) < 0)
236                 die("error: ioctl");
237
238         close(fd);
239
240         return 0;
241 }