2016-10-10 03:55 PM
I am looking for an USB HID example that the firmware would receives for example a command from the PC then based on the input command, would display a few LED.
Currently there are a few examples from STM but it seems like only a one way communication in which the mouse would SendReport() in a while() loop. But I am looking for an example in which the firmware would receive various commands from the PC then based on that, decides what to do in a 2-way communication. Thanks.2016-10-11 02:15 AM
Hi, can you specify the part you are using ?
You might want to look into the custom hid examples to have a 2 way communication. But even on the mouse example you saw, the device use the endpoint 1 to send data (mouse coordinates) to the PC, and the PC can send data to the device using the endpoint 0 (which is a bidirectional endpoint).2016-10-11 08:01 AM
Thanks for the reply. I am using the STM32F446ZE-Nucleo board.
First I am still new to USB HID so some of what I say may be obvious. The mouse example although it has 2-way communication, I think the communication from the PC is only for the STANDARD request such as such as get_descriptor, get_interface .... and so on. The main program has a while loop that it would loop and USBD_HID_SendReport() and beyond that it doesn't really process any custom information from the PC. I am also looking at the custom HID example, and there appears to be a fops which probably handles custom request (or CLASS request), but I am not quite sure. If you're familiar with this example, maybe you could point to some specifics. USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops = { CustomHID_ReportDesc, CustomHID_Init, CustomHID_DeInit, CustomHID_OutEvent, }; Eventually I am looking to build an HID application to communicate with the uC from the PC, then using the uC I/O to control other parts of the board which is mostly what it is used for in most cases I think.2016-10-12 03:57 AM
Unfortunately I'm using a F0 part, and the USB lib is slightly different.
Nevertheless, in the USB device lib for F0x2 that I'm using, there is a file called ''usbd_custom_hid_core.c'' which has a structure of callbacks a bit like your fops :USBD_Class_cb_TypeDef USBD_HID_cb =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL,
/*EP0_TxSent*/
USBD_HID_EP0_RxReady,
/*EP0_RxReady*/
/* STATUS STAGE IN */
USBD_HID_DataIn,
/*DataIn*/
USBD_HID_DataOut,
/*DataOut*/
NULL,
/*SOF */
USBD_HID_GetCfgDesc,
};
Here I can receive data from the PC with the callback USBD_HID_DataOut, and send data to it with USBD_HID_DataIn. There is a pdf explaining some of the internals of the lib on the ST download web page. It maybe be a good start for you.
Or maybe Tsuneo could help you with this...
2016-10-12 04:12 AM
Hello,
For more details, on how you use the STM32Cube USB device library, you can refer to this : STM32Cubeâ„¢ USB device library.Regards2016-10-18 08:00 AM
Thanks for the example. I'll look into that although I am still trying to understand the flow of the Data_In() and Data_Out().
I found the example in the DFU project that provides at least part of what I need. I don't think DFU is a HID but they are similar. In the DFU example, first the fobs is defined along with a set of functions that will be calling the fops. These will be part of the CLASS_REQUEST. In the custom HID example that you posted, the DataIn() and DataOut() are still of the standard request, so I am trying to see if we can define a set of custom request to make things a little easy. So in the DFU example, it has something similar to what I am looking for. USBD_DFU_MediaTypeDef USBD_DFU_Flash_fops= { (uint8_t *)FLASH_DESC_STR, Flash_If_Init, Flash_If_DeInit, Flash_If_Erase, Flash_If_Write, Flash_If_Read, Flash_If_GetStatus, }; static void DFU_Detach (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); static void DFU_Download (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); static void DFU_Upload (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); static void DFU_GetStatus (USBD_HandleTypeDef *pdev); static void DFU_ClearStatus (USBD_HandleTypeDef *pdev); static void DFU_GetState (USBD_HandleTypeDef *pdev); static void DFU_Abort (USBD_HandleTypeDef *pdev); static void DFU_Leave (USBD_HandleTypeDef *pdev); Then a set of enum is defined to match that fops and the corresponding functions. typedef enum { DFU_DETACH = 0, DFU_DNLOAD , DFU_UPLOAD, DFU_GETSTATUS, DFU_CLRSTATUS, DFU_GETSTATE, DFU_ABORT } DFU_RequestTypeDef; Then at the USBD_DFU_Setup() function, the switch statement will detect which is being request and call the corresponding function accordingly. static uint8_t USBD_DFU_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { uint8_t *pbuf = 0; uint16_t len = 0; uint8_t ret = USBD_OK; USBD_DFU_HandleTypeDef *hdfu; hdfu = (USBD_DFU_HandleTypeDef*) pdev->pClassData; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case DFU_DNLOAD: DFU_Download(pdev, req); break; case DFU_UPLOAD: DFU_Upload(pdev, req); break; case DFU_GETSTATUS: DFU_GetStatus(pdev); break; .......... The hard thing for me about USB is that not only you have to understand the codes which is quite a bit of work, you have to understand the standard which can take a lot of time, and you also have to know how to write the driver to test out your USB firmware (unless you know someone who can do it for you).