AnsweredAssumed Answered

STM32Cube USB CDC missing break signal handling

Question asked by pbk on May 31, 2014
Latest reply on Jun 9, 2014 by Montassar BEN ROMDHANE
Hello. Adding this in case anyone else stumbles into the same issue.

I was porting an F4 project from the Standard Peripheral libraries to the new STM32Cube HAL. The communication protocol implemented in the system uses the CDC Send_Break signal to perform some actions in the target. After finishing the port and testing Tx/Rx communications, I realized that the target was not responding to commands that issued the break signal in the host application.

Looking at the new HAL USB descriptors, I added the D2/Send_Break bit in the bmCapabilities byte of the Abstract Control Management part of the descriptor. The old USB device library was able to handle breaks when that bit was added (although I have discovered that some hosts send breaks even if that bit is off). However, the new USB HAL library did not receive break signal requests. I was only able to see SET/GET_LINE_CODING commands in the CDC Control callback of the interface.

Digging into the new CDC implementation, I found that the USBD_CDC_Setup function in the new usbd_cdc.c file looks like this:


static uint8_t  USBD_CDC_Setup (USBD_HandleTypeDef *pdev,
                                USBD_SetupReqTypedef *req)
{
  USBD_CDC_HandleTypeDef   *hcdc = pdev->pClassData;
 
  switch (req->bmRequest & USB_REQ_TYPE_MASK)
  {
  case USB_REQ_TYPE_CLASS :
    if (req->wLength)
    {
      if (req->bmRequest & 0x80)
      {
        ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest,
                                                          (uint8_t *)hcdc->data,
                                                          req->wLength);
          USBD_CtlSendData (pdev,
                            (uint8_t *)hcdc->data,
                            req->wLength);
      }
      else
      {
        hcdc->CmdOpCode = req->bRequest;
        hcdc->CmdLength = req->wLength;
                                                      
        USBD_CtlPrepareRx (pdev,
                           (uint8_t *)hcdc->data,
                           req->wLength);
      }
      break;
    }
  }
  return USBD_OK;
}

The function is designed to process commands with payload data and a reply. Therefore, if the request (0x20) has a payload (req->wLength), like the SET/GET_LINE_CODING (0x20/0x21) commands do, the request will be processed. But if the request has a wLength field of zero, like the SEND_BREAK (0x23) command, it will be ignored. The previous version of that function had a direct call to the interface control callback in case of a no data request.

Regards.

Outcomes