blob: 00d8e7f20b3ca5a9d4b70574837cf95f33245972 [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{
Eddie James21b177e2018-12-11 13:14:46 -060013/*
14 * @class Input
15 * @brief Receives events from RFB clients and sends reports to the USB input
16 * device
17 */
18class Input
19{
20 public:
21 /*
22 * @brief Constructs Input object
23 *
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080024 * @param[in] kbdPath - Path to the USB keyboard device
25 * @param[in] ptrPath - Path to the USB mouse device
Marvin Linfe685fb2022-10-25 16:20:08 +080026 * @param[in] udc - Name of UDC
Eddie James21b177e2018-12-11 13:14:46 -060027 */
Marvin Linfe685fb2022-10-25 16:20:08 +080028 Input(const std::string& kbdPath, const std::string& ptrPath,
29 const std::string& udc);
Eddie James21b177e2018-12-11 13:14:46 -060030 ~Input();
31 Input(const Input&) = default;
32 Input& operator=(const Input&) = default;
33 Input(Input&&) = default;
34 Input& operator=(Input&&) = default;
35
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070036 /* @brief Connects HID gadget to host */
37 void connect();
38 /* @brief Disconnects HID gadget from host */
39 void disconnect();
Eddie James21b177e2018-12-11 13:14:46 -060040 /*
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
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080059 /* @brief Sends a wakeup data packet to the USB input device */
60 void sendWakeupPacket();
Eddie James21b177e2018-12-11 13:14:46 -060061
62 private:
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080063 static constexpr int NUM_MODIFIER_BITS = 4;
64 static constexpr int KEY_REPORT_LENGTH = 8;
Tejas Patil3fa0bfb2021-12-23 15:44:47 +053065 static constexpr int PTR_REPORT_LENGTH = 6;
Eddie James21b177e2018-12-11 13:14:46 -060066
Eddie James21b177e2018-12-11 13:14:46 -060067 /* @brief HID modifier bits mapped to shift and control key codes */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080068 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 };
Eddie James21b177e2018-12-11 13:14:46 -060074 /* @brief HID modifier bits mapped to meta and alt key codes */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080075 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 };
Jae Hyun Yooc11257d2020-07-22 23:39:18 -070081 /* @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";
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -070087 /* @brief Retry limit for writing an HID report */
88 static constexpr int HID_REPORT_RETRY_MAX = 5;
Eddie James21b177e2018-12-11 13:14:46 -060089 /*
90 * @brief Translates a RFB-specific key code to HID modifier bit
91 *
92 * @param[in] key - key code
93 */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -080094 static uint8_t keyToMod(rfbKeySym key);
Eddie James21b177e2018-12-11 13:14:46 -060095 /*
96 * @brief Translates a RFB-specific key code to HID scancode
97 *
98 * @param[in] key - key code
99 */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800100 static uint8_t keyToScancode(rfbKeySym key);
Eddie James21b177e2018-12-11 13:14:46 -0600101
George Liuf79f6f52022-07-06 09:32:35 +0800102 bool writeKeyboard(const uint8_t* report);
103 void writePointer(const uint8_t* report);
Eddie James7cf1f1d2019-09-30 15:05:16 -0500104
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800105 /* @brief File descriptor for the USB keyboard device */
106 int keyboardFd;
107 /* @brief File descriptor for the USB mouse device */
108 int pointerFd;
Eddie James21b177e2018-12-11 13:14:46 -0600109 /* @brief Data for keyboard report */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800110 uint8_t keyboardReport[KEY_REPORT_LENGTH];
Eddie James21b177e2018-12-11 13:14:46 -0600111 /* @brief Data for pointer report */
Jae Hyun Yoo7dfac9f2019-01-15 10:14:59 -0800112 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;
Marvin Linfe685fb2022-10-25 16:20:08 +0800117 /* @brief Name of UDC */
118 std::string udcName;
Eddie James21b177e2018-12-11 13:14:46 -0600119 /*
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;
Jae Hyun Yooc11257d2020-07-22 23:39:18 -0700124 /* @brief Handle of the HID gadget UDC */
125 std::ofstream hidUdcStream;
Jae Hyun Yoo673ac2e2020-07-30 00:29:19 -0700126 /* @brief Mutex for sending keyboard reports */
127 std::mutex keyMutex;
128 /* @brief Mutex for sending pointer reports */
129 std::mutex ptrMutex;
Eddie James21b177e2018-12-11 13:14:46 -0600130};
131
132} // namespace ikvm