cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F105/107 HID USB device SET_REPORT, GET_REPORT

steliosioakim
Associate II
Posted on June 21, 2013 at 10:50

Dear all,

I am using the ''STM32_USB-Host-Device_Lib_V2.1.0'', which I think is the only one that fully supports the STM32f105/107 OTG functionality and has a Custom HID demo project, to add USB functionality on my design. I am trying to make the device be recognized as an HID device for input AND output meaning that I want to control my device over a computer software that I've already implemented and successfully used with an STM32F103 series microcontroller.

Unfortunately, the library that was used to implement the embedded software on the STM32F103 does not work with the STM32F105 one and the one that works (''STM32_USB-Host-Device_Lib_V2.1.0'') has only IN functionality implemented.

What I am asking for here is if someone has used the STM32F105 to implement both IN and OUT functionality on their design and which library they've used to do it. Basically the library that I am using now is missing the GET_REPORT function and has only the SEND_REPORT.

Thanks,

Stelios

#hid #usb
10 REPLIES 10
tsuneo
Senior
Posted on June 22, 2013 at 21:22

STM32_USB-Host-Device_Lib_V2.1.0 has just a HID mouse/joystick example.

To change it into a vendor-specific HID, 1) Descriptors bInterfaceSubClass/bInterfaceProtocol field of the interface descriptor - set to 0 for both fields

\STM32_USB-Host-Device_Lib_V2.1.0\Libraries\STM32_USB_Device_Library\Class\hid\src\usbd_hid_core.c
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
...
/************** Descriptor of Joystick Mouse interface ****************/
...
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ // <----- 0
0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/ // <----- 0

Replace the report descriptor

\STM32_USB-Host-Device_Lib_V2.1.0\Libraries\STM32_USB_Device_Library\Class\hid\inc\usbd_hid_core.h
#define HID_MOUSE_REPORT_DESC_SIZE 74 // <--- set to the size of your report descriptor
usbd_hid_core.c
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
// <--- fill your report descriptor
};

2) Interrupt OUT endpoint Add an endpoint descriptor for the interrupt OUT endpoint

usbd_hid_core.h
#define USB_HID_CONFIG_DESC_SIZ 34 // <--- (34 + 7)
usbd_hid_core.c
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
...
/************** Descriptor of Joystick Mouse interface ****************/
...
0x01, /*bNumEndpoints*/ // <------ 2
...
/* 34 */
// <------ append an endpoint descriptor
0x07, /*bLength: Endpoint Descriptor size*/
USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
HID_OUT_EP, /*bEndpointAddress: Endpoint Address (OUT)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_OUT_PACKET, /*wMaxPacketSize: 4 Byte max */
0x00,
0x0A, /*bInterval: Polling Interval (10 ms)*/
} ;

USBD_HID_Init() already opens the HID_OUT_EP. Add DCD_EP_PrepareRx() call to this subroutine.

usbd_hid_core.c
static uint8_t USBD_HID_Init (void *pdev, 
uint8_t cfgidx)
{
...
/* Open EP OUT */
DCD_EP_Open(pdev,
HID_OUT_EP,
HID_OUT_PACKET,
USB_OTG_EP_INT);
// <----- add these lines
/* Prepare Out endpoint to receive next packet */
DCD_EP_PrepareRx(pdev,
HID_OUT_EP,
(uint8_t*)(USB_Rx_Buffer),
HID_OUT_PACKET);
return USBD_OK;
}

When the OUT endpoint has received a packet, DataOut callback is called. Register usbd_hid_DataOut() callback to USBD_HID_cb on DataOut position.

