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