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 /** Acm Cdc 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_cdc_acm.h"
30 #include "ux_host_stack.h"
31
32
33 #if defined(UX_HOST_STANDALONE)
34 #define UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT (UX_STATE_WAIT)
35 #define UX_HOST_CLASS_CDC_ACM_INIT_DESCRIPTORS_PARSE (UX_STATE_NEXT)
36
37 #define UX_HOST_CLASS_CDC_ACM_INIT_DELAY_WAIT (UX_STATE_CLASS_STEP + 0)
38 #define UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_SET (UX_STATE_CLASS_STEP + 1)
39 #define UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_GET (UX_STATE_CLASS_STEP + 2)
40 #define UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_CHECK (UX_STATE_CLASS_STEP + 3)
41 #define UX_HOST_CLASS_CDC_ACM_INIT_LINE_STATE_SET (UX_STATE_CLASS_STEP + 4)
42 #define UX_HOST_CLASS_CDC_ACM_INIT_ERROR (UX_STATE_CLASS_STEP + 5)
43 #define UX_HOST_CLASS_CDC_ACM_INIT_DONE (UX_STATE_CLASS_STEP + 6)
44
45
46 static inline UINT _ux_host_class_cdc_acm_activate_wait(UX_HOST_CLASS_COMMAND *command);
47 #endif
48
49
50 /**************************************************************************/
51 /* */
52 /* FUNCTION RELEASE */
53 /* */
54 /* _ux_host_class_cdc_acm_entry PORTABLE C */
55 /* 6.1.12 */
56 /* AUTHOR */
57 /* */
58 /* Chaoqiong Xiao, Microsoft Corporation */
59 /* */
60 /* DESCRIPTION */
61 /* */
62 /* This function is the entry point of the cdc_acm class. It will be */
63 /* called by the USBX stack enumeration module when there is a new */
64 /* cdc_acm on the bus or when the USB cdc_acm is removed. */
65 /* */
66 /* A CDC class can have multiple interfaces, one for Control and one */
67 /* for Data. Here we filter for the Communication Class with ACM */
68 /* subclass and the Communication Data Class. */
69 /* */
70 /* */
71 /* INPUT */
72 /* */
73 /* command Acm Cdc class command */
74 /* */
75 /* OUTPUT */
76 /* */
77 /* Completion Status */
78 /* */
79 /* CALLS */
80 /* */
81 /* _ux_host_class_cdc_acm_activate Activate cdc_acm class */
82 /* _ux_host_class_cdc_acm_deactivate Deactivate cdc_acm class */
83 /* */
84 /* CALLED BY */
85 /* */
86 /* Acm Cdc Class */
87 /* */
88 /* RELEASE HISTORY */
89 /* */
90 /* DATE NAME DESCRIPTION */
91 /* */
92 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
93 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
94 /* resulting in version 6.1 */
95 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
96 /* added standalone support, */
97 /* resulting in version 6.1.10 */
98 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
99 /* fixed parameter/variable */
100 /* names conflict C++ keyword, */
101 /* resulting in version 6.1.12 */
102 /* */
103 /**************************************************************************/
_ux_host_class_cdc_acm_entry(UX_HOST_CLASS_COMMAND * command)104 UINT _ux_host_class_cdc_acm_entry(UX_HOST_CLASS_COMMAND *command)
105 {
106
107 UINT status;
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_CDC_DATA_CLASS) ||
121 ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) &&
122 (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_ACM_SUBCLASS)) ||
123 ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) &&
124 (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_DLC_SUBCLASS))))
125 {
126 /* Check for IAD presence. */
127 if ((command -> ux_host_class_command_iad_class == 0) && (command -> ux_host_class_command_iad_subclass == 0))
128
129 /* No IAD, we accept this class. */
130 return(UX_SUCCESS);
131
132 else
133 {
134
135 if ((command -> ux_host_class_command_iad_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) &&
136 (command -> ux_host_class_command_iad_subclass == UX_HOST_CLASS_CDC_ACM_SUBCLASS))
137
138 /* There is an IAD and this is for CDC-ACM. */
139 return(UX_SUCCESS);
140
141 else
142
143 /* The IAD does not match with CDC-ACM. */
144 return(UX_NO_CLASS_MATCH);
145 }
146 }
147
148 else
149
150 /* No match. */
151 return(UX_NO_CLASS_MATCH);
152
153 case UX_HOST_CLASS_COMMAND_ACTIVATE:
154
155 /* The activate command is used when the device inserted has found a parent and
156 is ready to complete the enumeration. */
157 status = _ux_host_class_cdc_acm_activate(command);
158 return(status);
159
160 #if defined(UX_HOST_STANDALONE)
161 case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT:
162 status = _ux_host_class_cdc_acm_activate_wait(command);
163 return(status);
164 #endif
165
166 case UX_HOST_CLASS_COMMAND_DEACTIVATE:
167
168 /* The deactivate command is used when the device has been extracted either
169 directly or when its parents has been extracted. */
170 status = _ux_host_class_cdc_acm_deactivate(command);
171 return(status);
172
173 default:
174
175 /* Error trap. */
176 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED);
177
178 /* If trace is enabled, insert this event into the trace buffer. */
179 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
180
181 return(UX_FUNCTION_NOT_SUPPORTED);
182 }
183 }
184
185 #if defined(UX_HOST_STANDALONE)
_ux_host_class_cdc_acm_descriptors_parse(UX_HOST_CLASS_CDC_ACM * cdc_acm)186 static inline VOID _ux_host_class_cdc_acm_descriptors_parse(UX_HOST_CLASS_CDC_ACM *cdc_acm)
187 {
188
189 UX_ENDPOINT *control_endpoint;
190 UX_TRANSFER *transfer_request;
191 UX_INTERFACE *interface_ptr;
192 UCHAR *descriptor;
193 ULONG total_descriptor_length;
194 UCHAR descriptor_length;
195 UCHAR descriptor_type;
196 UCHAR descriptor_byte2;
197 ULONG interface_found;
198 ULONG interface_parsed;
199 UCHAR offset;
200
201 /* We need to get the default control endpoint transfer request pointer. */
202 control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_control_endpoint;
203 transfer_request = &control_endpoint -> ux_endpoint_transfer_request;
204
205 /* Check if transfer is done success. */
206 if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS ||
207 transfer_request -> ux_transfer_request_actual_length !=
208 transfer_request -> ux_transfer_request_requested_length)
209 {
210 cdc_acm -> ux_host_class_cdc_acm_status = UX_DESCRIPTOR_CORRUPTED;
211 cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_HOST_CLASS_CDC_ACM_INIT_ERROR;
212 return;
213 }
214
215 /* Get the interface. */
216 interface_ptr = cdc_acm -> ux_host_class_cdc_acm_interface;
217
218 /* Parse the descriptor. */
219 total_descriptor_length = transfer_request -> ux_transfer_request_actual_length;
220 descriptor = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated;
221 interface_found = UX_FALSE;
222 interface_parsed = UX_FALSE;
223
224 while(total_descriptor_length)
225 {
226
227 /* Get descriptor length, type, subtype. */
228 descriptor_length = *descriptor;
229 descriptor_type = *(descriptor + 1);
230 descriptor_byte2 = *(descriptor + 2);
231
232 /* Make sure this descriptor has at least the minimum length. */
233 if (descriptor_length < 3 || descriptor_length > total_descriptor_length)
234 {
235 /* Descriptor is corrupted. */
236 break;
237 }
238
239 /* Process related descriptors. */
240 switch(descriptor_type)
241 {
242 case UX_INTERFACE_DESCRIPTOR_ITEM:
243
244 /* Check if interface is what we expected. */
245 if (interface_ptr -> ux_interface_descriptor.bInterfaceNumber == descriptor_byte2)
246 {
247
248 /* Mark found. */
249 interface_found = UX_TRUE;
250 }
251 else
252 {
253
254 /* Run out of expected interface. */
255 if (interface_found)
256 {
257
258 interface_parsed = UX_TRUE;
259 }
260 }
261 break;
262
263 case UX_HOST_CLASS_CDC_ACM_CS_INTERFACE:
264
265 /* Check if we are in correct interface. */
266 if (interface_found)
267 {
268
269 /* Check bDescriptorSubType. */
270 switch(descriptor_byte2)
271 {
272 case UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_DESCRIPTOR:
273
274 /* Store capabilities. */
275 cdc_acm -> ux_host_class_cdc_acm_capabilities =
276 *(descriptor + UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_CAPABILITIES);
277 break;
278
279 case UX_HOST_CLASS_CDC_ACM_UNION_DESCRIPTOR:
280
281 /* Check related interfaces. */
282 for (offset = UX_HOST_CLASS_CDC_ACM_UNION_FUNCTIONAL_MASTER;
283 offset < descriptor_length;
284 offset ++)
285 {
286
287 /* Save the interface in interface bitmap. */
288 cdc_acm -> ux_host_class_cdc_acm_interfaces_bitmap |=
289 1u << *(descriptor + offset);
290 }
291 break;
292
293 default:
294 break;
295 }
296 }
297 break;
298
299 default:
300 break;
301 }
302
303 /* Next descriptor. */
304 descriptor += descriptor_length;
305 total_descriptor_length -= descriptor_length;
306 }
307
308 /* We can free the resource now. */
309 _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_allocated);
310 cdc_acm -> ux_host_class_cdc_acm_allocated = UX_NULL;
311
312 /* Descriptor fail. */
313 if (interface_parsed == UX_FALSE)
314 {
315
316 /* Error trap. */
317 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED);
318
319 /* If trace is enabled, insert this event into the trace buffer. */
320 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
321
322 /* Descriptor is corrupted. */
323 cdc_acm -> ux_host_class_cdc_acm_status = UX_DESCRIPTOR_CORRUPTED;
324 cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_HOST_CLASS_CDC_ACM_INIT_ERROR;
325 return;
326 }
327
328 /* Descriptor is parsed. */
329 cdc_acm -> ux_host_class_cdc_acm_tick = _ux_utility_time_get();
330 cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_HOST_CLASS_CDC_ACM_INIT_DELAY_WAIT;
331 }
332
_ux_host_class_cdc_acm_activate_wait(UX_HOST_CLASS_COMMAND * command)333 static inline UINT _ux_host_class_cdc_acm_activate_wait(UX_HOST_CLASS_COMMAND *command)
334 {
335
336 UX_HOST_CLASS *cdc_acm_class;
337 UX_HOST_CLASS_CDC_ACM *cdc_acm_inst;
338 UX_INTERFACE *interface_ptr;
339 UX_HOST_CLASS_CDC_ACM *cdc_acm;
340 UX_ENDPOINT *control_endpoint;
341 UX_TRANSFER *transfer;
342 UCHAR *buffer;
343 ULONG rate, stop_bit, parity, data_bit;
344 UINT status;
345 ULONG tick, diff;
346
347 /* Get the instance for this class. */
348 interface_ptr = (UX_INTERFACE *)command -> ux_host_class_command_container;
349 cdc_acm = (UX_HOST_CLASS_CDC_ACM *) interface_ptr -> ux_interface_class_instance;
350
351 /* Run initialize state machine. */
352 switch(cdc_acm -> ux_host_class_cdc_acm_cmd_state)
353 {
354 case UX_HOST_CLASS_CDC_ACM_INIT_DESCRIPTORS_PARSE:
355 _ux_host_class_cdc_acm_descriptors_parse(cdc_acm);
356 break;
357
358 case UX_HOST_CLASS_CDC_ACM_INIT_DELAY_WAIT:
359 tick = _ux_utility_time_get();
360 diff = _ux_utility_time_elapsed(cdc_acm -> ux_host_class_cdc_acm_tick, tick);
361 if (diff > UX_MS_TO_TICK(UX_HOST_CLASS_CDC_ACM_DEVICE_INIT_DELAY))
362 {
363 /* Allocate some buffer for commands. */
364 cdc_acm -> ux_host_class_cdc_acm_allocated =
365 _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY,
366 8);
367
368 if (cdc_acm -> ux_host_class_cdc_acm_allocated == UX_NULL)
369 {
370 cdc_acm -> ux_host_class_cdc_acm_status = UX_MEMORY_INSUFFICIENT;
371 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
372 UX_HOST_CLASS_CDC_ACM_INIT_ERROR;
373 break;
374 }
375 control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device ->
376 ux_device_control_endpoint;
377 transfer = &control_endpoint -> ux_endpoint_transfer_request;
378
379 /* Initialize transfer buffer. */
380 transfer -> ux_transfer_request_data_pointer = (UCHAR *)
381 cdc_acm -> ux_host_class_cdc_acm_allocated;
382
383 /* Initialize transfer flags. */
384 transfer -> ux_transfer_request_flags = 0;
385
386 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
387 UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_SET;
388 }
389 break;
390
391 case UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_SET:
392
393 /* Put line coding things in buffer. */
394 buffer = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated;
395 rate = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE;
396 stop_bit = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_STOP_BIT;
397 parity = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_PARITY;
398 data_bit = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT;
399 _ux_utility_long_put(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE, rate);
400 *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT) = (UCHAR)stop_bit;
401 *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY) = (UCHAR)parity;
402 *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT) = (UCHAR)data_bit;
403
404 status = _ux_host_class_cdc_acm_command(cdc_acm,
405 UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_CODING, 0,
406 buffer, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH);
407 if (status != UX_SUCCESS)
408 {
409 cdc_acm -> ux_host_class_cdc_acm_status = status;
410 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
411 UX_HOST_CLASS_CDC_ACM_INIT_ERROR;
412 break;
413 }
414 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
415 UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT;
416 cdc_acm -> ux_host_class_cdc_acm_next_state =
417 UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_GET;
418 break;
419
420 case UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_GET:
421
422 /* Get line coding things from device. */
423 buffer = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated;
424 status = _ux_host_class_cdc_acm_command(cdc_acm,
425 UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_CODING, 0,
426 buffer, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH);
427 if (status != UX_SUCCESS)
428 {
429 cdc_acm -> ux_host_class_cdc_acm_status = status;
430 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
431 UX_HOST_CLASS_CDC_ACM_INIT_ERROR;
432 break;
433 }
434 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
435 UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT;
436 cdc_acm -> ux_host_class_cdc_acm_next_state =
437 UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_CHECK;
438 break;
439
440 case UX_HOST_CLASS_CDC_ACM_INIT_LINE_CODING_CHECK:
441
442 /* Check line coding things in buffer. */
443 buffer = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated;
444 rate = _ux_utility_long_get(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE);
445 stop_bit = *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT);
446 parity = *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY);
447 data_bit = *(buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT);
448 if (rate != UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE ||
449 stop_bit != UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_STOP_BIT ||
450 parity != UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_PARITY ||
451 data_bit != UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT)
452 {
453 cdc_acm -> ux_host_class_cdc_acm_status = UX_DEVICE_ENUMERATION_FAILURE;
454 cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_HOST_CLASS_CDC_ACM_INIT_ERROR;
455 break;
456 }
457
458 /* Fall through. */
459 case UX_HOST_CLASS_CDC_ACM_INIT_LINE_STATE_SET:
460
461 /* Put line state things. */
462 buffer = (UCHAR *)cdc_acm -> ux_host_class_cdc_acm_allocated;
463 *(buffer) = UX_HOST_CLASS_CDC_ACM_CTRL_DTR | UX_HOST_CLASS_CDC_ACM_CTRL_RTS;
464 status = _ux_host_class_cdc_acm_command(cdc_acm,
465 UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_STATE,
466 *(buffer), UX_NULL, 0);
467 if (status != UX_SUCCESS)
468 {
469 cdc_acm -> ux_host_class_cdc_acm_status = status;
470 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
471 UX_HOST_CLASS_CDC_ACM_INIT_ERROR;
472 break;
473 }
474 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
475 UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT;
476 cdc_acm -> ux_host_class_cdc_acm_next_state =
477 UX_HOST_CLASS_CDC_ACM_INIT_DONE;
478 break;
479
480 case UX_HOST_CLASS_CDC_ACM_INIT_ERROR:
481 /* Fall through. */
482 case UX_HOST_CLASS_CDC_ACM_INIT_DONE:
483
484 /* Free allocated buffer. */
485 if (cdc_acm -> ux_host_class_cdc_acm_allocated)
486 {
487 _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_allocated);
488 cdc_acm -> ux_host_class_cdc_acm_allocated = UX_NULL;
489 }
490
491 /* Check status. */
492 if (cdc_acm -> ux_host_class_cdc_acm_status == UX_SUCCESS)
493 {
494
495 /* We scan CDC ACM instances to find the DATA instance. */
496 /* Get class. */
497 cdc_acm_class = cdc_acm -> ux_host_class_cdc_acm_class;
498
499 /* Get first instance linked to the class. */
500 cdc_acm_inst = (UX_HOST_CLASS_CDC_ACM *)cdc_acm_class -> ux_host_class_first_instance;
501
502 /* Scan all instances. */
503 while(cdc_acm_inst)
504 {
505
506 /* Get interface of the instance. */
507 interface_ptr = cdc_acm_inst -> ux_host_class_cdc_acm_interface;
508
509 /* If this data interface is inside the associate list, link it. */
510 if (cdc_acm -> ux_host_class_cdc_acm_interfaces_bitmap &
511 (1ul << interface_ptr -> ux_interface_descriptor.bInterfaceNumber))
512 {
513
514 /* Save control instance and we are done. */
515 cdc_acm_inst -> ux_host_class_cdc_acm_control = cdc_acm;
516 break;
517 }
518
519 /* Next instance. */
520 cdc_acm_inst = cdc_acm_inst -> ux_host_class_cdc_acm_next_instance;
521 }
522
523 /* Mark the cdc_acm as live now. Both interfaces need to be live. */
524 cdc_acm -> ux_host_class_cdc_acm_state = UX_HOST_CLASS_INSTANCE_LIVE;
525
526 /* If all is fine and the device is mounted, we may need to inform the application
527 if a function has been programmed in the system structure. */
528 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
529 {
530
531 /* Call system change function. */
532 _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm);
533 }
534
535 /* If trace is enabled, insert this event into the trace buffer. */
536 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_ACTIVATE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
537
538 /* If trace is enabled, register this object. */
539 UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, cdc_acm, 0, 0, 0)
540
541 /* Reset CMD state. */
542 cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_STATE_RESET;
543 }
544 else
545 {
546
547 /* On error case, it's possible data buffer allocated for interrupt endpoint and transfer started, stop and free it. */
548 if (cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint &&
549 cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer)
550 {
551
552 /* The first transfer request has already been initiated. Abort it. */
553 _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint);
554
555 /* Free the memory for the data pointer. */
556 _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
557 }
558
559 /* Destroy the instance. */
560 _ux_host_stack_class_instance_destroy(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm);
561
562 /* Unmount instance. */
563 interface_ptr = cdc_acm -> ux_host_class_cdc_acm_interface;
564 interface_ptr -> ux_interface_class_instance = UX_NULL;
565
566 /* Free instance. */
567 _ux_utility_memory_free(cdc_acm);
568 }
569
570 /* Done, OK to go on. */
571 return(UX_STATE_NEXT);
572
573 case UX_HOST_CLASS_CDC_ACM_INIT_TRANSFER_WAIT:
574
575 /* Get transfer. */
576 control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_control_endpoint;
577 transfer = &control_endpoint -> ux_endpoint_transfer_request;
578
579 /* Transfer state machine. */
580 status = _ux_host_stack_transfer_run(transfer);
581
582 /* Is it done? */
583 if (status <= UX_STATE_NEXT)
584 {
585
586 /* Is there error? */
587 if (transfer -> ux_transfer_request_completion_code != UX_SUCCESS)
588 {
589 cdc_acm -> ux_host_class_cdc_acm_cmd_state = UX_STATE_EXIT;
590 break;
591 }
592
593 /* No error, next state. */
594 cdc_acm -> ux_host_class_cdc_acm_cmd_state =
595 cdc_acm -> ux_host_class_cdc_acm_next_state;
596 break;
597 }
598
599 /* Keep waiting. */
600 break;
601
602 /* UX_STATE_RESET, UX_STATE_EXIT, UX_STATE_IDLE, ... */
603 default:
604
605 /* Do nothing. */
606 return(UX_STATE_NEXT);
607 }
608
609 /* Keep waiting. */
610 return(UX_STATE_WAIT);
611 }
612 #endif
613