Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Cannot receive Data through USB HID from PC

Hi  Guys,

               I want to implement a Vendor-defined USB HID device,But encountered the following problems:

                   1.When the PC sends data via USB HID , the slave(52840) cannot enter the response Event (APP_USBD_HID_USER_EVT_OUT_REPORT_READY) in main.c , i can not  use app_usbd_hid_generic_out_report_get fuction  to  receive data  in  hid_user_ev_handler。

                   2. The received data and data length are incorrect ,Data is all zerohid_generic_ep_transfer_out function  in app_usbd_hid_generic.c)

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);
     bsp_board_led_on(3);
    NRF_LOG_INFO("p_rep_buff->size :%d , data:", p_rep_buff->size);
   NRF_LOG_HEXDUMP_INFO( p_rep_buff->p_buff, p_rep_buff->size);
    return app_usbd_ep_transfer(ep_addr, &transfer);
}

LOG:

 0> <info> app: p_rep_buff->size :32 , data:
 0> <info> app:  00 00 00 00 00 00 00 00|........
 0> <info> app:  00 00 00 00 00 00 00 00|........
 0> <info> app:  00 00 00 00 00 00 00 00|........
 0> <info> app:  00 00 00 00 00 00 00 00|........

        I want to where code is wrong,Below is my code:

#define HID_VENDOR_OUT_INTERFACE  	4
#define HID_VENDOR_OUT_EPIN       NRFX_USBD_EPOUT4

#define VENDOR_OUT_ENDPOINT_LIST()                                 \
(                                                            	\
				HID_VENDOR_OUT_EPIN                          							\
)

#define APP_USBD_VENDOR_OUT_REPORT_DSC() { \
    0x06, 0x00, 0xff, /* Usage Page (Vendor Defined 0xFF00) */	\
	0x09,0x01, \
    0xA1, 0x01,     /* Collection (Application) */\
	0x0A, 0x01, 0xff, /* Usage (0xFF01) */				\
	0x15, 0x00,       /* Logical Minimum (0) */			\
	0x26, 0xff, 0x00, /* Logical Maximum (255) */			\
	0x75, 0x08,       /* Report Size (8) */				\
	0x95, 29,       /* Report Count */		\
	0x91, 0x02,        /* Feature (Data, Variable, Absolute) */	\
    0xC0,\
}

APP_USBD_HID_GENERIC_SUBCLASS_REPORT_DESC(vendor_out,APP_USBD_VENDOR_OUT_REPORT_DSC());

static const app_usbd_hid_subclass_desc_t * vendor_out_reps[] = {&vendor_out};


APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_vendor_out,
                                HID_VENDOR_OUT_INTERFACE,
                                hid_user_ev_handler,
                                VENDOR_OUT_ENDPOINT_LIST(),
                                vendor_out_reps,
                                REPORT_IN_QUEUE_SIZE,
                                REPORT_OUT_MAXSIZE,
                                REPORT_FEATURE_MAXSIZE,
                                APP_USBD_HID_SUBCLASS_BOOT,
                                APP_USBD_HID_PROTO_KEYBOARD);    
                  
                               
app_usbd_class_inst_t const * class_inst_generic5;
class_inst_generic5 = app_usbd_hid_generic_class_inst_get(&m_app_hid_vendor_out);

ret = hid_generic_idle_handler_set(class_inst_generic5, idle_handle);
APP_ERROR_CHECK(ret);

