blob: 04bad9788b6faeb5c30aca9eb2fbe5ae74ea3f63 [file] [log] [blame]
Steve Kondik95027ea2017-06-14 17:22:58 -07001//
2// vncflinger - Copyright (C) 2017 Steve Kondik
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//
17
Steve Kondik107d2e52017-06-13 17:34:56 -070018#define LOG_TAG "VNC-InputDevice"
19#include <utils/Log.h>
20
Steve Kondik961b4cc2017-06-22 18:10:50 -070021#include <future>
22
Steve Kondik107d2e52017-06-13 17:34:56 -070023#include "InputDevice.h"
24
25#include <fcntl.h>
26#include <stdio.h>
27
28#include <sys/ioctl.h>
29
30#include <linux/input.h>
31#include <linux/uinput.h>
32
Steve Kondik107d2e52017-06-13 17:34:56 -070033using namespace android;
34
Steve Kondik6ec5bc82017-06-15 01:31:51 -070035
Steve Kondik107d2e52017-06-13 17:34:56 -070036static const struct UInputOptions {
37 int cmd;
38 int bit;
39} kOptions[] = {
40 {UI_SET_EVBIT, EV_KEY},
Steve Kondik16230812017-06-15 12:54:36 -070041 {UI_SET_EVBIT, EV_REP},
Steve Kondik6ec5bc82017-06-15 01:31:51 -070042 {UI_SET_EVBIT, EV_REL},
Steve Kondik16230812017-06-15 12:54:36 -070043 {UI_SET_RELBIT, REL_X},
44 {UI_SET_RELBIT, REL_Y},
45 {UI_SET_RELBIT, REL_WHEEL},
Steve Kondik107d2e52017-06-13 17:34:56 -070046 {UI_SET_EVBIT, EV_ABS},
Steve Kondik107d2e52017-06-13 17:34:56 -070047 {UI_SET_ABSBIT, ABS_X},
48 {UI_SET_ABSBIT, ABS_Y},
Steve Kondik16230812017-06-15 12:54:36 -070049 {UI_SET_EVBIT, EV_SYN},
Steve Kondik107d2e52017-06-13 17:34:56 -070050 {UI_SET_PROPBIT, INPUT_PROP_DIRECT},
51};
52
Steve Kondik961b4cc2017-06-22 18:10:50 -070053status_t InputDevice::start_async(uint32_t width, uint32_t height) {
54 // don't block the caller since this can take a few seconds
55 std::async(&InputDevice::start, this, width, height);
56
57 return NO_ERROR;
58}
59
Steve Kondik107d2e52017-06-13 17:34:56 -070060status_t InputDevice::start(uint32_t width, uint32_t height) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070061 Mutex::Autolock _l(mLock);
62
Steve Kondika890c5e2017-06-15 02:46:23 -070063 mLeftClicked = mMiddleClicked = mRightClicked = false;
64
Steve Kondik107d2e52017-06-13 17:34:56 -070065 struct input_id id = {
66 BUS_VIRTUAL, /* Bus type */
67 1, /* Vendor */
68 1, /* Product */
Steve Kondik6ec5bc82017-06-15 01:31:51 -070069 4, /* Version */
Steve Kondik107d2e52017-06-13 17:34:56 -070070 };
71
Steve Kondik6ec5bc82017-06-15 01:31:51 -070072 if (mFD >= 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070073 ALOGE("Input device already open!");
74 return NO_INIT;
75 }
76
Steve Kondik6ec5bc82017-06-15 01:31:51 -070077 mFD = open(UINPUT_DEVICE, O_WRONLY | O_NONBLOCK);
78 if (mFD < 0) {
79 ALOGE("Failed to open %s: err=%d", UINPUT_DEVICE, mFD);
Steve Kondik107d2e52017-06-13 17:34:56 -070080 return NO_INIT;
81 }
82
83 unsigned int idx = 0;
84 for (idx = 0; idx < sizeof(kOptions) / sizeof(kOptions[0]); idx++) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070085 if (ioctl(mFD, kOptions[idx].cmd, kOptions[idx].bit) < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070086 ALOGE("uinput ioctl failed: %d %d", kOptions[idx].cmd, kOptions[idx].bit);
87 goto err_ioctl;
88 }
89 }
90
91 for (idx = 0; idx < KEY_MAX; idx++) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070092 if (ioctl(mFD, UI_SET_KEYBIT, idx) < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070093 ALOGE("UI_SET_KEYBIT failed");
94 goto err_ioctl;
95 }
96 }
97
Steve Kondik6ec5bc82017-06-15 01:31:51 -070098 memset(&mUserDev, 0, sizeof(mUserDev));
99 strncpy(mUserDev.name, "VNC-RemoteInput", UINPUT_MAX_NAME_SIZE);
Steve Kondik107d2e52017-06-13 17:34:56 -0700100
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700101 mUserDev.id = id;
Steve Kondik107d2e52017-06-13 17:34:56 -0700102
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700103 mUserDev.absmin[ABS_X] = 0;
104 mUserDev.absmax[ABS_X] = width;
105 mUserDev.absmin[ABS_Y] = 0;
106 mUserDev.absmax[ABS_Y] = height;
Steve Kondik107d2e52017-06-13 17:34:56 -0700107
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700108 if (write(mFD, &mUserDev, sizeof(mUserDev)) != sizeof(mUserDev)) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700109 ALOGE("Failed to configure uinput device");
110 goto err_ioctl;
111 }
112
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700113 if (ioctl(mFD, UI_DEV_CREATE) == -1) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700114 ALOGE("UI_DEV_CREATE failed");
115 goto err_ioctl;
116 }
117
Steve Kondik961b4cc2017-06-22 18:10:50 -0700118 mOpened = true;
119
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700120 ALOGD("Virtual input device created successfully (%dx%d)", width, height);
121 return NO_ERROR;
Steve Kondik107d2e52017-06-13 17:34:56 -0700122
123err_ioctl:
124 int prev_errno = errno;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700125 ::close(mFD);
Steve Kondik107d2e52017-06-13 17:34:56 -0700126 errno = prev_errno;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700127 mFD = -1;
Steve Kondik107d2e52017-06-13 17:34:56 -0700128 return NO_INIT;
129}
130
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700131status_t InputDevice::reconfigure(uint32_t width, uint32_t height) {
132 stop();
Steve Kondik961b4cc2017-06-22 18:10:50 -0700133 return start_async(width, height);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700134}
135
Steve Kondik107d2e52017-06-13 17:34:56 -0700136status_t InputDevice::stop() {
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700137 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700138
139 mOpened = false;
140
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700141 if (mFD < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700142 return OK;
143 }
144
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700145 ioctl(mFD, UI_DEV_DESTROY);
146 close(mFD);
147 mFD = -1;
Steve Kondik107d2e52017-06-13 17:34:56 -0700148
149 return OK;
150}
151
152status_t InputDevice::inject(uint16_t type, uint16_t code, int32_t value) {
153 struct input_event event;
154 memset(&event, 0, sizeof(event));
155 gettimeofday(&event.time, 0); /* This should not be able to fail ever.. */
156 event.type = type;
157 event.code = code;
158 event.value = value;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700159 if (write(mFD, &event, sizeof(event)) != sizeof(event)) return BAD_VALUE;
Steve Kondik107d2e52017-06-13 17:34:56 -0700160 return OK;
161}
162
163status_t InputDevice::injectSyn(uint16_t type, uint16_t code, int32_t value) {
164 if (inject(type, code, value) != OK) {
165 return BAD_VALUE;
166 }
167 return inject(EV_SYN, SYN_REPORT, 0);
168}
169
170status_t InputDevice::movePointer(int32_t x, int32_t y) {
171 if (inject(EV_REL, REL_X, x) != OK) {
172 return BAD_VALUE;
173 }
174 return injectSyn(EV_REL, REL_Y, y);
175}
176
177status_t InputDevice::setPointer(int32_t x, int32_t y) {
178 if (inject(EV_ABS, ABS_X, x) != OK) {
179 return BAD_VALUE;
180 }
181 return injectSyn(EV_ABS, ABS_Y, y);
182}
183
184status_t InputDevice::press(uint16_t code) {
185 return inject(EV_KEY, code, 1);
186}
187
188status_t InputDevice::release(uint16_t code) {
189 return inject(EV_KEY, code, 0);
190}
191
192status_t InputDevice::click(uint16_t code) {
193 if (press(code) != OK) {
194 return BAD_VALUE;
195 }
196 return release(code);
197}
198
Steve Kondik961b4cc2017-06-22 18:10:50 -0700199void InputDevice::keyEvent(bool down, uint32_t key) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700200 int code;
201 int sh = 0;
202 int alt = 0;
203
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700204 Mutex::Autolock _l(mLock);
Steve Kondik961b4cc2017-06-22 18:10:50 -0700205 if (!mOpened) return;
Steve Kondik107d2e52017-06-13 17:34:56 -0700206
Steve Kondik961b4cc2017-06-22 18:10:50 -0700207 if ((code = keysym2scancode(key, &sh, &alt))) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700208 int ret = 0;
209
210 if (key && down) {
211 if (sh) press(42); // left shift
212 if (alt) press(56); // left alt
213
214 inject(EV_SYN, SYN_REPORT, 0);
215
216 ret = press(code);
217 if (ret != 0) {
218 ALOGE("Error: %d (%s)\n", errno, strerror(errno));
219 }
220
221 inject(EV_SYN, SYN_REPORT, 0);
222
223 ret = release(code);
224 if (ret != 0) {
225 ALOGE("Error: %d (%s)\n", errno, strerror(errno));
226 }
227
228 inject(EV_SYN, SYN_REPORT, 0);
229
230 if (alt) release(56); // left alt
231 if (sh) release(42); // left shift
232
233 inject(EV_SYN, SYN_REPORT, 0);
234 }
235 }
236}
237
Steve Kondik961b4cc2017-06-22 18:10:50 -0700238void InputDevice::pointerEvent(int buttonMask, int x, int y) {
239 Mutex::Autolock _l(mLock);
240 if (!mOpened) return;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700241
242 ALOGV("pointerEvent: buttonMask=%x x=%d y=%d", buttonMask, x, y);
243
Steve Kondika890c5e2017-06-15 02:46:23 -0700244 if ((buttonMask & 1) && mLeftClicked) { // left btn clicked and moving
245 inject(EV_ABS, ABS_X, x);
246 inject(EV_ABS, ABS_Y, y);
247 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik107d2e52017-06-13 17:34:56 -0700248
Steve Kondik2c9d0cf2017-06-15 23:39:29 -0700249 } else if (buttonMask & 1) { // left btn clicked
Steve Kondika890c5e2017-06-15 02:46:23 -0700250 mLeftClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700251
252 inject(EV_ABS, ABS_X, x);
253 inject(EV_ABS, ABS_Y, y);
254 inject(EV_KEY, BTN_TOUCH, 1);
255 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700256 } else if (mLeftClicked) // left btn released
Steve Kondik107d2e52017-06-13 17:34:56 -0700257 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700258 mLeftClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700259 inject(EV_ABS, ABS_X, x);
260 inject(EV_ABS, ABS_Y, y);
261 inject(EV_KEY, BTN_TOUCH, 0);
262 inject(EV_SYN, SYN_REPORT, 0);
263 }
264
265 if (buttonMask & 4) // right btn clicked
266 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700267 mRightClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700268 press(158); // back key
269 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700270 } else if (mRightClicked) // right button released
Steve Kondik107d2e52017-06-13 17:34:56 -0700271 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700272 mRightClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700273 release(158);
274 inject(EV_SYN, SYN_REPORT, 0);
275 }
276
277 if (buttonMask & 2) // mid btn clicked
278 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700279 mMiddleClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700280 press(KEY_END);
281 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700282 } else if (mMiddleClicked) // mid btn released
Steve Kondik107d2e52017-06-13 17:34:56 -0700283 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700284 mMiddleClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700285 release(KEY_END);
286 inject(EV_SYN, SYN_REPORT, 0);
287 }
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700288
289 if (buttonMask & 8) {
290 inject(EV_REL, REL_WHEEL, 1);
Steve Kondika890c5e2017-06-15 02:46:23 -0700291 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700292 }
293
294 if (buttonMask & 0x10) {
295 inject(EV_REL, REL_WHEEL, -1);
Steve Kondika890c5e2017-06-15 02:46:23 -0700296 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700297 }
Steve Kondik107d2e52017-06-13 17:34:56 -0700298}
299
300// q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m
301static const int qwerty[] = {30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50,
302 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44};
303// ,!,",#,$,%,&,',(,),*,+,,,-,.,/
304static const int spec1[] = {57, 2, 40, 4, 5, 6, 8, 40, 10, 11, 9, 13, 51, 12, 52, 52};
305static const int spec1sh[] = {0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1};
306// :,;,<,=,>,?,@
307static const int spec2[] = {39, 39, 227, 13, 228, 53, 3};
308static const int spec2sh[] = {1, 0, 1, 1, 1, 1, 1};
309// [,\,],^,_,`
310static const int spec3[] = {26, 43, 27, 7, 12, 399};
311static const int spec3sh[] = {0, 0, 0, 1, 1, 0};
312// {,|,},~
313static const int spec4[] = {26, 43, 27, 215, 14};
314static const int spec4sh[] = {1, 1, 1, 1, 0};
315
Steve Kondik961b4cc2017-06-22 18:10:50 -0700316int InputDevice::keysym2scancode(uint32_t c, int* sh, int* alt) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700317 int real = 1;
318 if ('a' <= c && c <= 'z') return qwerty[c - 'a'];
319 if ('A' <= c && c <= 'Z') {
320 (*sh) = 1;
321 return qwerty[c - 'A'];
322 }
323 if ('1' <= c && c <= '9') return c - '1' + 2;
324 if (c == '0') return 11;
325 if (32 <= c && c <= 47) {
326 (*sh) = spec1sh[c - 32];
327 return spec1[c - 32];
328 }
329 if (58 <= c && c <= 64) {
330 (*sh) = spec2sh[c - 58];
331 return spec2[c - 58];
332 }
333 if (91 <= c && c <= 96) {
334 (*sh) = spec3sh[c - 91];
335 return spec3[c - 91];
336 }
337 if (123 <= c && c <= 127) {
338 (*sh) = spec4sh[c - 123];
339 return spec4[c - 123];
340 }
341 switch (c) {
342 case 0xff08:
343 return 14; // backspace
344 case 0xff09:
345 return 15; // tab
346 case 1:
347 (*alt) = 1;
348 return 34; // ctrl+a
349 case 3:
350 (*alt) = 1;
351 return 46; // ctrl+c
352 case 4:
353 (*alt) = 1;
354 return 32; // ctrl+d
355 case 18:
356 (*alt) = 1;
357 return 31; // ctrl+r
358 case 0xff0D:
359 return 28; // enter
360 case 0xff1B:
361 return 158; // esc -> back
362 case 0xFF51:
363 return 105; // left -> DPAD_LEFT
364 case 0xFF53:
365 return 106; // right -> DPAD_RIGHT
366 case 0xFF54:
367 return 108; // down -> DPAD_DOWN
368 case 0xFF52:
369 return 103; // up -> DPAD_UP
370 // case 360:
371 // return 232;// end -> DPAD_CENTER (ball click)
372 case 0xff50:
373 return KEY_HOME; // home
Steve Kondik107d2e52017-06-13 17:34:56 -0700374 case 0xffff:
375 return 158; // del -> back
376 case 0xff55:
377 return 229; // PgUp -> menu
378 case 0xffcf:
379 return 127; // F2 -> search
380 case 0xffe3:
381 return 127; // left ctrl -> search
382 case 0xff56:
383 return 61; // PgUp -> call
384 case 0xff57:
385 return 107; // End -> endcall
386 case 0xffc2:
387 return 211; // F5 -> focus
388 case 0xffc3:
389 return 212; // F6 -> camera
390 case 0xffc4:
391 return 150; // F7 -> explorer
392 case 0xffc5:
393 return 155; // F8 -> envelope
394
395 case 50081:
396 case 225:
397 (*alt) = 1;
398 if (real) return 48; // a with acute
399 return 30; // a with acute -> a with ring above
400
401 case 50049:
402 case 193:
403 (*sh) = 1;
404 (*alt) = 1;
405 if (real) return 48; // A with acute
406 return 30; // A with acute -> a with ring above
407
408 case 50089:
409 case 233:
410 (*alt) = 1;
411 return 18; // e with acute
412
413 case 50057:
414 case 201:
415 (*sh) = 1;
416 (*alt) = 1;
417 return 18; // E with acute
418
419 case 50093:
420 case 0xffbf:
421 (*alt) = 1;
422 if (real) return 36; // i with acute
423 return 23; // i with acute -> i with grave
424
425 case 50061:
426 case 205:
427 (*sh) = 1;
428 (*alt) = 1;
429 if (real) return 36; // I with acute
430 return 23; // I with acute -> i with grave
431
432 case 50099:
433 case 243:
434 (*alt) = 1;
435 if (real) return 16; // o with acute
436 return 24; // o with acute -> o with grave
437
438 case 50067:
439 case 211:
440 (*sh) = 1;
441 (*alt) = 1;
442 if (real) return 16; // O with acute
443 return 24; // O with acute -> o with grave
444
445 case 50102:
446 case 246:
447 (*alt) = 1;
448 return 25; // o with diaeresis
449
450 case 50070:
451 case 214:
452 (*sh) = 1;
453 (*alt) = 1;
454 return 25; // O with diaeresis
455
456 case 50577:
457 case 245:
458 (*alt) = 1;
459 if (real) return 19; // Hungarian o
460 return 25; // Hungarian o -> o with diaeresis
461
462 case 50576:
463 case 213:
464 (*sh) = 1;
465 (*alt) = 1;
466 if (real) return 19; // Hungarian O
467 return 25; // Hungarian O -> O with diaeresis
468
469 case 50106:
470 // case 0xffbe:
471 // (*alt)=1;
472 // if (real)
473 // return 17; //u with acute
474 // return 22; //u with acute -> u with grave
475 case 50074:
476 case 218:
477 (*sh) = 1;
478 (*alt) = 1;
479 if (real) return 17; // U with acute
480 return 22; // U with acute -> u with grave
481 case 50108:
482 case 252:
483 (*alt) = 1;
484 return 47; // u with diaeresis
485
486 case 50076:
487 case 220:
488 (*sh) = 1;
489 (*alt) = 1;
490 return 47; // U with diaeresis
491
492 case 50609:
493 case 251:
494 (*alt) = 1;
495 if (real) return 45; // Hungarian u
496 return 47; // Hungarian u -> u with diaeresis
497
498 case 50608:
499 case 219:
500 (*sh) = 1;
501 (*alt) = 1;
502 if (real) return 45; // Hungarian U
503 return 47; // Hungarian U -> U with diaeresis
504 }
505 return 0;
506}