Skip to content

Commit fca7f26

Browse files
committed
Device CDC ACM support control class
1 parent 515c9a4 commit fca7f26

9 files changed

+292
-226
lines changed

common/usbx_device_classes/inc/ux_device_class_cdc_acm.h

Lines changed: 66 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,42 @@
11
/***************************************************************************
2-
* Copyright (c) 2024 Microsoft Corporation
3-
*
2+
* Copyright (c) 2024 Microsoft Corporation
3+
*
44
* This program and the accompanying materials are made available under the
55
* terms of the MIT License which is available at
66
* https://opensource.org/licenses/MIT.
7-
*
7+
*
88
* SPDX-License-Identifier: MIT
99
**************************************************************************/
1010

1111
/**************************************************************************/
1212
/**************************************************************************/
13-
/** */
14-
/** USBX Component */
13+
/** */
14+
/** USBX Component */
1515
/** */
1616
/** CDC Class */
1717
/** */
1818
/**************************************************************************/
1919
/**************************************************************************/
2020

21-
/**************************************************************************/
22-
/* */
23-
/* COMPONENT DEFINITION RELEASE */
24-
/* */
25-
/* ux_device_class_cdc_acm.h PORTABLE C */
21+
/**************************************************************************/
22+
/* */
23+
/* COMPONENT DEFINITION RELEASE */
24+
/* */
25+
/* ux_device_class_cdc_acm.h PORTABLE C */
2626
/* 6.3.0 */
2727
/* AUTHOR */
2828
/* */
2929
/* Chaoqiong Xiao, Microsoft Corporation */
3030
/* */
3131
/* DESCRIPTION */
32-
/* */
33-
/* This file defines the equivalences for the USBX Device Class CDC */
34-
/* ACM component. */
35-
/* */
36-
/* RELEASE HISTORY */
37-
/* */
38-
/* DATE NAME DESCRIPTION */
39-
/* */
32+
/* */
33+
/* This file defines the equivalences for the USBX Device Class CDC */
34+
/* ACM component. */
35+
/* */
36+
/* RELEASE HISTORY */
37+
/* */
38+
/* DATE NAME DESCRIPTION */
39+
/* */
4040
/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
4141
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
4242
/* used UX prefix to refer to */
@@ -69,15 +69,15 @@
6969
#ifndef UX_DEVICE_CLASS_CDC_ACM_H
7070
#define UX_DEVICE_CLASS_CDC_ACM_H
7171

72-
/* Determine if a C++ compiler is being used. If so, ensure that standard
73-
C is used to process the API information. */
72+
/* Determine if a C++ compiler is being used. If so, ensure that standard
73+
C is used to process the API information. */
7474

75-
#ifdef __cplusplus
75+
#ifdef __cplusplus
7676

