GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_hid_entry.c Lines: 26 26 100.0 %
Date: 2026-03-06 18:57:10 Branches: 13 13 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 Class                                                           */
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_stack.h"
31
32
33
#if defined(UX_HOST_STANDALONE)
34
#define UX_HOST_CLASS_HID_ENUM_HID_DESC_READ            (UX_STATE_WAIT)
35
#define UX_HOST_CLASS_HID_ENUM_HID_DESC_PARSE           (UX_STATE_CLASS_STEP + 1)
36
#define UX_HOST_CLASS_HID_ENUM_REPORT_DESC_READ         (UX_STATE_CLASS_STEP + 2)
37
#define UX_HOST_CLASS_HID_ENUM_REPORT_DESC_PARSE        (UX_STATE_CLASS_STEP + 3)
38
#define UX_HOST_CLASS_HID_ENUM_CLIENT_SEARCH            (UX_STATE_CLASS_STEP + 4)
39
#define UX_HOST_CLASS_HID_ENUM_CLIENT_ACTIVATE_WAIT     (UX_STATE_CLASS_STEP + 6)
40
#define UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT            (UX_STATE_CLASS_STEP + 7)
41
#define UX_HOST_CLASS_HID_ENUM_ERROR                    (UX_STATE_CLASS_STEP + 8)
42
#define UX_HOST_CLASS_HID_ENUM_DONE                     (UX_STATE_CLASS_STEP + 9)
43
44
45
static inline UINT _ux_host_class_hid_activate_wait(UX_HOST_CLASS_COMMAND *command);
46
#endif
47
48
49
/**************************************************************************/
50
/*                                                                        */
51
/*  FUNCTION                                               RELEASE        */
52
/*                                                                        */
53
/*    _ux_host_class_hid_entry                            PORTABLE C      */
54
/*                                                           6.1.12       */
55
/*  AUTHOR                                                                */
56
/*                                                                        */
57
/*    Chaoqiong Xiao, Microsoft Corporation                               */
58
/*                                                                        */
59
/*  DESCRIPTION                                                           */
60
/*                                                                        */
61
/*    This function is the entry point of the HID class. It will be       */
62
/*    called by the USB stack enumeration module when there is a new      */
63
/*    device on the bus or when there is a device extraction.             */
64
/*                                                                        */
65
/*  INPUT                                                                 */
66
/*                                                                        */
67
/*    command                               Pointer to command            */
68
/*                                                                        */
69
/*  OUTPUT                                                                */
70
/*                                                                        */
71
/*    Completion Status                                                   */
72
/*                                                                        */
73
/*  CALLS                                                                 */
74
/*                                                                        */
75
/*    _ux_host_class_hid_activate           Activate HID class            */
76
/*    _ux_host_class_hid_deactivate         Deactivate HID class          */
77
/*    _ux_utility_memory_free               Free memory                   */
78
/*                                                                        */
79
/*  CALLED BY                                                             */
80
/*                                                                        */
81
/*    Application                                                         */
82
/*    HID Class                                                           */
83
/*                                                                        */
84
/**************************************************************************/
85
2362
UINT  _ux_host_class_hid_entry(UX_HOST_CLASS_COMMAND *command)
86
{
87
88
UINT                                status;
89
INT                                 scan_index;
90
UX_HOST_CLASS_HID_CLIENT            *client;
91
UX_HOST_CLASS_HID_CLIENT_COMMAND    client_command;
92
93
94
    /* The command request will tell us we need to do here, either a enumeration
95
       query, an activation or a deactivation.  */
96

2362
    switch (command -> ux_host_class_command_request)
97
    {
98
99
1478
    case UX_HOST_CLASS_COMMAND_QUERY:
100
101
        /* The query command is used to let the stack enumeration process know if we want to own
102
           this device or not.  */
103
1478
        if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) &&
104
726
            (command -> ux_host_class_command_class == UX_HOST_CLASS_HID_CLASS))
105
718
            return(UX_SUCCESS);
106
        else
