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