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 /* 1521b177e0SEddie James * @class Input 1621b177e0SEddie James * @brief Receives events from RFB clients and sends reports to the USB input 1721b177e0SEddie James * device 1821b177e0SEddie James */ 1921b177e0SEddie James class Input 2021b177e0SEddie James { 2121b177e0SEddie James public: 2221b177e0SEddie James /* 2321b177e0SEddie James * @brief Constructs Input object 2421b177e0SEddie James * 257dfac9ffSJae Hyun Yoo * @param[in] kbdPath - Path to the USB keyboard device 267dfac9ffSJae Hyun Yoo * @param[in] ptrPath - Path to the USB mouse device 2721b177e0SEddie James */ 287dfac9ffSJae Hyun Yoo Input(const std::string& kbdPath, const std::string& ptrPath); 2921b177e0SEddie James ~Input(); 3021b177e0SEddie James Input(const Input&) = default; 3121b177e0SEddie James Input& operator=(const Input&) = default; 3221b177e0SEddie James Input(Input&&) = default; 3321b177e0SEddie James Input& operator=(Input&&) = default; 3421b177e0SEddie James 35c11257d8SJae Hyun Yoo /* @brief Connects HID gadget to host */ 36c11257d8SJae Hyun Yoo void connect(); 37c11257d8SJae Hyun Yoo /* @brief Disconnects HID gadget from host */ 38c11257d8SJae Hyun Yoo void disconnect(); 3921b177e0SEddie James /* 4021b177e0SEddie James * @brief RFB client key event handler 4121b177e0SEddie James * 4221b177e0SEddie James * @param[in] down - Boolean indicating whether key is pressed or not 4321b177e0SEddie James * @param[in] key - Key code 4421b177e0SEddie James * @param[in] cl - Handle to the RFB client 4521b177e0SEddie James */ 4621b177e0SEddie James static void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl); 4721b177e0SEddie James /* 4821b177e0SEddie James * @brief RFB client pointer event handler 4921b177e0SEddie James * 5021b177e0SEddie James * @param[in] buttonMask - Bitmask indicating which buttons have been 5121b177e0SEddie James * pressed 5221b177e0SEddie James * @param[in] x - Pointer x-coordinate 5321b177e0SEddie James * @param[in] y - Pointer y-coordinate 5421b177e0SEddie James * @param[in] cl - Handle to the RFB client 5521b177e0SEddie James */ 5621b177e0SEddie James static void pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl); 5721b177e0SEddie James 587dfac9ffSJae Hyun Yoo /* @brief Sends a wakeup data packet to the USB input device */ 597dfac9ffSJae Hyun Yoo void sendWakeupPacket(); 6021b177e0SEddie James 6121b177e0SEddie James private: 627dfac9ffSJae Hyun Yoo static constexpr int NUM_MODIFIER_BITS = 4; 637dfac9ffSJae Hyun Yoo static constexpr int KEY_REPORT_LENGTH = 8; 64*3fa0bfbaSTejas Patil static constexpr int PTR_REPORT_LENGTH = 6; 6521b177e0SEddie James 6621b177e0SEddie James /* @brief HID modifier bits mapped to shift and control key codes */ 677dfac9ffSJae Hyun Yoo static constexpr uint8_t shiftCtrlMap[NUM_MODIFIER_BITS] = { 687dfac9ffSJae Hyun Yoo 0x02, // left shift 697dfac9ffSJae Hyun Yoo 0x20, // right shift 707dfac9ffSJae Hyun Yoo 0x01, // left control 717dfac9ffSJae Hyun Yoo 0x10 // right control 727dfac9ffSJae Hyun Yoo }; 7321b177e0SEddie James /* @brief HID modifier bits mapped to meta and alt key codes */ 747dfac9ffSJae Hyun Yoo static constexpr uint8_t metaAltMap[NUM_MODIFIER_BITS] = { 757dfac9ffSJae Hyun Yoo 0x08, // left meta 767dfac9ffSJae Hyun Yoo 0x80, // right meta 777dfac9ffSJae Hyun Yoo 0x04, // left alt 787dfac9ffSJae Hyun Yoo 0x40 // right alt 797dfac9ffSJae Hyun Yoo }; 80c11257d8SJae Hyun Yoo /* @brief Path to the HID gadget UDC */ 81c11257d8SJae Hyun Yoo static constexpr const char* hidUdcPath = 82c11257d8SJae Hyun Yoo "/sys/kernel/config/usb_gadget/obmc_hid/UDC"; 83c11257d8SJae Hyun Yoo /* @brief Path to the USB virtual hub */ 84c11257d8SJae Hyun Yoo static constexpr const char* usbVirtualHubPath = 85c11257d8SJae Hyun Yoo "/sys/bus/platform/devices/1e6a0000.usb-vhub"; 86673ac2ebSJae Hyun Yoo /* @brief Retry limit for writing an HID report */ 87673ac2ebSJae Hyun Yoo static constexpr int HID_REPORT_RETRY_MAX = 5; 8821b177e0SEddie James /* 8921b177e0SEddie James * @brief Translates a RFB-specific key code to HID modifier bit 9021b177e0SEddie James * 9121b177e0SEddie James * @param[in] key - key code 9221b177e0SEddie James */ 937dfac9ffSJae Hyun Yoo static uint8_t keyToMod(rfbKeySym key); 9421b177e0SEddie James /* 9521b177e0SEddie James * @brief Translates a RFB-specific key code to HID scancode 9621b177e0SEddie James * 9721b177e0SEddie James * @param[in] key - key code 9821b177e0SEddie James */ 997dfac9ffSJae Hyun Yoo static uint8_t keyToScancode(rfbKeySym key); 10021b177e0SEddie James 1017cf1f1d4SEddie James bool writeKeyboard(const uint8_t *report); 1027cf1f1d4SEddie James void writePointer(const uint8_t *report); 1037cf1f1d4SEddie James 1047dfac9ffSJae Hyun Yoo /* @brief File descriptor for the USB keyboard device */ 1057dfac9ffSJae Hyun Yoo int keyboardFd; 1067dfac9ffSJae Hyun Yoo /* @brief File descriptor for the USB mouse device */ 1077dfac9ffSJae Hyun Yoo int pointerFd; 10821b177e0SEddie James /* @brief Data for keyboard report */ 1097dfac9ffSJae Hyun Yoo uint8_t keyboardReport[KEY_REPORT_LENGTH]; 11021b177e0SEddie James /* @brief Data for pointer report */ 1117dfac9ffSJae Hyun Yoo uint8_t pointerReport[PTR_REPORT_LENGTH]; 1127dfac9ffSJae Hyun Yoo /* @brief Path to the USB keyboard device */ 1137dfac9ffSJae Hyun Yoo std::string keyboardPath; 1147dfac9ffSJae Hyun Yoo /* @brief Path to the USB mouse device */ 1157dfac9ffSJae Hyun Yoo std::string pointerPath; 11621b177e0SEddie James /* 11721b177e0SEddie James * @brief Mapping of RFB key code to report data index to keep track 11821b177e0SEddie James * of which keys are down 11921b177e0SEddie James */ 12021b177e0SEddie James std::map<int, int> keysDown; 121c11257d8SJae Hyun Yoo /* @brief Handle of the HID gadget UDC */ 122c11257d8SJae Hyun Yoo std::ofstream hidUdcStream; 123673ac2ebSJae Hyun Yoo /* @brief Mutex for sending keyboard reports */ 124673ac2ebSJae Hyun Yoo std::mutex keyMutex; 125673ac2ebSJae Hyun Yoo /* @brief Mutex for sending pointer reports */ 126673ac2ebSJae Hyun Yoo std::mutex ptrMutex; 12721b177e0SEddie James }; 12821b177e0SEddie James 12921b177e0SEddie James } // namespace ikvm 130