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: 2026-03-06 18:57:10 Branches: 46 46 100.0 %

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