the USB CDC-ACM descriptor layout
For aUSB CDC-ACM (Virtual COM Port)device, the descriptor hierarchy typically looks like this:Device Descriptor │ └── Configuration Descriptor │ ├── Interface 0 (Communication Class Interface, CIC) │ ├── Header Functional Descriptor │ ├── Call Management Functional Descriptor │ ├── ACM Functional Descriptor │ ├── Union Functional Descriptor │ └── Endpoint Descriptor (Interrupt IN) │ └── Interface 1 (Data Class Interface, DIC) ├── Endpoint Descriptor (Bulk OUT) └── Endpoint Descriptor (Bulk IN)Example CDC-ACM Descriptor SetCommunication Interface (Interface 0)Interface Descriptor -------------------- bInterfaceClass 0x02 (CDC) bInterfaceSubClass 0x02 (ACM) bInterfaceProtocol 0x01 (AT Commands) bNumEndpoints 1Header Functional DescriptorbFunctionLength 5 bDescriptorType 0x24 (CS_INTERFACE) bDescriptorSubType 0x00 (Header) bcdCDC 0x0120Call Management DescriptorbFunctionLength 5 bDescriptorType 0x24 bDescriptorSubType 0x01 bmCapabilities 0x00 bDataInterface 1ACM Functional DescriptorbFunctionLength 4 bDescriptorType 0x24 bDescriptorSubType 0x02 bmCapabilities: bit0 Supports Set_Line_Coding bit1 Supports Set_Control_Line_State bit2 Supports Send_BreakCommon value:bmCapabilities 0x02 Union Functional DescriptorbFunctionLength 5 bDescriptorType 0x24 bDescriptorSubType 0x06 bMasterInterface 0 bSlaveInterface0 1Notification EndpointEndpoint Descriptor ------------------- bEndpointAddress 0x81 (Interrupt IN) bmAttributes 0x03 wMaxPacketSize 8 bInterval 16Data Interface (Interface 1)Interface Descriptor -------------------- bInterfaceClass 0x0A (CDC Data) bInterfaceSubClass 0x00 bInterfaceProtocol 0x00 bNumEndpoints 2Bulk OUT EndpointbEndpointAddress 0x02 bmAttributes 0x02 (Bulk) wMaxPacketSize 64 (FS)Bulk IN EndpointbEndpointAddress 0x82 bmAttributes 0x02 (Bulk) wMaxPacketSize 64 (FS)Descriptor Byte LayoutMany STM32/NXP/ESP32 examples use something close to:/* Interface Association Descriptor (optional) */ 08 0B 00 02 02 02 01 00 /* Communication Interface */ 09 04 00 00 01 02 02 01 00 ** Header Functional */ 05 *4 00 20 01 /* Call Management */ 05 *4 01 00 01 /* ACM */ 04 24 02 02 /* Union */ 05 24 06 00 01 /* Interrupt IN EP */ 07 05*81 03 08 00 10* /* Data Interface */ 09 04 01 00 02 0A 00 00 00 /* Bulk OUT */ 07 05 02 02 40 00 00 /* Bulk IN */ 07 05 82 02 40 00 00Enumeration Result in Windows/LinuxAfter enumeration, the host issues CDC class requests such as:SET_LINE_CODING GET_LINE_CODING SET_CONTROL_LINE_STATE SEND_BREAKSET_LINE_CODINGcarries UART settings:dwDTERate 115200 bCharFormat 0 *(1 stop bit) bParityType 0 (none) bDataBits 8 This is why CDC-ACM appears as aCOM portin Windows and as/dev/ttyACM0in Linux. The actual UART settings are often ignored by MCU firmware unless bridged to a real UART. The CDC ACM subclass is defined within the USB Communications Device Class specification. [usb.org], [cscott.net]Common Endpoint MapEP0 Control EP1*IN Interrupt (Notifications) EP2*OUT Bulk (Host - Device data) EP2*IN Bulk (Device - Host data)This is the descriptor structure youll see in STM32Cube USB CDC, TinyUSB CDC-ACM, Zephyr USB CDC, Linux gadget CDC-ACM, and most MCU virtual COM port implementations.