cancel
Showing results for 
Search instead for 
Did you mean: 

How to send USB HID Reports without guessing the HAL_Delay()?

smoothmanifolds
Associate III

I want to send USB HID Reports as fast as the MCU or the USB protocol allows.

 

In order to send an USB HID Report on an STM32F103 I'm doing something like:

 

USBD_HID_SendReport(&hUsbDeviceFS, (u8*)&report,sizeof(report));
HAL_Delay(some_delay);

 

or even:

 

USBD_HID_SendReport(&hUsbDeviceFS, (u8*)&report,sizeof(report));
for(volatile int k=0; k<some_other_delay; ++k)  asm volatile("nop");

 

but it's obviously dicey and suboptimal to "guess" at the correct sleep value (which in my case changes from situation to situation, and also depending on the size of the USB HID Report).

 

What I really want is to do is something like:

 

for(int i=0; i<N; ++i)  USBD_HID_SendReport(&hUsbDeviceFS, (u8*)&report,sizeof(report));

 

and have it just work (which it currently doesn't).

 

I tried modifying USBD_HID_SendReport() from the original:

 

 

uint8_t USBD_HID_SendReport(USBD_HandleTypeDef* pdev, uint8_t* report, uint16_t len){
	USBD_HID_HandleTypeDef* hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData;

	if(pdev->dev_state==USBD_STATE_CONFIGURED){
		if(hhid->state==HID_IDLE){  // if it's not idle, then it discards!
			hhid->state = HID_BUSY;
			USBD_LL_Transmit(pdev, HID_EPIN_ADDR, report, len);
		}
	}
	return USBD_OK;
}

 

 

to the following:

 

uint8_t USBD_HID_SendReport(USBD_HandleTypeDef* pdev, uint8_t* report, uint16_t len){
	USBD_HID_HandleTypeDef* hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData;

	if(pdev->dev_state==USBD_STATE_CONFIGURED){
		while(hhid->state!=HID_IDLE)  asm volatile("nop");
		hhid->state = HID_BUSY;
		USBD_LL_Transmit(pdev, HID_EPIN_ADDR, report, len);
	}
	return USBD_OK;
}

 

 but it's not working as intended.

 

So how I can achieve the desired result of sending USB HID Reports as fast as possible, without any manual wait, ie. something like:

 

for(int i=0; i<N; ++i)  USBD_HID_SendReport(&hUsbDeviceFS, (u8*)&report,sizeof(report));

 

 

5 REPLIES 5
smoothmanifolds
Associate III

False alarm; I don't know what I was doing wrong. This actually works.

smoothmanifolds
Associate III

But I still wonder if there's something wrong with this approach.

I may have found a situation where it's not working as intended.

FBL
ST Employee

Hi @smoothmanifolds 

I suggest ensuring that the endpoint is ready before sending the next report. 

 

I rephrase my answer: 

>> In HID class, we need to check first item in report descriptor, the remaining size of data or query the poll time from EP descriptor using USBD_HID_GetPollingInterval()

 

Also, you may need to check USB traffic if you observe NAKs from device side to make sure if the device is limiting the throughput.

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.

Hi @FBL how can I add a callback or use a SW flag?

How can I check (on the USB device) that the transmission is complete or that the USB endpoint is ready?

FBL
ST Employee

Hi @smoothmanifolds 

To clarify, we check if the size of the first bits in HID_Buffer (which indicates the size of the remaining data) is zero. If it is, we can proceed to call SendReport again.

https://github.com/STMicroelectronics/STM32CubeF1/blob/ac682c6bc31ea589f3c552531171aa0c9faeb0a9/Projects/STM3210E_EVAL/Applications/USB_Device/HID_Standalone/Src/stm32f1xx_it.c#L152

 

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.