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: 2024-12-12 17:16:36 Branches: 24 24 100.0 %

Line Branch Exec Source
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
/**************************************************************************/
103
632
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

632
    switch (command -> ux_host_class_command_request)
112
    {
113
114
363
    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
363
        if((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) &&
119
187
                             ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_DATA_CLASS) ||
120
95
                             ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) &&
121
92
                             (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_ACM_SUBCLASS)) ||
122
7
                             ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) &&
123
4
                             (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_DLC_SUBCLASS))))
124
        {
125
            /* Check for IAD presence.  */
126

182
            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
7
                return(UX_SUCCESS);
130
131
            else
132
            {
133
134
175
                if ((command -> ux_host_class_command_iad_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) &&
135
170
                        (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
168
                    return(UX_SUCCESS);
139
140
                else
141
142
                    /* The IAD does not match with CDC-ACM.  */
143
7
                    return(UX_NO_CLASS_MATCH);
144
            }
145
        }
146
147
        else
148
149
            /* No match.  */
150
181
            return(UX_NO_CLASS_MATCH);
151
152
171
    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
171
        status =  _ux_host_class_cdc_acm_activate(command);
157
170
        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
97
    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
97
        status =  _ux_host_class_cdc_acm_deactivate(command);
170
96
        return(status);
171
172
1
    default:
173
174
        /* Error trap. */
175
1
        _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
1
        return(UX_FUNCTION_NOT_SUPPORTED);
181
    }
182
}
183
184
#if defined(UX_HOST_STANDALONE)
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
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