77-
/* Yes, C++ compiler is present. Use standard C. */
78-
extern "C" {
77+
/* Yes, C++ compiler is present. Use standard C. */
78+
extern "C" {
7979

80-
#endif
80+
#endif
8181

8282
/* Internal option: enable the basic USBX error checking. This define is typically used
8383
while debugging application. */
@@ -89,6 +89,12 @@ extern "C" {
8989

9090
/* #define UX_DEVICE_CLASS_CDC_ACM_WRITE_AUTO_ZLP */
9191

92+
93+
/* Option: enable CDC ACM interrupt notifications (Serial State / Line State Change).
94+
When defined, the CDC ACM device class can send status notifications to the host
95+
via an Interrupt IN endpoint (if present in the interface). */
96+
/* #define UX_DEVICE_CLASS_CDC_ACM_ENABLE_NOTIFICATIONS */
97+
9298
/* Option: bulk out endpoint / read buffer size, must be larger than max packet size in framework, and aligned in 4-bytes. */
9399
#ifndef UX_DEVICE_CLASS_CDC_ACM_READ_BUFFER_SIZE
94100
#define UX_DEVICE_CLASS_CDC_ACM_READ_BUFFER_SIZE 512
@@ -116,7 +122,8 @@ extern "C" {
116122

117123

118124
/* Define CDC Class USB Class constants. */
119-
#define UX_SLAVE_CLASS_CDC_ACM_CLASS 10
125+
#define UX_SLAVE_CLASS_CDC_ACM_CONTROL_CLASS 0x02
126+
#define UX_SLAVE_CLASS_CDC_ACM_DATA_CLASS 0x0A
120127

121128
/* Device CDC Requests */
122129
#define UX_SLAVE_CLASS_CDC_ACM_SEND_ENCAPSULATED_COMMAND 0x00
@@ -172,6 +179,15 @@ extern "C" {
172179
#define UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_DTR 1
173180
#define UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_RTS 2
174181

182+
/* Define CDC ACM UART state bitmap (Serial State data). */
183+
#define UX_DEVICE_CLASS_CDC_ACM_UART_STATE_DCD 0x0001
184+
#define UX_DEVICE_CLASS_CDC_ACM_UART_STATE_DSR 0x0002
185+
#define UX_DEVICE_CLASS_CDC_ACM_UART_STATE_BREAK 0x0004
186+
#define UX_DEVICE_CLASS_CDC_ACM_UART_STATE_RING_SIGNAL 0x0008
187+
#define UX_DEVICE_CLASS_CDC_ACM_UART_STATE_FRAMING 0x0010
188+
#define UX_DEVICE_CLASS_CDC_ACM_UART_STATE_PARITY 0x0020
189+
#define UX_DEVICE_CLASS_CDC_ACM_UART_STATE_OVERRUN 0x0040
190+
175191
/* Define Transfer direction bits. */
176192
#define UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_XMIT 1
177193
#define UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_RCV 2
@@ -253,6 +269,10 @@ typedef struct UX_SLAVE_CLASS_CDC_ACM_STRUCT
253269
UCHAR ux_slave_class_cdc_acm_data_rts_state;
254270
UCHAR reserved[3];
255271

272+
#if defined(UX_DEVICE_CLASS_CDC_ACM_ENABLE_NOTIFICATIONS)
273+
USHORT ux_device_class_cdc_acm_serial_state;
274+
#endif
275+
256276
#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE
257277
#if !defined(UX_DEVICE_STANDALONE)
258278
UX_THREAD ux_slave_class_cdc_acm_bulkin_thread;
@@ -289,23 +309,23 @@ typedef struct UX_SLAVE_CLASS_CDC_ACM_STRUCT
289309

290310
/* Define some CDC Class structures */
291311

292-
typedef struct UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER_STRUCT
312+
typedef struct UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER_STRUCT
293313
{
294314
ULONG ux_slave_class_cdc_acm_parameter_baudrate;
295315
UCHAR ux_slave_class_cdc_acm_parameter_stop_bit;
296316
UCHAR ux_slave_class_cdc_acm_parameter_parity;
297317
UCHAR ux_slave_class_cdc_acm_parameter_data_bit;
298-
318+
299319
} UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER;
300320

301-
typedef struct UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER_STRUCT
321+
typedef struct UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER_STRUCT
302322
{
303323
UCHAR ux_slave_class_cdc_acm_parameter_rts;
304324
UCHAR ux_slave_class_cdc_acm_parameter_dtr;
305-
325+
306326
} UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER;
307327

308-
typedef struct UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER_STRUCT
328+
typedef struct UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER_STRUCT
309329
{
310330
UINT (*ux_device_class_cdc_acm_parameter_write_callback)(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, ULONG length);
311331
UINT (*ux_device_class_cdc_acm_parameter_read_callback)(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, UCHAR *data_pointer, ULONG length);
@@ -316,22 +336,22 @@ typedef struct UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER_STRUCT
316336

317337
/* Requests - Ethernet Networking Control Model */
318338

319-
#define UX_SLAVE_CLASS_CDC_ACM_SEND_ENCAPSULATED_COMMAND 0x00
339+
#define UX_SLAVE_CLASS_CDC_ACM_SEND_ENCAPSULATED_COMMAND 0x00
320340
/* Issues a command in the format of the supported control
321341
protocol. The intent of this mechanism is to support
322342
networking devices (e.g., host-based cable modems)
323343
that require an additional vendor-defined interface for
324344
media specific hardware configuration and
325345
management. */
326-
#define UX_SLAVE_CLASS_CDC_ACM_GET_ENCAPSULATED_RESPONSE 0x01
346+
#define UX_SLAVE_CLASS_CDC_ACM_GET_ENCAPSULATED_RESPONSE 0x01
327347
/* Requests a response in the format of the supported
328348
control protocol. */
329-
#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_MULTICAST_FILTERS 0x40
349+
#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_MULTICAST_FILTERS 0x40
330350
/* As applications are loaded and unloaded on the host,
331351
the networking transport will instruct the device's MAC
332352
driver to change settings of the Networking device's
333353
multicast filters. */
334-
#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x41
354+
#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x41
335355
/* Some hosts are able to conserve energy and stay quiet
336356
in a 'sleeping' state while not being used. USB
337357
Networking devices may provide special pattern filtering
@@ -340,13 +360,13 @@ typedef struct UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER_STRUCT
340360
host (e.g., an incoming web browser connection).
341361
Primitives are needed in management plane to negotiate
342362
the setting of these special filters */
343-
#define UX_SLAVE_CLASS_CDC_ACM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x42
363+
#define UX_SLAVE_CLASS_CDC_ACM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x42
344364
/* Retrieves the status of the above power management
345365
pattern filter setting */
346-
#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_PACKET_FILTER 0x43
366+
#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_PACKET_FILTER 0x43
347367
/* Sets device filter for running a network analyzer
348368
application on the host machine */
349-
#define UX_SLAVE_CLASS_CDC_ACM_GET_ETHERNET_STATISTIC 0x44
369+
#define UX_SLAVE_CLASS_CDC_ACM_GET_ETHERNET_STATISTIC 0x44
350370
/* Retrieves Ethernet device statistics such as frames
351371
transmitted, frames received, and bad frames received. */
352372

@@ -363,20 +383,20 @@ UINT _ux_device_class_cdc_acm_deactivate(UX_SLAVE_CLASS_COMMAND *command);
363383
UINT _ux_device_class_cdc_acm_entry(UX_SLAVE_CLASS_COMMAND *command);
364384
UINT _ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND *command);
365385
UINT _ux_device_class_cdc_acm_uninitialize(UX_SLAVE_CLASS_COMMAND *command);
366-
UINT _ux_device_class_cdc_acm_write(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
386+
UINT _ux_device_class_cdc_acm_write(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
367387
ULONG requested_length, ULONG *actual_length);
368-
UINT _ux_device_class_cdc_acm_read(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
388+
UINT _ux_device_class_cdc_acm_read(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
369389
ULONG requested_length, ULONG *actual_length);
370390
UINT _ux_device_class_cdc_acm_ioctl(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function,
371391
VOID *parameter);
372392
VOID _ux_device_class_cdc_acm_bulkin_thread(ULONG class_pointer);
373393
VOID _ux_device_class_cdc_acm_bulkout_thread(ULONG class_pointer);
374-
UINT _ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
394+
UINT _ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
375395
ULONG requested_length);
376396

377-
UINT _ux_device_class_cdc_acm_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
397+
UINT _ux_device_class_cdc_acm_write_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
378398
ULONG requested_length, ULONG *actual_length);
379-
UINT _ux_device_class_cdc_acm_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
399+
UINT _ux_device_class_cdc_acm_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
380400
ULONG requested_length, ULONG *actual_length);
381401

382402
UINT _ux_device_class_cdc_acm_tasks_run(VOID *instance);
@@ -419,10 +439,10 @@ UINT _uxe_device_class_cdc_acm_read_run(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR
419439

420440
#endif
421441

422-
/* Determine if a C++ compiler is being used. If so, complete the standard
423-
C conditional started above. */
442+
/* Determine if a C++ compiler is being used. If so, complete the standard
443+
C conditional started above. */
424444
#ifdef __cplusplus
425-
}
426-
#endif
445+
}
446+
#endif
427447

428448
#endif /* UX_DEVICE_CLASS_CDC_ACM_H */

common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/***************************************************************************
2-
* Copyright (c) 2024 Microsoft Corporation
3-
*
2+
* Copyright (c) 2024 Microsoft Corporation
3+
*
44
* This program and the accompanying materials are made available under the
55
* terms of the MIT License which is available at
66
* https://opensource.org/licenses/MIT.
7-
*
7+
*
88
* SPDX-License-Identifier: MIT
99
**************************************************************************/
1010

@@ -13,7 +13,7 @@
1313
/** */
1414
/** USBX Component */
1515
/** */
16-
/** Device CDC_ACM Class */
16+
/** Device CDC ACM Class */
1717
/** */
1818
/**************************************************************************/
1919
/**************************************************************************/
@@ -123,11 +123,19 @@ ULONG sent_length;
123123
/* This is the first time we are activated. We need the interface to the class. */
124124
interface_ptr = cdc_acm -> ux_slave_class_cdc_acm_interface;
125125

126+
/* Locate data interface. */
127+
if (interface_ptr -> ux_slave_interface_descriptor.bInterfaceClass != UX_SLAVE_CLASS_CDC_ACM_DATA_CLASS)
128+
{
129+
/* So the next interface is data interface. */
130+
interface_ptr = interface_ptr -> ux_slave_interface_next_interface;
131+
}
132+
126133
/* Locate the endpoints. */
127134
endpoint = interface_ptr -> ux_slave_interface_first_endpoint;
128135

129136
/* Check the endpoint direction, if IN we have the correct endpoint. */
130-
if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN)
137+
if (((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) ||
138+
((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) != UX_BULK_ENDPOINT))
131139
{
132140

133141
/* So the next endpoint has to be the IN endpoint. */
@@ -278,8 +286,9 @@ ULONG sent_length;
278286
}
279287
}
280288

281-
/* We need to suspend ourselves. We will be resumed by the device enumeration module or when a change of alternate setting happens. */
282-
_ux_device_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread);
289+
/* We need to suspend ourselves. We will be resumed by the device enumeration
290+
module or when a change of alternate setting happens. */
291+
_ux_device_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread);
283292
}
284293
}
285294
#endif

