cancel
Showing results for 
Search instead for 
Did you mean: 

USB CDC : How send SERIAL_STATE notification?

LMorg.1
Associate

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

7 REPLIES 7
Pavel A.
Evangelist III

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
Associate

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
Associate

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?

PriCepThyk
Associate

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

gbm
Lead III

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
PriCepThyk
Associate

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.

Pale_white
Associate

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.