blob: 83e407119e23b53a07836bc229d630bd5bd37c99 [file] [log] [blame]
Eddie James21b177e2018-12-11 13:14:46 -06001#pragma once
2
3#include <rfb/rfb.h>
4
Jae Hyun Yooc11257d2020-07-22 23:39:18 -07005#include <filesystem>
6#include <fstream>
Eddie James21b177e2018-12-11 13:14:46 -06007#include <map>
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -07008#include <mutex>
Eddie James21b177e2018-12-11 13:14:46 -06009#include <string>
10
11namespace ikvm
12{
13
14/*
15 * @class Input
16 * @brief Receives events from RFB clients and sends reports to the USB input
17 * device
18 */
19class Input
20{
21 public:
22 /*
23 * @brief Constructs Input object
24 *
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080025 * @param[in] kbdPath - Path to the USB keyboard device
26 * @param[in] ptrPath - Path to the USB mouse device
Marvin Linfe685fb2022-10-25 16:20:08 +080027 * @param[in] udc - Name of UDC
Eddie James21b177e2018-12-11 13:14:46 -060028 */
Marvin Linfe685fb2022-10-25 16:20:08 +080029 Input(const std::string& kbdPath, const std::string& ptrPath,
30 const std::string& udc);
Eddie James21b177e2018-12-11 13:14:46 -060031 ~Input();
32 Input(const Input&) = default;
33 Input& operator=(const Input&) = default;
34 Input(Input&&) = default;
35 Input& operator=(Input&&) = default;
36
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070037 /* @brief Connects HID gadget to host */
38 void connect();
39 /* @brief Disconnects HID gadget from host */
40 void disconnect();
Eddie James21b177e2018-12-11 13:14:46 -060041 /*
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
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080060 /* @brief Sends a wakeup data packet to the USB input device */
61 void sendWakeupPacket();
Eddie James21b177e2018-12-11 13:14:46 -060062
63 private:
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080064 static constexpr int NUM_MODIFIER_BITS = 4;
65 static constexpr int KEY_REPORT_LENGTH = 8;
Tejas Patil3fa0bfb2021-12-23 15:44:47 +053066 static constexpr int PTR_REPORT_LENGTH = 6;
Eddie James21b177e2018-12-11 13:14:46 -060067
Eddie James21b177e2018-12-11 13:14:46 -060068 /* @brief HID modifier bits mapped to shift and control key codes */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080069 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 };
Eddie James21b177e2018-12-11 13:14:46 -060075 /* @brief HID modifier bits mapped to meta and alt key codes */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080076 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 };
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070082 /* @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";
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -070088 /* @brief Retry limit for writing an HID report */
89 static constexpr int HID_REPORT_RETRY_MAX = 5;
Eddie James21b177e2018-12-11 13:14:46 -060090 /*
91 * @brief Translates a RFB-specific key code to HID modifier bit
92 *
93 * @param[in] key - key code
94 */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080095 static uint8_t keyToMod(rfbKeySym key);
Eddie James21b177e2018-12-11 13:14:46 -060096 /*
97 * @brief Translates a RFB-specific key code to HID scancode
98 *
99 * @param[in] key - key code
100 */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800101 static uint8_t keyToScancode(rfbKeySym key);
Eddie James21b177e2018-12-11 13:14:46 -0600102
George Liuf79f6f52022-07-06 09:32:35 +0800103 bool writeKeyboard(const uint8_t* report);
104 void writePointer(const uint8_t* report);
Eddie James7cf1f1d2019-09-30 15:05:16 -0500105
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800106 /* @brief File descriptor for the USB keyboard device */
107 int keyboardFd;
108 /* @brief File descriptor for the USB mouse device */
109 int pointerFd;
Eddie James21b177e2018-12-11 13:14:46 -0600110 /* @brief Data for keyboard report */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800111 uint8_t keyboardReport[KEY_REPORT_LENGTH];
Eddie James21b177e2018-12-11 13:14:46 -0600112 /* @brief Data for pointer report */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800113 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;
Marvin Linfe685fb2022-10-25 16:20:08 +0800118 /* @brief Name of UDC */
119 std::string udcName;
Eddie James21b177e2018-12-11 13:14:46 -0600120 /*
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;
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700125 /* @brief Handle of the HID gadget UDC */
126 std::ofstream hidUdcStream;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700127 /* @brief Mutex for sending keyboard reports */
128 std::mutex keyMutex;
129 /* @brief Mutex for sending pointer reports */
130 std::mutex ptrMutex;
Eddie James21b177e2018-12-11 13:14:46 -0600131};
132
133} // namespace ikvm