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