blob: ddfc4996c83d2e5cd22065249be6307a9722052b [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
21#include "InputDevice.h"
22
23#include <fcntl.h>
24#include <stdio.h>
25
26#include <sys/ioctl.h>
27
28#include <linux/input.h>
29#include <linux/uinput.h>
30
31#include <rfb/keysym.h>
32
33using namespace android;
34
Steve Kondik6ec5bc82017-06-15 01:31:51 -070035ANDROID_SINGLETON_STATIC_INSTANCE(InputDevice)
36
Steve Kondik107d2e52017-06-13 17:34:56 -070037static const struct UInputOptions {
38 int cmd;
39 int bit;
40} kOptions[] = {
41 {UI_SET_EVBIT, EV_KEY},
Steve Kondik6ec5bc82017-06-15 01:31:51 -070042 {UI_SET_EVBIT, EV_REL},
Steve Kondik107d2e52017-06-13 17:34:56 -070043 {UI_SET_EVBIT, EV_ABS},
44 {UI_SET_EVBIT, EV_SYN},
45 {UI_SET_ABSBIT, ABS_X},
46 {UI_SET_ABSBIT, ABS_Y},
Steve Kondik6ec5bc82017-06-15 01:31:51 -070047 {UI_SET_RELBIT, REL_WHEEL},
Steve Kondik107d2e52017-06-13 17:34:56 -070048 {UI_SET_PROPBIT, INPUT_PROP_DIRECT},
49};
50
Steve Kondik107d2e52017-06-13 17:34:56 -070051status_t InputDevice::start(uint32_t width, uint32_t height) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070052 Mutex::Autolock _l(mLock);
53
Steve Kondik107d2e52017-06-13 17:34:56 -070054 status_t err = OK;
Steve Kondik107d2e52017-06-13 17:34:56 -070055
Steve Kondika890c5e2017-06-15 02:46:23 -070056 mLeftClicked = mMiddleClicked = mRightClicked = false;
57
Steve Kondik107d2e52017-06-13 17:34:56 -070058 struct input_id id = {
59 BUS_VIRTUAL, /* Bus type */
60 1, /* Vendor */
61 1, /* Product */
Steve Kondik6ec5bc82017-06-15 01:31:51 -070062 4, /* Version */
Steve Kondik107d2e52017-06-13 17:34:56 -070063 };
64
Steve Kondik6ec5bc82017-06-15 01:31:51 -070065 if (mFD >= 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070066 ALOGE("Input device already open!");
67 return NO_INIT;
68 }
69
Steve Kondik6ec5bc82017-06-15 01:31:51 -070070 mFD = open(UINPUT_DEVICE, O_WRONLY | O_NONBLOCK);
71 if (mFD < 0) {
72 ALOGE("Failed to open %s: err=%d", UINPUT_DEVICE, mFD);
Steve Kondik107d2e52017-06-13 17:34:56 -070073 return NO_INIT;
74 }
75
76 unsigned int idx = 0;
77 for (idx = 0; idx < sizeof(kOptions) / sizeof(kOptions[0]); idx++) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070078 if (ioctl(mFD, kOptions[idx].cmd, kOptions[idx].bit) < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070079 ALOGE("uinput ioctl failed: %d %d", kOptions[idx].cmd, kOptions[idx].bit);
80 goto err_ioctl;
81 }
82 }
83
84 for (idx = 0; idx < KEY_MAX; idx++) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070085 if (ioctl(mFD, UI_SET_KEYBIT, idx) < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070086 ALOGE("UI_SET_KEYBIT failed");
87 goto err_ioctl;
88 }
89 }
90
Steve Kondik6ec5bc82017-06-15 01:31:51 -070091 memset(&mUserDev, 0, sizeof(mUserDev));
92 strncpy(mUserDev.name, "VNC-RemoteInput", UINPUT_MAX_NAME_SIZE);
Steve Kondik107d2e52017-06-13 17:34:56 -070093
Steve Kondik6ec5bc82017-06-15 01:31:51 -070094 mUserDev.id = id;
Steve Kondik107d2e52017-06-13 17:34:56 -070095
Steve Kondik6ec5bc82017-06-15 01:31:51 -070096 mUserDev.absmin[ABS_X] = 0;
97 mUserDev.absmax[ABS_X] = width;
98 mUserDev.absmin[ABS_Y] = 0;
99 mUserDev.absmax[ABS_Y] = height;
Steve Kondik107d2e52017-06-13 17:34:56 -0700100
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700101 if (write(mFD, &mUserDev, sizeof(mUserDev)) != sizeof(mUserDev)) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700102 ALOGE("Failed to configure uinput device");
103 goto err_ioctl;
104 }
105
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700106 if (ioctl(mFD, UI_DEV_CREATE) == -1) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700107 ALOGE("UI_DEV_CREATE failed");
108 goto err_ioctl;
109 }
110
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700111 ALOGD("Virtual input device created successfully (%dx%d)", width, height);
112 return NO_ERROR;
Steve Kondik107d2e52017-06-13 17:34:56 -0700113
114err_ioctl:
115 int prev_errno = errno;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700116 ::close(mFD);
Steve Kondik107d2e52017-06-13 17:34:56 -0700117 errno = prev_errno;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700118 mFD = -1;
Steve Kondik107d2e52017-06-13 17:34:56 -0700119 return NO_INIT;
120}
121
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700122status_t InputDevice::reconfigure(uint32_t width, uint32_t height) {
123 stop();
124 return start(width, height);
125}
126
Steve Kondik107d2e52017-06-13 17:34:56 -0700127status_t InputDevice::stop() {
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700128 Mutex::Autolock _l(mLock);
129 if (mFD < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700130 return OK;
131 }
132
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700133 ioctl(mFD, UI_DEV_DESTROY);
134 close(mFD);
135 mFD = -1;
Steve Kondik107d2e52017-06-13 17:34:56 -0700136
137 return OK;
138}
139
140status_t InputDevice::inject(uint16_t type, uint16_t code, int32_t value) {
141 struct input_event event;
142 memset(&event, 0, sizeof(event));
143 gettimeofday(&event.time, 0); /* This should not be able to fail ever.. */
144 event.type = type;
145 event.code = code;
146 event.value = value;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700147 if (write(mFD, &event, sizeof(event)) != sizeof(event)) return BAD_VALUE;
Steve Kondik107d2e52017-06-13 17:34:56 -0700148 return OK;
149}
150
151status_t InputDevice::injectSyn(uint16_t type, uint16_t code, int32_t value) {
152 if (inject(type, code, value) != OK) {
153 return BAD_VALUE;
154 }
155 return inject(EV_SYN, SYN_REPORT, 0);
156}
157
158status_t InputDevice::movePointer(int32_t x, int32_t y) {
159 if (inject(EV_REL, REL_X, x) != OK) {
160 return BAD_VALUE;
161 }
162 return injectSyn(EV_REL, REL_Y, y);
163}
164
165status_t InputDevice::setPointer(int32_t x, int32_t y) {
166 if (inject(EV_ABS, ABS_X, x) != OK) {
167 return BAD_VALUE;
168 }
169 return injectSyn(EV_ABS, ABS_Y, y);
170}
171
172status_t InputDevice::press(uint16_t code) {
173 return inject(EV_KEY, code, 1);
174}
175
176status_t InputDevice::release(uint16_t code) {
177 return inject(EV_KEY, code, 0);
178}
179
180status_t InputDevice::click(uint16_t code) {
181 if (press(code) != OK) {
182 return BAD_VALUE;
183 }
184 return release(code);
185}
186
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700187void InputDevice::onKeyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl) {
188 InputDevice::getInstance().keyEvent(down, key, cl);
189}
190
Steve Kondik107d2e52017-06-13 17:34:56 -0700191void InputDevice::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl) {
192 int code;
193 int sh = 0;
194 int alt = 0;
195
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700196 if (mFD < 0) return;
197
198 Mutex::Autolock _l(mLock);
Steve Kondik107d2e52017-06-13 17:34:56 -0700199
200 if ((code = keysym2scancode(key, cl, &sh, &alt))) {
201 int ret = 0;
202
203 if (key && down) {
204 if (sh) press(42); // left shift
205 if (alt) press(56); // left alt
206
207 inject(EV_SYN, SYN_REPORT, 0);
208
209 ret = press(code);
210 if (ret != 0) {
211 ALOGE("Error: %d (%s)\n", errno, strerror(errno));
212 }
213
214 inject(EV_SYN, SYN_REPORT, 0);
215
216 ret = release(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 if (alt) release(56); // left alt
224 if (sh) release(42); // left shift
225
226 inject(EV_SYN, SYN_REPORT, 0);
227 }
228 }
229}
230
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700231void InputDevice::onPointerEvent(int buttonMask, int x, int y, rfbClientPtr cl) {
232 InputDevice::getInstance().pointerEvent(buttonMask, x, y, cl);
233}
234
Steve Kondika890c5e2017-06-15 02:46:23 -0700235void InputDevice::pointerEvent(int buttonMask, int x, int y, rfbClientPtr /* cl */) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700236 if (mFD < 0) return;
237
238 ALOGV("pointerEvent: buttonMask=%x x=%d y=%d", buttonMask, x, y);
239
240 Mutex::Autolock _l(mLock);
Steve Kondik107d2e52017-06-13 17:34:56 -0700241
Steve Kondika890c5e2017-06-15 02:46:23 -0700242 if ((buttonMask & 1) && mLeftClicked) { // left btn clicked and moving
243 inject(EV_ABS, ABS_X, x);
244 inject(EV_ABS, ABS_Y, y);
245 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik107d2e52017-06-13 17:34:56 -0700246
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700247 } else if (buttonMask & 1) { // left btn clicked
Steve Kondika890c5e2017-06-15 02:46:23 -0700248 mLeftClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700249
250 inject(EV_ABS, ABS_X, x);
251 inject(EV_ABS, ABS_Y, y);
252 inject(EV_KEY, BTN_TOUCH, 1);
253 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700254 } else if (mLeftClicked) // left btn released
Steve Kondik107d2e52017-06-13 17:34:56 -0700255 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700256 mLeftClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700257 inject(EV_ABS, ABS_X, x);
258 inject(EV_ABS, ABS_Y, y);
259 inject(EV_KEY, BTN_TOUCH, 0);
260 inject(EV_SYN, SYN_REPORT, 0);
261 }
262
263 if (buttonMask & 4) // right btn clicked
264 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700265 mRightClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700266 press(158); // back key
267 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700268 } else if (mRightClicked) // right button released
Steve Kondik107d2e52017-06-13 17:34:56 -0700269 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700270 mRightClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700271 release(158);
272 inject(EV_SYN, SYN_REPORT, 0);
273 }
274
275 if (buttonMask & 2) // mid btn clicked
276 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700277 mMiddleClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700278 press(KEY_END);
279 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700280 } else if (mMiddleClicked) // mid btn released
Steve Kondik107d2e52017-06-13 17:34:56 -0700281 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700282 mMiddleClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700283 release(KEY_END);
284 inject(EV_SYN, SYN_REPORT, 0);
285 }
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700286
287 if (buttonMask & 8) {
288 inject(EV_REL, REL_WHEEL, 1);
Steve Kondika890c5e2017-06-15 02:46:23 -0700289 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700290 }
291
292 if (buttonMask & 0x10) {
293 inject(EV_REL, REL_WHEEL, -1);
Steve Kondika890c5e2017-06-15 02:46:23 -0700294 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700295 }
Steve Kondik107d2e52017-06-13 17:34:56 -0700296}
297
298// 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
299static const int qwerty[] = {30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50,
300 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44};
301// ,!,",#,$,%,&,',(,),*,+,,,-,.,/
302static const int spec1[] = {57, 2, 40, 4, 5, 6, 8, 40, 10, 11, 9, 13, 51, 12, 52, 52};
303static const int spec1sh[] = {0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1};
304// :,;,<,=,>,?,@
305static const int spec2[] = {39, 39, 227, 13, 228, 53, 3};
306static const int spec2sh[] = {1, 0, 1, 1, 1, 1, 1};
307// [,\,],^,_,`
308static const int spec3[] = {26, 43, 27, 7, 12, 399};
309static const int spec3sh[] = {0, 0, 0, 1, 1, 0};
310// {,|,},~
311static const int spec4[] = {26, 43, 27, 215, 14};
312static const int spec4sh[] = {1, 1, 1, 1, 0};
313
314int InputDevice::keysym2scancode(rfbKeySym c, rfbClientPtr cl, int* sh, int* alt) {
315 int real = 1;
316 if ('a' <= c && c <= 'z') return qwerty[c - 'a'];
317 if ('A' <= c && c <= 'Z') {
318 (*sh) = 1;
319 return qwerty[c - 'A'];
320 }
321 if ('1' <= c && c <= '9') return c - '1' + 2;
322 if (c == '0') return 11;
323 if (32 <= c && c <= 47) {
324 (*sh) = spec1sh[c - 32];
325 return spec1[c - 32];
326 }
327 if (58 <= c && c <= 64) {
328 (*sh) = spec2sh[c - 58];
329 return spec2[c - 58];
330 }
331 if (91 <= c && c <= 96) {
332 (*sh) = spec3sh[c - 91];
333 return spec3[c - 91];
334 }
335 if (123 <= c && c <= 127) {
336 (*sh) = spec4sh[c - 123];
337 return spec4[c - 123];
338 }
339 switch (c) {
340 case 0xff08:
341 return 14; // backspace
342 case 0xff09:
343 return 15; // tab
344 case 1:
345 (*alt) = 1;
346 return 34; // ctrl+a
347 case 3:
348 (*alt) = 1;
349 return 46; // ctrl+c
350 case 4:
351 (*alt) = 1;
352 return 32; // ctrl+d
353 case 18:
354 (*alt) = 1;
355 return 31; // ctrl+r
356 case 0xff0D:
357 return 28; // enter
358 case 0xff1B:
359 return 158; // esc -> back
360 case 0xFF51:
361 return 105; // left -> DPAD_LEFT
362 case 0xFF53:
363 return 106; // right -> DPAD_RIGHT
364 case 0xFF54:
365 return 108; // down -> DPAD_DOWN
366 case 0xFF52:
367 return 103; // up -> DPAD_UP
368 // case 360:
369 // return 232;// end -> DPAD_CENTER (ball click)
370 case 0xff50:
371 return KEY_HOME; // home
372 case 0xFFC8:
373 rfbShutdownServer(cl->screen, TRUE);
374 return 0; // F11 disconnect
375 case 0xffff:
376 return 158; // del -> back
377 case 0xff55:
378 return 229; // PgUp -> menu
379 case 0xffcf:
380 return 127; // F2 -> search
381 case 0xffe3:
382 return 127; // left ctrl -> search
383 case 0xff56:
384 return 61; // PgUp -> call
385 case 0xff57:
386 return 107; // End -> endcall
387 case 0xffc2:
388 return 211; // F5 -> focus
389 case 0xffc3:
390 return 212; // F6 -> camera
391 case 0xffc4:
392 return 150; // F7 -> explorer
393 case 0xffc5:
394 return 155; // F8 -> envelope
395
396 case 50081:
397 case 225:
398 (*alt) = 1;
399 if (real) return 48; // a with acute
400 return 30; // a with acute -> a with ring above
401
402 case 50049:
403 case 193:
404 (*sh) = 1;
405 (*alt) = 1;
406 if (real) return 48; // A with acute
407 return 30; // A with acute -> a with ring above
408
409 case 50089:
410 case 233:
411 (*alt) = 1;
412 return 18; // e with acute
413
414 case 50057:
415 case 201:
416 (*sh) = 1;
417 (*alt) = 1;
418 return 18; // E with acute
419
420 case 50093:
421 case 0xffbf:
422 (*alt) = 1;
423 if (real) return 36; // i with acute
424 return 23; // i with acute -> i with grave
425
426 case 50061:
427 case 205:
428 (*sh) = 1;
429 (*alt) = 1;
430 if (real) return 36; // I with acute
431 return 23; // I with acute -> i with grave
432
433 case 50099:
434 case 243:
435 (*alt) = 1;
436 if (real) return 16; // o with acute
437 return 24; // o with acute -> o with grave
438
439 case 50067:
440 case 211:
441 (*sh) = 1;
442 (*alt) = 1;
443 if (real) return 16; // O with acute
444 return 24; // O with acute -> o with grave
445
446 case 50102:
447 case 246:
448 (*alt) = 1;
449 return 25; // o with diaeresis
450
451 case 50070:
452 case 214:
453 (*sh) = 1;
454 (*alt) = 1;
455 return 25; // O with diaeresis
456
457 case 50577:
458 case 245:
459 (*alt) = 1;
460 if (real) return 19; // Hungarian o
461 return 25; // Hungarian o -> o with diaeresis
462
463 case 50576:
464 case 213:
465 (*sh) = 1;
466 (*alt) = 1;
467 if (real) return 19; // Hungarian O
468 return 25; // Hungarian O -> O with diaeresis
469
470 case 50106:
471 // case 0xffbe:
472 // (*alt)=1;
473 // if (real)
474 // return 17; //u with acute
475 // return 22; //u with acute -> u with grave
476 case 50074:
477 case 218:
478 (*sh) = 1;
479 (*alt) = 1;
480 if (real) return 17; // U with acute
481 return 22; // U with acute -> u with grave
482 case 50108:
483 case 252:
484 (*alt) = 1;
485 return 47; // u with diaeresis
486
487 case 50076:
488 case 220:
489 (*sh) = 1;
490 (*alt) = 1;
491 return 47; // U with diaeresis
492
493 case 50609:
494 case 251:
495 (*alt) = 1;
496 if (real) return 45; // Hungarian u
497 return 47; // Hungarian u -> u with diaeresis
498
499 case 50608:
500 case 219:
501 (*sh) = 1;
502 (*alt) = 1;
503 if (real) return 45; // Hungarian U
504 return 47; // Hungarian U -> U with diaeresis
505 }
506 return 0;
507}