blob: 0d35408d23e77cef1e4cc6d91f485dbb9e805727 [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{
22
23using namespace phosphor::logging;
24using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
25
Marvin Linfe685fb2022-10-25 16:20:08 +080026Input::Input(const std::string& kbdPath, const std::string& ptrPath,
27 const std::string& udc) :
28 keyboardFd(-1),
29 pointerFd(-1), keyboardReport{0}, pointerReport{0}, keyboardPath(kbdPath),
30 pointerPath(ptrPath), udcName(udc)
Eddie James21b177e2018-12-11 13:14:46 -060031{
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070032 hidUdcStream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
33 hidUdcStream.open(hidUdcPath, std::ios::out | std::ios::app);
34}
35
36Input::~Input()
37{
38 if (keyboardFd >= 0)
39 {
40 close(keyboardFd);
41 }
42
43 if (pointerFd >= 0)
44 {
45 close(pointerFd);
46 }
47
48 disconnect();
49 hidUdcStream.close();
50}
51
52void Input::connect()
53{
54 try
55 {
Marvin Linfe685fb2022-10-25 16:20:08 +080056 if (udcName.empty())
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070057 {
Troy Lee20de8592023-02-10 14:15:09 +080058 bool found = false;
Marvin Linfe685fb2022-10-25 16:20:08 +080059 for (const auto& port : fs::directory_iterator(usbVirtualHubPath))
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070060 {
Troy Lee20de8592023-02-10 14:15:09 +080061 // /sys/bus/platform/devices/1e6a0000.usb-vhub/1e6a0000.usb-vhub:pX
62 if (fs::is_directory(port) && !fs::is_symlink(port))
Marvin Linfe685fb2022-10-25 16:20:08 +080063 {
Troy Lee20de8592023-02-10 14:15:09 +080064 for (const auto& gadget :
65 fs::directory_iterator(port.path()))
66 {
67 // Kernel 6.0:
68 // /sys/.../1e6a0000.usb-vhub:pX/gadget.Y/suspended
69 // Kernel 5.15:
70 // /sys/.../1e6a0000.usb-vhub:pX/gadget/suspended
71 if (fs::is_directory(gadget) &&
72 gadget.path().string().find("gadget") !=
73 std::string::npos &&
74 !fs::exists(gadget.path() / "suspended"))
75 {
76 const std::string portId = gadget.path().filename();
77 hidUdcStream << portId << std::endl;
78 found = true;
79 break;
80 }
81 }
82 }
83 if (found)
84 {
Marvin Linfe685fb2022-10-25 16:20:08 +080085 break;
86 }
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070087 }
88 }
Marvin Linfe685fb2022-10-25 16:20:08 +080089 else // If UDC has been specified by '-u' parameter, connect to it.
90 {
91 hidUdcStream << udcName << std::endl;
92 }
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070093 }
94 catch (fs::filesystem_error& e)
95 {
96 log<level::ERR>("Failed to search USB virtual hub port",
97 entry("ERROR=%s", e.what()));
98 return;
99 }
100 catch (std::ofstream::failure& e)
101 {
102 log<level::ERR>("Failed to connect HID gadget",
103 entry("ERROR=%s", e.what()));
104 return;
105 }
106
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800107 if (!keyboardPath.empty())
Eddie James21b177e2018-12-11 13:14:46 -0600108 {
George Liuf79f6f52022-07-06 09:32:35 +0800109 keyboardFd =
110 open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800111 if (keyboardFd < 0)
112 {
113 log<level::ERR>("Failed to open input device",
114 entry("PATH=%s", keyboardPath.c_str()),
115 entry("ERROR=%s", strerror(errno)));
116 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno),
117 xyz::openbmc_project::Common::File::Open::PATH(
118 keyboardPath.c_str()));
119 }
Eddie James21b177e2018-12-11 13:14:46 -0600120 }
121
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800122 if (!pointerPath.empty())
123 {
Eddie James4749f932019-04-18 11:06:39 -0500124 pointerFd = open(pointerPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800125 if (pointerFd < 0)
126 {
127 log<level::ERR>("Failed to open input device",
128 entry("PATH=%s", pointerPath.c_str()),
129 entry("ERROR=%s", strerror(errno)));
130 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno),
131 xyz::openbmc_project::Common::File::Open::PATH(
132 pointerPath.c_str()));
133 }
134 }
Eddie James21b177e2018-12-11 13:14:46 -0600135}
136
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700137void Input::disconnect()
Eddie James21b177e2018-12-11 13:14:46 -0600138{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800139 if (keyboardFd >= 0)
140 {
141 close(keyboardFd);
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700142 keyboardFd = -1;
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800143 }
144
145 if (pointerFd >= 0)
146 {
147 close(pointerFd);
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700148 pointerFd = -1;
149 }
150
151 try
152 {
153 hidUdcStream << "" << std::endl;
154 }
155 catch (std::ofstream::failure& e)
156 {
157 log<level::ERR>("Failed to disconnect HID gadget",
158 entry("ERROR=%s", e.what()));
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800159 }
Eddie James21b177e2018-12-11 13:14:46 -0600160}
161
162void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
163{
164 Server::ClientData* cd = (Server::ClientData*)cl->clientData;
165 Input* input = cd->input;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700166 bool sendKeyboard = false;
167
168 if (input->keyboardFd < 0)
169 {
170 return;
171 }
Eddie James21b177e2018-12-11 13:14:46 -0600172
173 if (down)
174 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800175 uint8_t sc = keyToScancode(key);
Eddie James21b177e2018-12-11 13:14:46 -0600176
177 if (sc)
178 {
179 if (input->keysDown.find(key) == input->keysDown.end())
180 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800181 for (unsigned int i = 2; i < KEY_REPORT_LENGTH; ++i)
Eddie James21b177e2018-12-11 13:14:46 -0600182 {
183 if (!input->keyboardReport[i])
184 {
185 input->keyboardReport[i] = sc;
186 input->keysDown.insert(std::make_pair(key, i));
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700187 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600188 break;
189 }
190 }
191 }
192 }
193 else
194 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800195 uint8_t mod = keyToMod(key);
Eddie James21b177e2018-12-11 13:14:46 -0600196
197 if (mod)
198 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800199 input->keyboardReport[0] |= mod;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700200 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600201 }
202 }
203 }
204 else
205 {
206 auto it = input->keysDown.find(key);
207
208 if (it != input->keysDown.end())
209 {
210 input->keyboardReport[it->second] = 0;
211 input->keysDown.erase(it);
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700212 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600213 }
214 else
215 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800216 uint8_t mod = keyToMod(key);
Eddie James21b177e2018-12-11 13:14:46 -0600217
218 if (mod)
219 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800220 input->keyboardReport[0] &= ~mod;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700221 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600222 }
223 }
224 }
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700225
226 if (sendKeyboard)
227 {
228 input->writeKeyboard(input->keyboardReport);
229 }
Eddie James21b177e2018-12-11 13:14:46 -0600230}
231
232void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl)
233{
234 Server::ClientData* cd = (Server::ClientData*)cl->clientData;
235 Input* input = cd->input;
236 Server* server = (Server*)cl->screen->screenData;
237 const Video& video = server->getVideo();
238
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700239 if (input->pointerFd < 0)
240 {
241 return;
242 }
243
Tejas Patil3fa0bfb2021-12-23 15:44:47 +0530244 if (buttonMask > 4)
245 {
246 input->pointerReport[0] = 0;
247 if (buttonMask == 8)
248 {
249 input->pointerReport[5] = 1;
250 }
251 else if (buttonMask == 16)
252 {
253 input->pointerReport[5] = 0xff;
254 }
255 }
256 else
257 {
258 input->pointerReport[0] = ((buttonMask & 0x4) >> 1) |
George Liuf79f6f52022-07-06 09:32:35 +0800259 ((buttonMask & 0x2) << 1) |
260 (buttonMask & 0x1);
Tejas Patil3fa0bfb2021-12-23 15:44:47 +0530261 input->pointerReport[5] = 0;
262 }
Eddie James21b177e2018-12-11 13:14:46 -0600263
264 if (x >= 0 && (unsigned int)x < video.getWidth())
265 {
Jae Hyun Yoo2bc661d2019-02-25 13:52:47 -0800266 uint16_t xx = (uint16_t)(x * (SHRT_MAX + 1) / video.getWidth());
Eddie James21b177e2018-12-11 13:14:46 -0600267
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800268 memcpy(&input->pointerReport[1], &xx, 2);
Eddie James21b177e2018-12-11 13:14:46 -0600269 }
270
271 if (y >= 0 && (unsigned int)y < video.getHeight())
272 {
Jae Hyun Yoo2bc661d2019-02-25 13:52:47 -0800273 uint16_t yy = (uint16_t)(y * (SHRT_MAX + 1) / video.getHeight());
Eddie James21b177e2018-12-11 13:14:46 -0600274
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800275 memcpy(&input->pointerReport[3], &yy, 2);
Eddie James21b177e2018-12-11 13:14:46 -0600276 }
277
Eddie James21b177e2018-12-11 13:14:46 -0600278 rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700279 input->writePointer(input->pointerReport);
Eddie James21b177e2018-12-11 13:14:46 -0600280}
281
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800282void Input::sendWakeupPacket()
Eddie James21b177e2018-12-11 13:14:46 -0600283{
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800284 uint8_t wakeupReport[KEY_REPORT_LENGTH] = {0};
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800285
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800286 if (pointerFd >= 0)
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800287 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800288 uint16_t xy = SHRT_MAX / 2;
289
290 memcpy(&wakeupReport[1], &xy, 2);
291 memcpy(&wakeupReport[3], &xy, 2);
292
Eddie James7cf1f1d2019-09-30 15:05:16 -0500293 writePointer(wakeupReport);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800294 }
295
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800296 if (keyboardFd >= 0)
Eddie James21b177e2018-12-11 13:14:46 -0600297 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800298 memset(&wakeupReport[0], 0, KEY_REPORT_LENGTH);
299
300 wakeupReport[0] = keyToMod(XK_Shift_L);
301
Eddie James7cf1f1d2019-09-30 15:05:16 -0500302 if (!writeKeyboard(wakeupReport))
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800303 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800304 return;
305 }
306
307 wakeupReport[0] = 0;
308
Eddie James7cf1f1d2019-09-30 15:05:16 -0500309 writeKeyboard(wakeupReport);
Eddie James21b177e2018-12-11 13:14:46 -0600310 }
311}
312
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800313uint8_t Input::keyToMod(rfbKeySym key)
Eddie James21b177e2018-12-11 13:14:46 -0600314{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800315 uint8_t mod = 0;
Eddie James21b177e2018-12-11 13:14:46 -0600316
317 if (key >= XK_Shift_L && key <= XK_Control_R)
318 {
319 mod = shiftCtrlMap[key - XK_Shift_L];
320 }
321 else if (key >= XK_Meta_L && key <= XK_Alt_R)
322 {
323 mod = metaAltMap[key - XK_Meta_L];
324 }
325
326 return mod;
327}
328
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800329uint8_t Input::keyToScancode(rfbKeySym key)
Eddie James21b177e2018-12-11 13:14:46 -0600330{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800331 uint8_t scancode = 0;
Eddie James21b177e2018-12-11 13:14:46 -0600332
333 if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'))
334 {
335 scancode = USBHID_KEY_A + ((key & 0x5F) - 'A');
336 }
337 else if (key >= '1' && key <= '9')
338 {
339 scancode = USBHID_KEY_1 + (key - '1');
340 }
341 else if (key >= XK_F1 && key <= XK_F12)
342 {
343 scancode = USBHID_KEY_F1 + (key - XK_F1);
344 }
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700345 else if (key >= XK_KP_F1 && key <= XK_KP_F4)
346 {
347 scancode = USBHID_KEY_F1 + (key - XK_KP_F1);
348 }
349 else if (key >= XK_KP_1 && key <= XK_KP_9)
350 {
351 scancode = USBHID_KEY_KP_1 + (key - XK_KP_1);
352 }
Eddie James21b177e2018-12-11 13:14:46 -0600353 else
354 {
355 switch (key)
356 {
357 case XK_exclam:
358 scancode = USBHID_KEY_1;
359 break;
360 case XK_at:
361 scancode = USBHID_KEY_2;
362 break;
363 case XK_numbersign:
364 scancode = USBHID_KEY_3;
365 break;
366 case XK_dollar:
367 scancode = USBHID_KEY_4;
368 break;
369 case XK_percent:
370 scancode = USBHID_KEY_5;
371 break;
372 case XK_asciicircum:
373 scancode = USBHID_KEY_6;
374 break;
375 case XK_ampersand:
376 scancode = USBHID_KEY_7;
377 break;
378 case XK_asterisk:
379 scancode = USBHID_KEY_8;
380 break;
381 case XK_parenleft:
382 scancode = USBHID_KEY_9;
383 break;
384 case XK_0:
385 case XK_parenright:
386 scancode = USBHID_KEY_0;
387 break;
388 case XK_Return:
389 scancode = USBHID_KEY_RETURN;
390 break;
391 case XK_Escape:
392 scancode = USBHID_KEY_ESC;
393 break;
394 case XK_BackSpace:
395 scancode = USBHID_KEY_BACKSPACE;
396 break;
397 case XK_Tab:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700398 case XK_KP_Tab:
Eddie James21b177e2018-12-11 13:14:46 -0600399 scancode = USBHID_KEY_TAB;
400 break;
401 case XK_space:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700402 case XK_KP_Space:
Eddie James21b177e2018-12-11 13:14:46 -0600403 scancode = USBHID_KEY_SPACE;
404 break;
405 case XK_minus:
406 case XK_underscore:
407 scancode = USBHID_KEY_MINUS;
408 break;
409 case XK_plus:
410 case XK_equal:
411 scancode = USBHID_KEY_EQUAL;
412 break;
413 case XK_bracketleft:
414 case XK_braceleft:
415 scancode = USBHID_KEY_LEFTBRACE;
416 break;
417 case XK_bracketright:
418 case XK_braceright:
419 scancode = USBHID_KEY_RIGHTBRACE;
420 break;
421 case XK_backslash:
422 case XK_bar:
423 scancode = USBHID_KEY_BACKSLASH;
424 break;
425 case XK_colon:
426 case XK_semicolon:
427 scancode = USBHID_KEY_SEMICOLON;
428 break;
429 case XK_quotedbl:
430 case XK_apostrophe:
431 scancode = USBHID_KEY_APOSTROPHE;
432 break;
433 case XK_grave:
434 case XK_asciitilde:
435 scancode = USBHID_KEY_GRAVE;
436 break;
437 case XK_comma:
438 case XK_less:
439 scancode = USBHID_KEY_COMMA;
440 break;
441 case XK_period:
442 case XK_greater:
443 scancode = USBHID_KEY_DOT;
444 break;
445 case XK_slash:
446 case XK_question:
447 scancode = USBHID_KEY_SLASH;
448 break;
449 case XK_Caps_Lock:
450 scancode = USBHID_KEY_CAPSLOCK;
451 break;
452 case XK_Print:
453 scancode = USBHID_KEY_PRINT;
454 break;
455 case XK_Scroll_Lock:
456 scancode = USBHID_KEY_SCROLLLOCK;
457 break;
458 case XK_Pause:
459 scancode = USBHID_KEY_PAUSE;
460 break;
461 case XK_Insert:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700462 case XK_KP_Insert:
Eddie James21b177e2018-12-11 13:14:46 -0600463 scancode = USBHID_KEY_INSERT;
464 break;
465 case XK_Home:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700466 case XK_KP_Home:
Eddie James21b177e2018-12-11 13:14:46 -0600467 scancode = USBHID_KEY_HOME;
468 break;
469 case XK_Page_Up:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700470 case XK_KP_Page_Up:
Eddie James21b177e2018-12-11 13:14:46 -0600471 scancode = USBHID_KEY_PAGEUP;
472 break;
473 case XK_Delete:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700474 case XK_KP_Delete:
Eddie James21b177e2018-12-11 13:14:46 -0600475 scancode = USBHID_KEY_DELETE;
476 break;
477 case XK_End:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700478 case XK_KP_End:
Eddie James21b177e2018-12-11 13:14:46 -0600479 scancode = USBHID_KEY_END;
480 break;
481 case XK_Page_Down:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700482 case XK_KP_Page_Down:
Eddie James21b177e2018-12-11 13:14:46 -0600483 scancode = USBHID_KEY_PAGEDOWN;
484 break;
485 case XK_Right:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700486 case XK_KP_Right:
Eddie James21b177e2018-12-11 13:14:46 -0600487 scancode = USBHID_KEY_RIGHT;
488 break;
489 case XK_Left:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700490 case XK_KP_Left:
Eddie James21b177e2018-12-11 13:14:46 -0600491 scancode = USBHID_KEY_LEFT;
492 break;
493 case XK_Down:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700494 case XK_KP_Down:
Eddie James21b177e2018-12-11 13:14:46 -0600495 scancode = USBHID_KEY_DOWN;
496 break;
497 case XK_Up:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700498 case XK_KP_Up:
Eddie James21b177e2018-12-11 13:14:46 -0600499 scancode = USBHID_KEY_UP;
500 break;
501 case XK_Num_Lock:
502 scancode = USBHID_KEY_NUMLOCK;
503 break;
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700504 case XK_KP_Enter:
505 scancode = USBHID_KEY_KP_ENTER;
506 break;
507 case XK_KP_Equal:
508 scancode = USBHID_KEY_KP_EQUAL;
509 break;
510 case XK_KP_Multiply:
511 scancode = USBHID_KEY_KP_MULTIPLY;
512 break;
513 case XK_KP_Add:
514 scancode = USBHID_KEY_KP_ADD;
515 break;
516 case XK_KP_Subtract:
517 scancode = USBHID_KEY_KP_SUBTRACT;
518 break;
519 case XK_KP_Decimal:
520 scancode = USBHID_KEY_KP_DECIMAL;
521 break;
522 case XK_KP_Divide:
523 scancode = USBHID_KEY_KP_DIVIDE;
524 break;
525 case XK_KP_0:
526 scancode = USBHID_KEY_KP_0;
527 break;
Eddie James21b177e2018-12-11 13:14:46 -0600528 }
529 }
530
531 return scancode;
532}
533
George Liuf79f6f52022-07-06 09:32:35 +0800534bool Input::writeKeyboard(const uint8_t* report)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500535{
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700536 std::unique_lock<std::mutex> lk(keyMutex);
537 uint retryCount = HID_REPORT_RETRY_MAX;
538
539 while (retryCount > 0)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500540 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700541 if (write(keyboardFd, report, KEY_REPORT_LENGTH) == KEY_REPORT_LENGTH)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500542 {
Zev Weiss40fd5422021-06-17 05:41:40 +0000543 return true;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500544 }
545
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700546 if (errno != EAGAIN)
547 {
548 if (errno != ESHUTDOWN)
549 {
550 log<level::ERR>("Failed to write keyboard report",
551 entry("ERROR=%s", strerror(errno)));
552 }
553
554 break;
555 }
556
557 lk.unlock();
558 std::this_thread::sleep_for(std::chrono::milliseconds(10));
559 lk.lock();
560 retryCount--;
561 }
562
Zev Weiss40fd5422021-06-17 05:41:40 +0000563 return false;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500564}
565
George Liuf79f6f52022-07-06 09:32:35 +0800566void Input::writePointer(const uint8_t* report)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500567{
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700568 std::unique_lock<std::mutex> lk(ptrMutex);
569 uint retryCount = HID_REPORT_RETRY_MAX;
570
571 while (retryCount > 0)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500572 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700573 if (write(pointerFd, report, PTR_REPORT_LENGTH) == PTR_REPORT_LENGTH)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500574 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700575 break;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500576 }
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700577
578 if (errno != EAGAIN)
579 {
580 if (errno != ESHUTDOWN)
581 {
582 log<level::ERR>("Failed to write pointer report",
583 entry("ERROR=%s", strerror(errno)));
584 }
585
586 break;
587 }
588
589 lk.unlock();
590 std::this_thread::sleep_for(std::chrono::milliseconds(10));
591 lk.lock();
592 retryCount--;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500593 }
594}
595
Eddie James21b177e2018-12-11 13:14:46 -0600596} // namespace ikvm