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