usbd_hid_core.c
static uint8_t usbd_hid_DataOut (void *pdev, uint8_t epnum);
USBD_Class_cb_TypeDef USBD_HID_cb = 
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /*EP0_TxSent*/ 
NULL, /*EP0_RxReady*/
USBD_HID_DataIn, /*DataIn*/
NULL, /*DataOut*/ // <---- usbd_hid_DataOut
static uint8_t usbd_hid_DataOut (void *pdev, uint8_t epnum)
{ 
uint16_t USB_Rx_Cnt;
/* Get the received data buffer and update the counter */
USB_Rx_Cnt = ((USB_OTG_CORE_HANDLE*)pdev)->dev.out_ep[epnum].xfer_count;
//
// process received data on USB_Rx_Buffer[], here
//
/* Prepare Out endpoint to receive next packet */
DCD_EP_PrepareRx(pdev,
CDC_OUT_EP,
(uint8_t*)(USB_Rx_Buffer),
CDC_DATA_OUT_PACKET_SIZE);
return USBD_OK;
}

Tsuneo
steliosioakim
Associate II
Posted on July 02, 2013 at 11:04

Thanks a lot for your answer. We've now managed to implement this and the device is now recognized as both input and output HID. Using an HID tester we've tested it and the computer sends data to the device successfully. Unfortunately though we have a small (I think) issue with receiving data from the device. We send 4 8 bit words using a buffer but we do not receive the data that we send consistently, I mean, at some point of continuously receiving data we obtain exactly the correct data that we send but most of the times we get rubbish that we did not send. We've tried a lot of things but we could not find what the problem is. Did anyone come across this issue? What should we check?

Thanks,

Stelios
tsuneo
Senior
Posted on July 02, 2013 at 15:39

In the HID example, SysTick_Handler() sends the input report repeatedly.

Delete this code.

STM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\HID\src\stm32fxxx_it.c
void SysTick_Handler(void)
{
uint8_t *buf;
buf = USBD_HID_GetPos();
if((buf[1] != 0) ||(buf[2] != 0))
{
USBD_HID_SendReport (&USB_OTG_dev, 
buf,
4);
} 
}

Tsuneo
steliosioakim
Associate II
Posted on July 09, 2013 at 12:30

Thank you very much for your help. That was indeed part of the problem. Now everything works apart from the bug that sometimes when the usb is disconnected the RTOS running on the processor stops running and when the usb is connected back again it continues doing what it was doing before the disconnection. I know this may sound weird but if I remove the usb cable from the  computer slowly and very gentle this does not happen and the disconnection goes smoothly without interrupting the RTOS.

I am not sure if this is a hardware or a software issue. Have you ever experienced such a situation?

Thanks again.
justinwoolich
Associate III
Posted on April 03, 2014 at 18:34

Hi, thanks for posting this info up I have found it very useful for implementing a custom HID application. I am using a STM32F105 with a custom HID using the above information, it works fine except when i try to implement Report ID's, I can receive data into the STM32 but I can not send data out. I have tried various different report descriptors. I think the problem may be that I need to set the report id when sending data out of the STM32 but i dont know where i should do this. I have tried setting the first byte in the report array but it appears as though this is not used as the report ID. below is my report descriptor

This works with no Report ID's

0x06, 0x00, 0xff,                   // USAGE_PAGE (Vendor Defined Page 1)

0x09, 0x01,                         // USAGE (Vendor Usage 1)

0xa1, 0x01,                         // COLLECTION (Application)

// ------ common globals ------

0x15, 0x00,                         //   LOGICAL_MINIMUM (0)

0x26, 0xff, 0x00,                   //   LOGICAL_MAXIMUM (255)

0x75, 0x08,                         //   REPORT_SIZE (8)   - bits

// ------ input report ------

0x95, 0x3F,   //   REPORT_COUNT      - bytes

0x09, 0x01,                         //   USAGE (Vendor Usage 1)

0x81, 0x02,                         //   INPUT (Data,Var,Abs)

// ------ output report ------

0x95, 0x3F, //   REPORT_COUNT      - bytes

0x09, 0x01,                         //   USAGE (Vendor Usage 1)

0x91, 0x02,                         //   OUTPUT (Data,Var,Abs)

0xc0                                // END_COLLECTION

