xref: /openbmc/obmc-ikvm/ikvm_input.hpp (revision fda1393c1af885b95bf481518cb0c2e893d8423a)
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