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