but when i add in the report ID's to the report descriptor i can receive data on the STM32 that is sent with the report id 3 but data that is sent out of the STM32 does not arrive at the computer

0x06, 0x00, 0xff,                   // USAGE_PAGE (Vendor Defined Page 1)

0x09, 0x01,                         // USAGE (Vendor Usage 1)

0xa1, 0x01,                         // COLLECTION (Application)

// ------ common globals ------

0x15, 0x00,                         //   LOGICAL_MINIMUM (0)

0x26, 0xff, 0x00,                   //   LOGICAL_MAXIMUM (255)

0x75, 0x08,                         //   REPORT_SIZE (8)   - bits

// ------ input report ------

0x85, 0x03,

0x95, 0x3F,   //   REPORT_COUNT      - bytes

0x09, 0x01,                         //   USAGE (Vendor Usage 1)

0x81, 0x02,                         //   INPUT (Data,Var,Abs)

// ------ output report ------

0x85, 0x04,

0x95, 0x3F, //   REPORT_COUNT      - bytes

0x09, 0x01,                         //   USAGE (Vendor Usage 1)

0x91, 0x02,                         //   OUTPUT (Data,Var,Abs)

0xc0                                // END_COLLECTION

tsuneo
Senior
Posted on April 06, 2014 at 19:07

> i can receive data on the STM32 that is sent with the report id 3

??? Your report descriptor assigns Report ID: 3 to the input report. Do you mean Report ID: 4, which is assigned to the output report? > but data that is sent out of the STM32 does not arrive at the computer Did you modify these macros in usbd_conf.h? These values are assigned to the wMaxPacketSize of the endpoint descriptors.

usbd_conf.h
#define HID_IN_PACKET 4 // <---- 0x40
#define HID_OUT_PACKET 4 // <---- 0x40

Tsuneo
justinwoolich
Associate III
Posted on April 10, 2014 at 04:22

Hi thanks for responding.

Report ID 3 is working for input reports, but i can not work out how to set Report ID 4 for output reports, i have tried setting the first byte of the buffer used to send the report using USBD_HID_SendReport function but it does not seem to work.

I have changed the macros for the packet size, and it is working fine sending and receiving 64 bytes, the problem is just setting the report id for the output report.

If i remove the Report IDs from the Report Descriptor i can send and receive 64 byte reports with Report ID 0.

tsuneo
Senior
Posted on April 10, 2014 at 08:03

> If i remove the Report IDs from the Report Descriptor i can send and receive 64 byte reports with Report ID 0.

Sound like a problem on the host side.

Do you work on Windows?

To send 64-bytes output report with no report ID,

your PC app calls WriteFile() with 65 bytes buffer,

the first byte: 0, and 64 bytes body follows.

- The firmware receives just 64 bytes body, without the report ID field.

To send 63-bytes output report with report ID 4,

your PC app calls WriteFile() with 64 bytes buffer,

the first byte: 4, and 63 bytes body follows.

- The firmware receives 64 bytes, the report ID(4) and 63 bytes body.

Tsuneo

mike9307033
Associate II
Posted on March 12, 2015 at 10:37

this topic is very usefull.

i got another question. I'm using the same ic STM32F105, and i used STM32F103 before.

I want to output more than 64 byte data in to MPU in sereval time, but the data is in same part.

the code below:

void EP1_OUT_Callback(void)

{

  __IO uint16_t wEPVal = 0;

  u32 volatile n;

    PMAToUserBufferCopy(&USB_Receive_Buffer[USB_Receive_Length], ENDP1_RXADDR, REPORT_COUNT);

    USB_Receive_Length += 64;

    

    SetEPRxStatus(ENDP1, EP_RX_VALID);

    

    // wait for the interrupt

    n = 5333 * 5;

    while(n--);

    // check if this is the last packet

    wIstr = _GetISTR();

    if((wIstr & ISTR_CTR) == 0)

    {

        USB_Received_Flag = 1;

    }

}

but now i can't find USB_ISTR register now, how can i access the H/W Flag to check ISTR?