Ok, I'm probably doing something dumb, but I can't get libusb to let me transfer data to my device for the life of me.
Code:
#include <iostream>
#include <iomanip>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <libusb-1.0/libusb.h>
#define EP_DATA_IN 0x83
#define EP_DATA_OUT 0x02
#define DEVICE_CONFIGURATION 0
int main(int argc, char **argv)
{
int rc;
libusb_context *ctx = NULL;
libusb_device_handle *dev_handle;
int actual = 0;
unsigned char *data = new unsigned char[4];
data[0]='a';data[1]='b';data[2]='c';data[3]='d';
rc = libusb_init(&ctx);
if(rc < 0) {
std::cout << "Init Error " << rc << std::endl;
return 1;
}
libusb_set_debug(ctx, 6);
dev_handle = libusb_open_device_with_vid_pid(ctx, 0x03eb, 0x2423);
if (!dev_handle) {
fprintf(stderr, "Error finding USB device\n");
return 2;
}
if(libusb_kernel_driver_active(dev_handle, DEVICE_CONFIGURATION) == 1) {
std::cout << "Kernel Driver Active" << std::endl;
if(libusb_detach_kernel_driver(dev_handle, DEVICE_CONFIGURATION) == 0)
std::cout << "Kernel Driver Detached!" << std::endl;
}
rc = libusb_claim_interface(dev_handle, DEVICE_CONFIGURATION);
if(rc != 0) {
std::cout << "Cannot Claim Interface" << std::endl;
return 3;
}
std::cout << "Data->" << data << "<-" << std::endl;
std::cout << "Writing Data..." << std::endl;
std::cout << "Trying endpoint " << EP_DATA_OUT << "." << std::endl;
rc = libusb_bulk_transfer(dev_handle, EP_DATA_OUT, data, sizeof(data), &actual, 100);
if(rc == 0 && actual == 4)
{
std::cout << "Writing Successful!" << std::endl;
}
else
{
std::cout << "Write Error! Rc: " << rc << " Actual transfered bytes: " << actual << "." << std::endl;
std::cout << "Error code means: " << libusb_error_name(rc) << std::endl;
}
rc = libusb_release_interface(dev_handle, 0);
if(rc!=0) {
std::cout << "Cannot Release Interface" << std::endl;
return 1;
}
if (dev_handle)
libusb_close(dev_handle);
libusb_exit(ctx);
return 0;
}
Device in question:
pi@testpi:~$ sudo lsusb -d 03eb: -v
Bus 001 Device 004: ID 03eb:2423 Atmel Corp.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x03eb Atmel Corp.
idProduct 0x2423
bcdDevice 1.00
iManufacturer 1 ATMEL ASF
iProduct 2 Vendor Class Example
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 69
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 1
bNumEndpoints 6
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x85 EP 5 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0100 1x 256 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x06 EP 6 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0100 1x 256 bytes
bInterval 1
Device Status: 0x0001
Self Powered
And what I get when I run the code against the device:
pi@testpi:~/BatLogger/Interface/libusb_test$ ./make.sh
libusb: debug [libusb_get_device_list]
libusb: debug [libusb_get_device_descriptor]
libusb: debug [libusb_open] open 1.4
libusb: debug [usbi_add_pollfd] add fd 11 events 4
libusb: debug [libusb_kernel_driver_active] interface 0
libusb: debug [libusb_claim_interface] interface 0
Data->abcd<-
Writing Data...
Trying endpoint 2.
libusb: debug [add_to_flying_list] arm timerfd for timeout in 100ms (first in line)
libusb: debug [submit_bulk_transfer] need 1 urbs for new transfer with length 4
libusb: error [submit_bulk_transfer] submiturb failed error -1 errno=2
libusb: debug [submit_bulk_transfer] first URB failed, easy peasy
libusb: debug [disarm_timerfd]
Write Error! Rc: -1 Actual transfered bytes: 0.
Error code means: LIBUSB_ERROR_IO
libusb: debug [libusb_release_interface] interface 0
libusb: debug [libusb_close]
libusb: debug [usbi_remove_pollfd] remove fd 11
libusb: debug [libusb_exit]
libusb: debug [libusb_exit] destroying default context
As far as I know, I'm doing everything correctly. libusb_claim_interface
returns OK, there isn't a pre-existing driver attached to the device since I'm using a custom VID/PID combo, and EP_DATA_OUT
is a output endpoint (direction bit is 0, though to whom "out" is with respect to isn't described). Out of irritation, I've also tried every other possible endpoint (0-16, 0-16 | 1 << 7), with the exact same error for all of them.
Is there something silly I'm missing? Do I have to install a kernel module or something to make libusb play nice with me? I'm using libusb-1.0.
The error from the libusb debug message is error -1 errno=2
. where errno=2
corresponds to ERNOENT, but the few things I could find about that together with libusb didn't have a decent conclusion about what's actually going on.
Code is built g++ -std=c++11 -Wall -lrt -lusb-1.0 main.cpp -o main.bin
, though the fact that I'm using C++ is probably not relevant to the issue, since I'm not using one of the C++ libusb wrappers.