ret = app_usbd_class_append(class_inst_generic5);
APP_ERROR_CHECK(ret);

         Looking forward to your reply。


                    

 

 

 

              

              

  • I noticed that when the PC sent data, the program gave a warning in nrfx_usbd.c  line 1192。

    (NRFX_USBD_EP_WAITING,  /**< Data received, no buffer prepared already - waiting for configured transfer. */)

    SDK17.02
    
    /**
     * @brief React on data transfer finished.
     *
     * Auxiliary internal function.
     * @param ep     Endpoint number.
     * @param bitpos Bit position for selected endpoint number.
     */
    static void usbd_ep_data_handler(nrfx_usbd_ep_t ep, uint8_t bitpos)
    {
         ...
      
        if (NRF_USBD_EPIN_CHECK(ep))
        {
           ....
        }
        else
        {
            /* OUT endpoint (Host -> Device) */
            if (0 == (m_ep_dma_waiting & (1U << bitpos)))
            {
                NRFX_LOG_DEBUG("USBD event: EndpointData: Out waiting");
                /* No buffer prepared - send event to the application */
                NRFX_USBD_EP_TRANSFER_EVENT(evt, ep, NRFX_USBD_EP_WAITING);  // here
                m_event_handler(&evt);
            }
        }
    }

    I want to know how to set the receive buffer of the endpoint ?

  • Thanks for you reply,I ran into another problem。The first packet of data sent by the PC was successfully received, and the second packet of data failed to be received。

    The packet capture tool shows that the second packet of data was unsuccessful, and the device entered the stall pid.

     Function returns  failed  in  p_ep_conf->event_handler() function ( in app_usbd.c)

    void app_usbd_event_execute(app_usbd_internal_evt_t const * const p_event)
    {
        ASSERT(NULL != m_p_first_cinst);
        /* If no event queue is implemented, it has to be ensured that this function is never called
         * from the context higher than USB interrupt level
         * If queue is implemented it would be called always from Thread level
         * if the library is used correctly.
         * NOTE: Higher interrupt level -> lower priority value.
         */
        ASSERT(USBD_CONFIG_IRQ_PRIORITY <= current_int_priority_get());
        bsp_board_led_invert(2);
        /* Note - there should never be situation that event is generated on disconnected endpoint */
        switch (p_event->type)
        {
           
            ....
          
            case APP_USBD_EVT_DRV_EPTRANSFER:
            {
                app_usbd_ep_conf_t const * p_ep_conf =
                        app_usbd_ep_conf_access(p_event->drv_evt.data.eptransfer.ep);
                ASSERT(NULL != p_ep_conf->p_cinst);
                ASSERT(NULL != p_ep_conf->event_handler);
    
        	if (NRF_DRV_USBD_EPOUT4 == p_event->drv_evt.data.eptransfer.ep) {
        			static uint8_t receive_buffer[64];
        			static nrf_drv_usbd_ep_transfer_t usb_tranfer;
        		if (NRF_USBD_EP_WAITING == p_event->drv_evt.data.eptransfer.status) {
        				usb_tranfer.p_data.rx = receive_buffer;
        				usb_tranfer.size = 64;
        				int ret = nrf_drv_usbd_ep_transfer(p_event->drv_evt.data.eptransfer.ep, &usb_tranfer);
        
        		} else if (NRF_USBD_EP_OK == p_event->drv_evt.data.eptransfer.status) {
        			size_t size = 0;
        			nrf_drv_usbd_ep_status_get(p_event->drv_evt.data.eptransfer.ep, &size);
        				printf("Received %d bytes:\n", size);
        				for (int i = 0; i < size; i++) printf("0x%02X ", receive_buffer[i]);
        				printf("\n");
        		} else {
        			printf("Transfer failed on EPOUT1: %d\n", p_event->drv_evt.data.eptransfer.status);
        		}
        	}       
    
            
                if (NRF_SUCCESS != p_ep_conf->event_handler(p_ep_conf->p_cinst,
                                                           (app_usbd_complex_evt_t const *)p_event))   // not success here
                {
                    /* If error returned, every bulk/interrupt endpoint would be stalled */
                    if (!(0 == NRF_USBD_EP_NR_GET(p_event->drv_evt.data.eptransfer.ep) ||
                       NRF_USBD_EPISO_CHECK(p_event->drv_evt.data.eptransfer.ep)))
                    {
                        nrf_drv_usbd_ep_stall(p_event->drv_evt.data.eptransfer.ep); 
                    }
                }
                break;
            }
            .... 
    
            default:
                ASSERT(0);
                break;
        }
    }
    

    Please tell me how to solve this problem.

     

  • Hi, 

    Please create a new support case for the new issue. This is away from the original scope. 

    Please note that due to the Easter holiday, we're low on staff, so somewhat lower response times must be expected until April 6th. Sorry about the inconvenience.

    -Amanda H.

Related