blob: 8cdefe4109a1031c29c2a55df90ee8af9e5c677e [file] [log] [blame]
Eddie James21b177e2018-12-11 13:14:46 -06001#include "ikvm_input.hpp"
2
3#include "ikvm_server.hpp"
George Liuf79f6f52022-07-06 09:32:35 +08004#include "scancodes.hpp"
Eddie James21b177e2018-12-11 13:14:46 -06005
6#include <err.h>
7#include <errno.h>
8#include <fcntl.h>
9#include <rfb/keysym.h>
10#include <sys/stat.h>
11#include <sys/types.h>
12
13#include <phosphor-logging/elog-errors.hpp>
14#include <phosphor-logging/elog.hpp>
15#include <phosphor-logging/log.hpp>
16#include <xyz/openbmc_project/Common/File/error.hpp>
17
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070018namespace fs = std::filesystem;
19
Eddie James21b177e2018-12-11 13:14:46 -060020namespace ikvm
21{
Eddie James21b177e2018-12-11 13:14:46 -060022using namespace phosphor::logging;
23using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
24
Marvin Linfe685fb2022-10-25 16:20:08 +080025Input::Input(const std::string& kbdPath, const std::string& ptrPath,
26 const std::string& udc) :
Patrick Williams94f5f422024-08-16 15:22:08 -040027 keyboardFd(-1), pointerFd(-1), keyboardReport{0}, pointerReport{0},
28 keyboardPath(kbdPath), pointerPath(ptrPath), udcName(udc)
Eddie James21b177e2018-12-11 13:14:46 -060029{
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070030 hidUdcStream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
31 hidUdcStream.open(hidUdcPath, std::ios::out | std::ios::app);
32}
33
34Input::~Input()
35{
36 if (keyboardFd >= 0)
37 {
38 close(keyboardFd);
39 }
40
41 if (pointerFd >= 0)
42 {
43 close(pointerFd);
44 }
45
46 disconnect();
47 hidUdcStream.close();
48}
49
50void Input::connect()
51{
52 try
53 {
Marvin Linfe685fb2022-10-25 16:20:08 +080054 if (udcName.empty())
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070055 {
Troy Lee20de8592023-02-10 14:15:09 +080056 bool found = false;
Marvin Linfe685fb2022-10-25 16:20:08 +080057 for (const auto& port : fs::directory_iterator(usbVirtualHubPath))
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070058 {
Troy Lee20de8592023-02-10 14:15:09 +080059 // /sys/bus/platform/devices/1e6a0000.usb-vhub/1e6a0000.usb-vhub:pX
60 if (fs::is_directory(port) && !fs::is_symlink(port))
Marvin Linfe685fb2022-10-25 16:20:08 +080061 {
Troy Lee20de8592023-02-10 14:15:09 +080062 for (const auto& gadget :
63 fs::directory_iterator(port.path()))
64 {
65 // Kernel 6.0:
66 // /sys/.../1e6a0000.usb-vhub:pX/gadget.Y/suspended
67 // Kernel 5.15:
68 // /sys/.../1e6a0000.usb-vhub:pX/gadget/suspended
69 if (fs::is_directory(gadget) &&
70 gadget.path().string().find("gadget") !=
71 std::string::npos &&
72 !fs::exists(gadget.path() / "suspended"))
73 {
Troy Lee4148d0c2023-03-15 16:23:45 +080074 const std::string portId = port.path().filename();
Troy Lee20de8592023-02-10 14:15:09 +080075 hidUdcStream << portId << std::endl;
76 found = true;
77 break;
78 }
79 }
80 }
81 if (found)
82 {
Marvin Linfe685fb2022-10-25 16:20:08 +080083 break;
84 }
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070085 }
86 }
Marvin Linfe685fb2022-10-25 16:20:08 +080087 else // If UDC has been specified by '-u' parameter, connect to it.
88 {
89 hidUdcStream << udcName << std::endl;
90 }
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070091 }
92 catch (fs::filesystem_error& e)
93 {
94 log<level::ERR>("Failed to search USB virtual hub port",
95 entry("ERROR=%s", e.what()));
96 return;
97 }
98 catch (std::ofstream::failure& e)
99 {
100 log<level::ERR>("Failed to connect HID gadget",
101 entry("ERROR=%s", e.what()));
102 return;
103 }
104
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800105 if (!keyboardPath.empty())
Eddie James21b177e2018-12-11 13:14:46 -0600106 {
Patrick Williams94f5f422024-08-16 15:22:08 -0400107 keyboardFd =
108 open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800109 if (keyboardFd < 0)
110 {
111 log<level::ERR>("Failed to open input device",
112 entry("PATH=%s", keyboardPath.c_str()),
113 entry("ERROR=%s", strerror(errno)));
114 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno),
115 xyz::openbmc_project::Common::File::Open::PATH(
116 keyboardPath.c_str()));
117 }
Eddie James21b177e2018-12-11 13:14:46 -0600118 }
119
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800120 if (!pointerPath.empty())
121 {
Eddie James4749f932019-04-18 11:06:39 -0500122 pointerFd = open(pointerPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800123 if (pointerFd < 0)
124 {
125 log<level::ERR>("Failed to open input device",
126 entry("PATH=%s", pointerPath.c_str()),
127 entry("ERROR=%s", strerror(errno)));
128 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno),
129 xyz::openbmc_project::Common::File::Open::PATH(
130 pointerPath.c_str()));
131 }
132 }
Eddie James21b177e2018-12-11 13:14:46 -0600133}
134
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700135void Input::disconnect()
Eddie James21b177e2018-12-11 13:14:46 -0600136{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800137 if (keyboardFd >= 0)
138 {
139 close(keyboardFd);
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700140 keyboardFd = -1;
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800141 }
142
143 if (pointerFd >= 0)
144 {
145 close(pointerFd);
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700146 pointerFd = -1;
147 }
148
149 try
150 {
151 hidUdcStream << "" << std::endl;
152 }
153 catch (std::ofstream::failure& e)
154 {
155 log<level::ERR>("Failed to disconnect HID gadget",
156 entry("ERROR=%s", e.what()));
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800157 }
Eddie James21b177e2018-12-11 13:14:46 -0600158}
159
160void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
161{
162 Server::ClientData* cd = (Server::ClientData*)cl->clientData;
163 Input* input = cd->input;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700164 bool sendKeyboard = false;
165
166 if (input->keyboardFd < 0)
167 {
168 return;
169 }
Eddie James21b177e2018-12-11 13:14:46 -0600170
171 if (down)
172 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800173 uint8_t sc = keyToScancode(key);
Eddie James21b177e2018-12-11 13:14:46 -0600174
175 if (sc)
176 {
177 if (input->keysDown.find(key) == input->keysDown.end())
178 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800179 for (unsigned int i = 2; i < KEY_REPORT_LENGTH; ++i)
Eddie James21b177e2018-12-11 13:14:46 -0600180 {
181 if (!input->keyboardReport[i])
182 {
183 input->keyboardReport[i] = sc;
184 input->keysDown.insert(std::make_pair(key, i));
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700185 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600186 break;
187 }
188 }
189 }
190 }
191 else
192 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800193 uint8_t mod = keyToMod(key);
Eddie James21b177e2018-12-11 13:14:46 -0600194
195 if (mod)
196 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800197 input->keyboardReport[0] |= mod;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700198 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600199 }
200 }
201 }
202 else
203 {
204 auto it = input->keysDown.find(key);
205
206 if (it != input->keysDown.end())
207 {
208 input->keyboardReport[it->second] = 0;
209 input->keysDown.erase(it);
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700210 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600211 }
212 else
213 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800214 uint8_t mod = keyToMod(key);
Eddie James21b177e2018-12-11 13:14:46 -0600215
216 if (mod)
217 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800218 input->keyboardReport[0] &= ~mod;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700219 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600220 }
221 }
222 }
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700223
224 if (sendKeyboard)
225 {
226 input->writeKeyboard(input->keyboardReport);
227 }
Eddie James21b177e2018-12-11 13:14:46 -0600228}
229
230void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl)
231{
232 Server::ClientData* cd = (Server::ClientData*)cl->clientData;
233 Input* input = cd->input;
234 Server* server = (Server*)cl->screen->screenData;
235 const Video& video = server->getVideo();
236
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700237 if (input->pointerFd < 0)
238 {
239 return;
240 }
241
Tejas Patil3fa0bfb2021-12-23 15:44:47 +0530242 if (buttonMask > 4)
243 {
244 input->pointerReport[0] = 0;
245 if (buttonMask == 8)
246 {
247 input->pointerReport[5] = 1;
248 }
249 else if (buttonMask == 16)
250 {
251 input->pointerReport[5] = 0xff;
252 }
253 }
254 else
255 {
Patrick Williams94f5f422024-08-16 15:22:08 -0400256 input->pointerReport[0] =
257 ((buttonMask & 0x4) >> 1) | ((buttonMask & 0x2) << 1) |
258 (buttonMask & 0x1);
Tejas Patil3fa0bfb2021-12-23 15:44:47 +0530259 input->pointerReport[5] = 0;
260 }
Eddie James21b177e2018-12-11 13:14:46 -0600261
262 if (x >= 0 && (unsigned int)x < video.getWidth())
263 {
Jae Hyun Yoo2bc661d2019-02-25 13:52:47 -0800264 uint16_t xx = (uint16_t)(x * (SHRT_MAX + 1) / video.getWidth());
Eddie James21b177e2018-12-11 13:14:46 -0600265
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800266 memcpy(&input->pointerReport[1], &xx, 2);
Eddie James21b177e2018-12-11 13:14:46 -0600267 }
268
269 if (y >= 0 && (unsigned int)y < video.getHeight())
270 {
Jae Hyun Yoo2bc661d2019-02-25 13:52:47 -0800271 uint16_t yy = (uint16_t)(y * (SHRT_MAX + 1) / video.getHeight());
Eddie James21b177e2018-12-11 13:14:46 -0600272
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800273 memcpy(&input->pointerReport[3], &yy, 2);
Eddie James21b177e2018-12-11 13:14:46 -0600274 }
275
Eddie James21b177e2018-12-11 13:14:46 -0600276 rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700277 input->writePointer(input->pointerReport);
Eddie James21b177e2018-12-11 13:14:46 -0600278}
279
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800280void Input::sendWakeupPacket()
Eddie James21b177e2018-12-11 13:14:46 -0600281{
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800282 uint8_t wakeupReport[KEY_REPORT_LENGTH] = {0};
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800283
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800284 if (pointerFd >= 0)
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800285 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800286 uint16_t xy = SHRT_MAX / 2;
287
288 memcpy(&wakeupReport[1], &xy, 2);
289 memcpy(&wakeupReport[3], &xy, 2);
290
Eddie James7cf1f1d2019-09-30 15:05:16 -0500291 writePointer(wakeupReport);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800292 }
293
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800294 if (keyboardFd >= 0)
Eddie James21b177e2018-12-11 13:14:46 -0600295 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800296 memset(&wakeupReport[0], 0, KEY_REPORT_LENGTH);
297
298 wakeupReport[0] = keyToMod(XK_Shift_L);
299
Eddie James7cf1f1d2019-09-30 15:05:16 -0500300 if (!writeKeyboard(wakeupReport))
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800301 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800302 return;
303 }
304
305 wakeupReport[0] = 0;
306
Eddie James7cf1f1d2019-09-30 15:05:16 -0500307 writeKeyboard(wakeupReport);
Eddie James21b177e2018-12-11 13:14:46 -0600308 }
309}
310
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800311uint8_t Input::keyToMod(rfbKeySym key)
Eddie James21b177e2018-12-11 13:14:46 -0600312{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800313 uint8_t mod = 0;
Eddie James21b177e2018-12-11 13:14:46 -0600314
315 if (key >= XK_Shift_L && key <= XK_Control_R)
316 {
317 mod = shiftCtrlMap[key - XK_Shift_L];
318 }
319 else if (key >= XK_Meta_L && key <= XK_Alt_R)
320 {
321 mod = metaAltMap[key - XK_Meta_L];
322 }
323
324 return mod;
325}
326
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800327uint8_t Input::keyToScancode(rfbKeySym key)
Eddie James21b177e2018-12-11 13:14:46 -0600328{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800329 uint8_t scancode = 0;
Eddie James21b177e2018-12-11 13:14:46 -0600330
331 if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'))
332 {
333 scancode = USBHID_KEY_A + ((key & 0x5F) - 'A');
334 }
335 else if (key >= '1' && key <= '9')
336 {
337 scancode = USBHID_KEY_1 + (key - '1');
338 }
339 else if (key >= XK_F1 && key <= XK_F12)
340 {
341 scancode = USBHID_KEY_F1 + (key - XK_F1);
342 }
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700343 else if (key >= XK_KP_F1 && key <= XK_KP_F4)
344 {
345 scancode = USBHID_KEY_F1 + (key - XK_KP_F1);
346 }
347 else if (key >= XK_KP_1 && key <= XK_KP_9)
348 {
349 scancode = USBHID_KEY_KP_1 + (key - XK_KP_1);
350 }
Eddie James21b177e2018-12-11 13:14:46 -0600351 else
352 {
353 switch (key)
354 {
355 case XK_exclam:
356 scancode = USBHID_KEY_1;
357 break;
358 case XK_at:
359 scancode = USBHID_KEY_2;
360 break;
361 case XK_numbersign:
362 scancode = USBHID_KEY_3;
363 break;
364 case XK_dollar:
365 scancode = USBHID_KEY_4;
366 break;
367 case XK_percent:
368 scancode = USBHID_KEY_5;
369 break;
370 case XK_asciicircum:
371 scancode = USBHID_KEY_6;
372 break;
373 case XK_ampersand:
374 scancode = USBHID_KEY_7;
375 break;
376 case XK_asterisk:
377 scancode = USBHID_KEY_8;
378 break;
379 case XK_parenleft:
380 scancode = USBHID_KEY_9;
381 break;
382 case XK_0:
383 case XK_parenright:
384 scancode = USBHID_KEY_0;
385 break;
386 case XK_Return:
387 scancode = USBHID_KEY_RETURN;
388 break;
389 case XK_Escape:
390 scancode = USBHID_KEY_ESC;
391 break;
392 case XK_BackSpace:
393 scancode = USBHID_KEY_BACKSPACE;
394 break;
395 case XK_Tab:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700396 case XK_KP_Tab:
Eddie James21b177e2018-12-11 13:14:46 -0600397 scancode = USBHID_KEY_TAB;
398 break;
399 case XK_space:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700400 case XK_KP_Space:
Eddie James21b177e2018-12-11 13:14:46 -0600401 scancode = USBHID_KEY_SPACE;
402 break;
403 case XK_minus:
404 case XK_underscore:
405 scancode = USBHID_KEY_MINUS;
406 break;
407 case XK_plus:
408 case XK_equal:
409 scancode = USBHID_KEY_EQUAL;
410 break;
411 case XK_bracketleft:
412 case XK_braceleft:
413 scancode = USBHID_KEY_LEFTBRACE;
414 break;
415 case XK_bracketright:
416 case XK_braceright:
417 scancode = USBHID_KEY_RIGHTBRACE;
418 break;
419 case XK_backslash:
420 case XK_bar:
421 scancode = USBHID_KEY_BACKSLASH;
422 break;
423 case XK_colon:
424 case XK_semicolon:
425 scancode = USBHID_KEY_SEMICOLON;
426 break;
427 case XK_quotedbl:
428 case XK_apostrophe:
429 scancode = USBHID_KEY_APOSTROPHE;
430 break;
431 case XK_grave:
432 case XK_asciitilde:
433 scancode = USBHID_KEY_GRAVE;
434 break;
435 case XK_comma:
436 case XK_less:
437 scancode = USBHID_KEY_COMMA;
438 break;
439 case XK_period:
440 case XK_greater:
441 scancode = USBHID_KEY_DOT;
442 break;
443 case XK_slash:
444 case XK_question:
445 scancode = USBHID_KEY_SLASH;
446 break;
447 case XK_Caps_Lock:
448 scancode = USBHID_KEY_CAPSLOCK;
449 break;
450 case XK_Print:
451 scancode = USBHID_KEY_PRINT;
452 break;
453 case XK_Scroll_Lock:
454 scancode = USBHID_KEY_SCROLLLOCK;
455 break;
456 case XK_Pause:
457 scancode = USBHID_KEY_PAUSE;
458 break;
459 case XK_Insert:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700460 case XK_KP_Insert:
Eddie James21b177e2018-12-11 13:14:46 -0600461 scancode = USBHID_KEY_INSERT;
462 break;
463 case XK_Home:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700464 case XK_KP_Home:
Eddie James21b177e2018-12-11 13:14:46 -0600465 scancode = USBHID_KEY_HOME;
466 break;
467 case XK_Page_Up:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700468 case XK_KP_Page_Up:
Eddie James21b177e2018-12-11 13:14:46 -0600469 scancode = USBHID_KEY_PAGEUP;
470 break;
471 case XK_Delete:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700472 case XK_KP_Delete:
Eddie James21b177e2018-12-11 13:14:46 -0600473 scancode = USBHID_KEY_DELETE;
474 break;
475 case XK_End:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700476 case XK_KP_End:
Eddie James21b177e2018-12-11 13:14:46 -0600477 scancode = USBHID_KEY_END;
478 break;
479 case XK_Page_Down:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700480 case XK_KP_Page_Down:
Eddie James21b177e2018-12-11 13:14:46 -0600481 scancode = USBHID_KEY_PAGEDOWN;
482 break;
483 case XK_Right:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700484 case XK_KP_Right:
Eddie James21b177e2018-12-11 13:14:46 -0600485 scancode = USBHID_KEY_RIGHT;
486 break;
487 case XK_Left:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700488 case XK_KP_Left:
Eddie James21b177e2018-12-11 13:14:46 -0600489 scancode = USBHID_KEY_LEFT;
490 break;
491 case XK_Down:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700492 case XK_KP_Down:
Eddie James21b177e2018-12-11 13:14:46 -0600493 scancode = USBHID_KEY_DOWN;
494 break;
495 case XK_Up:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700496 case XK_KP_Up:
Eddie James21b177e2018-12-11 13:14:46 -0600497 scancode = USBHID_KEY_UP;
498 break;
499 case XK_Num_Lock:
500 scancode = USBHID_KEY_NUMLOCK;
501 break;
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700502 case XK_KP_Enter:
503 scancode = USBHID_KEY_KP_ENTER;
504 break;
505 case XK_KP_Equal:
506 scancode = USBHID_KEY_KP_EQUAL;
507 break;
508 case XK_KP_Multiply:
509 scancode = USBHID_KEY_KP_MULTIPLY;
510 break;
511 case XK_KP_Add:
512 scancode = USBHID_KEY_KP_ADD;
513 break;
514 case XK_KP_Subtract:
515 scancode = USBHID_KEY_KP_SUBTRACT;
516 break;
517 case XK_KP_Decimal:
518 scancode = USBHID_KEY_KP_DECIMAL;
519 break;
520 case XK_KP_Divide:
521 scancode = USBHID_KEY_KP_DIVIDE;
522 break;
523 case XK_KP_0:
524 scancode = USBHID_KEY_KP_0;
525 break;
Eddie James21b177e2018-12-11 13:14:46 -0600526 }
527 }
528
529 return scancode;
530}
531
George Liuf79f6f52022-07-06 09:32:35 +0800532bool Input::writeKeyboard(const uint8_t* report)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500533{
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700534 std::unique_lock<std::mutex> lk(keyMutex);
535 uint retryCount = HID_REPORT_RETRY_MAX;
536
537 while (retryCount > 0)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500538 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700539 if (write(keyboardFd, report, KEY_REPORT_LENGTH) == KEY_REPORT_LENGTH)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500540 {
Zev Weiss40fd5422021-06-17 05:41:40 +0000541 return true;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500542 }
543
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700544 if (errno != EAGAIN)
545 {
546 if (errno != ESHUTDOWN)
547 {
548 log<level::ERR>("Failed to write keyboard report",
549 entry("ERROR=%s", strerror(errno)));
550 }
551
552 break;
553 }
554
555 lk.unlock();
556 std::this_thread::sleep_for(std::chrono::milliseconds(10));
557 lk.lock();
558 retryCount--;
559 }
560
Zev Weiss40fd5422021-06-17 05:41:40 +0000561 return false;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500562}
563
George Liuf79f6f52022-07-06 09:32:35 +0800564void Input::writePointer(const uint8_t* report)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500565{
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700566 std::unique_lock<std::mutex> lk(ptrMutex);
567 uint retryCount = HID_REPORT_RETRY_MAX;
568
569 while (retryCount > 0)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500570 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700571 if (write(pointerFd, report, PTR_REPORT_LENGTH) == PTR_REPORT_LENGTH)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500572 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700573 break;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500574 }
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700575
576 if (errno != EAGAIN)
577 {
578 if (errno != ESHUTDOWN)
579 {
580 log<level::ERR>("Failed to write pointer report",
581 entry("ERROR=%s", strerror(errno)));
582 }
583
584 break;
585 }
586
587 lk.unlock();
588 std::this_thread::sleep_for(std::chrono::milliseconds(10));
589 lk.lock();
590 retryCount--;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500591 }
592}
593
Eddie James21b177e2018-12-11 13:14:46 -0600594} // namespace ikvm