1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   HID Keyboard Client                                                 */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /**************************************************************************/
24 /*                                                                        */
25 /*  COMPONENT DEFINITION                                   RELEASE        */
26 /*                                                                        */
27 /*    ux_host_class_hid_keyboard.h                        PORTABLE C      */
28 /*                                                           6.2.0        */
29 /*  AUTHOR                                                                */
30 /*                                                                        */
31 /*    Chaoqiong Xiao, Microsoft Corporation                               */
32 /*                                                                        */
33 /*  DESCRIPTION                                                           */
34 /*                                                                        */
35 /*    This file contains all the header and extern functions used by the  */
36 /*    USBX HID keyboard client.                                           */
37 /*                                                                        */
38 /*  RELEASE HISTORY                                                       */
39 /*                                                                        */
40 /*    DATE              NAME                      DESCRIPTION             */
41 /*                                                                        */
42 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
43 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
44 /*                                            used UX prefix to refer to  */
45 /*                                            TX symbols instead of using */
46 /*                                            them directly,              */
47 /*                                            resulting in version 6.1    */
48 /*  08-02-2021     Wen Wang                 Modified comment(s),          */
49 /*                                            added extern "C" keyword    */
50 /*                                            for compatibility with C++, */
51 /*                                            resulting in version 6.1.8  */
52 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
53 /*                                            added standalone support,   */
54 /*                                            resulting in version 6.1.10 */
55 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
56 /*                                            fixed clients management,   */
57 /*                                            resulting in version 6.1.11 */
58 /*  10-31-2022     Chaoqiong Xiao           Modified comment(s),          */
59 /*                                            improved HID OUTPUT report  */
60 /*                                            handling in standalone mode,*/
61 /*                                            resulting in version 6.2.0  */
62 /*                                                                        */
63 /**************************************************************************/
64 
65 #ifndef UX_HOST_CLASS_HID_KEYBOARD_H
66 #define UX_HOST_CLASS_HID_KEYBOARD_H
67 
68 /* Determine if a C++ compiler is being used.  If so, ensure that standard
69    C is used to process the API information.  */
70 
71 #ifdef   __cplusplus
72 
73 /* Yes, C++ compiler is present.  Use standard C.  */
74 extern   "C" {
75 
76 #endif
77 
78 
79 /* Internal option: enable the basic USBX error checking. This define is typically used
80    while debugging application.  */
81 #if defined(UX_ENABLE_ERROR_CHECKING) && !defined(UX_DEVICE_CLASS_HID_KEYBOARD_ENABLE_ERROR_CHECKING)
82 #define UX_DEVICE_CLASS_HID_KEYBOARD_ENABLE_ERROR_CHECKING
83 #endif
84 
85 
86 /* Define HID Keyboard Class constants.  */
87 
88 #define UX_HOST_CLASS_HID_KEYBOARD_BUFFER_LENGTH            128
89 #define UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH       64
90 
91 /* Each item in usage array takes 4 bytes. Check memory bytes calculation overflow here.  */
92 #if UX_OVERFLOW_CHECK_MULC_ULONG(UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH, 4)
93 #error UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH too large for memory allocation
94 #endif
95 
96 /* Define HID Keyboard Class LED keys.  */
97 
98 #define UX_HID_LED_KEY_CAPS_LOCK                            0x39
99 #define UX_HID_LED_KEY_NUM_LOCK                             0x53
100 #define UX_HID_LED_KEY_SCROLL_LOCK                          0x47
101 
102 
103 /* Define HID Keyboard Class Modifier Keys.  */
104 
105 #define UX_HID_MODIFIER_KEY_LEFT_CONTROL                    0xe0
106 #define UX_HID_MODIFIER_KEY_LEFT_SHIFT                      0xe1
107 #define UX_HID_MODIFIER_KEY_LEFT_ALT                        0xe2
108 #define UX_HID_MODIFIER_KEY_LEFT_GUI                        0xe3
109 #define UX_HID_MODIFIER_KEY_RIGHT_CONTROL                   0xe4
110 #define UX_HID_MODIFIER_KEY_RIGHT_SHIFT                     0xe5
111 #define UX_HID_MODIFIER_KEY_RIGHT_ALT                       0xe6
112 #define UX_HID_MODIFIER_KEY_RIGHT_GUI                       0xe7
113 
114 
115 /* Define HID Keyboard States.  */
116 
117 #define UX_HID_KEYBOARD_STATE_NUM_LOCK                      0x0001
118 #define UX_HID_KEYBOARD_STATE_CAPS_LOCK                     0x0002
119 #define UX_HID_KEYBOARD_STATE_SCROLL_LOCK                   0x0004
120 #define UX_HID_KEYBOARD_STATE_MASK_LOCK                     0x0007
121 
122 #define UX_HID_KEYBOARD_STATE_LEFT_SHIFT                    0x0100
123 #define UX_HID_KEYBOARD_STATE_RIGHT_SHIFT                   0x0200
124 #define UX_HID_KEYBOARD_STATE_SHIFT                         0x0300
125 
126 #define UX_HID_KEYBOARD_STATE_LEFT_ALT                      0x0400
127 #define UX_HID_KEYBOARD_STATE_RIGHT_ALT                     0x0800
128 #define UX_HID_KEYBOARD_STATE_ALT                           0x0a00
129 
130 #define UX_HID_KEYBOARD_STATE_LEFT_CTRL                     0x1000
131 #define UX_HID_KEYBOARD_STATE_RIGHT_CTRL                    0x2000
132 #define UX_HID_KEYBOARD_STATE_CTRL                          0x3000
133 
134 #define UX_HID_KEYBOARD_STATE_LEFT_GUI                      0x4000
135 #define UX_HID_KEYBOARD_STATE_RIGHT_GUI                     0x8000
136 #define UX_HID_KEYBOARD_STATE_GUI                           0xa000
137 
138 #define UX_HID_KEYBOARD_STATE_KEY_UP                        0x10000
139 #define UX_HID_KEYBOARD_STATE_FUNCTION                      0x20000
140 
141 /* Define HID keyboard generic equivalences.  */
142 
143 #define UX_HID_KEYBOARD_NO_KEY                              0
144 #define UX_HID_KEYBOARD_PHANTOM_STATE                       0x01
145 #define UX_HID_KEYBOARD_KEY_LETTER_A                        0x04
146 #define UX_HID_KEYBOARD_KEY_LETTER_Z                        0x1D
147 #define UX_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE             0x54
148 #define UX_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE             0x67
149 #define UX_HID_KEYBOARD_KEYS_UPPER_RANGE                    115
150 
151 /* Define HID keyboard ioctl Functions.  */
152 
153 #define UX_HID_KEYBOARD_IOCTL_SET_LAYOUT                    0
154 #define UX_HID_KEYBOARD_IOCTL_DISABLE_KEYS_DECODE           1
155 #define UX_HID_KEYBOARD_IOCTL_ENABLE_KEYS_DECODE            2
156 
157 /* Define HID keyboard layout array.  */
158 
159 #define UX_HID_KEYBOARD_REGULAR_ARRAY_US                                    \
160    0,0,0,0,                                                                 \
161    'a','b','c','d','e','f','g','h','i','j','k','l','m','n',                 \
162    'o','p','q','r','s','t','u','v','w','x','y','z',                         \
163    '1','2','3','4','5','6','7','8','9','0',                                 \
164    0x0d,0x1b,0x08,0x07,0x20,'-','=','[',']',                                \
165    '\\','#',';',0x27,'`',',','.','/',0xf0,                                  \
166    0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,             \
167    0x00,0xf1,0x00,0xd2,0xc7,0xc9,0xd3,0xcf,0xd1,0xcd,0xcb,0xd0,0xc8,0xf2,   \
168    '/','*','-','+',                                                         \
169    0x0d,'1','2','3','4','5','6','7','8','9','0','.','\\',0x00,0x00,'=',     \
170    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
171 
172 #define UX_HID_KEYBOARD_SHIFT_ARRAY_US                                      \
173    0,0,0,0,                                                                 \
174    'A','B','C','D','E','F','G','H','I','J','K','L','M','N',                 \
175    'O','P','Q','R','S','T','U','V','W','X','Y','Z',                         \
176    '!','@','#','$','%','^','&','*','(',')',                                 \
177    0x0d,0x1b,0x08,0x07,0x20,'_','+','{','}',                                \
178    '|','~',':','"','~','<','>','?',0xf0,                                    \
179    0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,             \
180    0x00,0xf1,0x00,0xd2,0xc7,0xc9,0xd3,0xcf,0xd1,0xcd,0xcb,0xd0,0xc8,0xf2,   \
181    '/','*','-','+',                                                         \
182    0x0d,'1','2','3','4','5','6','7','8','9','0','.','\\',0x00,0x00,'=',     \
183    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
184 
185 #define UX_HID_KEYBOARD_NUMLOCK_ON_ARRAY                                    \
186    '/','*','-','+',                                                         \
187    0x0d,                                                                    \
188    '1','2','3','4','5','6','7','8','9','0',                                 \
189    '.','\\',0x00,0x00,'=',
190 
191 #define UX_HID_KEYBOARD_NUMLOCK_OFF_ARRAY                                   \
192    '/','*','-','+',                                                         \
193    0x0d,                                                                    \
194    0xcf,0xd0,0xd1,0xcb,'5',0xcd,0xc7,0xc8,0xc9,0xd2,                        \
195    0xd3,'\\',0x00,0x00,'=',
196 
197 /* Define HID Keyboard layout (key mapping) structure.  */
198 
199 typedef struct UX_HOST_CLASS_HID_KEYBOARD_LAYOUT_STRUCT
200 {
201 
202     UCHAR           *ux_host_class_hid_keyboard_layout_regular_array;
203     UCHAR           *ux_host_class_hid_keyboard_layout_shift_array;
204     UCHAR           *ux_host_class_hid_keyboard_layout_numlock_on_array;
205     UCHAR           *ux_host_class_hid_keyboard_layout_numlock_off_array;
206     ULONG           ux_host_class_hid_keyboard_layout_keys_upper_range;
207     ULONG           ux_host_class_hid_keyboard_layout_letters_lower_range;
208     ULONG           ux_host_class_hid_keyboard_layout_letters_upper_range;
209     ULONG           ux_host_class_hid_keyboard_layout_keypad_lower_range;
210     ULONG           ux_host_class_hid_keyboard_layout_keypad_upper_range;
211 } UX_HOST_CLASS_HID_KEYBOARD_LAYOUT;
212 
213 /* Define HID Keyboard Class structure.  */
214 
215 typedef struct UX_HOST_CLASS_HID_KEYBOARD_STRUCT
216 {
217 
218     ULONG           ux_host_class_hid_keyboard_state;
219     UCHAR           *ux_host_class_hid_keyboard_key_state;
220     ULONG           ux_host_class_hid_keyboard_key_count;
221     UX_HOST_CLASS_HID   *ux_host_class_hid_keyboard_hid;
222     USHORT          ux_host_class_hid_keyboard_id;
223 #if !defined(UX_HOST_STANDALONE)
224     VOID            *ux_host_class_hid_keyboard_thread_stack;
225     UX_THREAD       ux_host_class_hid_keyboard_thread;
226     UX_SEMAPHORE    ux_host_class_hid_keyboard_semaphore;
227 #else
228     UX_HOST_CLASS_HID_REPORT
229                     *ux_host_class_hid_keyboard_out_report;
230     UINT            ux_host_class_hid_keyboard_status;
231     UCHAR           ux_host_class_hid_keyboard_enum_state;
232     UCHAR           ux_host_class_hid_keyboard_next_state;
233     UCHAR           ux_host_class_hid_keyboard_out_state;
234     UCHAR           reserved;
235 #endif
236     ULONG           ux_host_class_hid_keyboard_alternate_key_state;
237     ULONG           ux_host_class_hid_keyboard_led_mask;
238     ULONG           *ux_host_class_hid_keyboard_usage_array;
239     ULONG           *ux_host_class_hid_keyboard_usage_array_head;
240     ULONG           *ux_host_class_hid_keyboard_usage_array_tail;
241     UX_HOST_CLASS_HID_KEYBOARD_LAYOUT *ux_host_class_hid_keyboard_layout;
242     ULONG           ux_host_class_hid_keyboard_keys_decode_disable;
243 } UX_HOST_CLASS_HID_KEYBOARD;
244 
245 typedef struct UX_HOST_CLASS_HID_CLIENT_KEYBOARD_STRUCT
246 {
247     UX_HOST_CLASS_HID_KEYBOARD   ux_host_class_hid_client_keyboard_keyboard;
248     UX_HOST_CLASS_HID_CLIENT     ux_host_class_hid_client_keyboard_client;
249 } UX_HOST_CLASS_HID_CLIENT_KEYBOARD;
250 
251 /* Define HID Keyboard Class function prototypes.  */
252 
253 VOID    _ux_host_class_hid_keyboard_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback);
254 UINT    _ux_host_class_hid_keyboard_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command);
255 UINT    _ux_host_class_hid_keyboard_deactivate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command);
256 UINT    _ux_host_class_hid_keyboard_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command);
257 VOID    _ux_host_class_hid_keyboard_thread(ULONG thread_entry);
258 UINT    _ux_host_class_hid_keyboard_key_get(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance,
259                                             ULONG *keyboard_key, ULONG *keyboard_state);
260 UINT    _ux_host_class_hid_keyboard_ioctl(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance,
261                                         ULONG ioctl_function, VOID *parameter);
262 
263 VOID    _ux_host_class_hid_keyboard_tasks_run(UX_HOST_CLASS_HID_CLIENT *client);
264 
265 
266 UINT    _uxe_host_class_hid_keyboard_key_get(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance,
267                                             ULONG *keyboard_key, ULONG *keyboard_state);
268 UINT    _uxe_host_class_hid_keyboard_ioctl(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance,
269                                         ULONG ioctl_function, VOID *parameter);
270 
271 
272 /* Define HID Keyboard Class API prototypes.  */
273 
274 #define ux_host_class_hid_keyboard_entry                   _ux_host_class_hid_keyboard_entry
275 
276 #if defined(UX_DEVICE_CLASS_HID_KEYBOARD_ENABLE_ERROR_CHECKING)
277 
278 #define ux_host_class_hid_keyboard_key_get                 _uxe_host_class_hid_keyboard_key_get
279 #define ux_host_class_hid_keyboard_ioctl                   _uxe_host_class_hid_keyboard_ioctl
280 
281 #else
282 
283 #define ux_host_class_hid_keyboard_key_get                 _ux_host_class_hid_keyboard_key_get
284 #define ux_host_class_hid_keyboard_ioctl                   _ux_host_class_hid_keyboard_ioctl
285 
286 #endif
287 
288 /* Determine if a C++ compiler is being used.  If so, complete the standard
289    C conditional started above.  */
290 #ifdef __cplusplus
291 }
292 #endif
293 
294 #endif
295 
296