Skip to main content
LMorg.1
Associate
September 28, 2021
Question

USB CDC : How send SERIAL_STATE notification?

  • September 28, 2021
  • 7 replies
  • 4489 views

Hello,

I have to implement a USB CDC device that uses flow control. After a few research it seems to be possible to send a notification SERIAL_STATE that holds the signal DSR in its bitmap.

Also, I have found topics on this platform trying to answer this question:

  1. Notification SERIAL_STATE on VCP STM32F105
  2. 2. I'm trying to send signals DSR and DCD through the structure and command endpoint, see example USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev) { static uint8_t Buf[0xA]; Buf[0] = 0xA1; Buf[1] = 0x20; Buf[2] = 0; Buf[3] = 0; Buf
  3. CTS signal on USB CDC
  4. Send SERIAL_STATE with STM32CubeMX USB CDC driver

None of which are helpful, #2 and #3 are closed without an answer, #1 and #4 seems to use the same code which does not work for me yet.

Based on example from #4, here is my code:

// usbd_cdc_if.h
 typedef union
{
 uint8_t val;
 struct{
 unsigned dcd :1;
 unsigned dsr :1;
 unsigned break_err :1;
 unsigned ri :1;
 unsigned frame_err :1;
 unsigned parity_err :1;
 unsigned overrun_err :1;
 unsigned reserved :1;
 };
} USBD_CDC_SerialStateTypeDef;
 
uint8_t CDC_Serial_State(USBD_CDC_SerialStateTypeDef serial_state);
 
 
 
// usbd_cdc_if.c
uint8_t CDC_Serial_State_Buf[10] = {
 0xA1, // vmRequestType
 0x20, // SERIAL_STATE
 0x00, // wValue
 0x00,
 0x00, // wIndex
 0x00,
 0x02, // wLength
 0x00,
 0x00, // UART state bitmap
 0x00,
 };
 
/**
 * @brief CDC_Serial_State
 * Send SERIAL_STATE over USB IN interrupt endpoint through this function.
 * @note
 *
 *
 * @param serial_state: Uart State Bitmap Value
 * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
 */
uint8_t CDC_Serial_State(USBD_CDC_SerialStateTypeDef serial_state)
{
 USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)&hUsbDeviceHS.pClassData;
 
 if (hcdc->TxState != 0){
 return USBD_BUSY;
 }
 
 CDC_Serial_State_Buf[8] = serial_state.val;
 
 hUsbDeviceHS.ep0_state = USBD_EP0_STATUS_IN;
 hUsbDeviceHS.ep_in[0].total_length = 10;
 hUsbDeviceHS.ep_in[0].rem_length = 10;
 
 /* Start the transfer */
 USBD_LL_Transmit (&hUsbDeviceHS, CDC_CMD_EP, CDC_Serial_State_Buf, 10);
 
 return USBD_OK;
}

Now when calling CDC_Serial_State() the device seems to be stuck in the USB IRQ Handler and never returns from CDC_Serial_State().

What is the problem with this code? How am I supposed to send USB notifications?

Thanks for your support,

Morgan

This topic has been closed for replies.

7 replies

Pavel A.
September 29, 2021

Do you have an IN interrupt endpoint in your CDC control interface descriptor?

Do you see the host sending IN request to this endpoint?

LMorg.1
LMorg.1Author
Associate
September 29, 2021

Yes I do, from the STM32_USB_Device_Library I kept the default endpoints initialization:

Device Descriptor:
 bLength 18
 bDescriptorType 1
 bcdUSB 2.00
 bDeviceClass 2 Communications
 bDeviceSubClass 2 Abstract (modem)
 bDeviceProtocol 0 
 bMaxPacketSize0 64
 idVendor 0x0483 STMicroelectronics
 idProduct 0x5740 Virtual COM Port
 bcdDevice 2.00
 iManufacturer 1 
 iProduct 2 
 iSerial 3 
 bNumConfigurations 1
 Configuration Descriptor:
 bLength 9
 bDescriptorType 2
 wTotalLength 0x0043
 bNumInterfaces 2
 bConfigurationValue 1
 iConfiguration 0 
 bmAttributes 0xc0
 Self Powered
 MaxPower 100mA
 Interface Descriptor:
 bLength 9
 bDescriptorType 4
 bInterfaceNumber 0
 bAlternateSetting 0
 bNumEndpoints 1
 bInterfaceClass 2 Communications
 bInterfaceSubClass 2 Abstract (modem)
 bInterfaceProtocol 1 AT-commands (v.25ter)
 iInterface 0 
 CDC Header:
 bcdCDC 1.10
 CDC Call Management:
 bmCapabilities 0x00
 bDataInterface 1
 CDC ACM:
 bmCapabilities 0x02
 line coding and serial state
 CDC Union:
 bMasterInterface 0
 bSlaveInterface 1 
 Endpoint Descriptor:
 bLength 7
 bDescriptorType 5
 bEndpointAddress 0x82 EP 2 IN
 bmAttributes 3
 Transfer Type Interrupt
 Synch Type None
 Usage Type Data
 wMaxPacketSize 0x0008 1x 8 bytes
 bInterval 16
 Interface Descriptor:
 bLength 9
 bDescriptorType 4
 bInterfaceNumber 1
 bAlternateSetting 0
 bNumEndpoints 2
 bInterfaceClass 10 CDC Data
 bInterfaceSubClass 0 
 bInterfaceProtocol 0 
 iInterface 0 
 Endpoint Descriptor:
 bLength 7
 bDescriptorType 5
 bEndpointAddress 0x01 EP 1 OUT
 bmAttributes 2
 Transfer Type Bulk
 Synch Type None
 Usage Type Data
 wMaxPacketSize 0x0200 1x 512 bytes
 bInterval 0
 Endpoint Descriptor:
 bLength 7
 bDescriptorType 5
 bEndpointAddress 0x81 EP 1 IN
 bmAttributes 2
 Transfer Type Bulk
 Synch Type None
 Usage Type Data
 wMaxPacketSize 0x0200 1x 512 bytes
 bInterval 0

