blob: a4b6d7c464c88cea56dcce49af780464a1c774db [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 Kondik16230812017-06-15 12:54:36 -070042 {UI_SET_EVBIT, EV_REP},
Steve Kondik6ec5bc82017-06-15 01:31:51 -070043 {UI_SET_EVBIT, EV_REL},
Steve Kondik16230812017-06-15 12:54:36 -070044 {UI_SET_RELBIT, REL_X},
45 {UI_SET_RELBIT, REL_Y},
46 {UI_SET_RELBIT, REL_WHEEL},
Steve Kondik107d2e52017-06-13 17:34:56 -070047 {UI_SET_EVBIT, EV_ABS},
Steve Kondik107d2e52017-06-13 17:34:56 -070048 {UI_SET_ABSBIT, ABS_X},
49 {UI_SET_ABSBIT, ABS_Y},
Steve Kondik16230812017-06-15 12:54:36 -070050 {UI_SET_EVBIT, EV_SYN},
Steve Kondik107d2e52017-06-13 17:34:56 -070051 {UI_SET_PROPBIT, INPUT_PROP_DIRECT},
52};
53
Steve Kondik107d2e52017-06-13 17:34:56 -070054status_t InputDevice::start(uint32_t width, uint32_t height) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070055 Mutex::Autolock _l(mLock);
56
Steve Kondik107d2e52017-06-13 17:34:56 -070057 status_t err = OK;
Steve Kondik107d2e52017-06-13 17:34:56 -070058
Steve Kondika890c5e2017-06-15 02:46:23 -070059 mLeftClicked = mMiddleClicked = mRightClicked = false;
60
Steve Kondik107d2e52017-06-13 17:34:56 -070061 struct input_id id = {
62 BUS_VIRTUAL, /* Bus type */
63 1, /* Vendor */
64 1, /* Product */
Steve Kondik6ec5bc82017-06-15 01:31:51 -070065 4, /* Version */
Steve Kondik107d2e52017-06-13 17:34:56 -070066 };
67
Steve Kondik6ec5bc82017-06-15 01:31:51 -070068 if (mFD >= 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070069 ALOGE("Input device already open!");
70 return NO_INIT;
71 }
72
Steve Kondik6ec5bc82017-06-15 01:31:51 -070073 mFD = open(UINPUT_DEVICE, O_WRONLY | O_NONBLOCK);
74 if (mFD < 0) {
75 ALOGE("Failed to open %s: err=%d", UINPUT_DEVICE, mFD);
Steve Kondik107d2e52017-06-13 17:34:56 -070076 return NO_INIT;
77 }
78
79 unsigned int idx = 0;
80 for (idx = 0; idx < sizeof(kOptions) / sizeof(kOptions[0]); idx++) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070081 if (ioctl(mFD, kOptions[idx].cmd, kOptions[idx].bit) < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070082 ALOGE("uinput ioctl failed: %d %d", kOptions[idx].cmd, kOptions[idx].bit);
83 goto err_ioctl;
84 }
85 }
86
87 for (idx = 0; idx < KEY_MAX; idx++) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -070088 if (ioctl(mFD, UI_SET_KEYBIT, idx) < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -070089 ALOGE("UI_SET_KEYBIT failed");
90 goto err_ioctl;
91 }
92 }
93
Steve Kondik6ec5bc82017-06-15 01:31:51 -070094 memset(&mUserDev, 0, sizeof(mUserDev));
95 strncpy(mUserDev.name, "VNC-RemoteInput", UINPUT_MAX_NAME_SIZE);
Steve Kondik107d2e52017-06-13 17:34:56 -070096
Steve Kondik6ec5bc82017-06-15 01:31:51 -070097 mUserDev.id = id;
Steve Kondik107d2e52017-06-13 17:34:56 -070098
Steve Kondik6ec5bc82017-06-15 01:31:51 -070099 mUserDev.absmin[ABS_X] = 0;
100 mUserDev.absmax[ABS_X] = width;
101 mUserDev.absmin[ABS_Y] = 0;
102 mUserDev.absmax[ABS_Y] = height;
Steve Kondik107d2e52017-06-13 17:34:56 -0700103
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700104 if (write(mFD, &mUserDev, sizeof(mUserDev)) != sizeof(mUserDev)) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700105 ALOGE("Failed to configure uinput device");
106 goto err_ioctl;
107 }
108
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700109 if (ioctl(mFD, UI_DEV_CREATE) == -1) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700110 ALOGE("UI_DEV_CREATE failed");
111 goto err_ioctl;
112 }
113
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700114 ALOGD("Virtual input device created successfully (%dx%d)", width, height);
115 return NO_ERROR;
Steve Kondik107d2e52017-06-13 17:34:56 -0700116
117err_ioctl:
118 int prev_errno = errno;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700119 ::close(mFD);
Steve Kondik107d2e52017-06-13 17:34:56 -0700120 errno = prev_errno;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700121 mFD = -1;
Steve Kondik107d2e52017-06-13 17:34:56 -0700122 return NO_INIT;
123}
124
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700125status_t InputDevice::reconfigure(uint32_t width, uint32_t height) {
126 stop();
127 return start(width, height);
128}
129
Steve Kondik107d2e52017-06-13 17:34:56 -0700130status_t InputDevice::stop() {
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700131 Mutex::Autolock _l(mLock);
132 if (mFD < 0) {
Steve Kondik107d2e52017-06-13 17:34:56 -0700133 return OK;
134 }
135
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700136 ioctl(mFD, UI_DEV_DESTROY);
137 close(mFD);
138 mFD = -1;
Steve Kondik107d2e52017-06-13 17:34:56 -0700139
140 return OK;
141}
142
143status_t InputDevice::inject(uint16_t type, uint16_t code, int32_t value) {
144 struct input_event event;
145 memset(&event, 0, sizeof(event));
146 gettimeofday(&event.time, 0); /* This should not be able to fail ever.. */
147 event.type = type;
148 event.code = code;
149 event.value = value;
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700150 if (write(mFD, &event, sizeof(event)) != sizeof(event)) return BAD_VALUE;
Steve Kondik107d2e52017-06-13 17:34:56 -0700151 return OK;
152}
153
154status_t InputDevice::injectSyn(uint16_t type, uint16_t code, int32_t value) {
155 if (inject(type, code, value) != OK) {
156 return BAD_VALUE;
157 }
158 return inject(EV_SYN, SYN_REPORT, 0);
159}
160
161status_t InputDevice::movePointer(int32_t x, int32_t y) {
162 if (inject(EV_REL, REL_X, x) != OK) {
163 return BAD_VALUE;
164 }
165 return injectSyn(EV_REL, REL_Y, y);
166}
167
168status_t InputDevice::setPointer(int32_t x, int32_t y) {
169 if (inject(EV_ABS, ABS_X, x) != OK) {
170 return BAD_VALUE;
171 }
172 return injectSyn(EV_ABS, ABS_Y, y);
173}
174
175status_t InputDevice::press(uint16_t code) {
176 return inject(EV_KEY, code, 1);
177}
178
179status_t InputDevice::release(uint16_t code) {
180 return inject(EV_KEY, code, 0);
181}
182
183status_t InputDevice::click(uint16_t code) {
184 if (press(code) != OK) {
185 return BAD_VALUE;
186 }
187 return release(code);
188}
189
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700190void InputDevice::onKeyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl) {
191 InputDevice::getInstance().keyEvent(down, key, cl);
192}
193
Steve Kondik107d2e52017-06-13 17:34:56 -0700194void InputDevice::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl) {
195 int code;
196 int sh = 0;
197 int alt = 0;
198
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700199 if (mFD < 0) return;
200
201 Mutex::Autolock _l(mLock);
Steve Kondik107d2e52017-06-13 17:34:56 -0700202
203 if ((code = keysym2scancode(key, cl, &sh, &alt))) {
204 int ret = 0;
205
206 if (key && down) {
207 if (sh) press(42); // left shift
208 if (alt) press(56); // left alt
209
210 inject(EV_SYN, SYN_REPORT, 0);
211
212 ret = press(code);
213 if (ret != 0) {
214 ALOGE("Error: %d (%s)\n", errno, strerror(errno));
215 }
216
217 inject(EV_SYN, SYN_REPORT, 0);
218
219 ret = release(code);
220 if (ret != 0) {
221 ALOGE("Error: %d (%s)\n", errno, strerror(errno));
222 }
223
224 inject(EV_SYN, SYN_REPORT, 0);
225
226 if (alt) release(56); // left alt
227 if (sh) release(42); // left shift
228
229 inject(EV_SYN, SYN_REPORT, 0);
230 }
231 }
232}
233
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700234void InputDevice::onPointerEvent(int buttonMask, int x, int y, rfbClientPtr cl) {
235 InputDevice::getInstance().pointerEvent(buttonMask, x, y, cl);
236}
237
Steve Kondika890c5e2017-06-15 02:46:23 -0700238void InputDevice::pointerEvent(int buttonMask, int x, int y, rfbClientPtr /* cl */) {
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700239 if (mFD < 0) return;
240
241 ALOGV("pointerEvent: buttonMask=%x x=%d y=%d", buttonMask, x, y);
242
243 Mutex::Autolock _l(mLock);
Steve Kondik107d2e52017-06-13 17:34:56 -0700244
Steve Kondika890c5e2017-06-15 02:46:23 -0700245 if ((buttonMask & 1) && mLeftClicked) { // left btn clicked and moving
246 inject(EV_ABS, ABS_X, x);
247 inject(EV_ABS, ABS_Y, y);
248 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik107d2e52017-06-13 17:34:56 -0700249
Steve Kondik2c9d0cf2017-06-15 23:39:29 -0700250 } else if (buttonMask & 1) { // left btn clicked
Steve Kondika890c5e2017-06-15 02:46:23 -0700251 mLeftClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700252
253 inject(EV_ABS, ABS_X, x);
254 inject(EV_ABS, ABS_Y, y);
255 inject(EV_KEY, BTN_TOUCH, 1);
256 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700257 } else if (mLeftClicked) // left btn released
Steve Kondik107d2e52017-06-13 17:34:56 -0700258 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700259 mLeftClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700260 inject(EV_ABS, ABS_X, x);
261 inject(EV_ABS, ABS_Y, y);
262 inject(EV_KEY, BTN_TOUCH, 0);
263 inject(EV_SYN, SYN_REPORT, 0);
264 }
265
266 if (buttonMask & 4) // right btn clicked
267 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700268 mRightClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700269 press(158); // back key
270 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700271 } else if (mRightClicked) // right button released
Steve Kondik107d2e52017-06-13 17:34:56 -0700272 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700273 mRightClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700274 release(158);
275 inject(EV_SYN, SYN_REPORT, 0);
276 }
277
278 if (buttonMask & 2) // mid btn clicked
279 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700280 mMiddleClicked = true;
Steve Kondik107d2e52017-06-13 17:34:56 -0700281 press(KEY_END);
282 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondika890c5e2017-06-15 02:46:23 -0700283 } else if (mMiddleClicked) // mid btn released
Steve Kondik107d2e52017-06-13 17:34:56 -0700284 {
Steve Kondika890c5e2017-06-15 02:46:23 -0700285 mMiddleClicked = false;
Steve Kondik107d2e52017-06-13 17:34:56 -0700286 release(KEY_END);
287 inject(EV_SYN, SYN_REPORT, 0);
288 }
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700289
290 if (buttonMask & 8) {
291 inject(EV_REL, REL_WHEEL, 1);
Steve Kondika890c5e2017-06-15 02:46:23 -0700292 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700293 }
294
295 if (buttonMask & 0x10) {
296 inject(EV_REL, REL_WHEEL, -1);
Steve Kondika890c5e2017-06-15 02:46:23 -0700297 inject(EV_SYN, SYN_REPORT, 0);
Steve Kondik6ec5bc82017-06-15 01:31:51 -0700298 }
Steve Kondik107d2e52017-06-13 17:34:56 -0700299}
300
301// 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
302static const int qwerty[] = {30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50,
303 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44};
304// ,!,",#,$,%,&,',(,),*,+,,,-,.,/
305static const int spec1[] = {57, 2, 40, 4, 5, 6, 8, 40, 10, 11, 9, 13, 51, 12, 52, 52};
306static const int spec1sh[] = {0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1};
307// :,;,<,=,>,?,@
308static const int spec2[] = {39, 39, 227, 13, 228, 53, 3};
309static const int spec2sh[] = {1, 0, 1, 1, 1, 1, 1};
310// [,\,],^,_,`
311static const int spec3[] = {26, 43, 27, 7, 12, 399};
312static const int spec3sh[] = {0, 0, 0, 1, 1, 0};
313// {,|,},~
314static const int spec4[] = {26, 43, 27, 215, 14};
315static const int spec4sh[] = {1, 1, 1, 1, 0};
316
317int InputDevice::keysym2scancode(rfbKeySym c, rfbClientPtr cl, int* sh, int* alt) {
318 int real = 1;
319 if ('a' <= c && c <= 'z') return qwerty[c - 'a'];
320 if ('A' <= c && c <= 'Z') {
321 (*sh) = 1;
322 return qwerty[c - 'A'];
323 }
324 if ('1' <= c && c <= '9') return c - '1' + 2;
325 if (c == '0') return 11;
326 if (32 <= c && c <= 47) {
327 (*sh) = spec1sh[c - 32];
328 return spec1[c - 32];
329 }
330 if (58 <= c && c <= 64) {
331 (*sh) = spec2sh[c - 58];
332 return spec2[c - 58];
333 }
334 if (91 <= c && c <= 96) {
335 (*sh) = spec3sh[c - 91];
336 return spec3[c - 91];
337 }
338 if (123 <= c && c <= 127) {
339 (*sh) = spec4sh[c - 123];
340 return spec4[c - 123];
341 }
342 switch (c) {
343 case 0xff08:
344 return 14; // backspace
345 case 0xff09:
346 return 15; // tab
347 case 1:
348 (*alt) = 1;
349 return 34; // ctrl+a
350 case 3:
351 (*alt) = 1;
352 return 46; // ctrl+c
353 case 4:
354 (*alt) = 1;
355 return 32; // ctrl+d
356 case 18:
357 (*alt) = 1;
358 return 31; // ctrl+r
359 case 0xff0D:
360 return 28; // enter
361 case 0xff1B:
362 return 158; // esc -> back
363 case 0xFF51:
364 return 105; // left -> DPAD_LEFT
365 case 0xFF53:
366 return 106; // right -> DPAD_RIGHT
367 case 0xFF54:
368 return 108; // down -> DPAD_DOWN
369 case 0xFF52:
370 return 103; // up -> DPAD_UP
371 // case 360:
372 // return 232;// end -> DPAD_CENTER (ball click)
373 case 0xff50:
374 return KEY_HOME; // home
375 case 0xFFC8:
376 rfbShutdownServer(cl->screen, TRUE);
377 return 0; // F11 disconnect
378 case 0xffff:
379 return 158; // del -> back
380 case 0xff55:
381 return 229; // PgUp -> menu
382 case 0xffcf:
383 return 127; // F2 -> search
384 case 0xffe3:
385 return 127; // left ctrl -> search
386 case 0xff56:
387 return 61; // PgUp -> call
388 case 0xff57:
389 return 107; // End -> endcall
390 case 0xffc2:
391 return 211; // F5 -> focus
392 case 0xffc3:
393 return 212; // F6 -> camera
394 case 0xffc4:
395 return 150; // F7 -> explorer
396 case 0xffc5:
397 return 155; // F8 -> envelope
398
399 case 50081:
400 case 225:
401 (*alt) = 1;
402 if (real) return 48; // a with acute
403 return 30; // a with acute -> a with ring above
404
405 case 50049:
406 case 193:
407 (*sh) = 1;
408 (*alt) = 1;
409 if (real) return 48; // A with acute
410 return 30; // A with acute -> a with ring above
411
412 case 50089:
413 case 233:
414 (*alt) = 1;
415 return 18; // e with acute
416
417 case 50057:
418 case 201:
419 (*sh) = 1;
420 (*alt) = 1;
421 return 18; // E with acute
422
423 case 50093:
424 case 0xffbf:
425 (*alt) = 1;
426 if (real) return 36; // i with acute
427 return 23; // i with acute -> i with grave
428
429 case 50061:
430 case 205:
431 (*sh) = 1;
432 (*alt) = 1;
433 if (real) return 36; // I with acute
434 return 23; // I with acute -> i with grave
435
436 case 50099:
437 case 243:
438 (*alt) = 1;
439 if (real) return 16; // o with acute
440 return 24; // o with acute -> o with grave
441
442 case 50067:
443 case 211:
444 (*sh) = 1;
445 (*alt) = 1;
446 if (real) return 16; // O with acute
447 return 24; // O with acute -> o with grave
448
449 case 50102:
450 case 246:
451 (*alt) = 1;
452 return 25; // o with diaeresis
453
454 case 50070:
455 case 214:
456 (*sh) = 1;
457 (*alt) = 1;
458 return 25; // O with diaeresis
459
460 case 50577:
461 case 245:
462 (*alt) = 1;
463 if (real) return 19; // Hungarian o
464 return 25; // Hungarian o -> o with diaeresis
465
466 case 50576:
467 case 213:
468 (*sh) = 1;
469 (*alt) = 1;
470 if (real) return 19; // Hungarian O
471 return 25; // Hungarian O -> O with diaeresis
472
473 case 50106:
474 // case 0xffbe:
475 // (*alt)=1;
476 // if (real)
477 // return 17; //u with acute
478 // return 22; //u with acute -> u with grave
479 case 50074:
480 case 218:
481 (*sh) = 1;
482 (*alt) = 1;
483 if (real) return 17; // U with acute
484 return 22; // U with acute -> u with grave
485 case 50108:
486 case 252:
487 (*alt) = 1;
488 return 47; // u with diaeresis
489
490 case 50076:
491 case 220:
492 (*sh) = 1;
493 (*alt) = 1;
494 return 47; // U with diaeresis
495
496 case 50609:
497 case 251:
498 (*alt) = 1;
499 if (real) return 45; // Hungarian u
500 return 47; // Hungarian u -> u with diaeresis
501
502 case 50608:
503 case 219:
504 (*sh) = 1;
505 (*alt) = 1;
506 if (real) return 45; // Hungarian U
507 return 47; // Hungarian U -> U with diaeresis
508 }
509 return 0;
510}