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: 2024-12-12 17:16:36 Branches: 13 13 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 Class                                                           */
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_stack.h"
30
31
32
#if defined(UX_HOST_STANDALONE)
33
#define UX_HOST_CLASS_HID_ENUM_HID_DESC_READ            (UX_STATE_WAIT)
34
#define UX_HOST_CLASS_HID_ENUM_HID_DESC_PARSE           (UX_STATE_CLASS_STEP + 1)
35
#define UX_HOST_CLASS_HID_ENUM_REPORT_DESC_READ         (UX_STATE_CLASS_STEP + 2)
36
#define UX_HOST_CLASS_HID_ENUM_REPORT_DESC_PARSE        (UX_STATE_CLASS_STEP + 3)
37
#define UX_HOST_CLASS_HID_ENUM_CLIENT_SEARCH            (UX_STATE_CLASS_STEP + 4)
38
#define UX_HOST_CLASS_HID_ENUM_CLIENT_ACTIVATE_WAIT     (UX_STATE_CLASS_STEP + 6)
39
#define UX_HOST_CLASS_HID_ENUM_TRANSFER_WAIT            (UX_STATE_CLASS_STEP + 7)
40
#define UX_HOST_CLASS_HID_ENUM_ERROR                    (UX_STATE_CLASS_STEP + 8)
41
#define UX_HOST_CLASS_HID_ENUM_DONE                     (UX_STATE_CLASS_STEP + 9)
42
43
44
static inline UINT _ux_host_class_hid_activate_wait(UX_HOST_CLASS_COMMAND *command);
45
#endif
46
47
48
/**************************************************************************/
49
/*                                                                        */
50
/*  FUNCTION                                               RELEASE        */
51
/*                                                                        */
52
/*    _ux_host_class_hid_entry                            PORTABLE C      */
53
/*                                                           6.1.12       */
54
/*  AUTHOR                                                                */
55
/*                                                                        */
56
/*    Chaoqiong Xiao, Microsoft Corporation                               */
57
/*                                                                        */
58
/*  DESCRIPTION                                                           */
59
/*                                                                        */
60
/*    This function is the entry point of the HID class. It will be       */
61
/*    called by the USB stack enumeration module when there is a new      */
62
/*    device on the bus or when there is a device extraction.             */
63
/*                                                                        */
64
/*  INPUT                                                                 */
65
/*                                                                        */
66
/*    command                               Pointer to command            */
67
/*                                                                        */
68
/*  OUTPUT                                                                */
69
/*                                                                        */
70
/*    Completion Status                                                   */
71
/*                                                                        */
72
/*  CALLS                                                                 */
73
/*                                                                        */
74
/*    _ux_host_class_hid_activate           Activate HID class            */
75
/*    _ux_host_class_hid_deactivate         Deactivate HID class          */
76
/*    _ux_utility_memory_free               Free memory                   */
77
/*                                                                        */
78
/*  CALLED BY                                                             */
79
/*                                                                        */
80
/*    Application                                                         */
81
/*    HID Class                                                           */
82
/*                                                                        */
83
/*  RELEASE HISTORY                                                       */
84
/*                                                                        */
85
/*    DATE              NAME                      DESCRIPTION             */
86
/*                                                                        */
87
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
88
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
89
/*                                            added destroy command,      */
90
/*                                            resulting in version 6.1    */
91
/*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
92
/*                                            added standalone support,   */
93
/*                                            resulting in version 6.1.10 */
94
/*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
95
/*                                            fixed uninited variable,    */
96
/*                                            fixed parameter/variable    */
97
/*                                            names conflict C++ keyword, */
98
/*                                            resulting in version 6.1.12 */
99
/*                                                                        */
100
/**************************************************************************/
101
2362
UINT  _ux_host_class_hid_entry(UX_HOST_CLASS_COMMAND *command)
102
{
103
104
UINT                                status;
105
INT                                 scan_index;
106
UX_HOST_CLASS_HID_CLIENT            *client;
107
UX_HOST_CLASS_HID_CLIENT_COMMAND    client_command;
108
109
110
    /* The command request will tell us we need to do here, either a enumeration
111
       query, an activation or a deactivation.  */
112

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