107
760
            return(UX_NO_CLASS_MATCH);
108
109
110
712
    case UX_HOST_CLASS_COMMAND_ACTIVATE:
111
112
        /* The activate command is used when the device inserted has found a parent and
113
           is ready to complete the enumeration.   */
114
115
712
        status =  _ux_host_class_hid_activate(command);
116
712
        return(status);
117
118
119
#if defined(UX_HOST_STANDALONE)
120
    case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT:
121
        status = _ux_host_class_hid_activate_wait(command);
122
        return(status);
123
#endif
124
125
126
167
    case UX_HOST_CLASS_COMMAND_DEACTIVATE:
127
128
        /* The deactivate command is used when the device has been extracted either
129
           directly or when its parents has been extracted.  */
130
131
167
        status =  _ux_host_class_hid_deactivate(command);
132
167
        return(status);
133
134
4
    case UX_HOST_CLASS_COMMAND_DESTROY:
135
136
        /* The destroy command is used when the class is unregistered.  */
137
138
        /* Free allocated resources for clients.  */
139
4
        if (command -> ux_host_class_command_class_ptr -> ux_host_class_client != UX_NULL)
140
        {
141
142
            /* Get client.  */
143
3
            client = command -> ux_host_class_command_class_ptr -> ux_host_class_client;
144
145
            /* Inform clients for destroy.  */
146
27
            for (scan_index = 0; scan_index < UX_HOST_CLASS_HID_MAX_CLIENTS; scan_index ++)
147
            {
148
149
                /* Inform client for destroy.  */
150
24
                client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_DESTROY;
151
24
                client_command.ux_host_class_hid_client_command_container = (VOID *)command -> ux_host_class_command_class_ptr;
152
24
                client -> ux_host_class_hid_client_handler(&client_command);
153
            }
154
155
            /* Free clients memory.  */
156
3
            _ux_utility_memory_free(command -> ux_host_class_command_class_ptr -> ux_host_class_client);
157
3
            command -> ux_host_class_command_class_ptr -> ux_host_class_client = UX_NULL;
158
        }
159
4
        return(UX_SUCCESS);
160
161
1
    default:
162
163
        /* Error trap. */
164
1
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED);
165
166
        /* If trace is enabled, insert this event into the trace buffer.  */
167
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
168
169
        /* Return error status.  */
170
1
        return(UX_FUNCTION_NOT_SUPPORTED);
171
    }
