• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007 The Android Open Source Project
3  *
4  * Input event device.
5  */
6 #include "Common.h"
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13 #include <linux/input.h>
14 
15 
16 /*
17  * Input event device state.
18  */
19 typedef struct EventState {
20     struct input_id ident;
21 
22     char*   name;
23     char*   location;
24     char*   idstr;
25     int     protoVersion;
26 } EventState;
27 
28 /*
29  * Key bit mask, for EVIOCGBIT(EV_KEY).
30  *
31  * (For now, just pretend to be a "goldfish" like the emulator.)
32  */
33 static const unsigned char gKeyBitMask[64] = {
34     // These bits indicate which keys the device has
35     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
36     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
37     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39     // These bits indicate other capabilities, such
40     // as whether it's a trackball or a touchscreen
41     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42     0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // touchscreen
43     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 };
46 
47 /*
48  * Abs bit mask, for EVIOCGBIT(EV_ABS).
49  *
50  * Pretend to be a normal single touch panel
51  */
52 static const unsigned char gAbsBitMask[64] = {
53     // these bits indicate the capabilities of the touch screen
54     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ABS_X, ABS_Y
55     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 };
63 
64 /*
65  * Set some stuff up.
66  */
configureInitialState(const char * pathName,EventState * eventState)67 static void configureInitialState(const char* pathName, EventState* eventState)
68 {
69     /*
70      * Swim like a goldfish.
71      */
72     eventState->ident.bustype = 0;
73     eventState->ident.vendor = 0;
74     eventState->ident.product = 0;
75     eventState->ident.version = 0;
76 
77     eventState->name = strdup(gWrapSim.keyMap);
78     eventState->location = strdup("");
79     eventState->idstr = strdup("");
80     eventState->protoVersion = 0x010000;
81 }
82 
83 /*
84  * Free up the state structure.
85  */
freeState(EventState * eventState)86 static void freeState(EventState* eventState)
87 {
88     if (eventState != NULL) {
89         free(eventState->name);
90         free(eventState->location);
91         free(eventState->idstr);
92         free(eventState);
93     }
94 }
95 
96 /*
97  * Handle one of the EVIOCGABS requests.
98  *
99  * Currently not doing much here.
100  */
handleAbsGet(int reqIdx,void * argp)101 static void handleAbsGet(int reqIdx, void* argp)
102 {
103     struct input_absinfo info;
104 
105     switch (reqIdx) {
106     case ABS_X:
107         wsLog("  req for abs X\n");
108         break;
109     case ABS_Y:
110         wsLog("  req for abs Y\n");
111         break;
112     case ABS_PRESSURE:
113         wsLog("  req for abs PRESSURE\n");
114         break;
115     case ABS_TOOL_WIDTH:
116         wsLog("  req for abs TOOL_WIDTH\n");
117         break;
118     default:
119         wsLog("  req for unexpected event abs 0x%02x\n", reqIdx);
120         break;
121     }
122 
123     memset(&info, 0, sizeof(info));
124     memcpy(argp, &info, sizeof(struct input_absinfo));
125 }
126 
127 /*
128  * Return the next available input event.
129  *
130  * We just pass this through to the real "read", since "fd" is real.
131  */
readEvent(FakeDev * dev,int fd,void * buf,size_t count)132 static ssize_t readEvent(FakeDev* dev, int fd, void* buf, size_t count)
133 {
134     return _ws_read(fd, buf, count);
135 }
136 
137 /*
138  * Somebody is trying to write to the event pipe.  This can be used to set
139  * the state of LED.
140  */
writeEvent(FakeDev * dev,int fd,const void * buf,size_t count)141 static ssize_t writeEvent(FakeDev* dev, int fd, const void* buf, size_t count)
142 {
143     const struct input_event* piev;
144 
145     if (count == sizeof(*piev)) {
146         piev = (const struct input_event*) buf;
147 
148         if (piev->type == EV_LED) {
149             wsLog("%s: set LED code=%d value=%d\n",
150                 dev->debugName, piev->code, piev->value);
151         } else {
152             wsLog("%s: writeEvent got %d bytes, type=%d\n",
153                 dev->debugName, count, piev->type);
154         }
155     } else {
156         wsLog("%s: warning: writeEvent got %d bytes, not sure why\n",
157             dev->debugName, count);
158     }
159 
160     return count;
161 }
162 
163 /*
164  * Handle event ioctls.
165  */
ioctlEvent(FakeDev * dev,int fd,int request,void * argp)166 static int ioctlEvent(FakeDev* dev, int fd, int request, void* argp)
167 {
168     EventState* state = (EventState*) dev->state;
169     unsigned int urequest = (unsigned int) request;
170 
171     wsLog("%s: ioctl(0x%x, %p)\n", dev->debugName, urequest, argp);
172 
173     if (_IOC_TYPE(urequest) != _IOC_TYPE(EVIOCGVERSION)) {
174         wsLog("%s: inappropriate ioctl 0x%08x\n", dev->debugName, urequest);
175         return -1;
176     }
177 
178     if (urequest == EVIOCGVERSION) {
179         *(int*)argp = state->protoVersion;
180     } else if (urequest == EVIOCGID) {
181         memcpy(argp, &state->ident, sizeof(struct input_id));
182     } else if (_IOC_NR(urequest) == _IOC_NR(EVIOCGNAME(0))) {
183         int maxLen = _IOC_SIZE(urequest);
184         int strLen = (int) strlen(state->name);
185         if (strLen >= maxLen) {
186             errno = EINVAL;
187             return -1;
188         }
189         memcpy(argp, state->name, strLen+1);
190         return strLen;
191     } else if (_IOC_NR(urequest) == _IOC_NR(EVIOCGPHYS(0))) {
192         int maxLen = _IOC_SIZE(urequest);
193         int strLen = (int) strlen(state->location);
194         if (strLen >= maxLen) {
195             errno = EINVAL;
196             return -1;
197         }
198         memcpy(argp, state->location, strLen+1);
199         return strLen;
200     } else if (_IOC_NR(urequest) == _IOC_NR(EVIOCGUNIQ(0))) {
201         /* device doesn't seem to support this, neither will we */
202         return -1;
203     } else if (_IOC_NR(urequest) == _IOC_NR(EVIOCGBIT(EV_KEY,0))) {
204         /* keys */
205         int maxLen = _IOC_SIZE(urequest);
206         if (maxLen > (int) sizeof(gKeyBitMask))
207             maxLen = sizeof(gKeyBitMask);
208         memcpy(argp, gKeyBitMask, maxLen);
209     } else if (_IOC_NR(urequest) == _IOC_NR(EVIOCGBIT(EV_REL,0))) {
210         /* relative controllers (trackball) */
211         int maxLen = _IOC_SIZE(urequest);
212         memset(argp, 0xff, maxLen);
213     } else if (!getenv("NOTOUCH") && _IOC_NR(urequest) == _IOC_NR(EVIOCGBIT(EV_ABS,0))) {
214         // absolute controllers (touch screen)
215         int maxLen = _IOC_SIZE(urequest);
216         if (maxLen > (int) sizeof(gAbsBitMask))
217             maxLen = sizeof(gAbsBitMask);
218         memcpy(argp, gAbsBitMask, maxLen);
219 
220     } else if (_IOC_NR(urequest) >= _IOC_NR(EVIOCGABS(ABS_X)) &&
221                _IOC_NR(urequest) <= _IOC_NR(EVIOCGABS(ABS_MAX)))
222     {
223         /* get abs value / limits */
224         int reqIdx = _IOC_NR(urequest) - _IOC_NR(EVIOCGABS(ABS_X));
225         handleAbsGet(reqIdx, argp);
226     } else {
227         wsLog("GLITCH: UNKNOWN ioctl request 0x%x on %s\n",
228             urequest, dev->debugName);
229         return -1;
230     }
231 
232     return 0;
233 }
234 
235 /*
236  * Free up our state before closing down the fake descriptor.
237  */
closeEvent(FakeDev * dev,int fd)238 static int closeEvent(FakeDev* dev, int fd)
239 {
240     freeState((EventState*)dev->state);
241     dev->state = NULL;
242     if (gWrapSim.keyInputDevice == dev) {
243         gWrapSim.keyInputDevice = NULL;
244         wsLog("Sim input device closed\n");
245     }
246     return 0;
247 }
248 
249 /*
250  * Open an input event device.
251  */
wsOpenDevEvent(const char * pathName,int flags)252 FakeDev* wsOpenDevEvent(const char* pathName, int flags)
253 {
254     FakeDev* newDev = wsCreateRealFakeDev(pathName);
255     if (newDev != NULL) {
256         newDev->read = readEvent;
257         newDev->write = writeEvent;
258         newDev->ioctl = ioctlEvent;
259         newDev->close = closeEvent;
260 
261         EventState* eventState = calloc(1, sizeof(EventState));
262 
263         configureInitialState(pathName, eventState);
264         newDev->state = eventState;
265 
266         /*
267          * First one opened becomes the place where we queue up input
268          * events from the simulator.  This approach will fail if the
269          * app opens the device, then opens it a second time for input,
270          * then closes the first.  The app doesn't currently do this (though
271          * it does do quick opens to fiddle with LEDs).
272          */
273         if (gWrapSim.keyInputDevice == NULL) {
274             gWrapSim.keyInputDevice = newDev;
275             wsLog("Device %p / %d will receive sim input events\n",
276                 newDev, newDev->fd);
277         }
278     }
279 
280     return newDev;
281 }
282 
283 /*
284  * Write a key event.
285  */
sendKeyEvent(FakeDev * dev,int code,int isDown)286 static int sendKeyEvent(FakeDev* dev, int code, int isDown)
287 {
288     struct input_event iev;
289     ssize_t actual;
290 
291     gettimeofday(&iev.time, NULL);
292     iev.type = EV_KEY;
293     iev.code = code;
294     iev.value = (isDown != 0) ? 1 : 0;
295 
296     actual = _ws_write(dev->otherFd, &iev, sizeof(iev));
297     if (actual != (ssize_t) sizeof(iev)) {
298         wsLog("WARNING: send key event partial write (%d of %d)\n",
299             actual, sizeof(iev));
300         return -1;
301     }
302 
303     return 0;
304 }
305 
306 /*
307  * Write an absolute (touch screen) event.
308  */
sendAbsButton(FakeDev * dev,int x,int y,int isDown)309 static int sendAbsButton(FakeDev* dev, int x, int y, int isDown)
310 {
311     struct input_event iev;
312     ssize_t actual;
313 
314     wsLog("absButton x=%d y=%d down=%d\n", x, y, isDown);
315 
316     gettimeofday(&iev.time, NULL);
317     iev.type = EV_KEY;
318     iev.code = BTN_TOUCH;
319     iev.value = (isDown != 0) ? 1 : 0;
320 
321     actual = _ws_write(dev->otherFd, &iev, sizeof(iev));
322     if (actual != (ssize_t) sizeof(iev)) {
323         wsLog("WARNING: send touch event partial write (%d of %d)\n",
324             actual, sizeof(iev));
325         return -1;
326     }
327 
328     return 0;
329 }
330 
331 /*
332  * Write an absolute (touch screen) event.
333  */
sendAbsMovement(FakeDev * dev,int x,int y)334 static int sendAbsMovement(FakeDev* dev, int x, int y)
335 {
336     struct input_event iev;
337     ssize_t actual;
338 
339     wsLog("absMove x=%d y=%d\n", x, y);
340 
341     gettimeofday(&iev.time, NULL);
342     iev.type = EV_ABS;
343     iev.code = ABS_X;
344     iev.value = x;
345 
346     actual = _ws_write(dev->otherFd, &iev, sizeof(iev));
347     if (actual != (ssize_t) sizeof(iev)) {
348         wsLog("WARNING: send abs movement event partial X write (%d of %d)\n",
349             actual, sizeof(iev));
350         return -1;
351     }
352 
353     iev.code = ABS_Y;
354     iev.value = y;
355 
356     actual = _ws_write(dev->otherFd, &iev, sizeof(iev));
357     if (actual != (ssize_t) sizeof(iev)) {
358         wsLog("WARNING: send abs movement event partial Y write (%d of %d)\n",
359             actual, sizeof(iev));
360         return -1;
361     }
362 
363     return 0;
364 }
365 
366 /*
367  * Not quite sure what this is for, but the emulator does it.
368  */
sendAbsSyn(FakeDev * dev)369 static int sendAbsSyn(FakeDev* dev)
370 {
371     struct input_event iev;
372     ssize_t actual;
373 
374     gettimeofday(&iev.time, NULL);
375     iev.type = EV_SYN;
376     iev.code = 0;
377     iev.value = 0;
378 
379     actual = _ws_write(dev->otherFd, &iev, sizeof(iev));
380     if (actual != (ssize_t) sizeof(iev)) {
381         wsLog("WARNING: send abs movement syn (%d of %d)\n",
382             actual, sizeof(iev));
383         return -1;
384     }
385 
386     return 0;
387 }
388 
389 /*
390  * Send a key event to the fake key event device.
391  *
392  * We have to translate the simulator key event into one or more device
393  * key events.
394  */
wsSendSimKeyEvent(int key,int isDown)395 void wsSendSimKeyEvent(int key, int isDown)
396 {
397     FakeDev* dev;
398     EventState* state;
399 
400     dev = gWrapSim.keyInputDevice;
401     if (dev == NULL)
402         return;
403 
404     sendKeyEvent(dev, key, isDown);
405 }
406 
407 /*
408  * Send a touch-screen event to the fake key event device.
409  *
410  * We have to translate the simulator key event into one or more device
411  * key events.
412  */
wsSendSimTouchEvent(int action,int x,int y)413 void wsSendSimTouchEvent(int action, int x, int y)
414 {
415     FakeDev* dev;
416     EventState* state;
417 
418     dev = gWrapSim.keyInputDevice;
419     if (dev == NULL)
420         return;
421 
422     if (action == kTouchDown) {
423         sendAbsMovement(dev, x, y);
424         sendAbsButton(dev, x, y, 1);
425         sendAbsSyn(dev);
426     } else if (action == kTouchUp) {
427         sendAbsButton(dev, x, y, 0);
428         sendAbsSyn(dev);
429     } else if (action == kTouchDrag) {
430         sendAbsMovement(dev, x, y);
431         sendAbsSyn(dev);
432     } else {
433         wsLog("WARNING: unexpected sim touch action  %d\n", action);
434     }
435 }
436 
437