GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_hid_keyboard_callback.c Lines: 91 91 100.0 %
Date: 2024-12-12 17:16:36 Branches: 46 46 100.0 %

Line Branch Exec Source
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