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

HID In reports does not trigger Event: APP_USBD_HID_USER_EVT_IN_REPORT_DONE with FreeFRTOS

I am trying to send multiple 64byte packets - in a loop - using app_usbd_hid_generic_in_report_set(). This together with the user event handler happens inside the same FreeRTOS thread.

Since I am in a loop I do not receive the event: APP_USBD_HID_USER_EVT_IN_REPORT_DONE which will allow me to send the next packet.

Question: Is there any other way to determine if the last In report has been successfully transferred which I can monitor in real time.

Perhaps I can monitor it and determine if when I can send the next packet - without waiting for the event handler.

while (currentPkt != NULL) {

        //if report still pending - do not send new packet
        if (!m_report_pending) {
	
            // Check whether data is valid
            if (currentPkt->data != NULL) { // if valid, send it

                m_report_pending = true;

                // Send each packet as IN report to host
                if (app_usbd_hid_generic_in_report_set(uhid_sc_instance,
                                                   currentPkt->data,
                                                   USB_HID_PACKET_SIZE) != NRF_SUCCESS) {
                    NRF_LOG_ERROR("Could not send response packet.");
                    goto end;
                }

            }
            else { // if not, send err packet
                NRF_LOG_WARNING("No valid data to send!");
            }
        
            // Traverse to next packet
            currentPkt = currentPkt->next;
       } 
}

....

//Event Handler
void uhid_sc_ev_handler(app_usbd_class_inst_t const * p_inst,
                                app_usbd_hid_user_event_t event)
{
    // Variables
    size_t outRepLen = 0;
    uint8_t *pOutReport = NULL;

    // Check occured event type
    switch (event)
    {
        // When a report has been received from the HOST
        case APP_USBD_HID_USER_EVT_OUT_REPORT_READY:
        {
            //NRF_LOG_DEBUG("Recevied msg from HOST!");

            // Get pointer OUT report
            pOutReport = app_usbd_hid_generic_out_report_get(uhid_sc_instance, &outRepLen);

            // Send to USB Thread's Queue
            if(uhid_sc_postToUsbThread(pOutReport, outRepLen) != EXIT_SUCCESS) {
                NRF_LOG_ERROR("Could not post post report to USB Thread.");
                NRF_LOG_WARNING("TODO: Pass to error handler thread.");
            }

            break;
        }
        // When a report has been sent to the HOST
        case APP_USBD_HID_USER_EVT_IN_REPORT_DONE:
        {
            // Message has been sent to host
            //NRF_LOG_DEBUG("Message successfully sent to HOST!");
            m_report_pending = false;

            break;
        }
        case APP_USBD_HID_USER_EVT_SET_BOOT_PROTO:
        {
            UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
            NRF_LOG_INFO("SET_BOOT_PROTO");
            break;
        }
        case APP_USBD_HID_USER_EVT_SET_REPORT_PROTO:
        {
            UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
            NRF_LOG_INFO("SET_REPORT_PROTO");
            break;
        }
        default:
            break;
    }
}

....

#define UHID_MNG_REPORT_IN_QUEUE_SIZE 64
#define UHID_MNG_REPORT_OUT_MAX_SIZE 63

//HID Instance
// 2. Build class instance
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_uhid_sc, 
                                USBD_HID_SC_INTERFACE,
                                uhid_sc_ev_handler,
                                (USBD_HID_SC_EPIN, USBD_HID_SC_EPOUT),
                                uhid_sc_reps,
                                UHID_SC_REPORT_IN_QUEUE_SIZE,
                                UHID_SC_REPORT_OUT_MAX_SIZE,
                                APP_USBD_HID_SUBCLASS_NONE,
                                APP_USBD_HID_PROTO_GENERIC);
                                
                                

  • Hi. 

    It is usually not a good idea to wait for an event in an eternal loop (perhaps unless you are doing it the main loop calling sd_app_evt_wait()). This is particularly a bad idea if you are doing it in a interrupt routine or event handler, as it will block the CPU from doing other tasks of lower or same priority.

    A way you could handle this is to wait for the call-back to the event handler. Then, in the event handler you can check for each relevant event and handle those separately. Please refer to examples/ble_peripheral/ble_app_hrs/main.c.
    You should also note that if you want do do a lot of processing, you should not do this in the event handler, as it runs with higher priority (think of it as an interrupt routine), but rather set a flag and do the processing in your main loop.

    You should continue to call sd_app_evt_wait() from your main loop.

    Best regards, 
    Joakim

Related