1 #include "ikvm_input.hpp" 2 3 #include "ikvm_server.hpp" 4 5 #include <err.h> 6 #include <errno.h> 7 #include <fcntl.h> 8 #include <rfb/keysym.h> 9 #include <sys/stat.h> 10 #include <sys/types.h> 11 12 #include <phosphor-logging/elog-errors.hpp> 13 #include <phosphor-logging/elog.hpp> 14 #include <phosphor-logging/log.hpp> 15 #include <xyz/openbmc_project/Common/File/error.hpp> 16 17 #include "scancodes.hpp" 18 19 namespace ikvm 20 { 21 22 using namespace phosphor::logging; 23 using namespace sdbusplus::xyz::openbmc_project::Common::File::Error; 24 25 Input::Input(const std::string& kbdPath, const std::string& ptrPath) : 26 keyboardFd(-1), pointerFd(-1), keyboardReport{0}, pointerReport{0}, 27 keyboardPath(kbdPath), pointerPath(ptrPath) 28 { 29 if (!keyboardPath.empty()) 30 { 31 keyboardFd = open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC); 32 if (keyboardFd < 0) 33 { 34 log<level::ERR>("Failed to open input device", 35 entry("PATH=%s", keyboardPath.c_str()), 36 entry("ERROR=%s", strerror(errno))); 37 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno), 38 xyz::openbmc_project::Common::File::Open::PATH( 39 keyboardPath.c_str())); 40 } 41 } 42 43 if (!pointerPath.empty()) 44 { 45 pointerFd = open(pointerPath.c_str(), O_RDWR | O_CLOEXEC); 46 if (pointerFd < 0) 47 { 48 log<level::ERR>("Failed to open input device", 49 entry("PATH=%s", pointerPath.c_str()), 50 entry("ERROR=%s", strerror(errno))); 51 elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno), 52 xyz::openbmc_project::Common::File::Open::PATH( 53 pointerPath.c_str())); 54 } 55 } 56 } 57 58 Input::~Input() 59 { 60 if (keyboardFd >= 0) 61 { 62 close(keyboardFd); 63 } 64 65 if (pointerFd >= 0) 66 { 67 close(pointerFd); 68 } 69 } 70 71 void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl) 72 { 73 Server::ClientData* cd = (Server::ClientData*)cl->clientData; 74 Input* input = cd->input; 75 76 if (down) 77 { 78 uint8_t sc = keyToScancode(key); 79 80 if (sc) 81 { 82 if (input->keysDown.find(key) == input->keysDown.end()) 83 { 84 for (unsigned int i = 2; i < KEY_REPORT_LENGTH; ++i) 85 { 86 if (!input->keyboardReport[i]) 87 { 88 input->keyboardReport[i] = sc; 89 input->keysDown.insert(std::make_pair(key, i)); 90 input->sendKeyboard = true; 91 break; 92 } 93 } 94 } 95 } 96 else 97 { 98 uint8_t mod = keyToMod(key); 99 100 if (mod) 101 { 102 input->keyboardReport[0] |= mod; 103 input->sendKeyboard = true; 104 } 105 } 106 } 107 else 108 { 109 auto it = input->keysDown.find(key); 110 111 if (it != input->keysDown.end()) 112 { 113 input->keyboardReport[it->second] = 0; 114 input->keysDown.erase(it); 115 input->sendKeyboard = true; 116 } 117 else 118 { 119 uint8_t mod = keyToMod(key); 120 121 if (mod) 122 { 123 input->keyboardReport[0] &= ~mod; 124 input->sendKeyboard = true; 125 } 126 } 127 } 128 } 129 130 void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl) 131 { 132 Server::ClientData* cd = (Server::ClientData*)cl->clientData; 133 Input* input = cd->input; 134 Server* server = (Server*)cl->screen->screenData; 135 const Video& video = server->getVideo(); 136 137 input->pointerReport[0] = buttonMask & 0xFF; 138 139 if (x >= 0 && (unsigned int)x < video.getWidth()) 140 { 141 uint16_t xx = (uint16_t)(x * (SHRT_MAX + 1) / video.getWidth()); 142 143 memcpy(&input->pointerReport[1], &xx, 2); 144 } 145 146 if (y >= 0 && (unsigned int)y < video.getHeight()) 147 { 148 uint16_t yy = (uint16_t)(y * (SHRT_MAX + 1) / video.getHeight()); 149 150 memcpy(&input->pointerReport[3], &yy, 2); 151 } 152 153 input->sendPointer = true; 154 rfbDefaultPtrAddEvent(buttonMask, x, y, cl); 155 } 156 157 void Input::sendWakeupPacket() 158 { 159 uint8_t wakeupReport[KEY_REPORT_LENGTH] = {0}; 160 161 if (pointerFd >= 0) 162 { 163 uint16_t xy = SHRT_MAX / 2; 164 165 memcpy(&wakeupReport[1], &xy, 2); 166 memcpy(&wakeupReport[3], &xy, 2); 167 168 if (write(pointerFd, wakeupReport, PTR_REPORT_LENGTH) != 169 PTR_REPORT_LENGTH) 170 { 171 log<level::ERR>("Failed to write pointer report", 172 entry("ERROR=%s", strerror(errno))); 173 } 174 } 175 176 if (keyboardFd >= 0) 177 { 178 memset(&wakeupReport[0], 0, KEY_REPORT_LENGTH); 179 180 wakeupReport[0] = keyToMod(XK_Shift_L); 181 182 if (write(keyboardFd, wakeupReport, KEY_REPORT_LENGTH) != 183 KEY_REPORT_LENGTH) 184 { 185 log<level::ERR>("Failed to write keyboard report", 186 entry("ERROR=%s", strerror(errno))); 187 return; 188 } 189 190 wakeupReport[0] = 0; 191 192 if (write(keyboardFd, wakeupReport, KEY_REPORT_LENGTH) != 193 KEY_REPORT_LENGTH) 194 { 195 log<level::ERR>("Failed to write keyboard report", 196 entry("ERROR=%s", strerror(errno))); 197 } 198 } 199 } 200 201 void Input::sendReport() 202 { 203 if (sendKeyboard && keyboardFd >= 0) 204 { 205 if (write(keyboardFd, keyboardReport, KEY_REPORT_LENGTH) != 206 KEY_REPORT_LENGTH) 207 { 208 log<level::ERR>("Failed to write keyboard report", 209 entry("ERROR=%s", strerror(errno))); 210 } 211 212 sendKeyboard = false; 213 } 214 215 if (sendPointer && pointerFd >= 0) 216 { 217 if (write(pointerFd, pointerReport, PTR_REPORT_LENGTH) != 218 PTR_REPORT_LENGTH) 219 { 220 log<level::ERR>("Failed to write pointer report", 221 entry("ERROR=%s", strerror(errno))); 222 } 223 224 sendPointer = false; 225 } 226 } 227 228 uint8_t Input::keyToMod(rfbKeySym key) 229 { 230 uint8_t mod = 0; 231 232 if (key >= XK_Shift_L && key <= XK_Control_R) 233 { 234 mod = shiftCtrlMap[key - XK_Shift_L]; 235 } 236 else if (key >= XK_Meta_L && key <= XK_Alt_R) 237 { 238 mod = metaAltMap[key - XK_Meta_L]; 239 } 240 241 return mod; 242 } 243 244 uint8_t Input::keyToScancode(rfbKeySym key) 245 { 246 uint8_t scancode = 0; 247 248 if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z')) 249 { 250 scancode = USBHID_KEY_A + ((key & 0x5F) - 'A'); 251 } 252 else if (key >= '1' && key <= '9') 253 { 254 scancode = USBHID_KEY_1 + (key - '1'); 255 } 256 else if (key >= XK_F1 && key <= XK_F12) 257 { 258 scancode = USBHID_KEY_F1 + (key - XK_F1); 259 } 260 else 261 { 262 switch (key) 263 { 264 case XK_exclam: 265 scancode = USBHID_KEY_1; 266 break; 267 case XK_at: 268 scancode = USBHID_KEY_2; 269 break; 270 case XK_numbersign: 271 scancode = USBHID_KEY_3; 272 break; 273 case XK_dollar: 274 scancode = USBHID_KEY_4; 275 break; 276 case XK_percent: 277 scancode = USBHID_KEY_5; 278 break; 279 case XK_asciicircum: 280 scancode = USBHID_KEY_6; 281 break; 282 case XK_ampersand: 283 scancode = USBHID_KEY_7; 284 break; 285 case XK_asterisk: 286 scancode = USBHID_KEY_8; 287 break; 288 case XK_parenleft: 289 scancode = USBHID_KEY_9; 290 break; 291 case XK_0: 292 case XK_parenright: 293 scancode = USBHID_KEY_0; 294 break; 295 case XK_Return: 296 scancode = USBHID_KEY_RETURN; 297 break; 298 case XK_Escape: 299 scancode = USBHID_KEY_ESC; 300 break; 301 case XK_BackSpace: 302 scancode = USBHID_KEY_BACKSPACE; 303 break; 304 case XK_Tab: 305 scancode = USBHID_KEY_TAB; 306 break; 307 case XK_space: 308 scancode = USBHID_KEY_SPACE; 309 break; 310 case XK_minus: 311 case XK_underscore: 312 scancode = USBHID_KEY_MINUS; 313 break; 314 case XK_plus: 315 case XK_equal: 316 scancode = USBHID_KEY_EQUAL; 317 break; 318 case XK_bracketleft: 319 case XK_braceleft: 320 scancode = USBHID_KEY_LEFTBRACE; 321 break; 322 case XK_bracketright: 323 case XK_braceright: 324 scancode = USBHID_KEY_RIGHTBRACE; 325 break; 326 case XK_backslash: 327 case XK_bar: 328 scancode = USBHID_KEY_BACKSLASH; 329 break; 330 case XK_colon: 331 case XK_semicolon: 332 scancode = USBHID_KEY_SEMICOLON; 333 break; 334 case XK_quotedbl: 335 case XK_apostrophe: 336 scancode = USBHID_KEY_APOSTROPHE; 337 break; 338 case XK_grave: 339 case XK_asciitilde: 340 scancode = USBHID_KEY_GRAVE; 341 break; 342 case XK_comma: 343 case XK_less: 344 scancode = USBHID_KEY_COMMA; 345 break; 346 case XK_period: 347 case XK_greater: 348 scancode = USBHID_KEY_DOT; 349 break; 350 case XK_slash: 351 case XK_question: 352 scancode = USBHID_KEY_SLASH; 353 break; 354 case XK_Caps_Lock: 355 scancode = USBHID_KEY_CAPSLOCK; 356 break; 357 case XK_Print: 358 scancode = USBHID_KEY_PRINT; 359 break; 360 case XK_Scroll_Lock: 361 scancode = USBHID_KEY_SCROLLLOCK; 362 break; 363 case XK_Pause: 364 scancode = USBHID_KEY_PAUSE; 365 break; 366 case XK_Insert: 367 scancode = USBHID_KEY_INSERT; 368 break; 369 case XK_Home: 370 scancode = USBHID_KEY_HOME; 371 break; 372 case XK_Page_Up: 373 scancode = USBHID_KEY_PAGEUP; 374 break; 375 case XK_Delete: 376 scancode = USBHID_KEY_DELETE; 377 break; 378 case XK_End: 379 scancode = USBHID_KEY_END; 380 break; 381 case XK_Page_Down: 382 scancode = USBHID_KEY_PAGEDOWN; 383 break; 384 case XK_Right: 385 scancode = USBHID_KEY_RIGHT; 386 break; 387 case XK_Left: 388 scancode = USBHID_KEY_LEFT; 389 break; 390 case XK_Down: 391 scancode = USBHID_KEY_DOWN; 392 break; 393 case XK_Up: 394 scancode = USBHID_KEY_UP; 395 break; 396 case XK_Num_Lock: 397 scancode = USBHID_KEY_NUMLOCK; 398 break; 399 } 400 } 401 402 return scancode; 403 } 404 405 } // namespace ikvm 406