3

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:

  1. had to add "include Linux/interface.h" line to a bunch of the header files due to an unsigned reference in Linux/uinterface.h

  2. 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?

Community
  • 1
  • 1
lolmuly
  • 43
  • 6

0 Answers0