AnsweredAssumed Answered

usbh hid custom device issues

Question asked by gorse.joseph on Aug 9, 2016
Latest reply on May 2, 2018 by gorse.joseph
Hello,

I am trying to get a custom HID device to work on my STM32F429ZI board using the USB Host driver from the latest CubeMX for F4. I have successfully received boot mode keyboard data with this driver. The intended device requires report mode as far as I can tell.

The device enumerates fine and with a few modifications we make it through to the usbh_hid.c USBH_HID_Process() state machine. As described here by Tsuneo Chinzei, I've added some states so that we can send data over the interrupt out EP then receive data from the interrupt in EP. 

001.static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
002.{
003. 
004.  USBH_StatusTypeDef status = USBH_OK;
005.  HID_HandleTypeDef *HID_Handle =  (HID_HandleTypeDef *) phost->pActiveClass->pData;
006.  USBH_URBStateTypeDef urb_state;
007.  static uint8_t _buf[61];
008.   
009.  switch (HID_Handle->state)
010.  {
011.  case HID_INIT:
012.//    HID_Handle->Init(phost);
013.    memset (_buf, 0, sizeof(_buf));
014.    _buf[0] = 2;
015.    HID_Handle->state = HID_IDLE;
016.  case HID_IDLE:
017.    // 7.2 Class-Specific Requests
018.    if(USBH_HID_GetReport (phost, // 10100001 - D2H, CLASS REQ
019.                           0x01, // Type 1 in, 2 out, 3 feature, ff res
020.                            0,   // Id
021.                            HID_Handle->pData,
022.                            HID_Handle->length) == USBH_OK)
023.    {
024.      printf("USBH_HID_GetReport(phost, type=0x1, Id=0, len=0x%x, HID_Handle->pData=0x%x 0x%x)\n",
025.          HID_Handle->length,HID_Handle->pData[0],HID_Handle->pData[1]);
026.       
027.//      fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
028.      HID_Handle->state = HID_SYNC;
029.    }
030.     
031.    break;
032.     
033.  case HID_SYNC:
034. 
035.    /* Sync with start of Even Frame */
036.    if(phost->Timer & 1)
037.    {
038.      HID_Handle->state = HID_SEND_DATA;
039.    }
040.#if (USBH_USE_OS == 1)
041.    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
042.#endif  
043.    break;
044.     
045.  case HID_SEND_DATA:
046.    memset (HID_Handle->pData, 0, HID_Handle->length);
047.    HID_Handle->pData[0] = 2;
048. 
049.    USBH_InterruptSendData(phost,
050.                                    HID_Handle->pData,
051.                                    HID_Handle->length,
052.                                    HID_Handle->OutPipe);
053. 
054.    HID_Handle->state = HID_POLL_SEND;
055.//    HID_Handle->timer = phost->Timer;
056.//    HID_Handle->DataReady = 0;
057.    break;
058. 
059.  case HID_POLL_SEND:
060. 
061.    if(USBH_LL_GetURBState(phost , HID_Handle->OutPipe) == USBH_URB_DONE)
062.    {
063.      HID_Handle->state = HID_GET_DATA;
064.    }
065.    else if(USBH_LL_GetURBState(phost , HID_Handle->OutPipe) == USBH_URB_STALL) /* IN Endpoint Stalled */
066.    {
067.      printf("HID_POLL_SEND stalled");
068.      /* Issue Clear Feature on interrupt IN endpoint */
069.      if(USBH_ClrFeature(phost,
070.                         HID_Handle->ep_addr) == USBH_OK)
071.      {
072.        /* Change state to issue next OUT token */
073.        HID_Handle->state = HID_SYNC;
074.      }
075.    }
076.    break;
077. 
078.  case HID_GET_DATA:
079. 
080.    USBH_InterruptReceiveData(phost,
081.                              HID_Handle->pData,
082.                              HID_Handle->length,
083.                              HID_Handle->InPipe);
084.     
085.    HID_Handle->state = HID_POLL_GET;
086.    HID_Handle->timer = phost->Timer;
087.    HID_Handle->DataReady = 0;
088.    break;
089.     
090.  case HID_POLL_GET:
091.     
092.    if(USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_DONE)
093.    {
094.      if(HID_Handle->DataReady == 0)
095.      {
096.//        fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
097.        HID_Handle->DataReady = 1;
098.        USBH_HID_EventCallback(phost);
099.#if (USBH_USE_OS == 1)
100.    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
101.#endif         
102.      }
103.    }
104.    else if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_STALL) /* IN Endpoint Stalled */
105.    {
106.      printf("HID_POLL_GET stalled");
107.      /* Issue Clear Feature on interrupt IN endpoint */
108.      if(USBH_ClrFeature(phost,
109.                         HID_Handle->ep_addr) == USBH_OK)
110.      {
111.        /* Change state to issue next IN token */
112.        HID_Handle->state = HID_GET_DATA;
113.      }
114.    }
115.     
116. 
117.    break;
118.     
119.  default:
120.    break;
121.  }
122.  return status;
123.}
124. 
125./**
126.  * @brief  USBH_HID_SOFProcess
127.  *         The function is for managing the SOF Process
128.  * @param  phost: Host handle
129.  * @retval USBH Status
130.  */
131.static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost)
132.{
133.  HID_HandleTypeDef *HID_Handle =  (HID_HandleTypeDef *) phost->pActiveClass->pData;
134.   
135.  if(HID_Handle->state == HID_POLL_GET)
136.  {
137.    if(( phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
138.    {
139.      HID_Handle->state = HID_SYNC;  // TODO: Send then get?
140.#if (USBH_USE_OS == 1)
141.    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
142.#endif      
143.    }
144.  }
145.  return USBH_OK;
146.}

Sending appears to always work, though the buffer never changes in the receive interrupt and it always says the URB status is IDLE.

For reference, this is a working example of what I want written in a handful of lines in ruby using the HID API library:
01.require "hid_api"
03. 
04.handle = HidApi::hid_open(0x05AC, 0x024F, 0)
05. 
06.buf = Array.new(61) { |i| (0) };
07.buf[0] = 0x2
08. 
09.while 1 do
10.  handle.write(buf)
11.  rbuf = handle.read_timeout(buf.length,1000)
12.  print rbuf.read_bytes(61).unpack("C*"), "\n"
13.  sleep(0.2)
14.end
15. 
16.HidApi::hid_close(handle)

How can I get this simple HID use case to work with the CubeMX USB Host driver?

Cheers,
Joe

Outcomes