My question is very similar to the question posed here: libusb interrupt transfer
I am reverse engineering a driver Linux-G13_1.0-r44.zip
found here: http://code.google.com/p/linux-g13-driver/downloads/list
to get it working under RHEL5.
It seems that everything is working correctly, however the only response i get from libusb_interrupt_transfer is a timeout error "-7"
Output of: "lsusb -v -d 046d:c21c"
Bus 006 Device 010: ID 046d:c21c Logitech, Inc.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x046d Logitech, Inc.
idProduct 0xc21c
bcdDevice 2.03
iManufacturer 0
iProduct 1 G13
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 41
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 61
Report Descriptor: (length is 61)
Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
(null)
Item(Local ): Usage, data= [ 0x00 ] 0
(null)
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Global): Report ID, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x07 ] 7
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Main ): Input, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report ID, data= [ 0x03 ] 3
Item(Local ): Usage, data= [ 0x02 ] 2
(null)
Item(Global): Report Count, data= [ 0xdf 0x03 ] 991
Item(Main ): Output, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report ID, data= [ 0x07 ] 7
Item(Local ): Usage, data= [ 0x03 ] 3
(null)
Item(Global): Report Count, data= [ 0x04 ] 4
Item(Main ): Feature, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report ID, data= [ 0x04 ] 4
Item(Local ): Usage, data= [ 0x04 ] 4
(null)
Item(Main ): Feature, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report ID, data= [ 0x05 ] 5
Item(Local ): Usage, data= [ 0x05 ] 5
(null)
Item(Main ): Feature, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report ID, data= [ 0x06 ] 6
Item(Local ): Usage, data= [ 0x06 ] 6
(null)
Item(Global): Report Count, data= [ 0x01 0x01 ] 257
Item(Main ): Feature, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 2
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
Defined in Constants.h:
#define G13_INTERFACE 0
#define G13_KEY_ENDPOINT 1
#define G13_LCD_ENDPOINT 2
#define G13_KEY_READ_TIMEOUT 0
#define G13_VENDOR_ID 0x046d
#define G13_PRODUCT_ID 0xc21c
#define G13_REPORT_SIZE 8
#define G13_LCD_BUFFER_SIZE 0x3c0
#define G13_NUM_KEYS 40
G13.cpp:
#include "Constants.h"
...
int G13::read() {
unsigned char buffer[G13_REPORT_SIZE];
int size;
cout << "prebuffer: " << buffer << "\n";
cout << "presize: " << size << "\n";
int error = libusb_interrupt_transfer(handle, LIBUSB_ENDPOINT_IN | G13_KEY_ENDPOINT, buffer, G13_REPORT_SIZE, &size, 1000);
cout << "buffer: " << buffer << "\n";
cout << "size: " << size << "\n";
if (error && error != LIBUSB_ERROR_TIMEOUT) {
std::map<int, std::string> errors;
errors[LIBUSB_SUCCESS] = "LIBUSB_SUCCESS";
errors[LIBUSB_ERROR_IO] = "LIBUSB_ERROR_IO";
errors[LIBUSB_ERROR_INVALID_PARAM] = "LIBUSB_ERROR_INVALID_PARAM";
errors[LIBUSB_ERROR_ACCESS] = "LIBUSB_ERROR_ACCESS";
errors[LIBUSB_ERROR_NO_DEVICE] = "LIBUSB_ERROR_NO_DEVICE";
errors[LIBUSB_ERROR_NOT_FOUND] = "LIBUSB_ERROR_NOT_FOUND";
errors[LIBUSB_ERROR_BUSY] = "LIBUSB_ERROR_BUSY";
errors[LIBUSB_ERROR_TIMEOUT] = "LIBUSB_ERROR_TIMEOUT";
errors[LIBUSB_ERROR_OVERFLOW] = "LIBUSB_ERROR_OVERFLOW";
errors[LIBUSB_ERROR_PIPE] = "LIBUSB_ERROR_PIPE";
errors[LIBUSB_ERROR_INTERRUPTED] = "LIBUSB_ERROR_INTERRUPTED";
errors[LIBUSB_ERROR_NO_MEM] = "LIBUSB_ERROR_NO_MEM";
errors[LIBUSB_ERROR_NOT_SUPPORTED] = "LIBUSB_ERROR_NOT_SUPPORTED";
errors[LIBUSB_ERROR_OTHER] = "LIBUSB_ERROR_OTHER ";
cerr << "Error while reading keys: " << error << " (" << errors[error]
<< ")" << endl;
cerr << "Stopping daemon" << endl;
return -1;
}
if (size == G13_REPORT_SIZE) {
parse_joystick(buffer);
parse_keys(buffer);
send_event(EV_SYN, SYN_REPORT, 0);
}
return 0;
}
"sudo ./Linux-G13-Driver", whilst mashing keys on the device, returns:
Found Device: 0x1abebd20
Kernel driver detached
Device Loaded: 0x1abebd20
loading /root/.g13/bindings-0.properties
prebuffer: �
presize: 255
buffer: #
size: 0
prebuffer: #
presize: 0
buffer: #
size: 0
prebuffer: #
presize: 0
buffer: #
size: 0
prebuffer: #
presize: 0
^C
Segmentation fault
i included the prebuffer and presize lines just to prove that it is in fact initializing the buffer. Also as Arne mentioned in the post I referenced at the top, the device seems to open properly, and both interfaces are properly claimed. The only thing he mentioned that I'm a bit confused by is "SET_INTERFACE" and "SET_CONFIGURATION" but maybe that's a windows only thing?
I should note that I had to do two things to get this to build correctly on rhel5:
had to add "include Linux/interface.h" line to a bunch of the header files due to an unsigned reference in Linux/uinterface.h
had to build libusb-1.0 because it wasn't included in my particular build of rhel5
I'm a bit new to linux so I tried libusb-1.0.8 and libusb-1.0.9 neither to any avail. My windows instincts tell me that the libusb build is my problem and that the library is not actually recieving interrupts from the usb device for some reason.
I apologize in advance for any major noob mistakes. Does anybody have any ideas?