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 Kenneth,

    I have more information.
    Our HID polling interval was set at 5ms (the recommendation by FIDO Alliance).
    When I set it to 16ms, it seems to avoid the OUT endpoint problem I've been experiencing.

    Larry

  • Hi Kenneth,

    We are failing the FIDO2 Conformance tool test suite with exactly the issue I have documented here.
    The change in the polling interval doesn't help very much after all.


    We really need to have some attention to this since we are now at risk of NOT having a viable product.

    Much time and effort has been put into this project and I have tried to do as much as possible to work around the issue without success.

    Can you please answer this post?

    Thank you,
    Larry

  • I understand, I can check with the team.

    Best regards,
    Kenneth

  • They have found an issue in your application, do the following:

    • replace bluink_process_usb_events() with:

    void bluink_process_usb_events( void )
    {
       while ( 1 ) 
       {
          app_usbd_event_queue_process();
       }
    }
    

    • in hid_u2f_user_ev_handler() in switch, replace case for APP_USBD_HID_USER_EVT_OUT_REPORT_READY with:

    case APP_USBD_HID_USER_EVT_OUT_REPORT_READY:
    {
          m_report_received += 1;
          size_t recv_size;            
          uint8_t *p_recv_buf = (uint8_t *)app_usbd_hid_generic_out_report_get(&m_app_hid_u2f, &recv_size);
          app_usbd_hid_generic_in_report_set(&m_app_hid_u2f, p_recv_buf, recv_size);
          break;
    }
    

    Please confirm this fixed the issue.

  • Hi Kenneth,

    Indeed, it has illustrated to me how to fix my issue.  Thank you very much!
    I was able to use the blinky test with your changes and I could send arbitrarily large messages at full speed.  I had to do quite a bit of experimenting to make this work with my use case:

    The challenge I have is that I am processing large messages coming from USB and sending them off through BT and responding (receiving BT then responding over USB).
    So I have to be able to manage buffers between USB and BT.

    I have some observations that I'd like to share and would like it if you could comment on them:

    1) If I process USB too fast (calling app_usbd_event_queue_process() too fast), then I run into the OUT endpoint issue.  I believe the root cause is that I need to have enough time to process the data before the next OUT event comes through.

    2) It seems that if I process USB too slow (i.e. not calling app_usbd_event_queue_process() often enough) that the device eventually hangs.  My guess is that the event queue fills up and things just can't go on.

    The trick was finding a balance between the two which can allow the BT processing that I need to do at the same time.
    Can you confirm that my understanding of app_usbd_event_queue_process() is correct?

    Again, thanks for your help.
    Larry

Reply
  • Hi Kenneth,

    Indeed, it has illustrated to me how to fix my issue.  Thank you very much!
    I was able to use the blinky test with your changes and I could send arbitrarily large messages at full speed.  I had to do quite a bit of experimenting to make this work with my use case:

    The challenge I have is that I am processing large messages coming from USB and sending them off through BT and responding (receiving BT then responding over USB).
    So I have to be able to manage buffers between USB and BT.

    I have some observations that I'd like to share and would like it if you could comment on them:

    1) If I process USB too fast (calling app_usbd_event_queue_process() too fast), then I run into the OUT endpoint issue.  I believe the root cause is that I need to have enough time to process the data before the next OUT event comes through.

    2) It seems that if I process USB too slow (i.e. not calling app_usbd_event_queue_process() often enough) that the device eventually hangs.  My guess is that the event queue fills up and things just can't go on.

    The trick was finding a balance between the two which can allow the BT processing that I need to do at the same time.
    Can you confirm that my understanding of app_usbd_event_queue_process() is correct?

    Again, thanks for your help.
    Larry

Children
  • 1. Calling `app_usbd_event_queue_process()` too often should not pose a problem. As soon as data is processed, it should be passed to the USB stack with `app_usbd_hid_generic_in_report_set()`. With no events left to process, USB stack just waits. But if you need a lot of time to process BLE data, calling `app_usbd_event_queue_process()` when there is no need may lead to slower processing.


    2. On the other hand, calling `app_usbd_event_queue_process()` too rarely is a problem - some events are not processed in time (which in this case lead to STALL of OUT reports).

    Best regards,
    Kenneth

  • Hello Larry, 

    Can you please share with me how this helped you fixed the issue? I am facing a similar issue and following the above discussions did not help me find the problem.

    Thanks

  • Yes.  The modified blinky project that was uploaded in this ticked illustrates the problem.  Kenneth was able to provide changes that made the issue go away.  That proved that a solution does exist.
    For my application I had to make sure that I was always able to process an OUT report as soon as I get the event (it meant I needed more buffers).  At the same time, I had to call app_usbd_event_queue_process() often enough to keep up with USB events.

    I hope that helps you.

    Larry

  • Thanks a lot Larry. I also followed the suggestions. What do you mean by calling app_usbd_event_queue_process() often enough? I saw you call it in bluink_process_usb_events (i.e., in the while loop as suggested by Kenneth)? Do you call it somewhere else as well?

    Much appreciated

    Hamed

  • In my real application, it's a bit trickier than a simple while loop, since I have to service BT events too.  I have to also worry about not starving BT.  It is in a while loop but being managed with other things at the same time.

Related