But I do not see the host sending request to this endpoint. By the way I monitor USB activity with Wireshark and usbmon.

Here is what I get from initialization, and then trying to send SERIAL STATE notification which is not seen :

No.	Time	Source	Destination	Protocol	Length	Info
1447	2.858586	host	3.17.0	USB	64	GET DESCRIPTOR Request DEVICE
1448	2.858787	3.17.0	host	USB	82	GET DESCRIPTOR Response DEVICE
1451	2.858847	host	3.17.0	USB	64	GET DESCRIPTOR Request CONFIGURATION
1452	2.859007	3.17.0	host	USB	73	GET DESCRIPTOR Response CONFIGURATION
1453	2.859023	host	3.17.0	USB	64	GET DESCRIPTOR Request CONFIGURATION
1454	2.859186	3.17.0	host	USB	131	GET DESCRIPTOR Response CONFIGURATION
1455	2.859206	host	3.17.0	USB	64	GET DESCRIPTOR Request STRING
1456	2.859356	3.17.0	host	USB	68	GET DESCRIPTOR Response STRING
1457	2.859367	host	3.17.0	USB	64	GET DESCRIPTOR Request STRING
1458	2.859533	3.17.0	host	USB	108	GET DESCRIPTOR Response STRING
1459	2.859550	host	3.17.0	USB	64	GET DESCRIPTOR Request STRING
1460	2.859763	3.17.0	host	USB	82	GET DESCRIPTOR Response STRING
1461	2.859770	host	3.17.0	USB	64	GET DESCRIPTOR Request STRING
1462	2.859917	3.17.0	host	USB	90	GET DESCRIPTOR Response STRING
1463	2.862682	host	3.17.0	USB	64	SET CONFIGURATION Request
1464	2.862883	3.17.0	host	USB	64	SET CONFIGURATION Response
1465	2.863011	host	3.17.0	USBCOM	71	SET LINE CODING Request
1466	2.863121	3.17.0	host	USB	64	URB_CONTROL out

AAbuh.1
Visitor II
April 28, 2023

Hey,

I'm still a beginner at this. I have a couple of questions, what parameter to use when calling the CDC_Serial_State() function, it says "Uart State Bitmap Value", let's say I want to send a ri signal (ring signal), what will be the parameter in this case?

And did you figure out how to fix the problem of being stuck in the USB IRQ Handler?

Explorer
November 29, 2023

Hello,
You succeeded implement a USB CDC device that uses flow control?

gbm
Super User
November 29, 2023

The notification is not implemented out-of-the-box in ST CDC. The notification should be sent via the interrupt in endpoint - in the example above it's 0x82 (not control EP 0/0x80). The notification packet content may be found in USB CDC class specification.

The overall program logic should be similar to that of a HID input device.

(My usual warning about ST USB): do NOT send anything from the main loop - USB transmit functions should only be called from an interrupt service routine of the same priority as USB hardware interrupt.

BTW do not specify protocol as 1 (AT commands) - it has some bad side effects.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Explorer
November 30, 2023

I'm still a beginner at this. I don't really understand where to call CDC_Serial_State. Maybe you have a sample project? It would help me a lot to figure this out.

Visitor II
January 11, 2024

Hello.
As gbm mentioned, I introduced Serial_State into the periodic timer interrupt handler as well as the HID device.
However, it did not solve the problem of getting stuck in the IRQ handler as described in this topic.
The solution in the following topic was very helpful in solving this problem.
USB CDC device on STM32H750B-DK, problem with DTXFSTS register

In my case, the stack was caused by Fifo not being assigned.