Skip to main content
Visitor II
September 28, 2021
Question

USB CDC : How send SERIAL_STATE notification?

  • September 28, 2021
  • 7 replies
  • 4385 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

    Super User
    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.1Author
    Visitor II
    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

    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?

    Graduate
    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.

    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.