Skip to main content
Vu.Andy
Associate III
October 10, 2016
Question

Looking for USB HID project example that receives command from PC then display LED?

  • October 10, 2016
  • 5 replies
  • 1266 views
Posted on October 11, 2016 at 00:55

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.
    This topic has been closed for replies.

    5 replies

    Senior III
    October 11, 2016
    Posted on October 11, 2016 at 11:15

    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).

    Vu.Andy
    Vu.AndyAuthor
    Associate III
    October 11, 2016
    Posted on October 11, 2016 at 17:01

    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.

    Senior III
    October 12, 2016
    Posted on October 12, 2016 at 12:57

    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...
    slimen
    Visitor II
    October 12, 2016
    Posted on October 12, 2016 at 13:12

    Hello,

    For more details, on how you use the STM32Cube USB device library, you can refer to this 

    http://www.st.com/content/ccc/resource/technical/document/user_manual/cf/38/e5/b5/dd/1d/4c/09/DM00108129.pdf/files/DM00108129.pdf/jcr:content/translations/en.DM00108129.pdf

    : STM32Cubeâ„¢ USB device library.

    Regards

    Vu.Andy
    Vu.AndyAuthor
    Associate III
    October 18, 2016
    Posted on October 18, 2016 at 17:00

    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).