Question
usbh hid custom device issues
Posted on August 09, 2016 at 06:36
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.cUSBH_HID_Process() state machine. As describedhttp://www.keil.com/forum/22428/stm32f4-usb-host-hid-application/
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.
static
USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
{
USBH_StatusTypeDef status = USBH_OK;
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
USBH_URBStateTypeDef urb_state;
static
uint8_t _buf[61];
switch
(HID_Handle->state)
{
case
HID_INIT:
// HID_Handle->Init(phost);
memset
(_buf, 0,
sizeof
(_buf));
_buf[0] = 2;
HID_Handle->state = HID_IDLE;
case
HID_IDLE:
// 7.2 Class-Specific Requests
if
(USBH_HID_GetReport (phost,
// 10100001 - D2H, CLASS REQ
0x01,
// Type 1 in, 2 out, 3 feature, ff res
0,
// Id
HID_Handle->pData,
HID_Handle->length) == USBH_OK)
{
printf
(
''USBH_HID_GetReport(phost, type=0x1, Id=0, len=0x%x, HID_Handle->pData=0x%x 0x%x)\n''
,
HID_Handle->length,HID_Handle->pData[0],HID_Handle->pData[1]);
// fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
HID_Handle->state = HID_SYNC;
}
break
;
case
HID_SYNC:
/* Sync with start of Even Frame */
if
(phost->Timer & 1)
{
HID_Handle->state = HID_SEND_DATA;
}
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
break
;
case
HID_SEND_DATA:
memset
(HID_Handle->pData, 0, HID_Handle->length);
HID_Handle->pData[0] = 2;
USBH_InterruptSendData(phost,
HID_Handle->pData,
HID_Handle->length,
HID_Handle->OutPipe);
HID_Handle->state = HID_POLL_SEND;
// HID_Handle->timer = phost->Timer;
// HID_Handle->DataReady = 0;
break
;
case
HID_POLL_SEND:
if
(USBH_LL_GetURBState(phost , HID_Handle->OutPipe) == USBH_URB_DONE)
{
HID_Handle->state = HID_GET_DATA;
}
else
if
(USBH_LL_GetURBState(phost , HID_Handle->OutPipe) == USBH_URB_STALL)
/* IN Endpoint Stalled */
{
printf
(
''HID_POLL_SEND stalled''
);
/* Issue Clear Feature on interrupt IN endpoint */
if
(USBH_ClrFeature(phost,
HID_Handle->ep_addr) == USBH_OK)
{
/* Change state to issue next OUT token */
HID_Handle->state = HID_SYNC;
}
}
break
;
case
HID_GET_DATA:
USBH_InterruptReceiveData(phost,
HID_Handle->pData,
HID_Handle->length,
HID_Handle->InPipe);
HID_Handle->state = HID_POLL_GET;
HID_Handle->timer = phost->Timer;
HID_Handle->DataReady = 0;
break
;
case
HID_POLL_GET:
if
(USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_DONE)
{
if
(HID_Handle->DataReady == 0)
{
// fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
HID_Handle->DataReady = 1;
USBH_HID_EventCallback(phost);
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
}
else
if
(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_STALL)
/* IN Endpoint Stalled */
{
printf
(
''HID_POLL_GET stalled''
);
/* Issue Clear Feature on interrupt IN endpoint */
if
(USBH_ClrFeature(phost,
HID_Handle->ep_addr) == USBH_OK)
{
/* Change state to issue next IN token */
HID_Handle->state = HID_GET_DATA;
}
}
break
;
default
:
break
;
}
return
status;
}
/**
* @brief USBH_HID_SOFProcess
* The function is for managing the SOF Process
* @param phost: Host handle
* @retval USBH Status
*/
static
USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost)
{
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
if
(HID_Handle->state == HID_POLL_GET)
{
if
(( phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
{
HID_Handle->state = HID_SYNC;
// TODO: Send then get?
#if (USBH_USE_OS == 1)
osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif
}
}
return
USBH_OK;
}
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:
require
''hid_api''
# http://www.signalus/oss/hidapi/
handle
=
HidApi::hid_open(
0x05AC
,
0x024F
,
0
)
buf
=
Array.new(
61
) { |i| (
0
) };
buf[
0
]
=
0x2
while
1
do
handle.write(buf)
rbuf
=
handle.read_timeout(buf.length,
1000
)
print
rbuf.read_bytes(
61
).unpack(
''C*''
),
''\n''
sleep(
0.2
)
end
HidApi::hid_close(handle)
How can I get this simple HID use case to work with the CubeMX USB Host driver?
Cheers,
Joe
#hid #!cubemx #usbh