blob: b900740ea38e61ed7b35d7bbafb35b6e7a4fe316 [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) :
27 keyboardFd(-1),
28 pointerFd(-1), keyboardReport{0}, pointerReport{0}, keyboardPath(kbdPath),
29 pointerPath(ptrPath), udcName(udc)
Eddie James21b177e2018-12-11 13:14:46 -060030{
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070031 hidUdcStream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
32 hidUdcStream.open(hidUdcPath, std::ios::out | std::ios::app);
33}
34
35Input::~Input()
36{
37 if (keyboardFd >= 0)
38 {
39 close(keyboardFd);
40 }
41
42 if (pointerFd >= 0)
43 {
44 close(pointerFd);
45 }
46
47 disconnect();
48 hidUdcStream.close();
49}
50
51void Input::connect()
52{
53 try
54 {
Marvin Linfe685fb2022-10-25 16:20:08 +080055 if (udcName.empty())
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070056 {
Troy Lee20de8592023-02-10 14:15:09 +080057 bool found = false;
Marvin Linfe685fb2022-10-25 16:20:08 +080058 for (const auto& port : fs::directory_iterator(usbVirtualHubPath))
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070059 {
Troy Lee20de8592023-02-10 14:15:09 +080060 // /sys/bus/platform/devices/1e6a0000.usb-vhub/1e6a0000.usb-vhub:pX
61 if (fs::is_directory(port) && !fs::is_symlink(port))
Marvin Linfe685fb2022-10-25 16:20:08 +080062 {
Troy Lee20de8592023-02-10 14:15:09 +080063 for (const auto& gadget :
64 fs::directory_iterator(port.path()))
65 {
66 // Kernel 6.0:
67 // /sys/.../1e6a0000.usb-vhub:pX/gadget.Y/suspended
68 // Kernel 5.15:
69 // /sys/.../1e6a0000.usb-vhub:pX/gadget/suspended
70 if (fs::is_directory(gadget) &&
71 gadget.path().string().find("gadget") !=
72 std::string::npos &&
73 !fs::exists(gadget.path() / "suspended"))
74 {
Troy Lee4148d0c2023-03-15 16:23:45 +080075 const std::string portId = port.path().filename();
Troy Lee20de8592023-02-10 14:15:09 +080076 hidUdcStream << portId << std::endl;
77 found = true;
78 break;
79 }
80 }
81 }
82 if (found)
83 {
Marvin Linfe685fb2022-10-25 16:20:08 +080084 break;
85 }
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070086 }
87 }
Marvin Linfe685fb2022-10-25 16:20:08 +080088 else // If UDC has been specified by '-u' parameter, connect to it.
89 {
90 hidUdcStream << udcName << std::endl;
91 }
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070092 }
93 catch (fs::filesystem_error& e)
94 {
95 log<level::ERR>("Failed to search USB virtual hub port",
96 entry("ERROR=%s", e.what()));
97 return;
98 }
99 catch (std::ofstream::failure& e)
100 {
101 log<level::ERR>("Failed to connect HID gadget",
102 entry("ERROR=%s", e.what()));
103 return;
104 }
105
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800106 if (!keyboardPath.empty())
Eddie James21b177e2018-12-11 13:14:46 -0600107 {
George Liuf79f6f52022-07-06 09:32:35 +0800108 keyboardFd =
109 open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800110 if (keyboardFd < 0)
111 {
112 log<level::ERR>("Failed to open input device",
113 entry("PATH=%s", keyboardPath.c_str()),
114 entry("ERROR=%s", strerror(errno)));
115 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno),
116 xyz::openbmc_project::Common::File::Open::PATH(
117 keyboardPath.c_str()));
118 }
Eddie James21b177e2018-12-11 13:14:46 -0600119 }
120
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800121 if (!pointerPath.empty())
122 {
Eddie James4749f932019-04-18 11:06:39 -0500123 pointerFd = open(pointerPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800124 if (pointerFd < 0)
125 {
126 log<level::ERR>("Failed to open input device",
127 entry("PATH=%s", pointerPath.c_str()),
128 entry("ERROR=%s", strerror(errno)));
129 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno),
130 xyz::openbmc_project::Common::File::Open::PATH(
131 pointerPath.c_str()));
132 }
133 }
Eddie James21b177e2018-12-11 13:14:46 -0600134}
135
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700136void Input::disconnect()
Eddie James21b177e2018-12-11 13:14:46 -0600137{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800138 if (keyboardFd >= 0)
139 {
140 close(keyboardFd);
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700141 keyboardFd = -1;
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800142 }
143
144 if (pointerFd >= 0)
145 {
146 close(pointerFd);
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700147 pointerFd = -1;
148 }
149
150 try
151 {
152 hidUdcStream << "" << std::endl;
153 }
154 catch (std::ofstream::failure& e)
155 {
156 log<level::ERR>("Failed to disconnect HID gadget",
157 entry("ERROR=%s", e.what()));
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800158 }
Eddie James21b177e2018-12-11 13:14:46 -0600159}
160
161void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
162{
163 Server::ClientData* cd = (Server::ClientData*)cl->clientData;
164 Input* input = cd->input;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700165 bool sendKeyboard = false;
166
167 if (input->keyboardFd < 0)
168 {
169 return;
170 }
Eddie James21b177e2018-12-11 13:14:46 -0600171
172 if (down)
173 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800174 uint8_t sc = keyToScancode(key);
Eddie James21b177e2018-12-11 13:14:46 -0600175
176 if (sc)
177 {
178 if (input->keysDown.find(key) == input->keysDown.end())
179 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800180 for (unsigned int i = 2; i < KEY_REPORT_LENGTH; ++i)
Eddie James21b177e2018-12-11 13:14:46 -0600181 {
182 if (!input->keyboardReport[i])
183 {
184 input->keyboardReport[i] = sc;
185 input->keysDown.insert(std::make_pair(key, i));
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700186 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600187 break;
188 }
189 }
190 }
191 }
192 else
193 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800194 uint8_t mod = keyToMod(key);
Eddie James21b177e2018-12-11 13:14:46 -0600195
196 if (mod)
197 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800198 input->keyboardReport[0] |= mod;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700199 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600200 }
201 }
202 }
203 else
204 {
205 auto it = input->keysDown.find(key);
206
207 if (it != input->keysDown.end())
208 {
209 input->keyboardReport[it->second] = 0;
210 input->keysDown.erase(it);
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700211 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600212 }
213 else
214 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800215 uint8_t mod = keyToMod(key);
Eddie James21b177e2018-12-11 13:14:46 -0600216
217 if (mod)
218 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800219 input->keyboardReport[0] &= ~mod;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700220 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600221 }
222 }
223 }
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700224
225 if (sendKeyboard)
226 {
227 input->writeKeyboard(input->keyboardReport);
228 }
Eddie James21b177e2018-12-11 13:14:46 -0600229}
230
231void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl)
232{
233 Server::ClientData* cd = (Server::ClientData*)cl->clientData;
234 Input* input = cd->input;
235 Server* server = (Server*)cl->screen->screenData;
236 const Video& video = server->getVideo();
237
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700238 if (input->pointerFd < 0)
239 {
240 return;
241 }
242
Tejas Patil3fa0bfb2021-12-23 15:44:47 +0530243 if (buttonMask > 4)
244 {
245 input->pointerReport[0] = 0;
246 if (buttonMask == 8)
247 {
248 input->pointerReport[5] = 1;
249 }
250 else if (buttonMask == 16)
251 {
252 input->pointerReport[5] = 0xff;
253 }
254 }
255 else
256 {
257 input->pointerReport[0] = ((buttonMask & 0x4) >> 1) |
George Liuf79f6f52022-07-06 09:32:35 +0800258 ((buttonMask & 0x2) << 1) |
259 (buttonMask & 0x1);
Tejas Patil3fa0bfb2021-12-23 15:44:47 +0530260 input->pointerReport[5] = 0;
261 }
Eddie James21b177e2018-12-11 13:14:46 -0600262
263 if (x >= 0 && (unsigned int)x < video.getWidth())
264 {
Jae Hyun Yoo2bc661d2019-02-25 13:52:47 -0800265 uint16_t xx = (uint16_t)(x * (SHRT_MAX + 1) / video.getWidth());
Eddie James21b177e2018-12-11 13:14:46 -0600266
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800267 memcpy(&input->pointerReport[1], &xx, 2);
Eddie James21b177e2018-12-11 13:14:46 -0600268 }
269
270 if (y >= 0 && (unsigned int)y < video.getHeight())
271 {
Jae Hyun Yoo2bc661d2019-02-25 13:52:47 -0800272 uint16_t yy = (uint16_t)(y * (SHRT_MAX + 1) / video.getHeight());
Eddie James21b177e2018-12-11 13:14:46 -0600273
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800274 memcpy(&input->pointerReport[3], &yy, 2);
Eddie James21b177e2018-12-11 13:14:46 -0600275 }
276
Eddie James21b177e2018-12-11 13:14:46 -0600277 rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700278 input->writePointer(input->pointerReport);
Eddie James21b177e2018-12-11 13:14:46 -0600279}
280
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800281void Input::sendWakeupPacket()
Eddie James21b177e2018-12-11 13:14:46 -0600282{
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800283 uint8_t wakeupReport[KEY_REPORT_LENGTH] = {0};
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800284
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800285 if (pointerFd >= 0)
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800286 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800287 uint16_t xy = SHRT_MAX / 2;
288
289 memcpy(&wakeupReport[1], &xy, 2);
290 memcpy(&wakeupReport[3], &xy, 2);
291
Eddie James7cf1f1d2019-09-30 15:05:16 -0500292 writePointer(wakeupReport);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800293 }
294
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800295 if (keyboardFd >= 0)
Eddie James21b177e2018-12-11 13:14:46 -0600296 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800297 memset(&wakeupReport[0], 0, KEY_REPORT_LENGTH);
298
299 wakeupReport[0] = keyToMod(XK_Shift_L);
300
Eddie James7cf1f1d2019-09-30 15:05:16 -0500301 if (!writeKeyboard(wakeupReport))
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800302 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800303 return;
304 }
305
306 wakeupReport[0] = 0;
307
Eddie James7cf1f1d2019-09-30 15:05:16 -0500308 writeKeyboard(wakeupReport);
Eddie James21b177e2018-12-11 13:14:46 -0600309 }
310}
311
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800312uint8_t Input::keyToMod(rfbKeySym key)
Eddie James21b177e2018-12-11 13:14:46 -0600313{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800314 uint8_t mod = 0;
Eddie James21b177e2018-12-11 13:14:46 -0600315
316 if (key >= XK_Shift_L && key <= XK_Control_R)
317 {
318 mod = shiftCtrlMap[key - XK_Shift_L];
319 }
320 else if (key >= XK_Meta_L && key <= XK_Alt_R)
321 {
322 mod = metaAltMap[key - XK_Meta_L];
323 }
324
325 return mod;
326}
327
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800328uint8_t Input::keyToScancode(rfbKeySym key)
Eddie James21b177e2018-12-11 13:14:46 -0600329{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800330 uint8_t scancode = 0;
Eddie James21b177e2018-12-11 13:14:46 -0600331
332 if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'))
333 {
334 scancode = USBHID_KEY_A + ((key & 0x5F) - 'A');
335 }
336 else if (key >= '1' && key <= '9')
337 {
338 scancode = USBHID_KEY_1 + (key - '1');
339 }
340 else if (key >= XK_F1 && key <= XK_F12)
341 {
342 scancode = USBHID_KEY_F1 + (key - XK_F1);
343 }
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700344 else if (key >= XK_KP_F1 && key <= XK_KP_F4)
345 {
346 scancode = USBHID_KEY_F1 + (key - XK_KP_F1);
347 }
348 else if (key >= XK_KP_1 && key <= XK_KP_9)
349 {
350 scancode = USBHID_KEY_KP_1 + (key - XK_KP_1);
351 }
Eddie James21b177e2018-12-11 13:14:46 -0600352 else
353 {
354 switch (key)
355 {
356 case XK_exclam:
357 scancode = USBHID_KEY_1;
358 break;
359 case XK_at:
360 scancode = USBHID_KEY_2;
361 break;
362 case XK_numbersign:
363 scancode = USBHID_KEY_3;
364 break;
365 case XK_dollar:
366 scancode = USBHID_KEY_4;
367 break;
368 case XK_percent:
369 scancode = USBHID_KEY_5;
370 break;
371 case XK_asciicircum:
372 scancode = USBHID_KEY_6;
373 break;
374 case XK_ampersand:
375 scancode = USBHID_KEY_7;
376 break;
377 case XK_asterisk:
378 scancode = USBHID_KEY_8;
379 break;
380 case XK_parenleft:
381 scancode = USBHID_KEY_9;
382 break;
383 case XK_0:
384 case XK_parenright:
385 scancode = USBHID_KEY_0;
386 break;
387 case XK_Return:
388 scancode = USBHID_KEY_RETURN;
389 break;
390 case XK_Escape:
391 scancode = USBHID_KEY_ESC;
392 break;
393 case XK_BackSpace:
394 scancode = USBHID_KEY_BACKSPACE;
395 break;
396 case XK_Tab:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700397 case XK_KP_Tab:
Eddie James21b177e2018-12-11 13:14:46 -0600398 scancode = USBHID_KEY_TAB;
399 break;
400 case XK_space:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700401 case XK_KP_Space:
Eddie James21b177e2018-12-11 13:14:46 -0600402 scancode = USBHID_KEY_SPACE;
403 break;
404 case XK_minus:
405 case XK_underscore:
406 scancode = USBHID_KEY_MINUS;
407 break;
408 case XK_plus:
409 case XK_equal:
410 scancode = USBHID_KEY_EQUAL;
411 break;
412 case XK_bracketleft:
413 case XK_braceleft:
414 scancode = USBHID_KEY_LEFTBRACE;
415 break;
416 case XK_bracketright:
417 case XK_braceright:
418 scancode = USBHID_KEY_RIGHTBRACE;
419 break;
420 case XK_backslash:
421 case XK_bar:
422 scancode = USBHID_KEY_BACKSLASH;
423 break;
424 case XK_colon:
425 case XK_semicolon:
426 scancode = USBHID_KEY_SEMICOLON;
427 break;
428 case XK_quotedbl:
429 case XK_apostrophe:
430 scancode = USBHID_KEY_APOSTROPHE;
431 break;
432 case XK_grave:
433 case XK_asciitilde:
434 scancode = USBHID_KEY_GRAVE;
435 break;
436 case XK_comma:
437 case XK_less:
438 scancode = USBHID_KEY_COMMA;
439 break;
440 case XK_period:
441 case XK_greater:
442 scancode = USBHID_KEY_DOT;
443 break;
444 case XK_slash:
445 case XK_question:
446 scancode = USBHID_KEY_SLASH;
447 break;
448 case XK_Caps_Lock:
449 scancode = USBHID_KEY_CAPSLOCK;
450 break;
451 case XK_Print:
452 scancode = USBHID_KEY_PRINT;
453 break;
454 case XK_Scroll_Lock:
455 scancode = USBHID_KEY_SCROLLLOCK;
456 break;
457 case XK_Pause:
458 scancode = USBHID_KEY_PAUSE;
459 break;
460 case XK_Insert:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700461 case XK_KP_Insert:
Eddie James21b177e2018-12-11 13:14:46 -0600462 scancode = USBHID_KEY_INSERT;
463 break;
464 case XK_Home:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700465 case XK_KP_Home:
Eddie James21b177e2018-12-11 13:14:46 -0600466 scancode = USBHID_KEY_HOME;
467 break;
468 case XK_Page_Up:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700469 case XK_KP_Page_Up:
Eddie James21b177e2018-12-11 13:14:46 -0600470 scancode = USBHID_KEY_PAGEUP;
471 break;
472 case XK_Delete:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700473 case XK_KP_Delete:
Eddie James21b177e2018-12-11 13:14:46 -0600474 scancode = USBHID_KEY_DELETE;
475 break;
476 case XK_End:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700477 case XK_KP_End:
Eddie James21b177e2018-12-11 13:14:46 -0600478 scancode = USBHID_KEY_END;
479 break;
480 case XK_Page_Down:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700481 case XK_KP_Page_Down:
Eddie James21b177e2018-12-11 13:14:46 -0600482 scancode = USBHID_KEY_PAGEDOWN;
483 break;
484 case XK_Right:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700485 case XK_KP_Right:
Eddie James21b177e2018-12-11 13:14:46 -0600486 scancode = USBHID_KEY_RIGHT;
487 break;
488 case XK_Left:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700489 case XK_KP_Left:
Eddie James21b177e2018-12-11 13:14:46 -0600490 scancode = USBHID_KEY_LEFT;
491 break;
492 case XK_Down:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700493 case XK_KP_Down:
Eddie James21b177e2018-12-11 13:14:46 -0600494 scancode = USBHID_KEY_DOWN;
495 break;
496 case XK_Up:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700497 case XK_KP_Up:
Eddie James21b177e2018-12-11 13:14:46 -0600498 scancode = USBHID_KEY_UP;
499 break;
500 case XK_Num_Lock:
501 scancode = USBHID_KEY_NUMLOCK;
502 break;
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700503 case XK_KP_Enter:
504 scancode = USBHID_KEY_KP_ENTER;
505 break;
506 case XK_KP_Equal:
507 scancode = USBHID_KEY_KP_EQUAL;
508 break;
509 case XK_KP_Multiply:
510 scancode = USBHID_KEY_KP_MULTIPLY;
511 break;
512 case XK_KP_Add:
513 scancode = USBHID_KEY_KP_ADD;
514 break;
515 case XK_KP_Subtract:
516 scancode = USBHID_KEY_KP_SUBTRACT;
517 break;
518 case XK_KP_Decimal:
519 scancode = USBHID_KEY_KP_DECIMAL;
520 break;
521 case XK_KP_Divide:
522 scancode = USBHID_KEY_KP_DIVIDE;
523 break;
524 case XK_KP_0:
525 scancode = USBHID_KEY_KP_0;
526 break;
Eddie James21b177e2018-12-11 13:14:46 -0600527 }
528 }
529
530 return scancode;
531}
532
George Liuf79f6f52022-07-06 09:32:35 +0800533bool Input::writeKeyboard(const uint8_t* report)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500534{
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700535 std::unique_lock<std::mutex> lk(keyMutex);
536 uint retryCount = HID_REPORT_RETRY_MAX;
537
538 while (retryCount > 0)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500539 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700540 if (write(keyboardFd, report, KEY_REPORT_LENGTH) == KEY_REPORT_LENGTH)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500541 {
Zev Weiss40fd5422021-06-17 05:41:40 +0000542 return true;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500543 }
544
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700545 if (errno != EAGAIN)
546 {
547 if (errno != ESHUTDOWN)
548 {
549 log<level::ERR>("Failed to write keyboard report",
550 entry("ERROR=%s", strerror(errno)));
551 }
552
553 break;
554 }
555
556 lk.unlock();
557 std::this_thread::sleep_for(std::chrono::milliseconds(10));
558 lk.lock();
559 retryCount--;
560 }
561
Zev Weiss40fd5422021-06-17 05:41:40 +0000562 return false;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500563}
564
George Liuf79f6f52022-07-06 09:32:35 +0800565void Input::writePointer(const uint8_t* report)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500566{
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700567 std::unique_lock<std::mutex> lk(ptrMutex);
568 uint retryCount = HID_REPORT_RETRY_MAX;
569
570 while (retryCount > 0)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500571 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700572 if (write(pointerFd, report, PTR_REPORT_LENGTH) == PTR_REPORT_LENGTH)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500573 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700574 break;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500575 }
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700576
577 if (errno != EAGAIN)
578 {
579 if (errno != ESHUTDOWN)
580 {
581 log<level::ERR>("Failed to write pointer report",
582 entry("ERROR=%s", strerror(errno)));
583 }
584
585 break;
586 }
587
588 lk.unlock();
589 std::this_thread::sleep_for(std::chrono::milliseconds(10));
590 lk.lock();
591 retryCount--;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500592 }
593}
594
Eddie James21b177e2018-12-11 13:14:46 -0600595} // namespace ikvm