cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 USB HID host with CP2110 - problems with modyfing the code

Marek Novak
Associate II
Posted on April 30, 2018 at 23:15

Hi,

I have a project where I need to communicate with CP2110 via USB (medical device having this interface). I am prototyping the application on STM32F746G-DISCO. I have started by running the Application example HID USBH_FS where I can plug in a USB mouse or keyboard the receive the data. This works so far. Then, I have started modyfing the code for CP2 First, I have tried to plug in the device as-is. It got correctly enumerated as CP2110 HID to Serial converter but obviously failed during execution of USBH_HID_InterfaceInit. I have edited following code so it passes the USBH_HID_InterfaceInit function with HID class started message:

interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, 0x00, 0xFF);�?

The Subclass of the device is not 0x01 (boot device) as for USB keyboard and mouse but 0x00. Next, I have added this code to the if-elseif structure determining whether it is a keyboard, mouse or not compatible device:

else if(phost->device.DevDesc.idVendor==0x10C4 && phost->device.DevDesc.idProduct==0xEA80) // CP2110
 {
 USBH_UsrLog ('CP2110 device found!');
 HID_Handle->Init = USBH_HID_MouseInit;
 }�?�?�?�?�?

I have kept the MouseInit function in there for now. I don't suspect it could cause any problems .. or could it?

So I have the HID class started. Now I am starting to be a little bit struggling as the HID Host library provided by ST seems not to be complete and finished. It has functions for getting the HID reports which is perfectly fine for keyboard and mouse but I need to transmit a report in order to configure the device. I tried to google for the solution but it always failed - either freezes after HID class start or is not compatible with the current library version.

Are there any working examples or any documentation which could help in implementing the USB HID Host for CP2110?

Any help would be really appreciated,

Best Regards,

Marek.

13 REPLIES 13
Marek Novak
Associate II
Posted on April 30, 2018 at 23:36

I have narrowed down the problem - it is in the USBH_HID_ClassRequest function.

It gets past if (USBH_HID_GetHIDDescriptor (phost, USB_HID_DESC_SIZE)== USBH_OK) but fails at the next one - if (USBH_HID_GetHIDReportDescriptor(phost, HID_Handle->HID_Desc.wItemLength) == USBH_OK)

It does not pass this if, tries it several times (three times most of the cases) and the program freezes. Probably the reason is that the HID_Handle->HID_Desc.wItemLength is huge - 919 which exceeds the USBH_MAX_DATA_BUFFER which is 512.

Posted on May 01, 2018 at 13:33

Is the report descriptor really this huge? Do you actually need to read it, or can skip this step an move on?

The HID example indeed is limited to the specific case of boot compatible keyboard and mouse.

(My board has F4, and I could not make even the mouse work without changes in the HID class code.

Will check if the F7 variant of this code differs from F4...)

-- pa

Posted on May 01, 2018 at 13:45

Hi Pavel, thanks for your reply. I will check the documentation of the chip whether the descriptor is that huge. I have also CP2110 development board coming to me this week so I will be able to test everything thoroughly after I get through this initial problems..

I don't think I have to read it. I have found an example (for Linux) of how CP2110 communicates with the host - 

https://github.com/graycatlabs/cp2110-c

 and the whole operation is based on simple reports which have few bytes each so I know how to configure the chip and communicate with it after HID initialization.

I have tried to skip the descriptor read but now it is still stuck forever in USBH_HID_ClassRequest, it cannot get past the HID_REQ_SET_IDLE state, specifically through USBH_HID_SetProtocol(phost,0), it returns USBH_BUSY all the time.

Posted on May 01, 2018 at 16:22

Perhaps this device does not support SET_IDLE request. Try to change this as follows:

case HID_REQ_SET_IDLE:

classReqStatus = USBH_HID_SetIdle (phost, 0, 0);

if (classReqStatus == USBH_OK)

{

    HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL;

}

else if(classReqStatus != USBH_BUSY) // Error: USBH_NOT_SUPPORTED ?

{

    USBH_ErrLog('HID: HID_SetIdle error %d', classReqStatus);

    HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL;

}

break;
Posted on May 01, 2018 at 17:37

Sorry, I made a mistake - it can get into HID_REQ_SET_PROTOCOL state but cannot get through 

USBH_HID_SetProtocol(phost,0).

This is where it gets stuck and cannot proceed. Also, in the HID_REQ_SET_IDLE, the reply of USBH_HID_SetIdle is USBH_NOT_SUPPORTED.
Posted on May 02, 2018 at 01:11

Do the same there: if

classReqStatus

 is not OK and not BUSY, just move to next state

-- pa

Posted on May 02, 2018 at 13:12

It is not BUSY, it is NOT_SUPPORTED, so I skipped it. I got to HID_MenuProcess where I modified the function by adding a new state HID_DEMO_CP2110 where the state machine is redirected if the device different from keyboard and mouse. First time I got a hardfault so I tried to power cycle the board which seems to solve the problem (maybe something 'bad' in RAM was preserved during reprogram, I don't really know). The Appli_state is now APPLICATION_READY. Next I would like to write a HID report to the device - the configuration. According to the library on GitHub as well as the packet information that I read out during the communication of the medical device with the app in PC, the configuration consists of two steps - both are host to device - this payload should be send through HID (in hex) - 41 01 and 50 00 00 4B 00 00 00 03 00. I have tried different combinations of inputs to USBH_HID_SetReport which I have placed inside USBH_CP2110Demo but with no success. It returns USBH_NOT_SUPPORTED. Do you know how to properly use it in order to communicate with the chip?

Here is the complete report from USB sniffer with working communication:

000113: Class-Specific Request (DOWN), 2018-05-02 12:50:0776032 +0.0000372 (1. Device: CP2110 HID USB-to-UART Bridge (CP210x UART Bridge))
Destination: Interface, Index 0
Reserved Bits: 34
Request: 0x9
Value: 0x341
Send 0x2 bytes to the device
41 01


000115: Class-Specific Request (DOWN), 2018-05-02 12:50:0815745 +0.0000188 (1. Device: CP2110 HID USB-to-UART Bridge (CP210x UART Bridge))
Destination: Interface, Index 0
Reserved Bits: 34
Request: 0x9
Value: 0x350
Send 0x9 bytes to the device
50 00 00 4B 00 00 00 03 00
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Marek Novak
Associate II
Posted on May 02, 2018 at 19:05

So I have spent almost the whole day studying the USB HID and I think I am getting closer now. According to the chip documentation, the only communication I will need is Control Out, Interrupt Out and Interrupt In reports. I have studied the structure of the code and it seems that this is covered in whole by the 'core' USB Host library and the HID is more or less a simple configuration and state machine tool for the protocol. So I have tried to use USBH_CtlSendData directly and it does not freezes the MCU and passes with USB_OK. However, when I try to read the configuration of the UART of the chip (report starting with 0x50) with USBH_CtlReceiveData, I am not sure how to do it. I tried to call the USBH_CtlReceiveData with the payload having the first byte 0x50 (to read the UART config of the CP2110 chip) and then I have polled USBH_LL_GetURBState(phost , 0) until it is USBH_URB_DONE but this seems to never happen. Did I make a mistake somewhere? How can I determine the number of pipes which are currently open? Unfortunately I don't have a hardware USB analyzer so I cannot look directly at the USB bus what is happening there.

Posted on May 03, 2018 at 02:32

For a medical project, maybe one should consider a production quality USB library (such as Segger's or Keil's).

The ST library is free, but we pay with our time and effort, right away and during the product lifecycle.

-- pa