blob: 295fb12772abfcc42a29db3e04f87ce736b1c897 [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
Eddie James21b177e2018-12-11 13:14:46 -060027 */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080028 Input(const std::string& kbdPath, const std::string& ptrPath);
Eddie James21b177e2018-12-11 13:14:46 -060029 ~Input();
30 Input(const Input&) = default;
31 Input& operator=(const Input&) = default;
32 Input(Input&&) = default;
33 Input& operator=(Input&&) = default;
34
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070035 /* @brief Connects HID gadget to host */
36 void connect();
37 /* @brief Disconnects HID gadget from host */
38 void disconnect();
Eddie James21b177e2018-12-11 13:14:46 -060039 /*
40 * @brief RFB client key event handler
41 *
42 * @param[in] down - Boolean indicating whether key is pressed or not
43 * @param[in] key - Key code
44 * @param[in] cl - Handle to the RFB client
45 */
46 static void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl);
47 /*
48 * @brief RFB client pointer event handler
49 *
50 * @param[in] buttonMask - Bitmask indicating which buttons have been
51 * pressed
52 * @param[in] x - Pointer x-coordinate
53 * @param[in] y - Pointer y-coordinate
54 * @param[in] cl - Handle to the RFB client
55 */
56 static void pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl);
57
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080058 /* @brief Sends a wakeup data packet to the USB input device */
59 void sendWakeupPacket();
Eddie James21b177e2018-12-11 13:14:46 -060060
61 private:
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080062 static constexpr int NUM_MODIFIER_BITS = 4;
63 static constexpr int KEY_REPORT_LENGTH = 8;
Tejas Patil3fa0bfb2021-12-23 15:44:47 +053064 static constexpr int PTR_REPORT_LENGTH = 6;
Eddie James21b177e2018-12-11 13:14:46 -060065
Eddie James21b177e2018-12-11 13:14:46 -060066 /* @brief HID modifier bits mapped to shift and control key codes */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080067 static constexpr uint8_t shiftCtrlMap[NUM_MODIFIER_BITS] = {
68 0x02, // left shift
69 0x20, // right shift
70 0x01, // left control
71 0x10 // right control
72 };
Eddie James21b177e2018-12-11 13:14:46 -060073 /* @brief HID modifier bits mapped to meta and alt key codes */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080074 static constexpr uint8_t metaAltMap[NUM_MODIFIER_BITS] = {
75 0x08, // left meta
76 0x80, // right meta
77 0x04, // left alt
78 0x40 // right alt
79 };
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070080 /* @brief Path to the HID gadget UDC */
81 static constexpr const char* hidUdcPath =
82 "/sys/kernel/config/usb_gadget/obmc_hid/UDC";
83 /* @brief Path to the USB virtual hub */
84 static constexpr const char* usbVirtualHubPath =
85 "/sys/bus/platform/devices/1e6a0000.usb-vhub";
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -070086 /* @brief Retry limit for writing an HID report */
87 static constexpr int HID_REPORT_RETRY_MAX = 5;
Eddie James21b177e2018-12-11 13:14:46 -060088 /*
89 * @brief Translates a RFB-specific key code to HID modifier bit
90 *
91 * @param[in] key - key code
92 */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080093 static uint8_t keyToMod(rfbKeySym key);
Eddie James21b177e2018-12-11 13:14:46 -060094 /*
95 * @brief Translates a RFB-specific key code to HID scancode
96 *
97 * @param[in] key - key code
98 */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080099 static uint8_t keyToScancode(rfbKeySym key);
Eddie James21b177e2018-12-11 13:14:46 -0600100
George Liuf79f6f52022-07-06 09:32:35 +0800101 bool writeKeyboard(const uint8_t* report);
102 void writePointer(const uint8_t* report);
Eddie James7cf1f1d2019-09-30 15:05:16 -0500103
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800104 /* @brief File descriptor for the USB keyboard device */
105 int keyboardFd;
106 /* @brief File descriptor for the USB mouse device */
107 int pointerFd;
Eddie James21b177e2018-12-11 13:14:46 -0600108 /* @brief Data for keyboard report */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800109 uint8_t keyboardReport[KEY_REPORT_LENGTH];
Eddie James21b177e2018-12-11 13:14:46 -0600110 /* @brief Data for pointer report */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800111 uint8_t pointerReport[PTR_REPORT_LENGTH];
112 /* @brief Path to the USB keyboard device */
113 std::string keyboardPath;
114 /* @brief Path to the USB mouse device */
115 std::string pointerPath;
Eddie James21b177e2018-12-11 13:14:46 -0600116 /*
117 * @brief Mapping of RFB key code to report data index to keep track
118 * of which keys are down
119 */
120 std::map<int, int> keysDown;
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700121 /* @brief Handle of the HID gadget UDC */
122 std::ofstream hidUdcStream;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700123 /* @brief Mutex for sending keyboard reports */
124 std::mutex keyMutex;
125 /* @brief Mutex for sending pointer reports */
126 std::mutex ptrMutex;
Eddie James21b177e2018-12-11 13:14:46 -0600127};
128
129} // namespace ikvm