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 |
|
|
/**************************************************************************/ |
33 |
|
|
/* */ |
34 |
|
|
/* FUNCTION RELEASE */ |
35 |
|
|
/* */ |
36 |
|
|
/* _ux_host_class_hid_keyboard_callback PORTABLE C */ |
37 |
|
|
/* 6.1.10 */ |
38 |
|
|
/* AUTHOR */ |
39 |
|
|
/* */ |
40 |
|
|
/* Chaoqiong Xiao, Microsoft Corporation */ |
41 |
|
|
/* */ |
42 |
|
|
/* DESCRIPTION */ |
43 |
|
|
/* */ |
44 |
|
|
/* This function is the callback mechanism for a report registration. */ |
45 |
|
|
/* */ |
46 |
|
|
/* INPUT */ |
47 |
|
|
/* */ |
48 |
|
|
/* callback Pointer to callback */ |
49 |
|
|
/* */ |
50 |
|
|
/* OUTPUT */ |
51 |
|
|
/* */ |
52 |
|
|
/* None */ |
53 |
|
|
/* */ |
54 |
|
|
/* CALLS */ |
55 |
|
|
/* */ |
56 |
|
|
/* _ux_utility_memory_copy Copy memory */ |
57 |
|
|
/* _ux_utility_memory_set Set memory */ |
58 |
|
|
/* */ |
59 |
|
|
/* CALLED BY */ |
60 |
|
|
/* */ |
61 |
|
|
/* HID Class when a report is generated */ |
62 |
|
|
/* */ |
63 |
|
|
/* RELEASE HISTORY */ |
64 |
|
|
/* */ |
65 |
|
|
/* DATE NAME DESCRIPTION */ |
66 |
|
|
/* */ |
67 |
|
|
/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ |
68 |
|
|
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ |
69 |
|
|
/* verified memset and memcpy */ |
70 |
|
|
/* cases, */ |
71 |
|
|
/* resulting in version 6.1 */ |
72 |
|
|
/* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ |
73 |
|
|
/* added standalone support, */ |
74 |
|
|
/* resulting in version 6.1.10 */ |
75 |
|
|
/* */ |
76 |
|
|
/**************************************************************************/ |
77 |
|
815 |
VOID _ux_host_class_hid_keyboard_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback) |
78 |
|
|
{ |
79 |
|
|
|
80 |
|
|
/* This array contains the bit for each alternate key (modifier or lock key) |
81 |
|
|
that we report to the application. For example, if you wanted to set the |
82 |
|
|
bit for the CAPS_LOCK key, you would do: |
83 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= alternate_key_bits[0]; |
84 |
|
|
Index 0 is used since it corresponds to the CAPS_LOCK bit in the array. Note |
85 |
|
|
that _alternate_key_state is what we report to the application. */ |
86 |
|
815 |
const ULONG alternate_key_bits[] = { |
87 |
|
|
UX_HID_KEYBOARD_STATE_CAPS_LOCK, |
88 |
|
|
UX_HID_KEYBOARD_STATE_NUM_LOCK, |
89 |
|
|
UX_HID_KEYBOARD_STATE_SCROLL_LOCK, |
90 |
|
|
UX_HID_KEYBOARD_STATE_LEFT_CTRL, |
91 |
|
|
UX_HID_KEYBOARD_STATE_LEFT_SHIFT, |
92 |
|
|
UX_HID_KEYBOARD_STATE_LEFT_ALT, |
93 |
|
|
UX_HID_KEYBOARD_STATE_LEFT_GUI, |
94 |
|
|
UX_HID_KEYBOARD_STATE_RIGHT_CTRL, |
95 |
|
|
UX_HID_KEYBOARD_STATE_RIGHT_SHIFT, |
96 |
|
|
UX_HID_KEYBOARD_STATE_RIGHT_ALT, |
97 |
|
|
UX_HID_KEYBOARD_STATE_RIGHT_GUI, |
98 |
|
|
}; |
99 |
|
|
|
100 |
|
|
/* Define the indices for each alternate key in the alternate key bits array. */ |
101 |
|
|
|
102 |
|
|
#define ALTERNATE_KEY_BITS_IDX_CAPS_LOCK ( 0) |
103 |
|
|
#define ALTERNATE_KEY_BITS_IDX_NUM_LOCK ( 1) |
104 |
|
|
#define ALTERNATE_KEY_BITS_IDX_SCROLL_LOCK ( 2) |
105 |
|
|
|
106 |
|
|
#define ALTERNATE_KEY_BITS_IDX_LEFT_CTRL ( 3) |
107 |
|
|
#define ALTERNATE_KEY_BITS_IDX_LEFT_SHIFT ( 4) |
108 |
|
|
#define ALTERNATE_KEY_BITS_IDX_LEFT_ALT ( 5) |
109 |
|
|
#define ALTERNATE_KEY_BITS_IDX_LEFT_GUI ( 6) |
110 |
|
|
#define ALTERNATE_KEY_BITS_IDX_RIGHT_CTRL ( 7) |
111 |
|
|
#define ALTERNATE_KEY_BITS_IDX_RIGHT_SHIFT ( 8) |
112 |
|
|
#define ALTERNATE_KEY_BITS_IDX_RIGHT_ALT ( 9) |
113 |
|
|
#define ALTERNATE_KEY_BITS_IDX_RIGHT_GUI (10) |
114 |
|
|
|
115 |
|
|
/* Define a macro to get the index of a modifier key in the alternate key bits array. */ |
116 |
|
|
#define GET_ALTERNATE_KEY_BITS_IDX(usage) ((usage) - UX_HID_MODIFIER_KEY_LEFT_CONTROL + ALTERNATE_KEY_BITS_IDX_LEFT_CTRL) |
117 |
|
|
|
118 |
|
|
/* Define key states. */ |
119 |
|
|
#define KEY_STATE_REGULAR (11) |
120 |
|
|
#define KEY_STATE_NO_KEY (12) |
121 |
|
|
|
122 |
|
|
#define KEY_UP ( 0) |
123 |
|
|
#define KEY_KEEP ( 1) |
124 |
|
|
#define KEY_DOWN ( 2) |
125 |
|
|
#define KEY_DEL ( 3) |
126 |
|
|
|
127 |
|
|
|
128 |
|
|
UX_HOST_CLASS_HID_CLIENT *hid_client; |
129 |
|
|
UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance; |
130 |
|
|
UX_HOST_CLASS_HID_KEYBOARD_LAYOUT *keyboard_layout; |
131 |
|
|
UCHAR *keypad_array; |
132 |
|
|
ULONG *array_head; |
133 |
|
|
ULONG *array_tail; |
134 |
|
|
ULONG *array_end; |
135 |
|
|
ULONG *array_start; |
136 |
|
|
ULONG *report_buffer; |
137 |
|
|
ULONG *report_buffer_end; |
138 |
|
815 |
ULONG keyboard_char = 0; |
139 |
|
|
ULONG shift_on; |
140 |
|
|
ULONG capslock_on; |
141 |
|
|
ULONG numlock_on; |
142 |
|
|
ULONG key_usage; |
143 |
|
|
ULONG key_value; |
144 |
|
|
|
145 |
|
|
/* This variable either contains an index into the alternate key bit array, |
146 |
|
|
or a value that describes the current key i.e. regular key or no key. */ |
147 |
|
|
UINT key_state; |
148 |
|
|
|
149 |
|
|
#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) |
150 |
|
|
UCHAR *previous_lock_key_states; |
151 |
|
|
UCHAR *current_lock_key_states; |
152 |
|
|
#else |
153 |
|
|
UINT i, i_save, new_count; |
154 |
|
|
UCHAR *state_usage; |
155 |
|
|
UCHAR *state_value; |
156 |
|
|
UCHAR *state_action; |
157 |
|
|
#endif |
158 |
|
|
|
159 |
|
|
|
160 |
|
|
/* Get the HID client instance that issued the callback. */ |
161 |
|
815 |
hid_client = callback -> ux_host_class_hid_report_callback_client; |
162 |
|
|
|
163 |
|
|
/* Get the keyboard local instance. */ |
164 |
|
815 |
keyboard_instance = (UX_HOST_CLASS_HID_KEYBOARD *) hid_client -> ux_host_class_hid_client_local_instance; |
165 |
|
|
|
166 |
|
|
/* Get the report buffer. */ |
167 |
|
815 |
report_buffer = (ULONG *)callback -> ux_host_class_hid_report_callback_buffer; |
168 |
|
|
|
169 |
|
|
/* Get the end of report buffer. */ |
170 |
|
815 |
report_buffer_end = &report_buffer[callback -> ux_host_class_hid_report_callback_actual_length]; |
171 |
|
|
|
172 |
|
|
#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) |
173 |
|
|
|
174 |
|
|
/* Get the previous states of the lock keys. */ |
175 |
|
815 |
previous_lock_key_states = &keyboard_instance -> ux_host_class_hid_keyboard_key_state[0]; |
176 |
|
|
|
177 |
|
|
/* Get the current states of the lock keys and immediately initialize them to zero; |
178 |
|
|
if a lock key is not pressed in this report, it will remain zero (not pressed). */ |
179 |
|
815 |
current_lock_key_states = &keyboard_instance -> ux_host_class_hid_keyboard_key_state[3]; |
180 |
|
815 |
_ux_utility_memory_set(current_lock_key_states, 0, 3); /* Use case of memset is verified. */ |
181 |
|
|
|
182 |
|
|
/* Scan the report buffer and decode it. */ |
183 |
✓✓ |
13040 |
while(report_buffer < report_buffer_end) |
184 |
|
|
{ |
185 |
|
|
|
186 |
|
|
/* Get usage and value from buffer. */ |
187 |
|
12225 |
key_usage = *report_buffer ++; |
188 |
|
12225 |
key_value = *report_buffer ++; |
189 |
|
|
|
190 |
|
|
/* Analyze the usage we have received. We eliminate the page from the usage. */ |
191 |
|
12225 |
key_usage &= 0xFF; |
192 |
|
|
#else |
193 |
|
|
|
194 |
|
|
/* Initialize key states for report processing. */ |
195 |
|
|
state_usage = keyboard_instance -> ux_host_class_hid_keyboard_key_state; |
196 |
|
|
state_value = state_usage + keyboard_instance -> ux_host_class_hid_keyboard_key_count * 2; |
197 |
|
|
state_action = state_value + keyboard_instance -> ux_host_class_hid_keyboard_key_count * 2; |
198 |
|
|
|
199 |
|
|
/* Reset state actions to DEL(not received). */ |
200 |
|
|
_ux_utility_memory_set(state_usage + keyboard_instance -> ux_host_class_hid_keyboard_key_count, 0, keyboard_instance -> ux_host_class_hid_keyboard_key_count); /* Use case of memset is verified. */ |
201 |
|
|
_ux_utility_memory_set(state_value + keyboard_instance -> ux_host_class_hid_keyboard_key_count, 0, keyboard_instance -> ux_host_class_hid_keyboard_key_count); /* Use case of memset is verified. */ |
202 |
|
|
_ux_utility_memory_set(state_action, KEY_DEL, keyboard_instance -> ux_host_class_hid_keyboard_key_count * 2); /* Use case of memset is verified. */ |
203 |
|
|
|
204 |
|
|
new_count = keyboard_instance -> ux_host_class_hid_keyboard_key_count; |
205 |
|
|
while(report_buffer < report_buffer_end) |
206 |
|
|
{ |
207 |
|
|
|
208 |
|
|
/* Get usage and value from buffer. */ |
209 |
|
|
key_usage = *report_buffer ++; |
210 |
|
|
key_value = *report_buffer ++; |
211 |
|
|
|
212 |
|
|
/* Analyze the usage we have received. We eliminate the page from the usage. */ |
213 |
|
|
key_usage &= 0xFF; |
214 |
|
|
key_value &= 0xFF; |
215 |
|
|
|
216 |
|
|
/* If there is no key or in phantom state (roll over), skip. */ |
217 |
|
|
if (key_usage <= UX_HID_KEYBOARD_PHANTOM_STATE) |
218 |
|
|
continue; |
219 |
|
|
|
220 |
|
|
/* Check if the key is previously reported. */ |
221 |
|
|
for (i = 0; i < keyboard_instance -> ux_host_class_hid_keyboard_key_count; i ++) |
222 |
|
|
{ |
223 |
|
|
|
224 |
|
|
/* Check if it's modified. */ |
225 |
|
|
if (state_usage[i] == key_usage) |
226 |
|
|
{ |
227 |
|
|
|
228 |
|
|
/* Replace action state. */ |
229 |
|
|
state_action[i] = (state_value[i] == key_value) ? KEY_KEEP : (key_value ? KEY_DOWN : KEY_UP); |
230 |
|
|
|
231 |
|
|
/* Replace key value. */ |
232 |
|
|
state_value[i] = key_value; |
233 |
|
|
break; |
234 |
|
|
} |
235 |
|
|
} |
236 |
|
|
|
237 |
|
|
/* When there is new key, add to new key list. */ |
238 |
|
|
if (i == keyboard_instance -> ux_host_class_hid_keyboard_key_count) |
239 |
|
|
{ |
240 |
|
|
|
241 |
|
|
/* Add key value. */ |
242 |
|
|
state_usage [new_count] = key_usage; |
243 |
|
|
state_value [new_count] = key_value; |
244 |
|
|
|
245 |
|
|
/* Add key action. */ |
246 |
|
|
state_action[new_count] = key_value ? KEY_DOWN : KEY_KEEP; |
247 |
|
|
|
248 |
|
|
new_count ++; |
249 |
|
|
} |
250 |
|
|
} /* while(report_buffer < report_buffer_end) */ |
251 |
|
|
|
252 |
|
|
/* Process pending key states. */ |
253 |
|
|
i_save = 0; |
254 |
|
|
for (i = 0; i < new_count; i ++) |
255 |
|
|
{ |
256 |
|
|
|
257 |
|
|
/* Get state value from buffer. */ |
258 |
|
|
key_usage = state_usage[i]; |
259 |
|
|
key_value = state_value[i]; |
260 |
|
|
key_state = state_action[i]; |
261 |
|
|
|
262 |
|
|
/* If no key, just skip. */ |
263 |
|
|
if (key_usage == 0) |
264 |
|
|
continue; |
265 |
|
|
|
266 |
|
|
/* If key not reported, add up event if it's enabled. */ |
267 |
|
|
if (key_state == KEY_DEL) |
268 |
|
|
{ |
269 |
|
|
|
270 |
|
|
/* Clear state, do not save. */ |
271 |
|
|
state_usage[i] = 0; |
272 |
|
|
state_action[i] = KEY_UP; |
273 |
|
|
} |
274 |
|
|
|
275 |
|
|
/* Key reported, process it. */ |
276 |
|
|
else |
277 |
|
|
{ |
278 |
|
|
|
279 |
|
|
/* We need to save key anyway. */ |
280 |
|
|
if (i_save < i) |
281 |
|
|
{ |
282 |
|
|
state_usage[i_save] = key_usage; |
283 |
|
|
state_value[i_save] = key_value; |
284 |
|
|
} |
285 |
|
|
i_save ++; |
286 |
|
|
} |
287 |
|
|
|
288 |
|
|
/* Skip keep keys. */ |
289 |
|
|
if (state_action[i] == KEY_KEEP) |
290 |
|
|
continue; |
291 |
|
|
|
292 |
|
|
/* Now handle key event. */ |
293 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state &= ~(UX_HID_KEYBOARD_STATE_FUNCTION | UX_HID_KEYBOARD_STATE_KEY_UP); |
294 |
|
|
#endif /* UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE */ |
295 |
|
|
|
296 |
|
|
/* Determine what key this is. */ |
297 |
✓✓✓✓ ✓✓ |
12225 |
switch(key_usage) |
298 |
|
|
{ |
299 |
|
|
|
300 |
|
|
/* This is the usage of a modifier key. Set or clear the appropriate |
301 |
|
|
bits in the alternate key state bitmap. */ |
302 |
|
6520 |
case UX_HID_MODIFIER_KEY_LEFT_SHIFT : |
303 |
|
|
case UX_HID_MODIFIER_KEY_RIGHT_SHIFT : |
304 |
|
|
case UX_HID_MODIFIER_KEY_LEFT_ALT : |
305 |
|
|
case UX_HID_MODIFIER_KEY_RIGHT_ALT : |
306 |
|
|
case UX_HID_MODIFIER_KEY_RIGHT_CONTROL : |
307 |
|
|
case UX_HID_MODIFIER_KEY_LEFT_CONTROL : |
308 |
|
|
case UX_HID_MODIFIER_KEY_RIGHT_GUI : |
309 |
|
|
case UX_HID_MODIFIER_KEY_LEFT_GUI : |
310 |
|
|
|
311 |
|
6520 |
key_state = GET_ALTERNATE_KEY_BITS_IDX(key_usage); |
312 |
|
|
|
313 |
|
|
/* We have received a modifier Key. Remember the state. */ |
314 |
✓✓ |
6520 |
if (key_value > 0) |
315 |
|
246 |
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= alternate_key_bits[key_state]; |
316 |
|
|
else |
317 |
|
6274 |
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state &= ~alternate_key_bits[key_state]; |
318 |
|
|
|
319 |
|
6520 |
break; |
320 |
|
|
|
321 |
|
|
/* This is the usage of a LOCK key. Just save the its index in the alternate |
322 |
|
|
key bit array. */ |
323 |
|
|
|
324 |
|
5 |
case UX_HID_LED_KEY_CAPS_LOCK : |
325 |
|
5 |
key_state = ALTERNATE_KEY_BITS_IDX_CAPS_LOCK; |
326 |
|
5 |
break; |
327 |
|
|
|
328 |
|
5 |
case UX_HID_LED_KEY_NUM_LOCK : |
329 |
|
5 |
key_state = ALTERNATE_KEY_BITS_IDX_NUM_LOCK; |
330 |
|
5 |
break; |
331 |
|
|
|
332 |
|
3 |
case UX_HID_LED_KEY_SCROLL_LOCK : |
333 |
|
3 |
key_state = ALTERNATE_KEY_BITS_IDX_SCROLL_LOCK; |
334 |
|
3 |
break; |
335 |
|
|
|
336 |
|
|
#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) |
337 |
|
|
|
338 |
|
|
/* Usage no key. */ |
339 |
|
4955 |
case UX_HID_KEYBOARD_NO_KEY : |
340 |
|
|
case UX_HID_KEYBOARD_PHANTOM_STATE : |
341 |
|
4955 |
key_state = KEY_STATE_NO_KEY; |
342 |
|
4955 |
break; |
343 |
|
|
#endif |
344 |
|
|
|
345 |
|
|
/* This is the usage of a regular key. Here, we just get the decoded |
346 |
|
|
value; we will add it to the queue later. */ |
347 |
|
737 |
default : |
348 |
|
|
|
349 |
|
|
/* By default the key will be saved. */ |
350 |
|
737 |
key_state = KEY_STATE_REGULAR; |
351 |
|
|
|
352 |
|
|
/* Skip decode if decode is disabled. */ |
353 |
✓✓ |
737 |
if (keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable == UX_TRUE) |
354 |
|
|
{ |
355 |
|
|
|
356 |
|
|
/* Use raw data (scan code) as key code. */ |
357 |
|
176 |
keyboard_char = key_value; |
358 |
|
176 |
break; |
359 |
|
|
} |
360 |
|
|
|
361 |
|
|
/* Get keyboard layout instance. */ |
362 |
|
561 |
keyboard_layout = keyboard_instance -> ux_host_class_hid_keyboard_layout; |
363 |
|
|
|
364 |
|
|
/* Is this key outside the valid range? */ |
365 |
✓✓ |
561 |
if (key_value > keyboard_layout -> ux_host_class_hid_keyboard_layout_keys_upper_range) |
366 |
|
|
{ |
367 |
|
|
|
368 |
|
|
/* Set a flag to discard it. */ |
369 |
|
3 |
key_state = KEY_STATE_NO_KEY; |
370 |
|
3 |
break; |
371 |
|
|
} |
372 |
|
|
|
373 |
|
|
/* We have received a regular key. Depending on the state of the shift or numlock status, the key should be mapped into |
374 |
|
|
one of the translation tables. We verify if the key is within our mapping range. */ |
375 |
|
|
|
376 |
|
|
/* Get SHIFT, CAPS_LOCK and NUM_LOCK states. */ |
377 |
✓✓ |
558 |
shift_on = (keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & UX_HID_KEYBOARD_STATE_SHIFT) ? UX_TRUE : UX_FALSE; |
378 |
|
558 |
capslock_on = (keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & UX_HID_KEYBOARD_STATE_CAPS_LOCK) ? UX_TRUE : UX_FALSE; |
379 |
|
558 |
numlock_on = (keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & UX_HID_KEYBOARD_STATE_NUM_LOCK) ? UX_TRUE : UX_FALSE; |
380 |
|
|
|
381 |
|
|
/* Check if we have letters ('a' to 'z'). */ |
382 |
✓✓ |
558 |
if (key_value >= keyboard_layout -> ux_host_class_hid_keyboard_layout_letters_lower_range && |
383 |
✓✓ |
549 |
key_value <= keyboard_layout -> ux_host_class_hid_keyboard_layout_letters_upper_range) |
384 |
|
|
{ |
385 |
|
|
|
386 |
|
|
/* We have letters, check the Shift and CapsLock state. */ |
387 |
✓✓ |
173 |
if (shift_on != capslock_on) |
388 |
|
|
|
389 |
|
|
/* Shift and CapsLock in different state: upper case. */ |
390 |
|
52 |
keyboard_char = keyboard_layout -> ux_host_class_hid_keyboard_layout_shift_array[key_value]; |
391 |
|
|
else |
392 |
|
|
|
393 |
|
|
/* Lower case. */ |
394 |
|
121 |
keyboard_char = keyboard_layout -> ux_host_class_hid_keyboard_layout_regular_array[key_value]; |
395 |
|
|
|
396 |
|
173 |
break; /* default: */ |
397 |
|
|
} |
398 |
|
|
|
399 |
|
|
/* Check if we have received a keypad key. They may be multiplexed. */ |
400 |
✓✓ |
385 |
if (key_value >= keyboard_layout -> ux_host_class_hid_keyboard_layout_keypad_lower_range && |
401 |
✓✓ |
170 |
key_value <= keyboard_layout -> ux_host_class_hid_keyboard_layout_keypad_upper_range) |
402 |
|
|
{ |
403 |
|
|
|
404 |
|
|
/* We have a keypad key. Check the NumLock state. */ |
405 |
✓✓ |
120 |
if (numlock_on) |
406 |
|
|
|
407 |
|
|
/* Numlock is on. */ |
408 |
|
100 |
keypad_array = keyboard_layout -> ux_host_class_hid_keyboard_layout_numlock_on_array; |
409 |
|
|
|
410 |
|
|
else |
411 |
|
|
|
412 |
|
|
/* Numlock is off. */ |
413 |
|
20 |
keypad_array = keyboard_layout -> ux_host_class_hid_keyboard_layout_numlock_off_array; |
414 |
|
|
|
415 |
|
|
/* Decode the keypad key. */ |
416 |
|
120 |
keyboard_char = keypad_array[key_value - |
417 |
|
120 |
keyboard_layout -> ux_host_class_hid_keyboard_layout_keypad_lower_range]; |
418 |
|
|
|
419 |
|
120 |
break; /* default: */ |
420 |
|
|
} |
421 |
|
|
|
422 |
|
|
/* Check the state of the shift. */ |
423 |
✓✓ |
265 |
if (shift_on) |
424 |
|
|
|
425 |
|
|
/* We get the key from the shifted array. */ |
426 |
|
130 |
keyboard_char = keyboard_layout -> ux_host_class_hid_keyboard_layout_shift_array[key_value]; |
427 |
|
|
|
428 |
|
|
else |
429 |
|
|
|
430 |
|
|
/* We get the key from the regular array. */ |
431 |
|
135 |
keyboard_char = keyboard_layout -> ux_host_class_hid_keyboard_layout_regular_array[key_value]; |
432 |
|
|
|
433 |
|
265 |
break; /* default: */ |
434 |
|
|
|
435 |
|
|
} /* switch(key_usage) */ |
436 |
|
|
|
437 |
|
|
#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) |
438 |
|
|
|
439 |
|
|
if (state_action[i] == KEY_UP) |
440 |
|
|
|
441 |
|
|
#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_KEY_DOWN_ONLY) |
442 |
|
|
|
443 |
|
|
/* Skip save. */ |
444 |
|
|
continue; |
445 |
|
|
#else |
446 |
|
|
|
447 |
|
|
/* Save key up state. */ |
448 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_KEY_UP; |
449 |
|
|
#endif |
450 |
|
|
#endif |
451 |
|
|
|
452 |
|
|
/* If there is no key, just try next. */ |
453 |
✓✓ |
12225 |
if (key_state == KEY_STATE_NO_KEY) |
454 |
|
4958 |
continue; |
455 |
|
|
|
456 |
|
|
/* Is this a LOCK key (i.e. caps lock, scroll lock or num lock)? */ |
457 |
✓✓ |
7267 |
if (key_state <= ALTERNATE_KEY_BITS_IDX_SCROLL_LOCK) |
458 |
|
|
{ |
459 |
|
|
|
460 |
|
|
/* Skip decode if decode is disabled. */ |
461 |
✓✓ |
13 |
if (keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable == UX_TRUE) |
462 |
|
|
{ |
463 |
|
|
|
464 |
|
|
/* Use raw data (scan code) as key code. */ |
465 |
|
3 |
keyboard_char = key_value; |
466 |
|
|
} |
467 |
|
|
else |
468 |
|
|
{ |
469 |
|
|
|
470 |
|
|
#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) |
471 |
|
|
|
472 |
|
|
/* Reflect the press in the current lock key state. */ |
473 |
|
10 |
current_lock_key_states[key_state] = (UCHAR)key_value; |
474 |
|
|
|
475 |
|
|
/* Take action only if key state changes from up to down (pressed). |
476 |
|
|
Remember that the nothing happens when lock keys are released. */ |
477 |
✓✓ |
10 |
if (previous_lock_key_states[key_state] == 0) |
478 |
|
|
#elif !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_KEY_DOWN_ONLY) |
479 |
|
|
|
480 |
|
|
/* Take action only if key state changes from up to down (pressed). */ |
481 |
|
|
if (state_action[i] == KEY_DOWN) |
482 |
|
|
#endif |
483 |
|
|
{ |
484 |
|
|
|
485 |
|
|
/* Reflect the change in the keyboard state. The state should be inverted. */ |
486 |
✓✓ |
9 |
if (keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & alternate_key_bits[key_state]) |
487 |
|
5 |
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state &= (ULONG)~alternate_key_bits[key_state]; |
488 |
|
|
else |
489 |
|
4 |
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= alternate_key_bits[key_state]; |
490 |
|
|
|
491 |
|
|
#if defined(UX_HOST_STANDALONE) |
492 |
|
|
|
493 |
|
|
/* Let background task to set LED status. */ |
494 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_out_state = UX_STATE_WAIT; |
495 |
|
|
#else |
496 |
|
|
|
497 |
|
|
/* Wake up the keyboard thread semaphore. */ |
498 |
|
9 |
_ux_host_semaphore_put(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); |
499 |
|
|
#endif |
500 |
|
|
} |
501 |
|
|
|
502 |
|
|
#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) && defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_LOCK_KEYS) |
503 |
|
|
|
504 |
|
|
/* Use usage and UX_HID_KEYBOARD_STATE_FUNCTION. */ |
505 |
|
|
keyboard_char = key_usage; |
506 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_FUNCTION; |
507 |
|
|
|
508 |
|
|
#else |
509 |
|
|
|
510 |
|
|
/* Check next usage & value. */ |
511 |
|
10 |
continue; |
512 |
|
|
#endif |
513 |
|
|
} |
514 |
|
|
} |
515 |
|
|
|
516 |
|
|
/* If it's modifier, check next usage & value. */ |
517 |
✓✓ |
7254 |
else if (key_state < KEY_STATE_REGULAR) |
518 |
|
|
{ |
519 |
|
|
#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) && defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_MODIFIER_KEYS) |
520 |
|
|
|
521 |
|
|
/* Use usage and UX_HID_KEYBOARD_STATE_FUNCTION. */ |
522 |
|
|
keyboard_char = key_usage; |
523 |
|
|
keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_FUNCTION; |
524 |
|
|
#else |
525 |
|
|
|
526 |
|
|
/* Check next usage & value. */ |
527 |
|
6520 |
continue; |
528 |
|
|
#endif |
529 |
|
|
} |
530 |
|
|
|
531 |
|
|
/* If we get here, then we have a regular key. Now it's time to save |
532 |
|
|
raw/decoded key in the key queue. */ |
533 |
|
|
|
534 |
|
|
/* This key should now be inserted in the circular array for the application to retrieve it. */ |
535 |
|
737 |
array_start = keyboard_instance -> ux_host_class_hid_keyboard_usage_array; |
536 |
|
737 |
array_end = array_start + UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH; |
537 |
|
737 |
array_head = keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head; |
538 |
|
737 |
array_tail = keyboard_instance -> ux_host_class_hid_keyboard_usage_array_tail; |
539 |
|
|
|
540 |
|
|
/* We have a single usage/value. We have to store it into the array. If the array overflows, |
541 |
|
|
there is no mechanism for flow control here so we ignore the usage/value until the |
542 |
|
|
applications makes more room in the array. */ |
543 |
|
|
|
544 |
|
|
/* Is the head at the end of the array and need to loop back? */ |
545 |
✓✓ |
737 |
if ((array_head + 2) >= array_end) |
546 |
|
20 |
array_head = array_start; |
547 |
|
|
else |
548 |
|
717 |
array_head += 2; |
549 |
|
|
|
550 |
|
|
/* Do we have enough space to store the new usage? */ |
551 |
✓✓ |
737 |
if (array_head != array_tail) |
552 |
|
|
{ |
553 |
|
|
|
554 |
|
|
/* Yes, we have some space. */ |
555 |
|
703 |
*keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head = keyboard_char; |
556 |
|
703 |
*(keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head + 1) = keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state; |
557 |
|
|
|
558 |
|
|
/* Now update the array head. */ |
559 |
|
703 |
keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head = array_head; |
560 |
|
|
} |
561 |
|
|
else |
562 |
|
|
|
563 |
|
|
/* Error trap. */ |
564 |
|
34 |
_ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); |
565 |
|
|
|
566 |
|
|
} /* while(report_buffer < report_buffer_end) */ |
567 |
|
|
|
568 |
|
|
#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) |
569 |
|
|
|
570 |
|
|
/* Copy the current lock key states to the previous states. Note that if |
571 |
|
|
a lock key wasn't down in this report, its current state would have |
572 |
|
|
remained zero (not pressed). */ |
573 |
|
815 |
_ux_utility_memory_copy(previous_lock_key_states, current_lock_key_states, 3); /* Use case of memcpy is verified. */ |
574 |
|
|
#else |
575 |
|
|
|
576 |
|
|
/* Clear redundant data after last saved key. */ |
577 |
|
|
_ux_utility_memory_set(state_usage + i_save, 0, keyboard_instance -> ux_host_class_hid_keyboard_key_count - i_save); /* Use case of memset is verified. */ |
578 |
|
|
#endif |
579 |
|
|
|
580 |
|
|
/* Return to caller. */ |
581 |
|
815 |
return; |
582 |
|
|
} |
583 |
|
|
|