# USB Bulk transfer over Arduino Due Native USB port

**URL:** <https://forum.arduino.cc/t/usb-bulk-transfer-over-arduino-due-native-usb-port/1407494>\
**Category:** Networking, Protocols, and Devices\
**Created:** [September 25, 2025, 9:56am UTC](https://forum.arduino.cc/t/usb-bulk-transfer-over-arduino-due-native-usb-port/1407494 "2025-09-25T09:56:35Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![skynext\_tech](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@skynext\_tech](https://forum.arduino.cc/u/skynext_tech)\
**Post date:** [September 25, 2025, 9:56am UTC](https://forum.arduino.cc/t/usb-bulk-transfer-over-arduino-due-native-usb-port/1407494/1 "2025-09-25T09:56:35Z")

</div>

Hi.  
I am trying to setup a minimal sketch to setup an USB interface with two bulk endpoints (IN and OUT) with 512 Byte max packet size, and perform a read operation from the host (using the PyUSB libusb wrapper in linux)

I've looked at some custom USB implementation based on PluggableUSB class inheritance such as ArduinoMIDI.

I understand that the framework core files will automatically configure the Arduino as a CDC device that supports SerialUSB features, Which means that I will have to declare a USB interface number just after those exposed by the already present CDC interface.

Here is the full code.

```arduino
#undef CDC_ENABLED // this is a test to try do disable inbuilt CDC (CDC.cpp) SerialUSB
// support

#include <Arduino.h>
#include <USBCore.h>
#include <USBCore.cpp>
#include <PluggableUSB.h>

#define STRID_LANGID 0
#define STRID_MANUFACTURER 1
#define STRID_PRODUCT 2
#define STRID_SERIAL 3

// Unique Vendor/Product IDs
//#define VENDOR_ID 0x2341 // Example: Arduino
//#define PRODUCT_ID 0x8008 // Example: custom device

// Endpoint parameters
#define BULK_IN_EP 1
#define BULK_OUT_EP 2
#define EP_SIZE 512 // Full-speed max bulk size

class MyUSBDevice : public PluggableUSBModule {
public:
    MyUSBDevice() : PluggableUSBModule(epsnum, ifsnum, epType) {
        //epType[0] = USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(1);
        //epType[1] = USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(3);
        epType[0] = EP_TYPE_BULK_IN;
        epType[1] = EP_TYPE_BULK_OUT;
        

        PluggableUSB().plug(this);
    }

    int getInterface(uint8_t* interfaceCount) override {

        uint8_t interfaceDescriptor[] = {    
            9, // bLength
            USB_INTERFACE_DESCRIPTOR_TYPE, 
            2, // bInterfaceNumber
            0, // bAlternateSetting
            2, // bNumEndpoints
            0xFF, // bInterfaceClass (vendor-specific = 0xFF)
            0x00, // bInterfaceSubClass
            0x00, // bInterfaceProtocol
            2, // iInterface
            //FIRST ENDPOINT IN
            0x07, // bLength
            0x05, // bDescriptorType = ENDPOINT
            0x84, // bEndPointAddress = IN endpoint 1
            0x02, // bmAttributes = Bulk
            0x00, 0x02, // wMaxPacketSize = 512 Bytes
            0x00, // bInterval (ignored for Bulk)
            //SECOND ENDPOINT OUT
            0x07, // bLength
            0x05, // bDescriptorType = ENDPOINT
            0x03, // bEndPointAddress = OUT endpoint 1
            0x02, // bmAttributes = Bulk
            0x00, 0x02, // wMaxPacketSize = 512 Bytes
            0x00 // bInterval (ignored for Bulk)
        };
        *interfaceCount += 1;
        return USBD_SendControl(0,interfaceDescriptor, sizeof(interfaceDescriptor));
    }

  
    static void sendStringDescriptor(uint8_t index)
    {
      
      switch(index)
      {
        case STRID_LANGID:
        USB_SendStringDescriptor(USB_StringDescriptor0,sizeof(USB_StringDescriptor0));
        break;
        case STRID_MANUFACTURER:
        USB_SendStringDescriptor(USB_StringDescriptor1,sizeof(USB_StringDescriptor1));
        break;
        case STRID_PRODUCT:
        USB_SendStringDescriptor(USB_StringDescriptor2,sizeof(USB_StringDescriptor2));
        break;
        case STRID_SERIAL:
        USB_SendStringDescriptor(USB_StringDescriptor3,sizeof(USB_StringDescriptor3));
        break;
        default:
        USBD_SendControl(0,nullptr,0); 
      }
    }

    int getDescriptor(USBSetup& setup) override {
        // Optionally return string descriptors or report IDs
        //uint8_t descType = setup.wValueH >> 8;
        //uint8_t descIndex = setup.wValueH & 0xFF;
        
        //switch(descType)
        //{
        // case USB_DEVICE_DESCRIPTOR_TYPE:
        // return false;
        // case USB_CONFIGURATION_DESCRIPTOR_TYPE:
        // return false;
        // case USB_STRING_DESCRIPTOR_TYPE:
        // sendStringDescriptor(descIndex);
        // return true;
        // default:
        // return false;
        //}

        return 0;
    }

    bool setup(USBSetup& setup) override {
        return false;
    }

    // Send data to host
    int sendData(const uint8_t* data, int len) {

        return USBD_Send(0x84, data, len);
    		        
    }

    // Send data to host
    int receiveData(const uint8_t* data) {
		uint32_t c;
		if (!USBD_Available(0x03)) {
			udd_ack_fifocon(0x03);
			return 0;
		}
		c = USBD_Recv(0x03);
        return c;
    }

private:
    uint32_t epType[2];
    uint8_t epsnum = 2;
    uint8_t ifsnum = 2;

    static constexpr uint8_t USB_StringDescriptor0[4] = {4,3,0x09,0x04};
    static constexpr uint8_t USB_StringDescriptor1[7] = {'C','O','M','P','A','N','Y'};
    static constexpr uint8_t USB_StringDescriptor2[6] = {'D','E','V','I','C','E'};
    static constexpr uint8_t USB_StringDescriptor3[6] = {'1','2','3','4','5','6'};
  

};

// Instantiate device
MyUSBDevice myUSB;

void setup() {
    //SerialUSB.end();
    USBD_InitControl(0);
    //SerialUSB.begin(9600); // optional debug over USB CDC
    //while (!SerialUSB) ; // wait for host
    //SerialUSB.println("Custom USB device starting...");
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(3000); // 10 Hz
    
        
}

void loop() {
    // Example: send 64 bytes periodically
    char buffer[EP_SIZE];
    for (int i = 0; i < EP_SIZE; i++) buffer[i] = 'z';
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000); // 10 Hz
    int r = myUSB.sendData((uint8_t*)buffer, EP_SIZE);
    //int c = myUSB.receiveData((uint8_t*)buffer);

    
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000); // 10 Hz
  
}

```

It seems that a custom implementation of PluggableUSB GetInterface callback is critical as it exposes the USB interface descriptor to the host during USB connection/enumeration.  
Without that dmesg complains. With it, interface is properly exposed and the host sees it.

As for GetDescriptor(USBSetup &setup) and Setup(USBSetup &setup), they seem to be optional for using standard bulk endpoints. USBMidi does not use them.

Obviously SendData() and ReceiveData() are required to send Bulk data, and they wrap  
USBD\_Send() and USBD\_Recv() respectively.

The sketch blocks on USBD\_Send(0x84, data, len);  
Which is expected as it waits for an URB "IN" message to send the data.

Now this is the code that performs the read on the host :

```arduino
import usb.core
import usb.util

# Find your device (replace with your VID and PID)
dev = usb.core.find(idVendor=0x2341, idProduct=0x003e)  
#dev = usb.core.find(idVendor=0x03eb, idProduct=0x6124)  
if dev is None:
    raise ValueError("Device not found")

# Detach kernel driver if necessary
if dev.is_kernel_driver_active(1):
    dev.detach_kernel_driver(1)

if dev.is_kernel_driver_active(2):
    dev.detach_kernel_driver(2)
# Set configuration
dev.set_configuration()

# Get endpoint (assuming bulk IN is endpoint 0x81)
cfg = dev.get_active_configuration()
#print(cfg)

intf = cfg[(2,0)]
print(intf)

ep = usb.util.find_descriptor(
    intf,
    custom_match=lambda e: 
        usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN
)
epout = usb.util.find_descriptor(
    intf,
    custom_match=lambda e: 
        usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT
)

print(epout.bEndpointAddress)
print(epout.wMaxPacketSize)
print(ep.bEndpointAddress)
print(ep.wMaxPacketSize)

# Poll loop
while True:
    print("loop")
    try:
        data = dev.read(ep.bEndpointAddress, 1, timeout=1000)
        print("DATA=\n")
        print(data)
    except usb.core.USBError as e:
        if e.errno == 110: # timeout
            continue
        else:
            raise

```

This is the result of the command LIBUSB\_DEBUG=4 python3 testusb.py  
The test involves a read operation of 1 byte length, but it behaves the same if the length is USB maxpacketsize = 512

```arduino
timestamp] [threadID] facility level [function call] <message>
--------------------------------------------------------------------------------
[0.000031] [0000b109] libusb: debug [libusb_init] created default context
[0.000045] [0000b109] libusb: debug [libusb_init] libusb v1.0.24.11584
[0.000057] [0000b109] libusb: debug [get_kernel_version] reported kernel version is 5.10.0-32-rt-amd64
[0.000084] [0000b109] libusb: debug [op_init] found usbfs at /dev/bus/usb
[0.000093] [0000b109] libusb: debug [op_init] max iso packet length is (likely) 98304 bytes
[0.000114] [0000b109] libusb: debug [op_init] sysfs is available
[0.000573] [0000b10b] libusb: debug [linux_udev_event_thread_main] udev event thread entering
[0.004691] [0000b109] libusb: debug [linux_get_device_address] getting address for device: usb1 detached: 0
[0.004705] [0000b109] libusb: debug [linux_get_device_address] scan usb1
[0.004758] [0000b109] libusb: debug [linux_get_device_address] bus=1 dev=1
[0.004767] [0000b109] libusb: debug [linux_enumerate_device] busnum 1 devaddr 1 session_id 257
[0.004777] [0000b109] libusb: debug [linux_enumerate_device] allocating new device for 1/1 (session 257)
[0.004939] [0000b109] libusb: debug [linux_get_device_address] getting address for device: 1-1 detached: 0
[0.004953] [0000b109] libusb: debug [linux_get_device_address] scan 1-1
[0.005002] [0000b109] libusb: debug [linux_get_device_address] bus=1 dev=2
[0.005011] [0000b109] libusb: debug [linux_enumerate_device] busnum 1 devaddr 2 session_id 258
[0.005021] [0000b109] libusb: debug [linux_enumerate_device] allocating new device for 1/2 (session 258)
[0.005068] [0000b109] libusb: debug [linux_get_parent_info] dev 0x55b7f11895b0 (1-1) has parent 0x55b7f11894c0 (usb1) port 1
[0.005177] [0000b109] libusb: debug [linux_get_device_address] getting address for device: 1-1.1 detached: 0
[0.005187] [0000b109] libusb: debug [linux_get_device_address] scan 1-1.1
[0.005228] [0000b109] libusb: debug [linux_get_device_address] bus=1 dev=3
[0.005235] [0000b109] libusb: debug [linux_enumerate_device] busnum 1 devaddr 3 session_id 259
[0.005245] [0000b109] libusb: debug [linux_enumerate_device] allocating new device for 1/3 (session 259)
[0.005299] [0000b109] libusb: debug [linux_get_parent_info] dev 0x55b7f1189810 (1-1.1) has parent 0x55b7f11895b0 (1-1) port 1
[0.005404] [0000b109] libusb: debug [linux_get_device_address] getting address for device: usb2 detached: 0
[0.005415] [0000b109] libusb: debug [linux_get_device_address] scan usb2
[0.005462] [0000b109] libusb: debug [linux_get_device_address] bus=2 dev=1
[0.005470] [0000b109] libusb: debug [linux_enumerate_device] busnum 2 devaddr 1 session_id 513
[0.005477] [0000b109] libusb: debug [linux_enumerate_device] allocating new device for 2/1 (session 513)
[0.005616] [0000b109] libusb: debug [linux_get_device_address] getting address for device: 2-1 detached: 0
[0.005627] [0000b109] libusb: debug [linux_get_device_address] scan 2-1
[0.005674] [0000b109] libusb: debug [linux_get_device_address] bus=2 dev=2
[0.005682] [0000b109] libusb: debug [linux_enumerate_device] busnum 2 devaddr 2 session_id 514
[0.005688] [0000b109] libusb: debug [linux_enumerate_device] allocating new device for 2/2 (session 514)
[0.005736] [0000b109] libusb: debug [linux_get_parent_info] dev 0x55b7f1189e60 (2-1) has parent 0x55b7f1189f60 (usb2) port 1
[0.005887] [0000b109] libusb: debug [linux_get_device_address] getting address for device: 2-1.1 detached: 0
[0.005899] [0000b109] libusb: debug [linux_get_device_address] scan 2-1.1
[0.005949] [0000b109] libusb: debug [linux_get_device_address] bus=2 dev=24
[0.005958] [0000b109] libusb: debug [linux_enumerate_device] busnum 2 devaddr 24 session_id 536
[0.005970] [0000b109] libusb: debug [linux_enumerate_device] allocating new device for 2/24 (session 536)
[0.006017] [0000b109] libusb: debug [linux_get_parent_info] dev 0x55b7f116f6d0 (2-1.1) has parent 0x55b7f1189e60 (2-1) port 1
[0.006134] [0000b109] libusb: debug [linux_get_device_address] getting address for device: 2-1.2 detached: 0
[0.006144] [0000b109] libusb: debug [linux_get_device_address] scan 2-1.2
[0.006194] [0000b109] libusb: debug [linux_get_device_address] bus=2 dev=38
[0.006202] [0000b109] libusb: debug [linux_enumerate_device] busnum 2 devaddr 38 session_id 550
[0.006212] [0000b109] libusb: debug [linux_enumerate_device] allocating new device for 2/38 (session 550)
[0.006260] [0000b109] libusb: debug [linux_get_parent_info] dev 0x55b7f116faf0 (2-1.2) has parent 0x55b7f1189e60 (2-1) port 2
[0.006353] [0000b109] libusb: debug [usbi_add_event_source] add fd 5 events 1
[0.006369] [0000b109] libusb: debug [usbi_io_init] using timer for timeouts
[0.006378] [0000b109] libusb: debug [usbi_add_event_source] add fd 6 events 1
[0.006492] [0000b109] libusb: debug [libusb_get_device_list]  
[0.006613] [0000b109] libusb: debug [libusb_get_device_descriptor]  
[0.006881] [0000b109] libusb: debug [libusb_open] open 2.38
[0.006921] [0000b109] libusb: debug [usbi_add_event_source] add fd 7 events 4
[0.006953] [0000b109] libusb: debug [libusb_kernel_driver_active] interface 1
[0.006990] [0000b109] libusb: debug [libusb_detach_kernel_driver] interface 1
[0.007225] [0000b109] libusb: debug [libusb_kernel_driver_active] interface 2
[0.007277] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.007291] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.007406] [0000b109] libusb: debug [libusb_set_configuration] configuration 1
[0.007610] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.007630] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.007751] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.007767] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.008119] [0000b109] libusb: debug [libusb_alloc_transfer] transfer 0x55b7f1132388
[0.008135] [0000b109] libusb: debug [libusb_submit_transfer] transfer 0x55b7f1132388
[0.008144] [0000b109] libusb: debug [add_to_flying_list] arm timer for timeout in 1000ms (first in line)
[0.008177] [0000b109] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[0.008189] [0000b109] libusb: debug [handle_events] event sources modified, reallocating event data
[0.008201] [0000b109] libusb: debug [usbi_wait_for_events] poll() 3 fds with timeout in 60000ms
[0.008299] [0000b109] libusb: debug [usbi_wait_for_events] poll() returned 1
[0.008319] [0000b109] libusb: debug [reap_for_handle] urb type=2 status=0 transferred=4
[0.008328] [0000b109] libusb: debug [handle_control_completion] handling completion status 0
[0.008337] [0000b109] libusb: debug [arm_timer_for_next_timeout] no timeouts, disarming timer
[0.008351] [0000b109] libusb: debug [usbi_handle_transfer_completion] transfer 0x55b7f1132388 has callback 0x7fe6365dedc0
[0.008360] [0000b109] libusb: debug [sync_transfer_cb] actual_length=4
[0.008371] [0000b109] libusb: debug [libusb_free_transfer] transfer 0x55b7f1132388
[0.008473] [0000b109] libusb: debug [libusb_alloc_transfer] transfer 0x55b7f1187a38
[0.008488] [0000b109] libusb: debug [libusb_submit_transfer] transfer 0x55b7f1187a38
[0.008497] [0000b109] libusb: debug [add_to_flying_list] arm timer for timeout in 1000ms (first in line)
[0.008518] [0000b109] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[0.008528] [0000b109] libusb: debug [usbi_wait_for_events] poll() 3 fds with timeout in 60000ms
[0.008671] [0000b109] libusb: debug [usbi_wait_for_events] poll() returned 1
[0.008689] [0000b109] libusb: debug [reap_for_handle] urb type=2 status=0 transferred=24
[0.008697] [0000b109] libusb: debug [handle_control_completion] handling completion status 0
[0.008706] [0000b109] libusb: debug [arm_timer_for_next_timeout] no timeouts, disarming timer
[0.008717] [0000b109] libusb: debug [usbi_handle_transfer_completion] transfer 0x55b7f1187a38 has callback 0x7fe6365dedc0
[0.008725] [0000b109] libusb: debug [sync_transfer_cb] actual_length=24
[0.008735] [0000b109] libusb: debug [libusb_free_transfer] transfer 0x55b7f1187a38
[0.009733] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.009796] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.009966] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.009980] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
    INTERFACE 2: Vendor Specific ===========================
     bLength : 0x9 (9 bytes)
     bDescriptorType : 0x4 Interface
     bInterfaceNumber : 0x2
     bAlternateSetting : 0x0
     bNumEndpoints : 0x2
     bInterfaceClass : 0xff Vendor Specific
     bInterfaceSubClass : 0x0
     bInterfaceProtocol : 0x0
     iInterface : 0x2 Arduino Due
      ENDPOINT 0x84: Bulk IN ===============================
       bLength : 0x7 (7 bytes)
       bDescriptorType : 0x5 Endpoint
       bEndpointAddress : 0x84 IN
       bmAttributes : 0x2 Bulk
       wMaxPacketSize : 0x200 (512 bytes)
       bInterval : 0x0
      ENDPOINT 0x3: Bulk OUT ===============================
       bLength : 0x7 (7 bytes)
       bDescriptorType : 0x5 Endpoint
       bEndpointAddress : 0x3 OUT
       bmAttributes : 0x2 Bulk
       wMaxPacketSize : 0x200 (512 bytes)
       bInterval : 0x0
[0.010197] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.010209] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.010319] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.010332] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.010414] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.010426] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
3
512
132
512
loop
[0.010603] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.010619] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.010730] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.010740] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.010854] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.010864] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.010983] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.010993] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.011066] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.011077] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.011182] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.011192] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.011299] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.011309] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.011446] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.011458] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.011534] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.011545] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.011652] [0000b109] libusb: debug [libusb_get_config_descriptor] index 0
[0.011663] [0000b109] libusb: debug [parse_configuration] skipping descriptor 0xb
[0.011801] [0000b109] libusb: debug [libusb_claim_interface] interface 2
[0.011930] [0000b109] libusb: debug [libusb_alloc_transfer] transfer 0x55b7f116f298
[0.011941] [0000b109] libusb: debug [libusb_submit_transfer] transfer 0x55b7f116f298
[0.011947] [0000b109] libusb: debug [add_to_flying_list] arm timer for timeout in 1000ms (first in line)
[0.011958] [0000b109] libusb: debug [submit_bulk_transfer] need 1 urbs for new transfer with length 1
[0.011986] [0000b109] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[0.011993] [0000b109] libusb: debug [usbi_wait_for_events] poll() 3 fds with timeout in 60000ms
[0.016064] [0000b109] libusb: debug [usbi_wait_for_events] poll() returned 1
[0.016103] [0000b109] libusb: debug [reap_for_handle] urb type=3 status=-71 transferred=0
[0.016111] [0000b109] libusb: debug [handle_bulk_completion] handling completion status -71 of bulk urb 1/1
[0.016117] [0000b109] libusb: debug [handle_bulk_completion] low-level bus error -71
[0.016125] [0000b109] libusb: debug [arm_timer_for_next_timeout] no timeouts, disarming timer
[0.016134] [0000b109] libusb: debug [usbi_handle_transfer_completion] transfer 0x55b7f116f298 has callback 0x7fe6365dedc0
[0.016140] [0000b109] libusb: debug [sync_transfer_cb] actual_length=0
[0.016150] [0000b109] libusb: debug [libusb_free_transfer] transfer 0x55b7f116f298
Traceback (most recent call last):
  File "/home/rod/Documents/PlatformIO/Projects/ad7606_arduino/src/testusb.py", line 49, in <module>
    data = dev.read(ep.bEndpointAddress, 1, timeout=1000)
  File "/root/anaconda3/lib/python3.9/site-packages/usb/core.py", line 1043, in read
    ret = fn(
  File "/root/anaconda3/lib/python3.9/site-packages/usb/backend/libusb1.py", line 850, in bulk_read
    return self.__read(self.lib.libusb_bulk_transfer,
  File "/root/anaconda3/lib/python3.9/site-packages/usb/backend/libusb1.py", line 958, in __read
    _check(retval)
  File "/root/anaconda3/lib/python3.9/site-packages/usb/backend/libusb1.py", line 604, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 5] Input/Output Error
[0.019599] [0000b109] libusb: debug [libusb_release_interface] interface 2
[0.019701] [0000b109] libusb: debug [libusb_close]  
[0.019724] [0000b109] libusb: debug [usbi_remove_event_source] remove fd 7
[0.019805] [0000b109] libusb: debug [libusb_exit]  
[0.019815] [0000b109] libusb: debug [libusb_exit] destroying default context
[0.019835] [0000b109] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[0.019849] [0000b109] libusb: debug [handle_events] event sources modified, reallocating event data
[0.019868] [0000b109] libusb: debug [usbi_wait_for_events] poll() 2 fds with timeout in 0ms
[0.019886] [0000b109] libusb: debug [usbi_wait_for_events] poll() returned 0
[0.019899] [0000b109] libusb: debug [libusb_unref_device] destroy device 2.38
[0.019915] [0000b109] libusb: debug [libusb_unref_device] destroy device 2.24
[0.019936] [0000b109] libusb: debug [libusb_unref_device] destroy device 2.2
[0.019948] [0000b109] libusb: debug [libusb_unref_device] destroy device 2.1
[0.019963] [0000b109] libusb: debug [libusb_unref_device] destroy device 1.3
[0.019979] [0000b109] libusb: debug [libusb_unref_device] destroy device 1.2
[0.019988] [0000b109] libusb: debug [libusb_unref_device] destroy device 1.1
[0.019997] [0000b109] libusb: debug [usbi_remove_event_source] remove fd 6
[0.020015] [0000b109] libusb: debug [usbi_remove_event_source] remove fd 5
[0.020043] [0000b10b] libusb: debug [linux_udev_event_thread_main] udev event thread exiting

```

The error is a USB protocol error -71. These are the error relevant lines.

```arduino
0.017488] [0000b13e] libusb: debug [usbi_wait_for_events] poll() 3 fds with timeout in 60000ms
[0.021526] [0000b13e] libusb: debug [usbi_wait_for_events] poll() returned 1
[0.021558] [0000b13e] libusb: debug [reap_for_handle] urb type=3 status=-71 transferred=0
[0.021571] [0000b13e] libusb: debug [handle_bulk_completion] handling completion status -71 of bulk urb 1/1
[0.021583] [0000b13e] libusb: debug [handle_bulk_completion] low-level bus error -71

```

And this is the Interface as seen in PyUSB :

```arduino
    INTERFACE 2: Vendor Specific ===========================
     bLength : 0x9 (9 bytes)
     bDescriptorType : 0x4 Interface
     bInterfaceNumber : 0x2
     bAlternateSetting : 0x0
     bNumEndpoints : 0x2
     bInterfaceClass : 0xff Vendor Specific
     bInterfaceSubClass : 0x0
     bInterfaceProtocol : 0x0
     iInterface : 0x2 Arduino Due
      ENDPOINT 0x84: Bulk IN ===============================
       bLength : 0x7 (7 bytes)
       bDescriptorType : 0x5 Endpoint
       bEndpointAddress : 0x84 IN
       bmAttributes : 0x2 Bulk
       wMaxPacketSize : 0x200 (512 bytes)
       bInterval : 0x0
      ENDPOINT 0x3: Bulk OUT ===============================
       bLength : 0x7 (7 bytes)
       bDescriptorType : 0x5 Endpoint
       bEndpointAddress : 0x3 OUT
       bmAttributes : 0x2 Bulk
       wMaxPacketSize : 0x200 (512 bytes)
       bInterval : 0x0

```

And system wide in /sys/kernel/debug/usb/devices

```arduino
T: Bus=02 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#= 38 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=2341 ProdID=003e Rev= 1.00
S: Manufacturer=Arduino
S: Product=Arduino Due
S: SerialNumber=C
C:* #Ifs= 3 Cfg#= 1 Atr=c0 MxPwr=500mA
A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=02 Prot=01
I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=00 Driver=(none)
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=4096ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=(none)
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

```

Any ideas on how to make the transfer work ? I mostly think that the error is on the Arduino Due firmware code side, as when i try to read using the interface 1 (CDC SerialUsb) there is no -71 error, albeit it returns an empty data array, but no low level protocol error.  
Besides all this, i found that the Native USB resource literature is scarce and that Native USB is severely under documented, besides the PluggableUSB tutorial.

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [March 24, 2026, 9:57am UTC](https://forum.arduino.cc/t/usb-bulk-transfer-over-arduino-due-native-usb-port/1407494/2 "2026-03-24T09:57:03Z")

</div>

Closed on March 24, 2026, 9:57am UTC

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
