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.
#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 :
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
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.
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 :
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
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.