172
}
173
174
#if defined(UX_HOST_STANDALONE)
175
static inline VOID _ux_host_class_hid_descriptor_read(UX_HOST_CLASS_HID *hid)
176
{
177
UX_INTERFACE                    *interface_ptr;
178
UX_CONFIGURATION                *configuration;
179
UX_ENDPOINT                     *control_endpoint;
180
UX_TRANSFER                     *transfer_request;
181
182
    /* We need to get the default control endpoint transfer request pointer.  */
183
    control_endpoint =  &hid -> ux_host_class_hid_device -> ux_device_control_endpoint;
184
    transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
185
186
    /* Need to allocate memory for the descriptor.  */
187
    interface_ptr = hid -> ux_host_class_hid_interface;
188
    configuration = interface_ptr -> ux_interface_configuration;
189
    hid -> ux_host_class_hid_allocated = _ux_utility_memory_allocate(
190
                    UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY,
191
                    configuration -> ux_configuration_descriptor.wTotalLength);
192
    if (hid -> ux_host_class_hid_allocated == UX_NULL)
193
    {
194
195
        /* Next: error.  */
196
        hid -> ux_host_class_hid_status = UX_MEMORY_INSUFFICIENT;
197
        hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR;
198
        return;
199
    }
200
201
    /* Create a transfer request for the GET_DESCRIPTOR request.  */
202
    transfer_request -> ux_transfer_request_data_pointer =      hid -> ux_host_class_hid_allocated;
203
    transfer_request -> ux_transfer_request_requested_length =  configuration -> ux_configuration_descriptor.wTotalLength;
204
    transfer_request -> ux_transfer_request_function =          UX_GET_DESCRIPTOR;
205
    transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
206
    transfer_request -> ux_transfer_request_value =             UX_CONFIGURATION_DESCRIPTOR_ITEM << 8;
207
    transfer_request -> ux_transfer_request_index =             0;
208
    UX_TRANSFER_STATE_RESET(transfer_request);
209
210
    /* Next: transfer and parse.  */
211
    hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT;
212
    hid -> ux_host_class_hid_next_state = UX_HOST_CLASS_HID_ENUM_HID_DESC_PARSE;
213
}
214
static inline VOID _ux_host_class_hid_report_descriptor_read(UX_HOST_CLASS_HID *hid)
215
{
216
UX_ENDPOINT                     *control_endpoint;
217
UX_TRANSFER                     *transfer_request;
218
219
    /* We need to get the default control endpoint transfer request pointer.  */
220
    control_endpoint =  &hid -> ux_host_class_hid_device -> ux_device_control_endpoint;
221
    transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
222
223
    /* Need to allocate memory for the descriptor.  */
224
    hid -> ux_host_class_hid_allocated = _ux_utility_memory_allocate(
225
                    UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY,
226
                    hid -> ux_host_class_hid_descriptor.wItemLength);
227
    if (hid -> ux_host_class_hid_allocated == UX_NULL)
228
    {
229
230
        /* Next: error.  */
231
        hid -> ux_host_class_hid_status = UX_MEMORY_INSUFFICIENT;
232
        hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR;
233
        return;
234
    }
235
236
    /* Create a transfer request for the GET_DESCRIPTOR request.  */
237
    transfer_request -> ux_transfer_request_data_pointer =      hid -> ux_host_class_hid_allocated;
238
    transfer_request -> ux_transfer_request_requested_length =  hid -> ux_host_class_hid_descriptor.wItemLength;
239
    transfer_request -> ux_transfer_request_function =          UX_GET_DESCRIPTOR;
240
    transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_INTERFACE;
241
    transfer_request -> ux_transfer_request_value =             UX_HOST_CLASS_HID_REPORT_DESCRIPTOR << 8;
242
    transfer_request -> ux_transfer_request_index =             hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber;
243
    UX_TRANSFER_STATE_RESET(transfer_request);
244
245
    /* Next: transfer and parse.  */
246
    hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT;
247
    hid -> ux_host_class_hid_next_state = UX_HOST_CLASS_HID_ENUM_REPORT_DESC_PARSE;
248
}
249
static inline VOID _ux_host_class_hid_hid_descriptor_parse(UX_HOST_CLASS_HID *hid)
250
{
251
UX_DEVICE                       *device;
252
UX_TRANSFER                     *transfer;
253
UCHAR                           *descriptor;
254
UINT                            descriptor_length;
255
UINT                            descriptor_type;
256
UINT                            descriptor_2;
257
ULONG                           total_length;
258
ULONG                           interface_number;
259
UINT                            interface_found = UX_FALSE;
260
261
    /* Get transfer.  */
262
    device = hid -> ux_host_class_hid_device;
263
    transfer = &device -> ux_device_control_endpoint.ux_endpoint_transfer_request;
264
265
    /* Get current interface number.  */
266
    interface_number = hid -> ux_host_class_hid_interface ->
267
                                    ux_interface_descriptor.bInterfaceNumber;
268
269
    /* Get received descriptor.  */
270
    descriptor = transfer -> ux_transfer_request_data_pointer;
271
    total_length = transfer -> ux_transfer_request_actual_length;
272
273
    /* The HID descriptor is embedded within the configuration descriptor.
274
        We parse the entire descriptor to locate the HID portion.  */
275
    while(total_length)
276
    {
277
278
        /* Get length and type of the descriptor.  */
279
        descriptor_length = *descriptor;
280
        descriptor_type   = *(descriptor + 1);
281
        descriptor_2      = *(descriptor + 2);
282
283
        /* Make sure this descriptor has at least the minimum length.  */
284
        if (descriptor_length < 3)
285
            break;
286
287
        switch(descriptor_type)
288
        {
289
        case UX_INTERFACE_DESCRIPTOR_ITEM:
290
291
            /* Check if interface is what we expected.  */
292
            interface_found = (interface_number == descriptor_2) ? UX_TRUE : UX_FALSE;
293
            break;
294
295
        case UX_HOST_CLASS_HID_DESCRIPTOR:
296
297
            /* Check if we are in expected interface.  */
298
            if (!interface_found)
299
                break;
300
301
            /* Save HID descriptor for later usage.
302
                Note only first 7 entries are saved, since we only support first
303
                9 bytes, no optional descriptors are supported for now. */
304
            _ux_utility_descriptor_parse(descriptor,
305
                _ux_system_hid_descriptor_structure, UX_HID_DESCRIPTOR_ENTRIES,
306
                (UCHAR *) &hid -> ux_host_class_hid_descriptor);
307
308
            /* Free allocated bytes.  */
309
            _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
310
            hid -> ux_host_class_hid_allocated = UX_NULL;
311
312
            /* Next: HID report descriptor read.  */
313
            hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_REPORT_DESC_READ;
314
            return;
315
316
        default:
317
            break;
318
        }
319
320
        /* Verify if the descriptor is still valid.  */
321
        if (descriptor_length > total_length)
322
            break;
323
324
        /* Next descriptor.  */
325
        descriptor += descriptor_length;
326
        total_length -= descriptor_length;
327
    }
328
329
    /* Error trap. */
330
    _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED);
