blob: 31c03282e1ee23593949c64e5769c34f592e1762 [file] [log] [blame]
Jorge E. Moreiraccd57452017-09-29 15:19:07 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "host/frontend/vnc_server/virtual_inputs.h"
Greg Hartman70ac1d22017-10-18 12:30:36 -070018#include <gflags/gflags.h>
Jorge E. Moreira02ccbd52018-01-25 16:57:48 -080019#include <linux/input.h>
20#include <linux/uinput.h>
Greg Hartmanca7fb192017-09-28 16:14:12 -070021
Cody Schuffelen038d4d92019-11-04 15:09:03 -080022#include <cstdint>
Jorge E. Moreira24307012017-09-22 14:35:21 -070023#include <mutex>
Jorge E. Moreira02ccbd52018-01-25 16:57:48 -080024#include "keysyms.h"
Greg Hartmanca7fb192017-09-28 16:14:12 -070025
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -080026#include <common/libs/fs/shared_select.h>
27#include <host/libs/config/cuttlefish_config.h>
28
Greg Hartman153b1062017-11-11 12:09:21 -080029using cvd::vnc::VirtualInputs;
Cody Schuffelen134ff032019-11-22 00:25:32 -080030using vsoc::input_events::InputEventsRegionView;
Greg Hartmanca7fb192017-09-28 16:14:12 -070031
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -080032DEFINE_int32(touch_fd, -1,
33 "A fd for a socket where to accept touch connections");
34
35DEFINE_int32(keyboard_fd, -1,
36 "A fd for a socket where to accept keyboard connections");
37
Cody Schuffelen038d4d92019-11-04 15:09:03 -080038DEFINE_bool(write_virtio_input, false,
39 "Whether to write the virtio_input struct over the socket");
40
Greg Hartmanca7fb192017-09-28 16:14:12 -070041namespace {
Cody Schuffelen038d4d92019-11-04 15:09:03 -080042// Necessary to define here as the virtio_input.h header is not available
43// in the host glibc.
44struct virtio_input_event {
45 std::uint16_t type;
46 std::uint16_t code;
47 std::int32_t value;
48};
49
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -080050void AddKeyMappings(std::map<uint32_t, uint16_t>* key_mapping) {
Jorge E. Moreira02ccbd52018-01-25 16:57:48 -080051 (*key_mapping)[cvd::xk::AltLeft] = KEY_LEFTALT;
52 (*key_mapping)[cvd::xk::ControlLeft] = KEY_LEFTCTRL;
53 (*key_mapping)[cvd::xk::ShiftLeft] = KEY_LEFTSHIFT;
54 (*key_mapping)[cvd::xk::AltRight] = KEY_RIGHTALT;
55 (*key_mapping)[cvd::xk::ControlRight] = KEY_RIGHTCTRL;
56 (*key_mapping)[cvd::xk::ShiftRight] = KEY_RIGHTSHIFT;
57 (*key_mapping)[cvd::xk::MetaLeft] = KEY_LEFTMETA;
58 (*key_mapping)[cvd::xk::MetaRight] = KEY_RIGHTMETA;
59 (*key_mapping)[cvd::xk::MultiKey] = KEY_COMPOSE;
Greg Hartmanca7fb192017-09-28 16:14:12 -070060
Jorge E. Moreira02ccbd52018-01-25 16:57:48 -080061 (*key_mapping)[cvd::xk::CapsLock] = KEY_CAPSLOCK;
62 (*key_mapping)[cvd::xk::NumLock] = KEY_NUMLOCK;
63 (*key_mapping)[cvd::xk::ScrollLock] = KEY_SCROLLLOCK;
64
65 (*key_mapping)[cvd::xk::BackSpace] = KEY_BACKSPACE;
66 (*key_mapping)[cvd::xk::Tab] = KEY_TAB;
67 (*key_mapping)[cvd::xk::Return] = KEY_ENTER;
68 (*key_mapping)[cvd::xk::Escape] = KEY_ESC;
69
70 (*key_mapping)[' '] = KEY_SPACE;
71 (*key_mapping)['!'] = KEY_1;
72 (*key_mapping)['"'] = KEY_APOSTROPHE;
73 (*key_mapping)['#'] = KEY_3;
74 (*key_mapping)['$'] = KEY_4;
75 (*key_mapping)['%'] = KEY_5;
76 (*key_mapping)['^'] = KEY_6;
77 (*key_mapping)['&'] = KEY_7;
78 (*key_mapping)['\''] = KEY_APOSTROPHE;
79 (*key_mapping)['('] = KEY_9;
80 (*key_mapping)[')'] = KEY_0;
81 (*key_mapping)['*'] = KEY_8;
82 (*key_mapping)['+'] = KEY_EQUAL;
83 (*key_mapping)[','] = KEY_COMMA;
84 (*key_mapping)['-'] = KEY_MINUS;
85 (*key_mapping)['.'] = KEY_DOT;
86 (*key_mapping)['/'] = KEY_SLASH;
87 (*key_mapping)['0'] = KEY_0;
88 (*key_mapping)['1'] = KEY_1;
89 (*key_mapping)['2'] = KEY_2;
90 (*key_mapping)['3'] = KEY_3;
91 (*key_mapping)['4'] = KEY_4;
92 (*key_mapping)['5'] = KEY_5;
93 (*key_mapping)['6'] = KEY_6;
94 (*key_mapping)['7'] = KEY_7;
95 (*key_mapping)['8'] = KEY_8;
96 (*key_mapping)['9'] = KEY_9;
97 (*key_mapping)[':'] = KEY_SEMICOLON;
98 (*key_mapping)[';'] = KEY_SEMICOLON;
99 (*key_mapping)['<'] = KEY_COMMA;
100 (*key_mapping)['='] = KEY_EQUAL;
101 (*key_mapping)['>'] = KEY_DOT;
102 (*key_mapping)['?'] = KEY_SLASH;
103 (*key_mapping)['@'] = KEY_2;
104 (*key_mapping)['A'] = KEY_A;
105 (*key_mapping)['B'] = KEY_B;
106 (*key_mapping)['C'] = KEY_C;
107 (*key_mapping)['D'] = KEY_D;
108 (*key_mapping)['E'] = KEY_E;
109 (*key_mapping)['F'] = KEY_F;
110 (*key_mapping)['G'] = KEY_G;
111 (*key_mapping)['H'] = KEY_H;
112 (*key_mapping)['I'] = KEY_I;
113 (*key_mapping)['J'] = KEY_J;
114 (*key_mapping)['K'] = KEY_K;
115 (*key_mapping)['L'] = KEY_L;
116 (*key_mapping)['M'] = KEY_M;
117 (*key_mapping)['N'] = KEY_N;
118 (*key_mapping)['O'] = KEY_O;
119 (*key_mapping)['P'] = KEY_P;
120 (*key_mapping)['Q'] = KEY_Q;
121 (*key_mapping)['R'] = KEY_R;
122 (*key_mapping)['S'] = KEY_S;
123 (*key_mapping)['T'] = KEY_T;
124 (*key_mapping)['U'] = KEY_U;
125 (*key_mapping)['V'] = KEY_V;
126 (*key_mapping)['W'] = KEY_W;
127 (*key_mapping)['X'] = KEY_X;
128 (*key_mapping)['Y'] = KEY_Y;
129 (*key_mapping)['Z'] = KEY_Z;
130 (*key_mapping)['['] = KEY_LEFTBRACE;
131 (*key_mapping)['\\'] = KEY_BACKSLASH;
132 (*key_mapping)[']'] = KEY_RIGHTBRACE;
133 (*key_mapping)['-'] = KEY_MINUS;
134 (*key_mapping)['_'] = KEY_MINUS;
135 (*key_mapping)['`'] = KEY_GRAVE;
136 (*key_mapping)['a'] = KEY_A;
137 (*key_mapping)['b'] = KEY_B;
138 (*key_mapping)['c'] = KEY_C;
139 (*key_mapping)['d'] = KEY_D;
140 (*key_mapping)['e'] = KEY_E;
141 (*key_mapping)['f'] = KEY_F;
142 (*key_mapping)['g'] = KEY_G;
143 (*key_mapping)['h'] = KEY_H;
144 (*key_mapping)['i'] = KEY_I;
145 (*key_mapping)['j'] = KEY_J;
146 (*key_mapping)['k'] = KEY_K;
147 (*key_mapping)['l'] = KEY_L;
148 (*key_mapping)['m'] = KEY_M;
149 (*key_mapping)['n'] = KEY_N;
150 (*key_mapping)['o'] = KEY_O;
151 (*key_mapping)['p'] = KEY_P;
152 (*key_mapping)['q'] = KEY_Q;
153 (*key_mapping)['r'] = KEY_R;
154 (*key_mapping)['s'] = KEY_S;
155 (*key_mapping)['t'] = KEY_T;
156 (*key_mapping)['u'] = KEY_U;
157 (*key_mapping)['v'] = KEY_V;
158 (*key_mapping)['w'] = KEY_W;
159 (*key_mapping)['x'] = KEY_X;
160 (*key_mapping)['y'] = KEY_Y;
161 (*key_mapping)['z'] = KEY_Z;
162 (*key_mapping)['{'] = KEY_LEFTBRACE;
163 (*key_mapping)['\\'] = KEY_BACKSLASH;
164 (*key_mapping)['|'] = KEY_BACKSLASH;
165 (*key_mapping)['}'] = KEY_RIGHTBRACE;
166 (*key_mapping)['~'] = KEY_GRAVE;
167
168 (*key_mapping)[cvd::xk::F1] = KEY_F1;
169 (*key_mapping)[cvd::xk::F2] = KEY_F2;
170 (*key_mapping)[cvd::xk::F3] = KEY_F3;
171 (*key_mapping)[cvd::xk::F4] = KEY_F4;
172 (*key_mapping)[cvd::xk::F5] = KEY_F5;
173 (*key_mapping)[cvd::xk::F6] = KEY_F6;
174 (*key_mapping)[cvd::xk::F7] = KEY_F7;
175 (*key_mapping)[cvd::xk::F8] = KEY_F8;
176 (*key_mapping)[cvd::xk::F9] = KEY_F9;
177 (*key_mapping)[cvd::xk::F10] = KEY_F10;
178 (*key_mapping)[cvd::xk::F11] = KEY_F11;
179 (*key_mapping)[cvd::xk::F12] = KEY_F12;
180 (*key_mapping)[cvd::xk::F13] = KEY_F13;
181 (*key_mapping)[cvd::xk::F14] = KEY_F14;
182 (*key_mapping)[cvd::xk::F15] = KEY_F15;
183 (*key_mapping)[cvd::xk::F16] = KEY_F16;
184 (*key_mapping)[cvd::xk::F17] = KEY_F17;
185 (*key_mapping)[cvd::xk::F18] = KEY_F18;
186 (*key_mapping)[cvd::xk::F19] = KEY_F19;
187 (*key_mapping)[cvd::xk::F20] = KEY_F20;
188 (*key_mapping)[cvd::xk::F21] = KEY_F21;
189 (*key_mapping)[cvd::xk::F22] = KEY_F22;
190 (*key_mapping)[cvd::xk::F23] = KEY_F23;
191 (*key_mapping)[cvd::xk::F24] = KEY_F24;
192
193 (*key_mapping)[cvd::xk::Keypad0] = KEY_KP0;
194 (*key_mapping)[cvd::xk::Keypad1] = KEY_KP1;
195 (*key_mapping)[cvd::xk::Keypad2] = KEY_KP2;
196 (*key_mapping)[cvd::xk::Keypad3] = KEY_KP3;
197 (*key_mapping)[cvd::xk::Keypad4] = KEY_KP4;
198 (*key_mapping)[cvd::xk::Keypad5] = KEY_KP5;
199 (*key_mapping)[cvd::xk::Keypad6] = KEY_KP6;
200 (*key_mapping)[cvd::xk::Keypad7] = KEY_KP7;
201 (*key_mapping)[cvd::xk::Keypad8] = KEY_KP8;
202 (*key_mapping)[cvd::xk::Keypad9] = KEY_KP9;
203 (*key_mapping)[cvd::xk::KeypadMultiply] = KEY_KPASTERISK;
204 (*key_mapping)[cvd::xk::KeypadSubtract] = KEY_KPMINUS;
205 (*key_mapping)[cvd::xk::KeypadAdd] = KEY_KPPLUS;
206 (*key_mapping)[cvd::xk::KeypadDecimal] = KEY_KPDOT;
207 (*key_mapping)[cvd::xk::KeypadEnter] = KEY_KPENTER;
208 (*key_mapping)[cvd::xk::KeypadDivide] = KEY_KPSLASH;
209 (*key_mapping)[cvd::xk::KeypadEqual] = KEY_KPEQUAL;
210 (*key_mapping)[cvd::xk::PlusMinus] = KEY_KPPLUSMINUS;
211
212 (*key_mapping)[cvd::xk::SysReq] = KEY_SYSRQ;
213 (*key_mapping)[cvd::xk::LineFeed] = KEY_LINEFEED;
214 (*key_mapping)[cvd::xk::Home] = KEY_HOME;
215 (*key_mapping)[cvd::xk::Up] = KEY_UP;
216 (*key_mapping)[cvd::xk::PageUp] = KEY_PAGEUP;
217 (*key_mapping)[cvd::xk::Left] = KEY_LEFT;
218 (*key_mapping)[cvd::xk::Right] = KEY_RIGHT;
219 (*key_mapping)[cvd::xk::End] = KEY_END;
220 (*key_mapping)[cvd::xk::Down] = KEY_DOWN;
221 (*key_mapping)[cvd::xk::PageDown] = KEY_PAGEDOWN;
222 (*key_mapping)[cvd::xk::Insert] = KEY_INSERT;
223 (*key_mapping)[cvd::xk::Delete] = KEY_DELETE;
224 (*key_mapping)[cvd::xk::Pause] = KEY_PAUSE;
225 (*key_mapping)[cvd::xk::KeypadSeparator] = KEY_KPCOMMA;
226 (*key_mapping)[cvd::xk::Yen] = KEY_YEN;
227 (*key_mapping)[cvd::xk::Cancel] = KEY_STOP;
228 (*key_mapping)[cvd::xk::Redo] = KEY_AGAIN;
229 (*key_mapping)[cvd::xk::Undo] = KEY_UNDO;
230 (*key_mapping)[cvd::xk::Find] = KEY_FIND;
231 (*key_mapping)[cvd::xk::Print] = KEY_PRINT;
232 (*key_mapping)[cvd::xk::VolumeDown] = KEY_VOLUMEDOWN;
233 (*key_mapping)[cvd::xk::Mute] = KEY_MUTE;
234 (*key_mapping)[cvd::xk::VolumeUp] = KEY_VOLUMEUP;
235 (*key_mapping)[cvd::xk::Menu] = KEY_MENU;
236 (*key_mapping)[cvd::xk::VNCMenu] = KEY_MENU;
237}
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800238
239void InitInputEvent(struct input_event* evt, uint16_t type, uint16_t code,
240 int32_t value) {
241 evt->type = type;
242 evt->code = code;
243 evt->value = value;
244}
245
Jorge E. Moreira02ccbd52018-01-25 16:57:48 -0800246} // namespace
247
Cody Schuffelen134ff032019-11-22 00:25:32 -0800248class VSoCVirtualInputs : public VirtualInputs {
249 public:
250 VSoCVirtualInputs()
251 : input_events_region_view_{
252 vsoc::input_events::InputEventsRegionView::GetInstance(
253 vsoc::GetDomain().c_str())} {
254 if (!input_events_region_view_) {
255 LOG(FATAL) << "Failed to open Input events region view";
256 }
257 }
258
259 void GenerateKeyPressEvent(int code, bool down) override {
260 if (keymapping_.count(code)) {
261 input_events_region_view_->HandleKeyboardEvent(down, keymapping_[code]);
262 } else {
263 LOG(ERROR) << "Unknown keycode" << code;
264 }
265 }
266
267 void PressPowerButton(bool down) override {
268 input_events_region_view_->HandlePowerButtonEvent(down);
269 }
270
271 void HandlePointerEvent(bool touch_down, int x, int y) override {
272 input_events_region_view_->HandleSingleTouchEvent(touch_down, x, y);
273 }
274
275 private:
276 vsoc::input_events::InputEventsRegionView* input_events_region_view_{};
277};
278
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800279class SocketVirtualInputs : public VirtualInputs {
280 public:
281 SocketVirtualInputs()
282 : client_connector_([this]() { ClientConnectorLoop(); }) {}
283
284 void GenerateKeyPressEvent(int key_code, bool down) override {
285 struct input_event events[2];
286 InitInputEvent(&events[0], EV_KEY, keymapping_[key_code], down);
287 InitInputEvent(&events[1], EV_SYN, 0, 0);
288
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800289 SendEvents(keyboard_socket_, events);
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800290 }
291
292 void PressPowerButton(bool down) override {
293 struct input_event events[2];
294 InitInputEvent(&events[0], EV_KEY, KEY_POWER, down);
295 InitInputEvent(&events[1], EV_SYN, 0, 0);
296
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800297 SendEvents(keyboard_socket_, events);
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800298 }
299
300 void HandlePointerEvent(bool touch_down, int x, int y) override {
301 // TODO(b/124121375): Use multitouch when available
302 struct input_event events[4];
303 InitInputEvent(&events[0], EV_ABS, ABS_X, x);
304 InitInputEvent(&events[1], EV_ABS, ABS_Y, y);
305 InitInputEvent(&events[2], EV_KEY, BTN_TOUCH, touch_down);
306 InitInputEvent(&events[3], EV_SYN, 0, 0);
307
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800308 SendEvents(touch_socket_, events);
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800309 }
310
311 private:
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800312 template<size_t num_events>
313 void SendEvents(cvd::SharedFD socket, struct input_event (&event_buffer)[num_events]) {
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800314 std::lock_guard<std::mutex> lock(socket_mutex_);
315 if (!socket->IsOpen()) {
316 // This is unlikely as it would only happen between the start of the vnc
317 // server and the connection of the VMM to the socket.
318 // If it happens, just drop the events as the VM is not yet ready to
319 // handle it.
320 return;
321 }
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800322
323 if (FLAGS_write_virtio_input) {
324 struct virtio_input_event virtio_events[num_events];
325 for (size_t i = 0; i < num_events; i++) {
326 virtio_events[i] = (struct virtio_input_event) {
327 .type = event_buffer[i].type,
328 .code = event_buffer[i].code,
329 .value = event_buffer[i].value,
330 };
331 }
332 auto ret = socket->Write(virtio_events, sizeof(virtio_events));
333 if (ret < 0) {
334 LOG(ERROR) << "Error sending input events: " << socket->StrError();
335 }
336 } else {
337 auto ret = socket->Write(event_buffer, sizeof(event_buffer));
338 if (ret < 0) {
339 LOG(ERROR) << "Error sending input events: " << socket->StrError();
340 }
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800341 }
342 }
343
344 void ClientConnectorLoop() {
345 auto touch_server = cvd::SharedFD::Dup(FLAGS_touch_fd);
346 close(FLAGS_touch_fd);
347 FLAGS_touch_fd = -1;
348
349 auto keyboard_server = cvd::SharedFD::Dup(FLAGS_keyboard_fd);
350 close(FLAGS_keyboard_fd);
351 FLAGS_keyboard_fd = -1;
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800352 LOG(INFO) << "Input socket host accepting connections...";
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800353
354 while (1) {
355 cvd::SharedFDSet read_set;
356 read_set.Set(touch_server);
357 read_set.Set(keyboard_server);
358 cvd::Select(&read_set, nullptr, nullptr, nullptr);
359 {
360 std::lock_guard<std::mutex> lock(socket_mutex_);
361 if (read_set.IsSet(touch_server)) {
362 touch_socket_ = cvd::SharedFD::Accept(*touch_server);
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800363 LOG(INFO) << "connected to touch";
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800364 }
365 if (read_set.IsSet(keyboard_server)) {
366 keyboard_socket_ = cvd::SharedFD::Accept(*keyboard_server);
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800367 LOG(INFO) << "connected to keyboard";
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800368 }
369 }
370 }
371 }
372 cvd::SharedFD touch_socket_;
373 cvd::SharedFD keyboard_socket_;
374 std::thread client_connector_;
375 std::mutex socket_mutex_;
376};
377
378VirtualInputs::VirtualInputs() { AddKeyMappings(&keymapping_); }
379
380VirtualInputs* VirtualInputs::Get() {
Cody Schuffelen038d4d92019-11-04 15:09:03 -0800381 return new SocketVirtualInputs();
Jorge E. Moreira24307012017-09-22 14:35:21 -0700382}