121b177e0SEddie James #pragma once 221b177e0SEddie James 321b177e0SEddie James #include <rfb/rfb.h> 421b177e0SEddie James 5c11257d8SJae Hyun Yoo #include <filesystem> 6c11257d8SJae Hyun Yoo #include <fstream> 721b177e0SEddie James #include <map> 8673ac2ebSJae Hyun Yoo #include <mutex> 921b177e0SEddie James #include <string> 1021b177e0SEddie James 1121b177e0SEddie James namespace ikvm 1221b177e0SEddie James { 1321b177e0SEddie James /* 1421b177e0SEddie James * @class Input 1521b177e0SEddie James * @brief Receives events from RFB clients and sends reports to the USB input 1621b177e0SEddie James * device 1721b177e0SEddie James */ 1821b177e0SEddie James class Input 1921b177e0SEddie James { 2021b177e0SEddie James public: 2121b177e0SEddie James /* 2221b177e0SEddie James * @brief Constructs Input object 2321b177e0SEddie James * 247dfac9ffSJae Hyun Yoo * @param[in] kbdPath - Path to the USB keyboard device 257dfac9ffSJae Hyun Yoo * @param[in] ptrPath - Path to the USB mouse device 26*fe685fb4SMarvin Lin * @param[in] udc - Name of UDC 2721b177e0SEddie James */ 28*fe685fb4SMarvin Lin Input(const std::string& kbdPath, const std::string& ptrPath, 29*fe685fb4SMarvin Lin const std::string& udc); 3021b177e0SEddie James ~Input(); 3121b177e0SEddie James Input(const Input&) = default; 3221b177e0SEddie James Input& operator=(const Input&) = default; 3321b177e0SEddie James Input(Input&&) = default; 3421b177e0SEddie James Input& operator=(Input&&) = default; 3521b177e0SEddie James 36c11257d8SJae Hyun Yoo /* @brief Connects HID gadget to host */ 37c11257d8SJae Hyun Yoo void connect(); 38c11257d8SJae Hyun Yoo /* @brief Disconnects HID gadget from host */ 39c11257d8SJae Hyun Yoo void disconnect(); 4021b177e0SEddie James /* 4121b177e0SEddie James * @brief RFB client key event handler 4221b177e0SEddie James * 4321b177e0SEddie James * @param[in] down - Boolean indicating whether key is pressed or not 4421b177e0SEddie James * @param[in] key - Key code 4521b177e0SEddie James * @param[in] cl - Handle to the RFB client 4621b177e0SEddie James */ 4721b177e0SEddie James static void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl); 4821b177e0SEddie James /* 4921b177e0SEddie James * @brief RFB client pointer event handler 5021b177e0SEddie James * 5121b177e0SEddie James * @param[in] buttonMask - Bitmask indicating which buttons have been 5221b177e0SEddie James * pressed 5321b177e0SEddie James * @param[in] x - Pointer x-coordinate 5421b177e0SEddie James * @param[in] y - Pointer y-coordinate 5521b177e0SEddie James * @param[in] cl - Handle to the RFB client 5621b177e0SEddie James */ 5721b177e0SEddie James static void pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl); 5821b177e0SEddie James 597dfac9ffSJae Hyun Yoo /* @brief Sends a wakeup data packet to the USB input device */ 607dfac9ffSJae Hyun Yoo void sendWakeupPacket(); 6121b177e0SEddie James 6221b177e0SEddie James private: 637dfac9ffSJae Hyun Yoo static constexpr int NUM_MODIFIER_BITS = 4; 647dfac9ffSJae Hyun Yoo static constexpr int KEY_REPORT_LENGTH = 8; 653fa0bfbaSTejas Patil static constexpr int PTR_REPORT_LENGTH = 6; 6621b177e0SEddie James 6721b177e0SEddie James /* @brief HID modifier bits mapped to shift and control key codes */ 687dfac9ffSJae Hyun Yoo static constexpr uint8_t shiftCtrlMap[NUM_MODIFIER_BITS] = { 697dfac9ffSJae Hyun Yoo 0x02, // left shift 707dfac9ffSJae Hyun Yoo 0x20, // right shift 717dfac9ffSJae Hyun Yoo 0x01, // left control 727dfac9ffSJae Hyun Yoo 0x10 // right control 737dfac9ffSJae Hyun Yoo }; 7421b177e0SEddie James /* @brief HID modifier bits mapped to meta and alt key codes */ 757dfac9ffSJae Hyun Yoo static constexpr uint8_t metaAltMap[NUM_MODIFIER_BITS] = { 767dfac9ffSJae Hyun Yoo 0x08, // left meta 777dfac9ffSJae Hyun Yoo 0x80, // right meta 787dfac9ffSJae Hyun Yoo 0x04, // left alt 797dfac9ffSJae Hyun Yoo 0x40 // right alt 807dfac9ffSJae Hyun Yoo }; 81c11257d8SJae Hyun Yoo /* @brief Path to the HID gadget UDC */ 82c11257d8SJae Hyun Yoo static constexpr const char* hidUdcPath = 83c11257d8SJae Hyun Yoo "/sys/kernel/config/usb_gadget/obmc_hid/UDC"; 84c11257d8SJae Hyun Yoo /* @brief Path to the USB virtual hub */ 85c11257d8SJae Hyun Yoo static constexpr const char* usbVirtualHubPath = 86c11257d8SJae Hyun Yoo "/sys/bus/platform/devices/1e6a0000.usb-vhub"; 87673ac2ebSJae Hyun Yoo /* @brief Retry limit for writing an HID report */ 88673ac2ebSJae Hyun Yoo static constexpr int HID_REPORT_RETRY_MAX = 5; 8921b177e0SEddie James /* 9021b177e0SEddie James * @brief Translates a RFB-specific key code to HID modifier bit 9121b177e0SEddie James * 9221b177e0SEddie James * @param[in] key - key code 9321b177e0SEddie James */ 947dfac9ffSJae Hyun Yoo static uint8_t keyToMod(rfbKeySym key); 9521b177e0SEddie James /* 9621b177e0SEddie James * @brief Translates a RFB-specific key code to HID scancode 9721b177e0SEddie James * 9821b177e0SEddie James * @param[in] key - key code 9921b177e0SEddie James */ 1007dfac9ffSJae Hyun Yoo static uint8_t keyToScancode(rfbKeySym key); 10121b177e0SEddie James 1027cf1f1d4SEddie James bool writeKeyboard(const uint8_t* report); 1037cf1f1d4SEddie James void writePointer(const uint8_t* report); 1047cf1f1d4SEddie James 1057dfac9ffSJae Hyun Yoo /* @brief File descriptor for the USB keyboard device */ 1067dfac9ffSJae Hyun Yoo int keyboardFd; 1077dfac9ffSJae Hyun Yoo /* @brief File descriptor for the USB mouse device */ 1087dfac9ffSJae Hyun Yoo int pointerFd; 10921b177e0SEddie James /* @brief Data for keyboard report */ 1107dfac9ffSJae Hyun Yoo uint8_t keyboardReport[KEY_REPORT_LENGTH]; 11121b177e0SEddie James /* @brief Data for pointer report */ 1127dfac9ffSJae Hyun Yoo uint8_t pointerReport[PTR_REPORT_LENGTH]; 1137dfac9ffSJae Hyun Yoo /* @brief Path to the USB keyboard device */ 1147dfac9ffSJae Hyun Yoo std::string keyboardPath; 1157dfac9ffSJae Hyun Yoo /* @brief Path to the USB mouse device */ 1167dfac9ffSJae Hyun Yoo std::string pointerPath; 117*fe685fb4SMarvin Lin /* @brief Name of UDC */ 118*fe685fb4SMarvin Lin std::string udcName; 11921b177e0SEddie James /* 12021b177e0SEddie James * @brief Mapping of RFB key code to report data index to keep track 12121b177e0SEddie James * of which keys are down 12221b177e0SEddie James */ 12321b177e0SEddie James std::map<int, int> keysDown; 124c11257d8SJae Hyun Yoo /* @brief Handle of the HID gadget UDC */ 125c11257d8SJae Hyun Yoo std::ofstream hidUdcStream; 126673ac2ebSJae Hyun Yoo /* @brief Mutex for sending keyboard reports */ 127673ac2ebSJae Hyun Yoo std::mutex keyMutex; 128673ac2ebSJae Hyun Yoo /* @brief Mutex for sending pointer reports */ 129673ac2ebSJae Hyun Yoo std::mutex ptrMutex; 13021b177e0SEddie James }; 13121b177e0SEddie James 13221b177e0SEddie James } // namespace ikvm 133