1 #pragma once 2 3 #include <rfb/rfb.h> 4 5 #include <filesystem> 6 #include <fstream> 7 #include <map> 8 #include <mutex> 9 #include <string> 10 11 namespace ikvm 12 { 13 14 /* 15 * @class Input 16 * @brief Receives events from RFB clients and sends reports to the USB input 17 * device 18 */ 19 class Input 20 { 21 public: 22 /* 23 * @brief Constructs Input object 24 * 25 * @param[in] kbdPath - Path to the USB keyboard device 26 * @param[in] ptrPath - Path to the USB mouse device 27 * @param[in] udc - Name of UDC 28 */ 29 Input(const std::string& kbdPath, const std::string& ptrPath, 30 const std::string& udc); 31 ~Input(); 32 Input(const Input&) = default; 33 Input& operator=(const Input&) = default; 34 Input(Input&&) = default; 35 Input& operator=(Input&&) = default; 36 37 /* @brief Connects HID gadget to host */ 38 void connect(); 39 /* @brief Disconnects HID gadget from host */ 40 void disconnect(); 41 /* 42 * @brief RFB client key event handler 43 * 44 * @param[in] down - Boolean indicating whether key is pressed or not 45 * @param[in] key - Key code 46 * @param[in] cl - Handle to the RFB client 47 */ 48 static void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl); 49 /* 50 * @brief RFB client pointer event handler 51 * 52 * @param[in] buttonMask - Bitmask indicating which buttons have been 53 * pressed 54 * @param[in] x - Pointer x-coordinate 55 * @param[in] y - Pointer y-coordinate 56 * @param[in] cl - Handle to the RFB client 57 */ 58 static void pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl); 59 60 /* @brief Sends a wakeup data packet to the USB input device */ 61 void sendWakeupPacket(); 62 63 private: 64 static constexpr int NUM_MODIFIER_BITS = 4; 65 static constexpr int KEY_REPORT_LENGTH = 8; 66 static constexpr int PTR_REPORT_LENGTH = 6; 67 68 /* @brief HID modifier bits mapped to shift and control key codes */ 69 static constexpr uint8_t shiftCtrlMap[NUM_MODIFIER_BITS] = { 70 0x02, // left shift 71 0x20, // right shift 72 0x01, // left control 73 0x10 // right control 74 }; 75 /* @brief HID modifier bits mapped to meta and alt key codes */ 76 static constexpr uint8_t metaAltMap[NUM_MODIFIER_BITS] = { 77 0x08, // left meta 78 0x80, // right meta 79 0x04, // left alt 80 0x40 // right alt 81 }; 82 /* @brief Path to the HID gadget UDC */ 83 static constexpr const char* hidUdcPath = 84 "/sys/kernel/config/usb_gadget/obmc_hid/UDC"; 85 /* @brief Path to the USB virtual hub */ 86 static constexpr const char* usbVirtualHubPath = 87 "/sys/bus/platform/devices/1e6a0000.usb-vhub"; 88 /* @brief Retry limit for writing an HID report */ 89 static constexpr int HID_REPORT_RETRY_MAX = 5; 90 /* 91 * @brief Translates a RFB-specific key code to HID modifier bit 92 * 93 * @param[in] key - key code 94 */ 95 static uint8_t keyToMod(rfbKeySym key); 96 /* 97 * @brief Translates a RFB-specific key code to HID scancode 98 * 99 * @param[in] key - key code 100 */ 101 static uint8_t keyToScancode(rfbKeySym key); 102 103 bool writeKeyboard(const uint8_t* report); 104 void writePointer(const uint8_t* report); 105 106 /* @brief File descriptor for the USB keyboard device */ 107 int keyboardFd; 108 /* @brief File descriptor for the USB mouse device */ 109 int pointerFd; 110 /* @brief Data for keyboard report */ 111 uint8_t keyboardReport[KEY_REPORT_LENGTH]; 112 /* @brief Data for pointer report */ 113 uint8_t pointerReport[PTR_REPORT_LENGTH]; 114 /* @brief Path to the USB keyboard device */ 115 std::string keyboardPath; 116 /* @brief Path to the USB mouse device */ 117 std::string pointerPath; 118 /* @brief Name of UDC */ 119 std::string udcName; 120 /* 121 * @brief Mapping of RFB key code to report data index to keep track 122 * of which keys are down 123 */ 124 std::map<int, int> keysDown; 125 /* @brief Handle of the HID gadget UDC */ 126 std::ofstream hidUdcStream; 127 /* @brief Mutex for sending keyboard reports */ 128 std::mutex keyMutex; 129 /* @brief Mutex for sending pointer reports */ 130 std::mutex ptrMutex; 131 }; 132 133 } // namespace ikvm 134