cancel
Showing results for 
Search instead for 
Did you mean: 

STM32CubeF4 Applications: USB Host HID Device Issue

bazookafighter
Associate II
Posted on March 11, 2016 at 10:16

As a start, I am an owner of an STM32F469I-Discovery board. When I tried out the USB Host applications that came with STM32CubeF4, whether it was ''HID_RTOS'' or ''HID_Standalone'', I could not input a single thing with my USB wired keyboards even though they were all enumerated successfully and I tried 3 different keyboards.

On the other hand, the USB mouse I had with me worked as intended by the examples provided. While I will admit that all 3 of the keyboards I tried are not your typical brand stuff (e.g. Logitech, Microsoft etc.) but some generic Chinese devices, they all work perfectly fine on Windows/Linux machines which leads to me to believe that it is very likely a software problem. As a matter of fact, I tried the same examples from STM32CubeF4 v1.10.00 and v1.11.00 and they both produced the same results which is not surprising since they are no changes as far as I could tell.

However, I cannot fully dismiss that it is not a hardware problem either. Therefore I would like to request all STM32F4xx users who have had success with using a USB keyboard in the examples which were mentioned above to provide more details about the keyboard you used.

If it is indeed a software problem, then perhaps ST may want to have a look at it. If it helps at all, I am posting the PID and VID of the USB wired keyboards I had used for my testing below.

Keyboard No. 1 - PID: 260h | VID: 9dah

Keyboard No. 2 - PID: 1503h |VID: 1241h

Keyboard No. 3 - PID: b23h | VID: 1a2ch

#otg #host #host #host #keyboard #host #stm32f4 #usb #usb
13 REPLIES 13
tsuneo
Senior
Posted on March 14, 2016 at 11:17

Maybe, your keyboards have gotten stuck at Get_Report. ST's host stack puts this request, just before polling HID interrupt endpoint. USB HID spec prescribes that Get_Report implementation is mandatory for boot keyboard. But popular keyboard chips haven't supported it.

For workaround, skip HID_IDLE state, in which Get_Report is issued by the stack, as follows.

\STM32Cube\Repository\STM32Cube_FW_F4_V1.0\Middlewares\ST
\STM32_USB_Host_Library\Class\HID\Src\usbh_hid.c
// line 357
static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
{
USBH_StatusTypeDef status = USBH_OK;
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
switch (HID_Handle->state)
{
case HID_INIT:
HID_Handle->Init(phost);
// <---- add these lines, from here
HID_Handle->state = HID_SYNC; // skip HID_IDLE state
break;
// <---- to here

Tsuneo
bazookafighter
Associate II
Posted on March 18, 2016 at 11:37

And just like that you have managed to solve a problem that has been plaguing me for days. Incredible work and thank you Tsuneo! However, we can all agree that this is simply a temporary fix to bypass the

USBH_HID_GetReport()

function for keyboards that do not seem to do well with it.

After what you explained, I looked up the USB HID specifications a little and found out that the Windows operating system has a similar implementation in the form of

HidD_GetInputReport()

. While I am not 100% sure how this is ultimately implemented in the real thing, it still begs one of my earlier questions - why do these odd devices work out of the box on Windows/Linux machines but not on my STM32 development board?

tsuneo
Senior
Posted on March 22, 2016 at 03:09

> why do these odd devices work out of the box on Windows/Linux machines but not on my STM32 development board?

Windows HID driver don't put any Get_Report request to keyboard/mouse. I believe it is the reason that these ''out-of-spec'' keyboards don't support Get_Report.

Linux sends Get_Report to keyboard/mouse just after enumeration. It ignores failure (STALL) on this request.

The real problems of Cube host stack are,

a) USBH_HID_Process() keeps USBH_HID_GetReport() call infinitely, without skipping this stage after a couple of USBH_HID_GetReport() failure.

b) when a target device would return STALL to call of USBH_CtlReq() (called by USBH_HID_GetReport()), USBH_CtlReq() returns USBH_BUSY, instead of USBH_FAIL.

c) another calls of USBH_CtlReq() keep returning USBH_BUSY, without sending any control request to the device.

These problems trap sequence of USBH_HID_Process() at the ''case HID_IDLE:''.

Tsuneo

bazookafighter
Associate II
Posted on March 25, 2016 at 09:58

Actually Tsuneo, I have strong reasons to believe that the Windows operating system does implement a GetReport() request to HID devices if you were to look at the sample codes provided by Microsoft to demonstrate how to write a user-mode client application that communicates with HID devices (

https://github.com/Microsoft/Windows-driver-samples/tree/master/hid/hclient

). It is the reason why I brought up the Windows equivalent of GetReport() in my previous post.

