How to transfer data through EPOUT2 in usbd-custom-hid-ep example

Hi,

The example that I use is from here.

I have to use the USB interface to send and receive data between the host PC and the nRF52840 chip.

In the example, I can only send the data from the chip to the computer through EPIN2, but can not send the data from the computer to the chip through EPOUT2.

 • send the data from the chip to the computer

   Press Button 2 → send the data through EPIN2 → SUCCESS (the array that the chip sent shows on the Python terminal, and "transfer complete" shows on PUTTY)

     

 • send the data from the computer to the chip

   Input the data (I use RTT Viewer to send the data. But when I input the string, it shows the warning messages.) → FAIL

       

What should I do to let the data transfer successfully?

What function should I add to call the NRF_DRV_USBD_EVT_EPTRANSFER event to let the receive_custom_data() function work? 

static void usbd_event_handler(nrf_drv_usbd_evt_t const * const p_event)
{
    switch (p_event->type)
    {
    ...
    case NRF_DRV_USBD_EVT_EPTRANSFER:
        if (NRF_DRV_USBD_EPIN2 == p_event->data.eptransfer.ep)
        {
            NRF_LOG_INFO("EP2IN transfer complete");
        }
        else if (NRF_DRV_USBD_EPOUT2 == p_event->data.eptransfer.ep)
        {
            NRF_LOG_INFO("EP2OUT transfer complete");
            receive_custom_data();
        }
        ...
        break;
    ...
}

  • Hi 

    Would you be able to share your python script with me so I can test it on my end? 

    Have you tried to send exactly 64 bytes to see if that works? 
    As far as I recall I only tested the example with 64 byte packets, it might need some modifications to support any packet size. 

    Best regards
    Torbjørn

  • Hi Torbjørn,

    Would you be able to share your python script with me so I can test it on my end? 

    Sure! This is my pyUSB code.

    import usb.core
    import usb.util
    
    import threading
    
    def write_data(dev, ep):
        while True:
            try:
                to_board = input("")
                to_board = to_board + "\n"
                dev.write(ep.bEndpointAddress, to_board.encode())
                #dev.write(ep.bEndpointAddress, "abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghi\n")
            except usb.core.USBError as e:
                data = None
                if e.args == ('Operation timed out',):
                    continue
    
    def read_data(dev, ep):
        while True:
            try:
                data = dev.read(ep.bEndpointAddress, ep.wMaxPacketSize)
                print(data)
            except usb.core.USBError as e:
                data = None
                if e.args == ('Operation timed out',):
                    continue
    
    def main():
        device = usb.core.find(idVendor=0x1915, idProduct=0x520B)
        '''
        for device in device:
            print(device)
        '''
        # use the first/default configuration
        device.set_configuration()
        # endpoint
        endpoint_in = device[0][(1,0)][0]
        endpoint_out = device[0][(1,0)][1]
        print(endpoint_in)
        print(endpoint_out)
        
        thread_r = threading.Thread(target=read_data, args = (device, endpoint_in))
        thread_r.start()
    
        thread_w = threading.Thread(target=write_data, args = (device, endpoint_out))
        thread_w.start()
        
    if __name__ == '__main__':
      main()
    

    Have you tried to send exactly 64 bytes to see if that works? 
    As far as I recall I only tested the example with 64 byte packets

    I didn't try it before getting your suggestion.

    Thanks to your suggestion, I tried sending 64-byte packets, then it works.

    it might need some modifications to support any packet size. 

    I need to modify the packet size so that the chip could receive the data from the computer regardless of the packet size.

    When the chip read the char '\n', then it has to transfer the packet through EPOUT2.

    But I can not find where the chip receives the packet to make the NRF_DRV_USBD_EVT_EPTRANSFER event called.

    So... Now I have another question: "Where should I modify the packet size in this example?"

    Best regards,

    Ning

  • Hi Ning

    Thanks for sharing the code. I will be out of office for a couple of days and won't be able to look into this until Friday unfortunately, and I will do my best to get back to you then with more information. 

    Please note that the example you are using is not an official example, and as such is not officially supported by us. Still, I will do my best to help once I am back in the office. 

    Best regards
    Torbjørn

  • Hi Torbjørn, 

    OK. I understand. I'll try my best, too. Look forward to your reply.

    Best regards,

    Ning

  • Hi Ning

    Sorry for the slow response. 

    After digging into this a bit more I realized this is probably just a limitation of the HID stack. Essentially HID reports operate with static fields in terms of size, you can't have dynamically sized fields like you can do with USB CDC or libusb for instance. 

    In other words you either need to pad your messages to 64 bytes, even if you don't have 64 byte to send, or you could create multiple alternative reports with different lengths and differentiate between them by using a report ID. This method is described here.

    The drawback of the report ID method is that you lose one byte of the payload to the report ID itself (the report ID is always the first byte of the HID report). 

    Best regards
    Torbjørn 

Related