GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_cdc_acm_entry.c Lines: 25 25 100.0 %
Date: 2026-03-06 18:57:10 Branches: 24 24 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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
/**************************************************************************/
89
632
UINT  _ux_host_class_cdc_acm_entry(UX_HOST_CLASS_COMMAND *command)
90
{
91
92
UINT    status;
93
94
95
    /* The command request will tell us we need to do here, either a enumeration
96
       query, an activation or a deactivation.  */
97

632
    switch (command -> ux_host_class_command_request)
98
    {
99
100
363
    case UX_HOST_CLASS_COMMAND_QUERY:
101
102
        /* The query command is used to let the stack enumeration process know if we want to own
103
           this device or not.  */
104
363
        if((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) &&
105
187
                             ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_DATA_CLASS) ||
106
95
                             ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) &&
107
92
                             (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_ACM_SUBCLASS)) ||
108
7
                             ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) &&
109
4
                             (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_DLC_SUBCLASS))))
110
        {
111
            /* Check for IAD presence.  */
112

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