xref: /openbmc/obmc-ikvm/ikvm_input.hpp (revision 033b18e0)
1 #pragma once
2 
3 #include <rfb/rfb.h>
4 
5 #include <filesystem>
6 #include <fstream>
7 #include <map>
8 #include <mutex>
9 #include <string>
10 
11 namespace ikvm
12 {
13 /*
14  * @class Input
15  * @brief Receives events from RFB clients and sends reports to the USB input
16  *        device
17  */
18 class Input
19 {
20   public:
21     /*
22      * @brief Constructs Input object
23      *
24      * @param[in] kbdPath - Path to the USB keyboard device
25      * @param[in] ptrPath - Path to the USB mouse device
26      * @param[in] udc - Name of UDC
27      */
28     Input(const std::string& kbdPath, const std::string& ptrPath,
29           const std::string& udc);
30     ~Input();
31     Input(const Input&) = default;
32     Input& operator=(const Input&) = default;
33     Input(Input&&) = default;
34     Input& operator=(Input&&) = default;
35 
36     /* @brief Connects HID gadget to host */
37     void connect();
38     /* @brief Disconnects HID gadget from host */
39     void disconnect();
40     /*
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 
59     /* @brief Sends a wakeup data packet to the USB input device */
60     void sendWakeupPacket();
61 
62   private:
63     static constexpr int NUM_MODIFIER_BITS = 4;
64     static constexpr int KEY_REPORT_LENGTH = 8;
65     static constexpr int PTR_REPORT_LENGTH = 6;
66 
67     /* @brief HID modifier bits mapped to shift and control key codes */
68     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     };
74     /* @brief HID modifier bits mapped to meta and alt key codes */
75     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     };
81     /* @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";
87     /* @brief Retry limit for writing an HID report */
88     static constexpr int HID_REPORT_RETRY_MAX = 5;
89     /*
90      * @brief Translates a RFB-specific key code to HID modifier bit
91      *
92      * @param[in] key - key code
93      */
94     static uint8_t keyToMod(rfbKeySym key);
95     /*
96      * @brief Translates a RFB-specific key code to HID scancode
97      *
98      * @param[in] key - key code
99      */
100     static uint8_t keyToScancode(rfbKeySym key);
101 
102     bool writeKeyboard(const uint8_t* report);
103     void writePointer(const uint8_t* report);
104 
105     /* @brief File descriptor for the USB keyboard device */
106     int keyboardFd;
107     /* @brief File descriptor for the USB mouse device */
108     int pointerFd;
109     /* @brief Data for keyboard report */
110     uint8_t keyboardReport[KEY_REPORT_LENGTH];
111     /* @brief Data for pointer report */
112     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;
117     /* @brief Name of UDC */
118     std::string udcName;
119     /*
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;
124     /* @brief Handle of the HID gadget UDC */
125     std::ofstream hidUdcStream;
126     /* @brief Mutex for sending keyboard reports */
127     std::mutex keyMutex;
128     /* @brief Mutex for sending pointer reports */
129     std::mutex ptrMutex;
130 };
131 
132 } // namespace ikvm
133