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