331
332
    /* If trace is enabled, insert this event into the trace buffer.  */
333
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
334
335
    /* Return an error.  */
336
    hid -> ux_host_class_hid_status = UX_DESCRIPTOR_CORRUPTED;
337
    hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR;
338
}
339
static inline VOID _ux_host_class_hid_report_descriptor_parse(UX_HOST_CLASS_HID *hid)
340
{
341
UX_DEVICE               *device;
342
UX_TRANSFER             *transfer;
343
UCHAR                   *descriptor;
344
ULONG                   length;
345
UX_HOST_CLASS_HID_ITEM  item;
346
UINT                    status = UX_SUCCESS;
347
348
    /* Get transfer.  */
349
    device = hid -> ux_host_class_hid_device;
350
    transfer = &device -> ux_device_control_endpoint.ux_endpoint_transfer_request;
351
352
    /* Get buffer and length.  */
353
    descriptor = hid -> ux_host_class_hid_allocated;
354
    length = transfer -> ux_transfer_request_actual_length;
355
356
    /* Parse the report descriptor and build the report items.  */
357
    while (length)
358
    {
359
360
        /* Get one item from the report and analyze it.  */
361
        _ux_host_class_hid_report_item_analyse(descriptor, length, &item);
362
363
        /* Point the descriptor right after the item identifier.  */
364
        descriptor +=  item.ux_host_class_hid_item_report_format;
365
366
        /* Process relative to the item type.  */
367
        switch (item.ux_host_class_hid_item_report_type)
368
        {
369
370
        case UX_HOST_CLASS_HID_TYPE_GLOBAL:
371
372
            /* This is a global item.  */
373
            status =  _ux_host_class_hid_global_item_parse(hid, &item, descriptor);
374
            break;
375
376
377
        case UX_HOST_CLASS_HID_TYPE_MAIN:
378
379
            /* This is a main item.  */
380
            status =  _ux_host_class_hid_main_item_parse(hid, &item, descriptor);
381
            break;
382
383
384
        case UX_HOST_CLASS_HID_TYPE_LOCAL:
385
386
            /* This is a local item.  */
387
            status =  _ux_host_class_hid_local_item_parse(hid, &item, descriptor);
388
            break;
389
390
        default:
391
392
            /* This is a reserved item, meaning it shouldn't be used!  */
393
394
            /* Set status to error. The check after this switch statement
395
                will handle the rest.  */
396
            status =  UX_DESCRIPTOR_CORRUPTED;
397
            break;
398
        }
399
400
        /* Recheck the status code.  */
401
        if (status != UX_SUCCESS)
402
        {
403
            break;
404
        }
405
406
        /* Jump to the next item.  */
407
        descriptor +=  item.ux_host_class_hid_item_report_length;
408
409
        /* Verify that the report descriptor is not corrupted.  */
410
        if (length < item.ux_host_class_hid_item_report_length)
411
        {
412
413
            /* Return error status.  */
414
            status = (UX_DESCRIPTOR_CORRUPTED);
415
            break;
416
        }
417
418
        /* Adjust the length.  */
419
        length -=  (ULONG)(item.ux_host_class_hid_item_report_length + item.ux_host_class_hid_item_report_format);
420
    }
421
422
    if (status != UX_SUCCESS)
423
    {
424
        hid -> ux_host_class_hid_status = status;
425
        hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR;
426
        return;
427
    }
428
429
    /* Search the HID interrupt endpoint.  */
430
    status = _ux_host_class_hid_interrupt_endpoint_search(hid);
431
    if (status != UX_SUCCESS)
432
    {
433
        hid -> ux_host_class_hid_status = status;
434
        hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR;
435
        return;
436
    }
437
438
    /* Allocated memory is no use now, free.  */
439
    _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
440
    hid -> ux_host_class_hid_allocated = UX_NULL;
441
442
    /* Next: search & activate client.  */
443
    hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_CLIENT_SEARCH;
444
}
445
static inline VOID _ux_host_class_hid_client_activate_wait(UX_HOST_CLASS_HID *hid)
446
{
447
UX_HOST_CLASS_HID_CLIENT_COMMAND    hid_client_command;
448
UINT                                status;
449
450
    hid_client_command.ux_host_class_hid_client_command_instance =   hid;
451
    hid_client_command.ux_host_class_hid_client_command_request =    UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT;
452
453
    /* Call the HID client with an activate command.  */
454
    status = hid -> ux_host_class_hid_client -> ux_host_class_hid_client_handler(&hid_client_command);
455
456
    /* Error.  */
457
    if (status < UX_STATE_NEXT)
458
    {
459
        hid -> ux_host_class_hid_client = UX_NULL;
460
        hid -> ux_host_class_hid_status = UX_DEVICE_ENUMERATION_FAILURE;
461
        hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR;
462
        return;
463
    }
464
465
    /* Success.  */
466
    if (status == UX_STATE_NEXT)
467
    {
468
        hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_DONE;
469
        return;
470
    }
471
472
    /* Wait.  */
473
    return;
474
}
475
static inline UINT _ux_host_class_hid_activate_wait(UX_HOST_CLASS_COMMAND *command)
476
{
477
478
UX_INTERFACE            *interface_ptr;
479
UX_ENDPOINT             *control_endpoint;
480
UX_TRANSFER             *transfer;
481
UX_HOST_CLASS_HID       *hid;
482
UINT                    status;
483
484
    /* Get the instance for this class.  */
485
    interface_ptr = (UX_INTERFACE *)command -> ux_host_class_command_container;
486
    hid =  (UX_HOST_CLASS_HID *) interface_ptr -> ux_interface_class_instance;
487
488
    /* Run initialize state machine.  */
489
    switch(hid -> ux_host_class_hid_enum_state)
490
    {
491
    case UX_HOST_CLASS_HID_ENUM_HID_DESC_READ            :
492
        _ux_host_class_hid_descriptor_read(hid);
493
        break;
494
495
    case UX_HOST_CLASS_HID_ENUM_HID_DESC_PARSE           :
496
        _ux_host_class_hid_hid_descriptor_parse(hid);
497
        break;
498
499
    case UX_HOST_CLASS_HID_ENUM_REPORT_DESC_READ         :
500
        _ux_host_class_hid_report_descriptor_read(hid);
501
        break;
502
503
    case UX_HOST_CLASS_HID_ENUM_REPORT_DESC_PARSE        :
504
        _ux_host_class_hid_report_descriptor_parse(hid);
505
        break;
506
507
    case UX_HOST_CLASS_HID_ENUM_CLIENT_SEARCH            :
508
509
        /* Search and activate client.  */
510
        status = _ux_host_class_hid_client_search(hid);
511
        if (status != UX_SUCCESS)
512
        {
513
514
            /* There is no client, but HID can still be used.  */
515
            hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_DONE;
516
            break;
517
        }
518
519
        /* Activate wait in case there is still steps for client.  */
520
        hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_CLIENT_ACTIVATE_WAIT;
521
522
        /* Fall through.  */
523
    case UX_HOST_CLASS_HID_ENUM_CLIENT_ACTIVATE_WAIT     :
524
        _ux_host_class_hid_client_activate_wait(hid);
525
        break;
526
527
    case UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT            :
528
529
        /* Get transfer.  */
530
        control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint;
531
        transfer = &control_endpoint -> ux_endpoint_transfer_request;
532
533
        /* Transfer state machine.  */
534
        status = _ux_host_stack_transfer_run(transfer);
535
536
        /* Is it done?  */
537
        if (status <= UX_STATE_NEXT)
538
        {
539
540
            /* Is there error?  */
541
            if (transfer -> ux_transfer_request_completion_code != UX_SUCCESS)
542
            {
543
                hid -> ux_host_class_hid_status = transfer -> ux_transfer_request_completion_code;
544
                hid -> ux_host_class_hid_enum_state = UX_STATE_EXIT;
545
                break;
546
            }
547
548
            /* No error, next state.  */
549
            hid -> ux_host_class_hid_enum_state = hid -> ux_host_class_hid_next_state;
550
            break;
551
        }
552
553
        /* Keep waiting.  */
554
        break;
555
556
    case UX_HOST_CLASS_HID_ENUM_ERROR                    :
557
558
        /* Clean interrupt endpoint.  */
559
        if (hid -> ux_host_class_hid_interrupt_endpoint &&
560
            hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer)
561
            _ux_utility_memory_free(hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
562
563
        /* Clean instance. */
564
        _ux_host_class_hid_instance_clean(hid);
565
566
        /* Error, destroy the class instance and return error code. */
567
        _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid);
568
569
        /* Unmount instance. */
570
        interface_ptr -> ux_interface_class_instance = UX_NULL;
571
572
        /* Free memory.  */
573
        if (hid -> ux_host_class_hid_allocated)
574
            _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
575
576
        /* Free instance. */
577
        _ux_utility_memory_free(hid);
578
        return(UX_STATE_NEXT);
579
580
    case UX_HOST_CLASS_HID_ENUM_DONE                     :
581
582
        /* Free temperary memory.  */
583
        if (hid -> ux_host_class_hid_allocated)
584
        {
585
            _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
586
            hid -> ux_host_class_hid_allocated = UX_NULL;
587
        }
588
589
        /* Mark the HID class as live now.  */
590
        hid -> ux_host_class_hid_state =  UX_HOST_CLASS_INSTANCE_LIVE;
591
592
        /* We may need to inform the application if a function has been programmed in the system structure.  */
593
        if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
594
        {
595
596
            /* Call system change function.  */
597
            _ux_system_host ->  ux_system_host_change_function(UX_DEVICE_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid);
598
        }
599
600
        /* If trace is enabled, insert this event into the trace buffer.  */
601
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_ACTIVATE, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
602
603
        /* If trace is enabled, register this object.  */
604
        UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, hid, 0, 0, 0)
605
606
        hid -> ux_host_class_hid_enum_state = UX_STATE_IDLE;
607
        return(UX_STATE_NEXT);
608
609
    default: /* IDLE, Other states.  */
610
        return(UX_STATE_NEXT);
611
    }
612
613
    /* By default, keep waiting.  */
614
    return(UX_STATE_WAIT);
615
}
616
#endif