common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/***************************************************************************
2-
* Copyright (c) 2024 Microsoft Corporation
3-
*
2+
* Copyright (c) 2024 Microsoft Corporation
3+
*
44
* This program and the accompanying materials are made available under the
55
* terms of the MIT License which is available at
66
* https://opensource.org/licenses/MIT.
7-
*
7+
*
88
* SPDX-License-Identifier: MIT
99
**************************************************************************/
1010

@@ -13,7 +13,7 @@
1313
/** */
1414
/** USBX Component */
1515
/** */
16-
/** Device CDC_ACM Class */
16+
/** Device CDC ACM Class */
1717
/** */
1818
/**************************************************************************/
1919
/**************************************************************************/
@@ -108,11 +108,19 @@ UINT status;
108108
/* This is the first time we are activated. We need the interface to the class. */
109109
interface_ptr = cdc_acm -> ux_slave_class_cdc_acm_interface;
110110

111+
/* Locate data interface. */
112+
if (interface_ptr -> ux_slave_interface_descriptor.bInterfaceClass != UX_SLAVE_CLASS_CDC_ACM_DATA_CLASS)
113+
{
114+
/* So the next interface is data interface. */
115+
interface_ptr = interface_ptr -> ux_slave_interface_next_interface;
116+
}
117+
111118
/* Locate the endpoints. */
112119
endpoint = interface_ptr -> ux_slave_interface_first_endpoint;
113120

114121
/* Check the endpoint direction, if OUT we have the correct endpoint. */
115-
if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT)
122+
if (((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) ||
123+
((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) != UX_BULK_ENDPOINT))
116124
{
117125

118126
/* So the next endpoint has to be the OUT endpoint. */

0 commit comments

Comments
 (0)