cancel
Showing results for 
Search instead for 
Did you mean: 

USB HOST cannot parse the last EndPoint

A.Ziru
Associate II

Hello!

After two week of struggle I understood that this problem is beyond my abilities.

I have a NUCLEO-H7A3ZI-Q setted as USB Host. I connect a MIDI Keyboard and the Host start the communication, gets all the descriptor and then start the parsing phase to define the device descriptor, the configuration descriptor, the interfaces descriptors and then the END POINTS descriptors.

It works, but it can't parse the last END POINT so the code never get out of a while loop.

Before showing the code and the configuration settings, I have to say that I have used an USB sniffer to check that the end point really exist. It exist and is normally read by the PC. So it's not a device problem.

Ok, let's see the settings

0693W00000KdDN1QAN.png0693W00000KdDM3QAN.pngHonestly except for the buffer size (which is at the maximum 256 byte) i think that there aren't wrong settings here because it communicates.

Below I have drew the structure and the values of the device descriptors from the three interfaces to the four end points. (The interface [1] has no end points. Is it normal?)

0693W00000KdDRXQA3.pngThe values that we are seeing there come from the hUsbHostHS HandletTipeDef and are the same that I see in the USB sniffer. Except for the last endpoint (marked with a red "?") the values coincide.

I drew the scheme because the online visualization of this structure is too long to be show in only one image.

Below I report the code where I should get the end points parsing. It comes from the default ST middleware package and except for the comment to highlight some key zone, I haven't done any modification.

//usbh_ctlreq.c
//LINE 402
static USBH_StatusTypeDef USBH_ParseCfgDesc(USBH_HandleTypeDef *phost, uint8_t *buf, uint16_t length)
{
  USBH_CfgDescTypeDef *cfg_desc = &phost->device.CfgDesc;
  USBH_StatusTypeDef           status = USBH_OK;
  USBH_InterfaceDescTypeDef    *pif ;
  USBH_EpDescTypeDef           *pep;
  USBH_DescHeader_t            *pdesc = (USBH_DescHeader_t *)(void *)buf;
  uint16_t                     ptr;
  uint8_t                      if_ix = 0U;
  uint8_t                      ep_ix = 0U;
 
  pdesc   = (USBH_DescHeader_t *)(void *)buf;
  //######################################### PARSING CONFIGURATION DESCRIPTOR ###############################################
  /* Parse configuration descriptor */
  cfg_desc->bLength             = *(uint8_t *)(buf + 0);
  cfg_desc->bDescriptorType     = *(uint8_t *)(buf + 1);
  cfg_desc->wTotalLength        = MIN(((uint16_t) LE16(buf + 2)), ((uint16_t)USBH_MAX_SIZE_CONFIGURATION));
  cfg_desc->bNumInterfaces      = *(uint8_t *)(buf + 4);
  cfg_desc->bConfigurationValue = *(uint8_t *)(buf + 5);
  cfg_desc->iConfiguration      = *(uint8_t *)(buf + 6);
  cfg_desc->bmAttributes        = *(uint8_t *)(buf + 7);
  cfg_desc->bMaxPower           = *(uint8_t *)(buf + 8);
 
  /* Make sure that the Confguration descriptor's bLength is equal to USB_CONFIGURATION_DESC_SIZE */
  if (cfg_desc->bLength  != USB_CONFIGURATION_DESC_SIZE)
  {
    cfg_desc->bLength = USB_CONFIGURATION_DESC_SIZE;
  }
 
  if (length > USB_CONFIGURATION_DESC_SIZE)
  {
    ptr = USB_LEN_CFG_DESC;
    pif = (USBH_InterfaceDescTypeDef *)NULL;
    //######################################### PARSING INTERFACES DESCRIPTORS ###############################################
    while ((if_ix < USBH_MAX_NUM_INTERFACES) && (ptr < cfg_desc->wTotalLength))
    {
      pdesc = USBH_GetNextDesc((uint8_t *)(void *)pdesc, &ptr);
      if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE)
      {
        /* Make sure that the interface descriptor's bLength is equal to USB_INTERFACE_DESC_SIZE */
        if (pdesc->bLength != USB_INTERFACE_DESC_SIZE)
        {
          pdesc->bLength = USB_INTERFACE_DESC_SIZE;
        }
 
        pif = &cfg_desc->Itf_Desc[if_ix];
        USBH_ParseInterfaceDesc(pif, (uint8_t *)(void *)pdesc);
 
        ep_ix = 0U;
        pep = (USBH_EpDescTypeDef *)NULL;
        //######################################### PARSING END POINTS DESCRIPTORS ###############################################
        // LOOP FROM HERE 
        while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength))
        {
          pdesc = USBH_GetNextDesc((uint8_t *)(void *)pdesc, &ptr);
       // LOOP TO HERE
          if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
          {
            /* Check if the endpoint is appartening to an audio streaming interface */
            if ((pif->bInterfaceClass == 0x01U) && (pif->bInterfaceSubClass == 0x02U))
            {
              /* Check if it is supporting the USB AUDIO 01 class specification */
              if ((pif->bInterfaceProtocol == 0x00U) && (pdesc->bLength != 0x09U))
              {
                pdesc->bLength = 0x09U;
              }
            }
            /* Make sure that the endpoint descriptor's bLength is equal to
               USB_ENDPOINT_DESC_SIZE for all other endpoints types */
            else if (pdesc->bLength != USB_ENDPOINT_DESC_SIZE)
            {
              pdesc->bLength = USB_ENDPOINT_DESC_SIZE;
            }
            else
            {
              /* ... */
            }
 
            pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix];
 
            status = USBH_ParseEPDesc(phost, pep, (uint8_t *)(void *)pdesc);
 
            ep_ix++;
          }
        }
 
        /* Check if the required endpoint(s) data are parsed */
        if (ep_ix < pif->bNumEndpoints)
        {
          return USBH_NOT_SUPPORTED;
        }
 
        if_ix++;
      }
    }
 
    /* Check if the required interface(s) data are parsed */
    if (if_ix < MIN(cfg_desc->bNumInterfaces, (uint8_t)USBH_MAX_NUM_INTERFACES))
    {
      return USBH_NOT_SUPPORTED;
    }
  }
 
  return status;
}

When I say that I spent two weeks on this problem I'm not exaggerating, I have studied every line of this function and I do not understand why it doesn't parse the end point.

I do not believe that much in those two possibilities but they are the only ones that come to mind:

  • The MAX SIZE CONFIGURATION BUFFER is too small
  • The Middleware is bugged somewhere

I mean, I have connected several other USB devices (Pen Drive, Mouse, keyboard even a Microscope) and from all of them I got the entire descriptors.

I hope I have presented the problem in a proper way.

If someone can help me i will be extremely grateful.

P.S.

The keyboard works well and I have tested it on the PC and it works properly.

10 REPLIES 10