This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Problems with OUT reports on USB HID

Hi,

I'm using the NRF52840 PDK version:

PCA10056

0.11.0

2018.3

With SDK version 15.2

I've been trying to develop an application based on the HID Generic example and am seeing some strange behaviours on the USB HID OUT endpoint.

I try to obtain the data in the APP_USBD_HID_USER_EVT_OUT_REPORT_READY event, at which point I use app_usbd_hid_generic_out_report_get to retrieve the data for processing in my main loop.

After more tracing and debugging, I've found that the hid_generic_ep_transfer_out handler is called when the OUT endpoint is busy.  When this happens the app_usbd_ep_transfer fails and app_usbd proceeds to stall the endpoint (in app_usbd_event_execute).

How can I avoid this situation?

Thanks,

Larry

Parents
  • Hi Larry,

    Do you have the possibility to order yourself a new nRF52840-DK, the preview kit you have contains engineering samples that have not gone through production test, and may thereby contain issues. What SDK example are you using for this test?

    Best regards,
    Kenneth

  • I'm using some code that I modified based on a sample.
    I can try to get a sample working as out of the box provided I can get the same test data to send to it.

    I can order another PDK.  I originally had 4 with engineering Rev A chips on it.  Then I ordered another because of USB issues and that one I believe is Rev B.  Are you saying that there are PDKs available which production chips on them?

    I also have some dongles (a few Nordic nRF52840 Dongles and some from MakerDiary nrf52840-mdk-usb-dongle).
    I'm hoping to get the application running on those so I can see if the problem still exists because I believe that they are using production chips.

    Larry

    I have some more information.  The issue only seems to occur when rapid HID frames are sent in succession.
    The test tool I'm using is from the FIDO Alliance.   One of the tests requires the device to pass a long echo, which can span multiple frames (a frame is 64 bytes - header information).
    So when I reduce my tests so that the message is always 64 bytes or less and I don't see any problems.

    Also, the SDK example I started from is the usbd_hid_generic example.
    The issue is with using that example is that it only has one IN endpoint.  I had to add another OUT endpoint for my application.  It will take a bit of effort to try to get it working.

    Both endpoints are of size 64 bytes.


    Larry

  • Hi Larry,

    The PDK go are no longer in production no, they are all DK v1.0.0 now. The build code should be QIAAC0 (or newer if someone read this in the future).

    Best regards,
    Kenneth

  • OK.  The USB dongles I have are QIAAC0.  Still trying to get them to work...

    I have added a small (5 ms) delay between HID frames on the FIDO test harness.
    This seems to make the problem go away (at least it is orders of magnitude better).
    Unfortunately, this is not a real solution as we don't control the host software in the real world.

    Larry

  • Are you able to provide a simple example that we may use to recreate it here?

    Please provide where I should put the project in the sdkv15.2 and also which project path I should open.

    Thanks,
    Kenneth

Reply Children
  • OUT report size has been limited to 64 bytes (63 data + 1 id) in SDK v15.1. But this should assert when size is too big. 

    It would be easier to understand what is failing with an example project.

    Best regards,
    Kenneth

  • I'm working on it (I'm trying to derive something simple from an example, but it's not that easy).
    Anyway, once I get it working, can you tell me how I should package it for you (i.e. where can I provide you with a zip file)?

  • OK,  I've managed to reproduce the problem in a "simple" project.
    I based the project on the ble_app_blinky example, mainly because my application also uses BLE.
    You can replace the entire ble_app_blinky folder with my supplied project and it should work./

    It's using the SDK as is, except I modified app_usbd_hid_generic.c to log the status of the out transfer (see code snippet).

    I'm using Segger embedded Studio 3.52 and am testing on my PCA10056 PDK.
    How shall I deliver the zip file and command line test application?

    static ret_code_t hid_generic_ep_transfer_out(app_usbd_class_inst_t const * p_inst)
    {
    
        app_usbd_hid_generic_t const * p_generic = hid_generic_get(p_inst);
        nrf_drv_usbd_ep_t              ep_addr   = app_usbd_hid_epout_addr_get(p_inst);
    
        /*Request setup data*/
        app_usbd_hid_report_buffer_t const * p_rep_buff;
    
        p_rep_buff = app_usbd_hid_rep_buff_out_get(&p_generic->specific.inst.hid_inst);
        NRF_DRV_USBD_TRANSFER_OUT(transfer, p_rep_buff->p_buff, p_rep_buff->size);
    
        ret_code_t ret = app_usbd_ep_transfer(ep_addr, &transfer);
        NRF_LOG_INFO("hid_generic OUT %d", ret ); 
        return ret;
    }
    
    
  • I also had to modify app_usbd_hid_generic_idle_report_set to declare the ret_code_t outside of the CRITICAL_REGION_ENTER, otherwise it would not compile  (I'm rather confused about this.  Perhaps I have a configuration issue).

    ret_code_t app_usbd_hid_generic_idle_report_set(app_usbd_hid_generic_t const * p_generic,
                                                    const void                   * p_buff,
                                                    size_t                         size)
    {
        app_usbd_class_inst_t const  * p_inst        = (app_usbd_class_inst_t const *)p_generic;
        app_usbd_hid_generic_ctx_t   * p_generic_ctx = hid_generic_ctx_get(p_generic);
    
        nrf_drv_usbd_ep_t ep_addr = app_usbd_hid_epin_addr_get(p_inst);
    
        app_usbd_hid_state_flag_clr(&p_generic_ctx->hid_ctx,
                                    APP_USBD_HID_STATE_FLAG_TRANS_IN_PROGRESS);
    
        NRF_DRV_USBD_TRANSFER_IN(transfer, p_buff, size);
    
        ret_code_t ret;
        CRITICAL_REGION_ENTER();
        ret = app_usbd_ep_transfer(ep_addr, &transfer);
        if (ret == NRF_SUCCESS)
        {
            app_usbd_hid_state_flag_set(&p_generic_ctx->hid_ctx,
                                        APP_USBD_HID_STATE_FLAG_TRANS_IN_PROGRESS);
        }
        CRITICAL_REGION_EXIT();
    
        return ret;
    }
    
    
Related