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 /**************************************************************************/
_ux_host_class_hid_entry(UX_HOST_CLASS_COMMAND * command)101 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 switch (command -> ux_host_class_command_request)
113 {
114
115 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 if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) &&
120 (command -> ux_host_class_command_class == UX_HOST_CLASS_HID_CLASS))
121 return(UX_SUCCESS);
122 else
123 return(UX_NO_CLASS_MATCH);
124
125
126 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 status = _ux_host_class_hid_activate(command);
132 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 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 status = _ux_host_class_hid_deactivate(command);
148 return(status);
149
150 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 if (command -> ux_host_class_command_class_ptr -> ux_host_class_client != UX_NULL)
156 {
157
158 /* Get client. */
159 client = command -> ux_host_class_command_class_ptr -> ux_host_class_client;
160
161 /* Inform clients for destroy. */
162 for (scan_index = 0; scan_index < UX_HOST_CLASS_HID_MAX_CLIENTS; scan_index ++)
163 {
164
165 /* Inform client for destroy. */
166 client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_DESTROY;
167 client_command.ux_host_class_hid_client_command_container = (VOID *)command -> ux_host_class_command_class_ptr;
168 client -> ux_host_class_hid_client_handler(&client_command);
169 }
170
171 /* Free clients memory. */
172 _ux_utility_memory_free(command -> ux_host_class_command_class_ptr -> ux_host_class_client);
173 command -> ux_host_class_command_class_ptr -> ux_host_class_client = UX_NULL;
174 }
175 return(UX_SUCCESS);
176
177 default:
178
179 /* Error trap. */
180 _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 return(UX_FUNCTION_NOT_SUPPORTED);
187 }
188 }
189
190 #if defined(UX_HOST_STANDALONE)
_ux_host_class_hid_descriptor_read(UX_HOST_CLASS_HID * hid)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 }
_ux_host_class_hid_report_descriptor_read(UX_HOST_CLASS_HID * hid)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 }
_ux_host_class_hid_hid_descriptor_parse(UX_HOST_CLASS_HID * hid)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 }
_ux_host_class_hid_report_descriptor_parse(UX_HOST_CLASS_HID * hid)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 }
_ux_host_class_hid_client_activate_wait(UX_HOST_CLASS_HID * hid)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 }
_ux_host_class_hid_activate_wait(UX_HOST_CLASS_COMMAND * command)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
633