/* Microsoft/Windows-driver-samples/hid/hclient/hclient.c */
/* line 684 */
void
CLM_SyncRead(
_In_ PHID_DEVICE pDevice,
_In_ BYTE reportID,
_In_ ULONG msecToSleep,
_In_ ULONG numReads)
{
HID_DEVICE syncDevice;
ULONG numReadsDone = 0;
RtlZeroMemory(&syncDevice, sizeof(syncDevice));
if (!OpenHidDevice(pDevice->DevicePath, 
TRUE,
FALSE,
FALSE,
FALSE,
&syncDevice))
{
printf(''Failed opening the device for synchronous read.
'');
goto Done;
}
printf(''Synchronous read started...
'');
while (INFINITE_READS == numReads || numReadsDone < 

numReads

)

{
syncDevice.InputReportBuffer[0] = reportID;

if (FALSE == HidD_GetInputReport(syncDevice.HidDevice,

syncDevice.InputReportBuffer,

syncDevice.Caps.InputReportByteLength ))

{

printf(''HidD_GetInputReport() failed. Error: 0x%
X'', GetLastError());

break;

}

numReadsDone++;
printf(''Read #%d:
'',numReadsDone);
CLM_PrintInputReport(&syncDevice);
if (msecToSleep > 0)
{
Sleep(msecToSleep);
}
}
printf(''Synchronous read stopped.
'');
Done:
CloseHidDevice(&syncDevice);
}

If this sample code is any indication of how Microsoft has been handling HID devices since 1998 (predates even Windows 98's release!), then it absolutely fails to explain why these, to quote you, ''out-of-spec'' devices work right out of the box on Windows machines but not on my development board. As for Linux, if I am understanding what you said correctly, that the operating system stalls on its own version of GetReport() function when it returns FALSE, then the same devices should not have worked either. However, as much as it scratches my head, they did and they exhibited no issues at all. In summary, the conclusion I have come to so far tells me that the STM32 USB Host stack produced by ST is not as robust as my use case scenario would like it to be. Both Windows and Linux have their own GetReport() request but that has not stopped them from not playing nice with my ''out-of-spec'' USB devices even when the request presumably fails, or not.
tsuneo
Senior
Posted on March 25, 2016 at 12:12

> Actually Tsuneo, I have strong reasons to believe that the Windows operating system does implement a GetReport() request to HID devices

I didn't tell you Windows wouldn't implement GetReport request.

I said, Windows don't put any GetReport to keyboard/mouse in usual operation.

USB keyboard and mouse are considered as ''System device'' on Windows. They are assigned to their specific driver by Windows, apart from other HID devices. These specific drivers don't send any GetReport request to keyboard and mouse in usual operation. Also, GetReport(INPUT) request from your PC application to these devices should fail (**1) by Windows.

(**1) GetReport(FEATURE) to keyboard/mouse could pass, if the device would define feature report.

> As for Linux, if I am understanding what you said correctly, that the operating system stalls on its own version of GetReport() function when it returns FALSE, then the same devices should not have worked either.

???

OS doesn't STALL, device does.

STALL isn't communication error. It's a correct ''signal'' issued by the device.

When device returns STALL to a request, it means the device doesn't support the request. When OS gets STALL,

a) OS would try the request a couple of times, if the request could be fairly required,

OR

b) OS would take other request to communicate the device, just it ignores the STALLed request.

Tsuneo

Wei-Chih Kuo
Associate
Posted on December 19, 2017 at 03:12

Hi, Tsuneo:

Recently, I also worked on usb host application to connect my another device which is not belonging to keyboard and mouse. I also had the same issue here and it can't get fixed even I applied the code change above.

I saw the uart log showed HID_INIT was done, and after that, nothing went on.

Would you please advise me how to fix it? Any information you need?

Thanks a lot.

BR,

Pico

Posted on January 19, 2018 at 16:25

Hi

kuo.pico

‌,

Could you please apply the patch suggested by

pavel_a

‌ in

https://community.st.com/0D50X00009XkZ4KSAV

and keep us informed if it fixes your issue or not?

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

WBuck
Associate II

Hello All

I tried the STM32746G-Discovery HID_RTOS without changes and it worked for a Logitech keyboard and mouse fine ... thank you.

I wanted to use a RFIDeas pcProx (card reader with keyboard emulation), this did not work hence me reading this thread.

I tried the first mod (via patch an manual) but this did not work and also stopped the Logitech devices working. So reading the above made me try this:

  switch (HID_Handle->state)
  {
  case HID_INIT:
    HID_Handle->Init(phost);
//    HID_Handle->state = HID_SYNC;
    HID_Handle->state = HID_IDLE;
    break;
 
  case HID_IDLE:
    if(USBH_HID_GetReport (phost, 0x01, 0, HID_Handle->pData, HID_Handle->length) == USBH_OK)
    {
        fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
    }
    HID_Handle->state = HID_SYNC;
    break;
 
  case HID_SYNC:

Taking the state change out of the if check means it is not locked up.

The card reader now works well as do the keyboard and mouse I tried.

Thanks for the help above.

I am now trying to create an HID application using cube but am having problems ... another thread, if anyone from here can help 🙂

Billy

WBuck
Associate II

Sorry just reviewing the above I missed commenting out the break on line 7.