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 |
|
|
/* Include necessary system files. */ |
24 |
|
|
|
25 |
|
|
#define UX_SOURCE_CODE |
26 |
|
|
|
27 |
|
|
#include "ux_api.h" |
28 |
|
|
#include "ux_host_class_hid.h" |
29 |
|
|
#include "ux_host_class_hid_keyboard.h" |
30 |
|
|
#include "ux_host_stack.h" |
31 |
|
|
|
32 |
|
|
/* Define USB HID keyboard mapping tables. */ |
33 |
|
|
|
34 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_REGULAR_ARRAY_DEFAULT |
35 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_REGULAR_ARRAY_DEFAULT UX_HID_KEYBOARD_REGULAR_ARRAY_US |
36 |
|
|
#endif |
37 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_SHIFT_ARRAY_DEFAULT |
38 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_SHIFT_ARRAY_DEFAULT UX_HID_KEYBOARD_SHIFT_ARRAY_US |
39 |
|
|
#endif |
40 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_ON_ARRAY_DEFAULT |
41 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_ON_ARRAY_DEFAULT UX_HID_KEYBOARD_NUMLOCK_ON_ARRAY |
42 |
|
|
#endif |
43 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_OFF_ARRAY_DEFAULT |
44 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_OFF_ARRAY_DEFAULT UX_HID_KEYBOARD_NUMLOCK_OFF_ARRAY |
45 |
|
|
#endif |
46 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEYS_UPPER_RANGE_DEFAULT |
47 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_KEYS_UPPER_RANGE_DEFAULT UX_HID_KEYBOARD_KEYS_UPPER_RANGE |
48 |
|
|
#endif |
49 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_A_DEFAULT |
50 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_A_DEFAULT UX_HID_KEYBOARD_KEY_LETTER_A |
51 |
|
|
#endif |
52 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_Z_DEFAULT |
53 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_Z_DEFAULT UX_HID_KEYBOARD_KEY_LETTER_Z |
54 |
|
|
#endif |
55 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE_DEFAULT |
56 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE_DEFAULT UX_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE |
57 |
|
|
#endif |
58 |
|
|
#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE_DEFAULT |
59 |
|
|
#define UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE_DEFAULT UX_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE |
60 |
|
|
#endif |
61 |
|
|
|
62 |
|
|
UCHAR ux_host_class_hid_keyboard_regular_array[] = |
63 |
|
|
{ |
64 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_REGULAR_ARRAY_DEFAULT |
65 |
|
|
}; |
66 |
|
|
|
67 |
|
|
UCHAR ux_host_class_hid_keyboard_shift_array[] = |
68 |
|
|
{ |
69 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_SHIFT_ARRAY_DEFAULT |
70 |
|
|
}; |
71 |
|
|
|
72 |
|
|
UCHAR ux_host_class_hid_keyboard_numlock_on_array[] = |
73 |
|
|
{ |
74 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_ON_ARRAY_DEFAULT |
75 |
|
|
}; |
76 |
|
|
|
77 |
|
|
UCHAR ux_host_class_hid_keyboard_numlock_off_array[] = |
78 |
|
|
{ |
79 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_OFF_ARRAY_DEFAULT |
80 |
|
|
}; |
81 |
|
|
|
82 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_LAYOUT ux_host_class_hid_keyboard_layout = |
83 |
|
|
{ |
84 |
|
|
ux_host_class_hid_keyboard_regular_array, |
85 |
|
|
ux_host_class_hid_keyboard_shift_array, |
86 |
|
|
ux_host_class_hid_keyboard_numlock_on_array, |
87 |
|
|
ux_host_class_hid_keyboard_numlock_off_array, |
88 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_KEYS_UPPER_RANGE_DEFAULT, |
89 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_A_DEFAULT, |
90 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_Z_DEFAULT, |
91 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE_DEFAULT, |
92 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE_DEFAULT, |
93 |
|
|
}; |
94 |
|
|
|
95 |
|
|
/**************************************************************************/ |
96 |
|
|
/* */ |
97 |
|
|
/* FUNCTION RELEASE */ |
98 |
|
|
/* */ |
99 |
|
|
/* _ux_host_class_hid_keyboard_activate PORTABLE C */ |
100 |
|
|
/* 6.1.11 */ |
101 |
|
|
/* AUTHOR */ |
102 |
|
|
/* */ |
103 |
|
|
/* Chaoqiong Xiao, Microsoft Corporation */ |
104 |
|
|
/* */ |
105 |
|
|
/* DESCRIPTION */ |
106 |
|
|
/* */ |
107 |
|
|
/* This function performs the enumeration of a HID Keyboard Client. */ |
108 |
|
|
/* */ |
109 |
|
|
/* INPUT */ |
110 |
|
|
/* */ |
111 |
|
|
/* command Pointer to command */ |
112 |
|
|
/* */ |
113 |
|
|
/* OUTPUT */ |
114 |
|
|
/* */ |
115 |
|
|
/* Completion Status */ |
116 |
|
|
/* */ |
117 |
|
|
/* CALLS */ |
118 |
|
|
/* */ |
119 |
|
|
/* _ux_host_class_hid_periodic_report_start */ |
120 |
|
|
/* Start periodic report */ |
121 |
|
|
/* _ux_host_class_hid_report_callback_register */ |
122 |
|
|
/* Register callback */ |
123 |
|
|
/* _ux_host_class_hid_report_id_get Get the report ID */ |
124 |
|
|
/* _ux_host_class_hid_idle_set Set the idle rate */ |
125 |
|
|
/* _ux_host_class_hid_report_set Do SET_REPORT */ |
126 |
|
|
/* _ux_utility_memory_allocate Allocate memory block */ |
127 |
|
|
/* _ux_utility_memory_free Free memory block */ |
128 |
|
|
/* _ux_host_semaphore_create Create semaphore */ |
129 |
|
|
/* _ux_host_semaphore_delete Delete semaphore */ |
130 |
|
|
/* _ux_utility_thread_create Create thread */ |
131 |
|
|
/* _ux_utility_thread_delete Delete thread */ |
132 |
|
|
/* */ |
133 |
|
|
/* CALLED BY */ |
134 |
|
|
/* */ |
135 |
|
|
/* HID Class */ |
136 |
|
|
/* */ |
137 |
|
|
/* RELEASE HISTORY */ |
138 |
|
|
/* */ |
139 |
|
|
/* DATE NAME DESCRIPTION */ |
140 |
|
|
/* */ |
141 |
|
|
/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ |
142 |
|
|
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ |
143 |
|
|
/* used UX prefix to refer to */ |
144 |
|
|
/* TX symbols instead of using */ |
145 |
|
|
/* them directly, */ |
146 |
|
|
/* resulting in version 6.1 */ |
147 |
|
|
/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ |
148 |
|
|
/* added standalone support, */ |
149 |
|
|
/* resulting in version 6.1.10 */ |
150 |
|
|
/* 04-25-2022 Chaoqiong Xiao Modified comment(s), */ |
151 |
|
|
/* fixed clients management, */ |
152 |
|
|
/* resulting in version 6.1.11 */ |
153 |
|
|
/* */ |
154 |
|
|
/**************************************************************************/ |
155 |
|
168 |
UINT _ux_host_class_hid_keyboard_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) |
156 |
|
|
{ |
157 |
|
|
|
158 |
|
|
UX_HOST_CLASS_HID_REPORT_CALLBACK call_back; |
159 |
|
|
#if !defined(UX_HOST_STANDALONE) |
160 |
|
|
UX_HOST_CLASS_HID_CLIENT_REPORT client_report; |
161 |
|
|
#endif |
162 |
|
|
UX_HOST_CLASS_HID_REPORT_GET_ID report_id; |
163 |
|
|
UX_HOST_CLASS_HID *hid; |
164 |
|
|
UX_HOST_CLASS_HID_CLIENT *hid_client; |
165 |
|
|
UX_HOST_CLASS_HID_CLIENT_KEYBOARD *client_keyboard; |
166 |
|
|
UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance; |
167 |
|
|
ULONG event_process_memory_size; |
168 |
|
168 |
UINT status = UX_SUCCESS; |
169 |
|
|
#ifdef UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE |
170 |
|
|
UX_HOST_CLASS_HID_FIELD *field; |
171 |
|
|
#endif |
172 |
|
|
|
173 |
|
|
|
174 |
|
|
/* Get the instance to the HID class. */ |
175 |
|
168 |
hid = command -> ux_host_class_hid_client_command_instance; |
176 |
|
|
|
177 |
|
|
/* Get some memory for both the HID class instance and copy of this client |
178 |
|
|
and for the callback. */ |
179 |
|
|
client_keyboard = (UX_HOST_CLASS_HID_CLIENT_KEYBOARD *) |
180 |
|
168 |
_ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, |
181 |
|
|
sizeof(UX_HOST_CLASS_HID_CLIENT_KEYBOARD)); |
182 |
✓✓ |
168 |
if (client_keyboard == UX_NULL) |
183 |
|
3 |
return(UX_MEMORY_INSUFFICIENT); |
184 |
|
|
|
185 |
|
|
/* Use allocated memory. |
186 |
|
|
* - create a client copy. |
187 |
|
|
* - get keyboard instance. |
188 |
|
|
*/ |
189 |
|
165 |
keyboard_instance = &client_keyboard -> ux_host_class_hid_client_keyboard_keyboard; |
190 |
|
165 |
hid_client = &client_keyboard -> ux_host_class_hid_client_keyboard_client; |
191 |
|
165 |
_ux_utility_memory_copy(hid_client, hid -> ux_host_class_hid_client, sizeof(UX_HOST_CLASS_HID_CLIENT)); /* Use case of memcpy is verified. */ |
192 |
|
|
|
193 |
|
|
/* Attach the remote control instance to the client instance. */ |
194 |
|
165 |
hid_client -> ux_host_class_hid_client_local_instance = (VOID *) keyboard_instance; |
195 |
|
|
|
196 |
|
|
/* Save the HID instance in the client instance. */ |
197 |
|
165 |
keyboard_instance -> ux_host_class_hid_keyboard_hid = hid; |
198 |
|
|
|
199 |
|
|
#if defined(UX_HOST_STANDALONE) |
200 |
|
|
|
201 |
|
|
/* Set client task function. */ |
202 |
|
|
hid_client -> ux_host_class_hid_client_function = _ux_host_class_hid_keyboard_tasks_run; |
203 |
|
|
|
204 |
|
|
/* The instance is mounting now. */ |
205 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_state = UX_HOST_CLASS_INSTANCE_MOUNTING; |
206 |
|
|
#else |
207 |
|
|
|
208 |
|
|
/* The instance is live now. */ |
209 |
|
165 |
keyboard_instance -> ux_host_class_hid_keyboard_state = UX_HOST_CLASS_INSTANCE_LIVE; |
210 |
|
|
#endif |
211 |
|
|
|
212 |
|
|
/* Allocate the round-robin buffer that the remote control instance will use |
213 |
|
|
* to store the usages as they come in. |
214 |
|
|
* Size calculation overflow is checked near where _USAGE_ARRAY_LENGTH is defined. |
215 |
|
|
*/ |
216 |
|
165 |
keyboard_instance -> ux_host_class_hid_keyboard_usage_array = (ULONG *) |
217 |
|
165 |
_ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH*4); |
218 |
✓✓ |
165 |
if (keyboard_instance -> ux_host_class_hid_keyboard_usage_array == UX_NULL) |
219 |
|
2 |
status = (UX_MEMORY_INSUFFICIENT); |
220 |
|
|
|
221 |
|
|
/* If we are OK, go on. */ |
222 |
✓✓ |
165 |
if (status == UX_SUCCESS) |
223 |
|
|
{ |
224 |
|
|
|
225 |
|
|
/* Initialize the head and tail of this array. */ |
226 |
|
163 |
keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head = keyboard_instance -> ux_host_class_hid_keyboard_usage_array; |
227 |
|
163 |
keyboard_instance -> ux_host_class_hid_keyboard_usage_array_tail = keyboard_instance -> ux_host_class_hid_keyboard_usage_array; |
228 |
|
|
|
229 |
|
|
/* Get the report ID for the keyboard. The keyboard is a INPUT report. |
230 |
|
|
This should be 0 but in case. */ |
231 |
|
163 |
report_id.ux_host_class_hid_report_get_report = UX_NULL; |
232 |
|
163 |
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT; |
233 |
|
163 |
status = _ux_host_class_hid_report_id_get(hid, &report_id); |
234 |
|
|
} |
235 |
|
|
|
236 |
|
|
/* If we are OK, go on. */ |
237 |
✓✓ |
165 |
if (status == UX_SUCCESS) |
238 |
|
|
{ |
239 |
|
|
|
240 |
|
|
/* Save the keyboard report ID. */ |
241 |
|
161 |
keyboard_instance -> ux_host_class_hid_keyboard_id = (USHORT)(report_id.ux_host_class_hid_report_get_id); |
242 |
|
|
|
243 |
|
|
#ifdef UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE |
244 |
|
|
|
245 |
|
|
/* Summarize number of usages to allocate state buffer for keyboard report. |
246 |
|
|
We reserve 3 bits for lock status, 8 bits for modifier status. |
247 |
|
|
We get number of keys from report of 8-bit array. |
248 |
|
|
Key usages bytes then saved if it's down. |
249 |
|
|
- 3 Locks - 8 Modifiers - N regular keys ... |
250 |
|
|
*/ |
251 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_key_count = 3 + 8; |
252 |
|
|
field = report_id.ux_host_class_hid_report_get_report -> ux_host_class_hid_report_field; |
253 |
|
|
while(field) |
254 |
|
|
{ |
255 |
|
|
if (field -> ux_host_class_hid_field_report_size == 8) |
256 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_key_count += field -> ux_host_class_hid_field_report_count; |
257 |
|
|
field = field -> ux_host_class_hid_field_next_field; |
258 |
|
|
} |
259 |
|
|
|
260 |
|
|
/* Process memory includes: |
261 |
|
|
- states for last [usage, value] and new [usage, value], (2 * 2) * max number of keys to log |
262 |
|
|
- actions for last and new buffers, 2 * max number of keys to log |
263 |
|
|
*/ |
264 |
|
|
UX_UTILITY_MULC_SAFE(keyboard_instance -> ux_host_class_hid_keyboard_key_count, 6, event_process_memory_size, status); |
265 |
|
|
|
266 |
|
|
/* Calculation overflow check. */ |
267 |
|
|
if (status == UX_SUCCESS) |
268 |
|
|
#else |
269 |
|
|
|
270 |
|
|
/* We reserve 3 bytes for lock keys, 3 for processing. */ |
271 |
|
161 |
keyboard_instance -> ux_host_class_hid_keyboard_key_count = 3; |
272 |
|
|
|
273 |
|
|
/* key count 3, multiply 2 is int safe. */ |
274 |
|
161 |
event_process_memory_size = keyboard_instance -> ux_host_class_hid_keyboard_key_count * 2; |
275 |
|
|
#endif |
276 |
|
|
|
277 |
|
|
{ |
278 |
|
|
|
279 |
|
|
/* Allocate memory for usages states. */ |
280 |
|
161 |
keyboard_instance -> ux_host_class_hid_keyboard_key_state = (UCHAR *) |
281 |
|
161 |
_ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, event_process_memory_size); |
282 |
✓✓ |
161 |
if (keyboard_instance -> ux_host_class_hid_keyboard_key_state == UX_NULL) |
283 |
|
2 |
status = UX_MEMORY_INSUFFICIENT; |
284 |
|
|
} |
285 |
|
|
} |
286 |
|
|
|
287 |
|
|
/* If we are OK, go on. */ |
288 |
✓✓ |
165 |
if (status == UX_SUCCESS) |
289 |
|
|
{ |
290 |
|
|
|
291 |
|
|
/* Initialize the report callback. */ |
292 |
|
159 |
call_back.ux_host_class_hid_report_callback_id = keyboard_instance -> ux_host_class_hid_keyboard_id; |
293 |
|
159 |
call_back.ux_host_class_hid_report_callback_function = _ux_host_class_hid_keyboard_callback; |
294 |
|
159 |
call_back.ux_host_class_hid_report_callback_buffer = UX_NULL; |
295 |
|
159 |
call_back.ux_host_class_hid_report_callback_flags = UX_HOST_CLASS_HID_REPORT_DECOMPRESSED; |
296 |
|
159 |
call_back.ux_host_class_hid_report_callback_length = 0; |
297 |
|
|
|
298 |
|
|
/* Register the report call back when data comes it on this report. */ |
299 |
|
159 |
status = _ux_host_class_hid_report_callback_register(hid, &call_back); |
300 |
|
|
} |
301 |
|
|
|
302 |
|
|
#if !defined(UX_HOST_STANDALONE) |
303 |
|
|
|
304 |
|
|
/* If we are OK, go on. */ |
305 |
✓✓ |
165 |
if (status == UX_SUCCESS) |
306 |
|
|
{ |
307 |
|
|
|
308 |
|
|
/* We need a semaphore now. This will be used to synchronize the HID report with the keyboard thread. */ |
309 |
|
159 |
status = _ux_host_semaphore_create(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore, "ux_host_class_hid_keyboard_semaphore", 0); |
310 |
✓✓ |
159 |
if(status != UX_SUCCESS) |
311 |
|
1 |
status = (UX_SEMAPHORE_ERROR); |
312 |
|
|
} |
313 |
|
|
|
314 |
|
|
/* If we are OK, go on. */ |
315 |
✓✓ |
165 |
if (status == UX_SUCCESS) |
316 |
|
|
{ |
317 |
|
|
|
318 |
|
|
/* The HID Keyboard needs a Thread to process LED changes. This process is asynchronous |
319 |
|
|
to the callback because it involves using the commands on the Control Pipe which cannot |
320 |
|
|
be done during callbacks. First allocate some stack memory. */ |
321 |
|
158 |
keyboard_instance -> ux_host_class_hid_keyboard_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); |
322 |
|
|
|
323 |
|
|
/* Check if stack memory was allocated. */ |
324 |
✓✓ |
158 |
if (keyboard_instance -> ux_host_class_hid_keyboard_thread_stack == UX_NULL) |
325 |
|
2 |
status = (UX_MEMORY_INSUFFICIENT); |
326 |
|
|
} |
327 |
|
|
|
328 |
|
|
/* If we are OK, go on. */ |
329 |
✓✓ |
165 |
if (status == UX_SUCCESS) |
330 |
|
|
|
331 |
|
|
/* Then create the actual thread. */ |
332 |
|
156 |
status = _ux_utility_thread_create(&keyboard_instance -> ux_host_class_hid_keyboard_thread, "ux_host_stack_keyboard_thread",_ux_host_class_hid_keyboard_thread, |
333 |
|
|
(ULONG) (ALIGN_TYPE) keyboard_instance, keyboard_instance -> ux_host_class_hid_keyboard_thread_stack, |
334 |
|
|
UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_KEYBOARD, |
335 |
|
|
UX_THREAD_PRIORITY_KEYBOARD, UX_NO_TIME_SLICE, UX_AUTO_START); |
336 |
|
|
|
337 |
|
|
#endif |
338 |
|
|
|
339 |
|
|
/* If we are OK, go on. */ |
340 |
✓✓ |
165 |
if (status == UX_SUCCESS) |
341 |
|
|
{ |
342 |
|
|
|
343 |
|
|
#if !defined(UX_HOST_STANDALONE) |
344 |
|
|
UX_THREAD_EXTENSION_PTR_SET(&(keyboard_instance -> ux_host_class_hid_keyboard_thread), keyboard_instance) |
345 |
|
|
#endif |
346 |
|
|
|
347 |
|
|
/* Default state of keyboard is with NumLock on. */ |
348 |
|
156 |
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_NUM_LOCK; |
349 |
|
|
|
350 |
|
|
/* We need to build the field for the LEDs. */ |
351 |
|
156 |
keyboard_instance -> ux_host_class_hid_keyboard_led_mask = keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & |
352 |
|
|
UX_HID_KEYBOARD_STATE_MASK_LOCK; |
353 |
|
|
|
354 |
|
|
#if defined(UX_HOST_STANDALONE) |
355 |
|
|
|
356 |
|
|
/* Initialize the keyboard layout and use it to decode keys. */ |
357 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_layout = &ux_host_class_hid_keyboard_layout; |
358 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable = UX_FALSE; |
359 |
|
|
|
360 |
|
|
/* Remaining things will be done in ACTIVATE_WAIT. |
361 |
|
|
- SET_REPORT(LEDs) |
362 |
|
|
- SET_IDLE(KEYs, 0) |
363 |
|
|
- _periodic_report_start() */ |
364 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_enum_state = UX_STATE_WAIT; |
365 |
|
|
|
366 |
|
|
/* It's fine, replace client with our copy. */ |
367 |
|
|
hid -> ux_host_class_hid_client = hid_client; |
368 |
|
|
return(status); |
369 |
|
|
#else |
370 |
|
|
|
371 |
|
|
/* We need to find the OUTPUT report for the keyboard LEDs. */ |
372 |
|
156 |
report_id.ux_host_class_hid_report_get_report = UX_NULL; |
373 |
|
156 |
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT; |
374 |
|
156 |
status = _ux_host_class_hid_report_id_get(hid, &report_id); |
375 |
|
|
|
376 |
|
|
/* The report ID should exist. If there is an error, we do not proceed. */ |
377 |
✓✓ |
156 |
if (status == UX_SUCCESS) |
378 |
|
|
{ |
379 |
|
|
|
380 |
|
|
/* Memorize the report pointer. */ |
381 |
|
152 |
client_report.ux_host_class_hid_client_report = report_id.ux_host_class_hid_report_get_report; |
382 |
|
|
|
383 |
|
|
/* The report set is raw since the LEDs mask is already in the right format. */ |
384 |
|
152 |
client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW; |
385 |
|
|
|
386 |
|
|
/* The length of this report is 1 byte. */ |
387 |
|
152 |
client_report.ux_host_class_hid_client_report_length = 1; |
388 |
|
|
|
389 |
|
|
/* The output report buffer is the LED mask field. */ |
390 |
|
152 |
client_report.ux_host_class_hid_client_report_buffer = &keyboard_instance -> ux_host_class_hid_keyboard_led_mask; |
391 |
|
|
|
392 |
|
|
/* The HID class will perform the SET_REPORT command. Do not check for error here, this is |
393 |
|
|
handled by the function itself. */ |
394 |
|
152 |
status = _ux_host_class_hid_report_set(hid, &client_report); |
395 |
|
|
} |
396 |
|
|
|
397 |
|
|
/* If we are OK, go on. */ |
398 |
✓✓ |
156 |
if (status == UX_SUCCESS) |
399 |
|
|
{ |
400 |
|
|
|
401 |
|
|
/* Set the idle rate of the keyboard to 0. This way a report is generated only when there is an activity. */ |
402 |
|
148 |
status = _ux_host_class_hid_idle_set(hid, 0, keyboard_instance -> ux_host_class_hid_keyboard_id); |
403 |
|
|
} |
404 |
|
|
|
405 |
|
|
/* If we are OK, go on. */ |
406 |
✓✓ |
156 |
if (status == UX_SUCCESS) |
407 |
|
|
{ |
408 |
|
|
|
409 |
|
|
/* Initialize the keyboard layout and use it to decode keys. */ |
410 |
|
146 |
keyboard_instance -> ux_host_class_hid_keyboard_layout = &ux_host_class_hid_keyboard_layout; |
411 |
|
146 |
keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable = UX_FALSE; |
412 |
|
|
|
413 |
|
|
/* Start the periodic report. */ |
414 |
|
146 |
status = _ux_host_class_hid_periodic_report_start(hid); |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
/* If we are OK, go on. */ |
418 |
✓✓ |
156 |
if (status == UX_SUCCESS) |
419 |
|
|
{ |
420 |
|
|
|
421 |
|
|
/* It's fine, replace client copy. */ |
422 |
|
145 |
hid -> ux_host_class_hid_client = hid_client; |
423 |
|
|
|
424 |
|
|
/* If all is fine and the device is mounted, we may need to inform the application |
425 |
|
|
if a function has been programmed in the system structure. */ |
426 |
✓✓ |
145 |
if (_ux_system_host -> ux_system_host_change_function != UX_NULL) |
427 |
|
|
{ |
428 |
|
|
|
429 |
|
|
/* Call system change function. */ |
430 |
|
119 |
_ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid_client); |
431 |
|
|
} |
432 |
|
|
|
433 |
|
|
/* If trace is enabled, insert this event into the trace buffer. */ |
434 |
|
|
UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_KEYBOARD_ACTIVATE, hid, keyboard_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) |
435 |
|
|
|
436 |
|
|
/* Return completion status. */ |
437 |
|
145 |
return(status); |
438 |
|
|
} |
439 |
|
|
|
440 |
|
|
/* There is error, delete thread. */ |
441 |
|
11 |
_ux_utility_thread_delete(&keyboard_instance -> ux_host_class_hid_keyboard_thread); |
442 |
|
|
#endif |
443 |
|
|
} |
444 |
|
|
|
445 |
|
|
/* We are here if there is error. */ |
446 |
|
|
|
447 |
|
|
/* Free usage state. */ |
448 |
✓✓ |
20 |
if (keyboard_instance -> ux_host_class_hid_keyboard_key_state) |
449 |
|
14 |
_ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_key_state); |
450 |
|
|
|
451 |
|
|
#if !defined(UX_HOST_STANDALONE) |
452 |
|
|
|
453 |
|
|
/* Free stack. */ |
454 |
✓✓ |
20 |
if (keyboard_instance -> ux_host_class_hid_keyboard_thread_stack) |
455 |
|
11 |
_ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_thread_stack); |
456 |
|
|
|
457 |
|
|
/* Delete semaphore. */ |
458 |
✓✓ |
20 |
if (keyboard_instance -> ux_host_class_hid_keyboard_semaphore.tx_semaphore_id != UX_EMPTY) |
459 |
|
13 |
_ux_host_semaphore_delete(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); |
460 |
|
|
|
461 |
|
|
#endif |
462 |
|
|
|
463 |
|
|
/* Free usage array. */ |
464 |
✓✓ |
20 |
if (keyboard_instance -> ux_host_class_hid_keyboard_usage_array) |
465 |
|
18 |
_ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_usage_array); |
466 |
|
|
|
467 |
|
|
/* Free instance. */ |
468 |
|
20 |
_ux_utility_memory_free(keyboard_instance); |
469 |
|
|
|
470 |
|
|
/* Return completion status. */ |
471 |
|
20 |
return(status); |
472 |
|
|
} |