blob: e9bd151ef34f32ca9aa69b32a858dec7592d0e0e [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
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080026Input::Input(const std::string& kbdPath, const std::string& ptrPath) :
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -070027 keyboardFd(-1), pointerFd(-1), keyboardReport{0}, pointerReport{0},
28 keyboardPath(kbdPath), pointerPath(ptrPath)
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 {
54 for (const auto& port : fs::directory_iterator(usbVirtualHubPath))
55 {
56 if (fs::is_directory(port) && !fs::is_symlink(port) &&
57 !fs::exists(port.path() / "gadget/suspended"))
58 {
59 const std::string portId = port.path().filename();
60 hidUdcStream << portId << std::endl;
61 break;
62 }
63 }
64 }
65 catch (fs::filesystem_error& e)
66 {
67 log<level::ERR>("Failed to search USB virtual hub port",
68 entry("ERROR=%s", e.what()));
69 return;
70 }
71 catch (std::ofstream::failure& e)
72 {
73 log<level::ERR>("Failed to connect HID gadget",
74 entry("ERROR=%s", e.what()));
75 return;
76 }
77
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080078 if (!keyboardPath.empty())
Eddie James21b177e2018-12-11 13:14:46 -060079 {
George Liuf79f6f52022-07-06 09:32:35 +080080 keyboardFd =
81 open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080082 if (keyboardFd < 0)
83 {
84 log<level::ERR>("Failed to open input device",
85 entry("PATH=%s", keyboardPath.c_str()),
86 entry("ERROR=%s", strerror(errno)));
87 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno),
88 xyz::openbmc_project::Common::File::Open::PATH(
89 keyboardPath.c_str()));
90 }
Eddie James21b177e2018-12-11 13:14:46 -060091 }
92
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080093 if (!pointerPath.empty())
94 {
Eddie James4749f932019-04-18 11:06:39 -050095 pointerFd = open(pointerPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080096 if (pointerFd < 0)
97 {
98 log<level::ERR>("Failed to open input device",
99 entry("PATH=%s", pointerPath.c_str()),
100 entry("ERROR=%s", strerror(errno)));
101 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno),
102 xyz::openbmc_project::Common::File::Open::PATH(
103 pointerPath.c_str()));
104 }
105 }
Eddie James21b177e2018-12-11 13:14:46 -0600106}
107
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700108void Input::disconnect()
Eddie James21b177e2018-12-11 13:14:46 -0600109{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800110 if (keyboardFd >= 0)
111 {
112 close(keyboardFd);
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700113 keyboardFd = -1;
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800114 }
115
116 if (pointerFd >= 0)
117 {
118 close(pointerFd);
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700119 pointerFd = -1;
120 }
121
122 try
123 {
124 hidUdcStream << "" << std::endl;
125 }
126 catch (std::ofstream::failure& e)
127 {
128 log<level::ERR>("Failed to disconnect HID gadget",
129 entry("ERROR=%s", e.what()));
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800130 }
Eddie James21b177e2018-12-11 13:14:46 -0600131}
132
133void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl)
134{
135 Server::ClientData* cd = (Server::ClientData*)cl->clientData;
136 Input* input = cd->input;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700137 bool sendKeyboard = false;
138
139 if (input->keyboardFd < 0)
140 {
141 return;
142 }
Eddie James21b177e2018-12-11 13:14:46 -0600143
144 if (down)
145 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800146 uint8_t sc = keyToScancode(key);
Eddie James21b177e2018-12-11 13:14:46 -0600147
148 if (sc)
149 {
150 if (input->keysDown.find(key) == input->keysDown.end())
151 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800152 for (unsigned int i = 2; i < KEY_REPORT_LENGTH; ++i)
Eddie James21b177e2018-12-11 13:14:46 -0600153 {
154 if (!input->keyboardReport[i])
155 {
156 input->keyboardReport[i] = sc;
157 input->keysDown.insert(std::make_pair(key, i));
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700158 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600159 break;
160 }
161 }
162 }
163 }
164 else
165 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800166 uint8_t mod = keyToMod(key);
Eddie James21b177e2018-12-11 13:14:46 -0600167
168 if (mod)
169 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800170 input->keyboardReport[0] |= mod;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700171 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600172 }
173 }
174 }
175 else
176 {
177 auto it = input->keysDown.find(key);
178
179 if (it != input->keysDown.end())
180 {
181 input->keyboardReport[it->second] = 0;
182 input->keysDown.erase(it);
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700183 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600184 }
185 else
186 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800187 uint8_t mod = keyToMod(key);
Eddie James21b177e2018-12-11 13:14:46 -0600188
189 if (mod)
190 {
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800191 input->keyboardReport[0] &= ~mod;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700192 sendKeyboard = true;
Eddie James21b177e2018-12-11 13:14:46 -0600193 }
194 }
195 }
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700196
197 if (sendKeyboard)
198 {
199 input->writeKeyboard(input->keyboardReport);
200 }
Eddie James21b177e2018-12-11 13:14:46 -0600201}
202
203void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl)
204{
205 Server::ClientData* cd = (Server::ClientData*)cl->clientData;
206 Input* input = cd->input;
207 Server* server = (Server*)cl->screen->screenData;
208 const Video& video = server->getVideo();
209
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700210 if (input->pointerFd < 0)
211 {
212 return;
213 }
214
Tejas Patil3fa0bfb2021-12-23 15:44:47 +0530215 if (buttonMask > 4)
216 {
217 input->pointerReport[0] = 0;
218 if (buttonMask == 8)
219 {
220 input->pointerReport[5] = 1;
221 }
222 else if (buttonMask == 16)
223 {
224 input->pointerReport[5] = 0xff;
225 }
226 }
227 else
228 {
229 input->pointerReport[0] = ((buttonMask & 0x4) >> 1) |
George Liuf79f6f52022-07-06 09:32:35 +0800230 ((buttonMask & 0x2) << 1) |
231 (buttonMask & 0x1);
Tejas Patil3fa0bfb2021-12-23 15:44:47 +0530232 input->pointerReport[5] = 0;
233 }
Eddie James21b177e2018-12-11 13:14:46 -0600234
235 if (x >= 0 && (unsigned int)x < video.getWidth())
236 {
Jae Hyun Yoo2bc661d2019-02-25 13:52:47 -0800237 uint16_t xx = (uint16_t)(x * (SHRT_MAX + 1) / video.getWidth());
Eddie James21b177e2018-12-11 13:14:46 -0600238
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800239 memcpy(&input->pointerReport[1], &xx, 2);
Eddie James21b177e2018-12-11 13:14:46 -0600240 }
241
242 if (y >= 0 && (unsigned int)y < video.getHeight())
243 {
Jae Hyun Yoo2bc661d2019-02-25 13:52:47 -0800244 uint16_t yy = (uint16_t)(y * (SHRT_MAX + 1) / video.getHeight());
Eddie James21b177e2018-12-11 13:14:46 -0600245
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800246 memcpy(&input->pointerReport[3], &yy, 2);
Eddie James21b177e2018-12-11 13:14:46 -0600247 }
248
Eddie James21b177e2018-12-11 13:14:46 -0600249 rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700250 input->writePointer(input->pointerReport);
Eddie James21b177e2018-12-11 13:14:46 -0600251}
252
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800253void Input::sendWakeupPacket()
Eddie James21b177e2018-12-11 13:14:46 -0600254{
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800255 uint8_t wakeupReport[KEY_REPORT_LENGTH] = {0};
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800256
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800257 if (pointerFd >= 0)
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800258 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800259 uint16_t xy = SHRT_MAX / 2;
260
261 memcpy(&wakeupReport[1], &xy, 2);
262 memcpy(&wakeupReport[3], &xy, 2);
263
Eddie James7cf1f1d2019-09-30 15:05:16 -0500264 writePointer(wakeupReport);
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800265 }
266
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800267 if (keyboardFd >= 0)
Eddie James21b177e2018-12-11 13:14:46 -0600268 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800269 memset(&wakeupReport[0], 0, KEY_REPORT_LENGTH);
270
271 wakeupReport[0] = keyToMod(XK_Shift_L);
272
Eddie James7cf1f1d2019-09-30 15:05:16 -0500273 if (!writeKeyboard(wakeupReport))
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800274 {
Jae Hyun Yooeaf5c5b2019-02-20 15:03:17 -0800275 return;
276 }
277
278 wakeupReport[0] = 0;
279
Eddie James7cf1f1d2019-09-30 15:05:16 -0500280 writeKeyboard(wakeupReport);
Eddie James21b177e2018-12-11 13:14:46 -0600281 }
282}
283
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800284uint8_t Input::keyToMod(rfbKeySym key)
Eddie James21b177e2018-12-11 13:14:46 -0600285{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800286 uint8_t mod = 0;
Eddie James21b177e2018-12-11 13:14:46 -0600287
288 if (key >= XK_Shift_L && key <= XK_Control_R)
289 {
290 mod = shiftCtrlMap[key - XK_Shift_L];
291 }
292 else if (key >= XK_Meta_L && key <= XK_Alt_R)
293 {
294 mod = metaAltMap[key - XK_Meta_L];
295 }
296
297 return mod;
298}
299
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800300uint8_t Input::keyToScancode(rfbKeySym key)
Eddie James21b177e2018-12-11 13:14:46 -0600301{
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800302 uint8_t scancode = 0;
Eddie James21b177e2018-12-11 13:14:46 -0600303
304 if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'))
305 {
306 scancode = USBHID_KEY_A + ((key & 0x5F) - 'A');
307 }
308 else if (key >= '1' && key <= '9')
309 {
310 scancode = USBHID_KEY_1 + (key - '1');
311 }
312 else if (key >= XK_F1 && key <= XK_F12)
313 {
314 scancode = USBHID_KEY_F1 + (key - XK_F1);
315 }
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700316 else if (key >= XK_KP_F1 && key <= XK_KP_F4)
317 {
318 scancode = USBHID_KEY_F1 + (key - XK_KP_F1);
319 }
320 else if (key >= XK_KP_1 && key <= XK_KP_9)
321 {
322 scancode = USBHID_KEY_KP_1 + (key - XK_KP_1);
323 }
Eddie James21b177e2018-12-11 13:14:46 -0600324 else
325 {
326 switch (key)
327 {
328 case XK_exclam:
329 scancode = USBHID_KEY_1;
330 break;
331 case XK_at:
332 scancode = USBHID_KEY_2;
333 break;
334 case XK_numbersign:
335 scancode = USBHID_KEY_3;
336 break;
337 case XK_dollar:
338 scancode = USBHID_KEY_4;
339 break;
340 case XK_percent:
341 scancode = USBHID_KEY_5;
342 break;
343 case XK_asciicircum:
344 scancode = USBHID_KEY_6;
345 break;
346 case XK_ampersand:
347 scancode = USBHID_KEY_7;
348 break;
349 case XK_asterisk:
350 scancode = USBHID_KEY_8;
351 break;
352 case XK_parenleft:
353 scancode = USBHID_KEY_9;
354 break;
355 case XK_0:
356 case XK_parenright:
357 scancode = USBHID_KEY_0;
358 break;
359 case XK_Return:
360 scancode = USBHID_KEY_RETURN;
361 break;
362 case XK_Escape:
363 scancode = USBHID_KEY_ESC;
364 break;
365 case XK_BackSpace:
366 scancode = USBHID_KEY_BACKSPACE;
367 break;
368 case XK_Tab:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700369 case XK_KP_Tab:
Eddie James21b177e2018-12-11 13:14:46 -0600370 scancode = USBHID_KEY_TAB;
371 break;
372 case XK_space:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700373 case XK_KP_Space:
Eddie James21b177e2018-12-11 13:14:46 -0600374 scancode = USBHID_KEY_SPACE;
375 break;
376 case XK_minus:
377 case XK_underscore:
378 scancode = USBHID_KEY_MINUS;
379 break;
380 case XK_plus:
381 case XK_equal:
382 scancode = USBHID_KEY_EQUAL;
383 break;
384 case XK_bracketleft:
385 case XK_braceleft:
386 scancode = USBHID_KEY_LEFTBRACE;
387 break;
388 case XK_bracketright:
389 case XK_braceright:
390 scancode = USBHID_KEY_RIGHTBRACE;
391 break;
392 case XK_backslash:
393 case XK_bar:
394 scancode = USBHID_KEY_BACKSLASH;
395 break;
396 case XK_colon:
397 case XK_semicolon:
398 scancode = USBHID_KEY_SEMICOLON;
399 break;
400 case XK_quotedbl:
401 case XK_apostrophe:
402 scancode = USBHID_KEY_APOSTROPHE;
403 break;
404 case XK_grave:
405 case XK_asciitilde:
406 scancode = USBHID_KEY_GRAVE;
407 break;
408 case XK_comma:
409 case XK_less:
410 scancode = USBHID_KEY_COMMA;
411 break;
412 case XK_period:
413 case XK_greater:
414 scancode = USBHID_KEY_DOT;
415 break;
416 case XK_slash:
417 case XK_question:
418 scancode = USBHID_KEY_SLASH;
419 break;
420 case XK_Caps_Lock:
421 scancode = USBHID_KEY_CAPSLOCK;
422 break;
423 case XK_Print:
424 scancode = USBHID_KEY_PRINT;
425 break;
426 case XK_Scroll_Lock:
427 scancode = USBHID_KEY_SCROLLLOCK;
428 break;
429 case XK_Pause:
430 scancode = USBHID_KEY_PAUSE;
431 break;
432 case XK_Insert:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700433 case XK_KP_Insert:
Eddie James21b177e2018-12-11 13:14:46 -0600434 scancode = USBHID_KEY_INSERT;
435 break;
436 case XK_Home:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700437 case XK_KP_Home:
Eddie James21b177e2018-12-11 13:14:46 -0600438 scancode = USBHID_KEY_HOME;
439 break;
440 case XK_Page_Up:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700441 case XK_KP_Page_Up:
Eddie James21b177e2018-12-11 13:14:46 -0600442 scancode = USBHID_KEY_PAGEUP;
443 break;
444 case XK_Delete:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700445 case XK_KP_Delete:
Eddie James21b177e2018-12-11 13:14:46 -0600446 scancode = USBHID_KEY_DELETE;
447 break;
448 case XK_End:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700449 case XK_KP_End:
Eddie James21b177e2018-12-11 13:14:46 -0600450 scancode = USBHID_KEY_END;
451 break;
452 case XK_Page_Down:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700453 case XK_KP_Page_Down:
Eddie James21b177e2018-12-11 13:14:46 -0600454 scancode = USBHID_KEY_PAGEDOWN;
455 break;
456 case XK_Right:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700457 case XK_KP_Right:
Eddie James21b177e2018-12-11 13:14:46 -0600458 scancode = USBHID_KEY_RIGHT;
459 break;
460 case XK_Left:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700461 case XK_KP_Left:
Eddie James21b177e2018-12-11 13:14:46 -0600462 scancode = USBHID_KEY_LEFT;
463 break;
464 case XK_Down:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700465 case XK_KP_Down:
Eddie James21b177e2018-12-11 13:14:46 -0600466 scancode = USBHID_KEY_DOWN;
467 break;
468 case XK_Up:
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700469 case XK_KP_Up:
Eddie James21b177e2018-12-11 13:14:46 -0600470 scancode = USBHID_KEY_UP;
471 break;
472 case XK_Num_Lock:
473 scancode = USBHID_KEY_NUMLOCK;
474 break;
Jae Hyun Yoo513d95e2019-08-20 11:26:53 -0700475 case XK_KP_Enter:
476 scancode = USBHID_KEY_KP_ENTER;
477 break;
478 case XK_KP_Equal:
479 scancode = USBHID_KEY_KP_EQUAL;
480 break;
481 case XK_KP_Multiply:
482 scancode = USBHID_KEY_KP_MULTIPLY;
483 break;
484 case XK_KP_Add:
485 scancode = USBHID_KEY_KP_ADD;
486 break;
487 case XK_KP_Subtract:
488 scancode = USBHID_KEY_KP_SUBTRACT;
489 break;
490 case XK_KP_Decimal:
491 scancode = USBHID_KEY_KP_DECIMAL;
492 break;
493 case XK_KP_Divide:
494 scancode = USBHID_KEY_KP_DIVIDE;
495 break;
496 case XK_KP_0:
497 scancode = USBHID_KEY_KP_0;
498 break;
Eddie James21b177e2018-12-11 13:14:46 -0600499 }
500 }
501
502 return scancode;
503}
504
George Liuf79f6f52022-07-06 09:32:35 +0800505bool Input::writeKeyboard(const uint8_t* report)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500506{
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700507 std::unique_lock<std::mutex> lk(keyMutex);
508 uint retryCount = HID_REPORT_RETRY_MAX;
509
510 while (retryCount > 0)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500511 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700512 if (write(keyboardFd, report, KEY_REPORT_LENGTH) == KEY_REPORT_LENGTH)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500513 {
Zev Weiss40fd5422021-06-17 05:41:40 +0000514 return true;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500515 }
516
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700517 if (errno != EAGAIN)
518 {
519 if (errno != ESHUTDOWN)
520 {
521 log<level::ERR>("Failed to write keyboard report",
522 entry("ERROR=%s", strerror(errno)));
523 }
524
525 break;
526 }
527
528 lk.unlock();
529 std::this_thread::sleep_for(std::chrono::milliseconds(10));
530 lk.lock();
531 retryCount--;
532 }
533
Zev Weiss40fd5422021-06-17 05:41:40 +0000534 return false;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500535}
536
George Liuf79f6f52022-07-06 09:32:35 +0800537void Input::writePointer(const uint8_t* report)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500538{
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700539 std::unique_lock<std::mutex> lk(ptrMutex);
540 uint retryCount = HID_REPORT_RETRY_MAX;
541
542 while (retryCount > 0)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500543 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700544 if (write(pointerFd, report, PTR_REPORT_LENGTH) == PTR_REPORT_LENGTH)
Eddie James7cf1f1d2019-09-30 15:05:16 -0500545 {
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700546 break;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500547 }
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700548
549 if (errno != EAGAIN)
550 {
551 if (errno != ESHUTDOWN)
552 {
553 log<level::ERR>("Failed to write pointer report",
554 entry("ERROR=%s", strerror(errno)));
555 }
556
557 break;
558 }
559
560 lk.unlock();
561 std::this_thread::sleep_for(std::chrono::milliseconds(10));
562 lk.lock();
563 retryCount--;
Eddie James7cf1f1d2019-09-30 15:05:16 -0500564 }
565}
566
Eddie James21b177e2018-12-11 13:14:46 -0600567} // namespace ikvm