libusb_interrupt_transfer() Blocks Until All `length` Bytes Received
The documentation for libusb_interrupt_transfer() states the following:
For interrupt reads, the
lengthfield indicates the maximum length of data you are expecting to receive. If less data arrives than expected, this function will return that data, so be sure to check thetransferredoutput parameter.
In my mind, the implication of this is that, the moment any data arrives before the timeout expires, libusb_interrupt_transfer() will return success and fill in transferred with the quantity of bytes actually received.
This is not what happens. Consider the following pseudo-code:
/* sizeof (struct dev_input_report) < sizeof (readbuf) */
struct dev_input_report *rep;
int retval, retsiz;
uint8_t readbuf[256];
retval = libusb_interrupt_transfer (g_handle, LIBUSB_ENDPOINT_IN | DEV_ENDPOINT,
readbuf, sizeof (readbuf),
&retsiz, 0);
if (!retval && retsiz == sizeof (struct dev_input_report)) {
rep = (struct dev_input_report *) readbuf;
handle_report (rep);
}
Based on the docs, the expectation is that libusb_interrupt_transfer() will block forever (timeout = 0) until something arrives. The first transferred bytes of readbuf will be filled with the report, and the function returns.
What actually happens is that libusb_interrupt_transfer() blocks until length bytes have been collected, which may require multiple reports -- not what you want when dealing with an interactive input device.
So either I'm misunderstanding something, or it would appear the docs are incorrect.
Please provide debug logs.
Is output from LIBUSB_DEBUG=4 sufficient?
Yes, that is good, max output.
Test program. This program attempts to locate a Logitech G13 "Gameboard" and get events from it. Compile with gcc libusbtest.c $(pkg-config --cflags --libs libusb-1.0)
#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <err.h>
#include <libusb.h>
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_G13 (0xc21c)
#define G13_ENDPOINT_KEY 1
#define G13_ENDPOINT_LCD 2
#define G13_REPORT_SIZE_KEY 8
#define G13_REPORT_SIZE_LCD 0x3c0
struct g13_input_report {
uint8_t report_id;
uint8_t joy_x, joy_y;
uint8_t keybits[5];
};
libusb_context *g_usbctx;
struct libusb_device_handle *g_handle;
int
connect_g13 (void)
{
libusb_device **usbdevs;
ssize_t ndevs;
int retval;
retval = libusb_init (&g_usbctx);
if (retval < 0) {
warn ("libusb init failed");
return -1;
}
ndevs = libusb_get_device_list (g_usbctx, &usbdevs);
if (ndevs < 0) {
warn ("libusb_get_device_list failed");
return -1;
}
for (int i = 0; i < ndevs; ++i) {
struct libusb_device_descriptor desc;
retval = libusb_get_device_descriptor (usbdevs[i], &desc);
if (retval < 0) {
warn ("failed to get descriptor %d", i);
return -1;
}
printf ("Checking index %d:\n", i);
printf (" idVendor = 0x%04hx\n", desc.idVendor);
printf (" idProduct = 0x%04hx\n", desc.idProduct);
printf (" bcdDevice = 0x%04hx\n", desc.bcdDevice);
if ( desc.idVendor == USB_VENDOR_ID_LOGITECH
&& desc.idProduct == USB_DEVICE_ID_LOGITECH_G13)
{
retval = libusb_open (usbdevs[i], &g_handle);
if (retval < 0) {
warn ("usb device open failed");
return -1;
}
/*
* This seems a bit racy to me...
*/
if (libusb_set_auto_detach_kernel_driver (g_handle, 1) < 0) {
if (libusb_kernel_driver_active (g_handle, 0)) {
if (!libusb_detach_kernel_driver (g_handle, 0)) {
warnx ("Kernel driver detached");
}
} else {
printf ("no kernel driver attached.\n");
}
}
retval = libusb_claim_interface (g_handle, 0);
if (retval < 0) {
warn ("Failed to claim usb device");
return -1;
}
}
}
libusb_free_device_list (usbdevs, 1);
return 0;
}
void
disconnect_g13 (void)
{
if (g_handle) {
libusb_release_interface (g_handle, 0);
libusb_close (g_handle);
g_handle = NULL;
}
if (g_usbctx) {
libusb_exit (g_usbctx);
g_usbctx = NULL;
}
}
int
main (int ac, char **av)
{
struct g13_input_report *rep;
int uif;
int retval;
int retsiz;
uint8_t buf[256];
retval = connect_g13();
if (retval < 0) {
errx (EXIT_FAILURE, "g13 connect failed");
}
for (;;) {
retval = libusb_interrupt_transfer (g_handle, LIBUSB_ENDPOINT_IN | G13_ENDPOINT_KEY,
buf, sizeof (buf),
&retsiz, 0);
if (retval) {
warnx ("interrupt transfer returned %d", retval);
if (retval == LIBUSB_ERROR_TIMEOUT)
continue;
}
if (retsiz >= sizeof (*rep)) {
rep = (struct g13_input_report *) buf;
printf ("nbytes: %d, keybits = [ %02hhx %02hhx %02hhx %02hhx %02hhx ]\n",
retsiz,
rep->keybits[0],
rep->keybits[1],
rep->keybits[2],
rep->keybits[3],
rep->keybits[4]);
}
}
disconnect_g13 ();
}
Output, after pressing/releasing a key on the G13 gameboard 16 times:
$ sudo LIBUSB_DEBUG=4 ./a.out
[timestamp] [threadID] facility level [function call] <message>
--------------------------------------------------------------------------------
[ 0.000038] [000c280c] libusb: debug [libusb_init] libusb v1.0.26.11724
[ 0.000076] [000c280c] libusb: debug [usbi_add_event_source] add fd 3 events 1
[ 0.000088] [000c280c] libusb: debug [usbi_io_init] using timer for timeouts
[ 0.000092] [000c280c] libusb: debug [usbi_add_event_source] add fd 4 events 1
[ 0.000102] [000c280c] libusb: debug [get_kernel_version] reported kernel version is 5.18.0-4-amd64
[ 0.000130] [000c280c] libusb: debug [op_init] found usbfs at /dev/bus/usb
[ 0.000134] [000c280c] libusb: debug [op_init] max iso packet length is (likely) 98304 bytes
[ 0.000140] [000c280c] libusb: debug [op_init] sysfs is available
[ 0.000326] [000c280d] libusb: debug [linux_udev_event_thread_main] udev event thread entering
[ 0.010607] [000c280c] libusb: debug [linux_get_device_address] getting address for device: usb1 detached: 0
[ 0.010618] [000c280c] libusb: debug [linux_get_device_address] scan usb1
[ 0.010648] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=1
[ 0.010653] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 1 session_id 257
[ 0.010656] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/1 (session 257)
[ 0.010743] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-10 detached: 0
[ 0.010750] [000c280c] libusb: debug [linux_get_device_address] scan 1-10
[ 0.010774] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=5
[ 0.010778] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 5 session_id 261
[ 0.010782] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/5 (session 261)
[ 0.010810] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa6e6360 (1-10) has parent 0x563aaa6e7b10 (usb1) port 10
[ 0.010879] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-10.3 detached: 0
[ 0.010884] [000c280c] libusb: debug [linux_get_device_address] scan 1-10.3
[ 0.010909] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=9
[ 0.010912] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 9 session_id 265
[ 0.010914] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/9 (session 265)
[ 0.010941] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa6e5e30 (1-10.3) has parent 0x563aaa6e6360 (1-10) port 3
[ 0.011011] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-10.4 detached: 0
[ 0.011016] [000c280c] libusb: debug [linux_get_device_address] scan 1-10.4
[ 0.011040] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=12
[ 0.011045] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 12 session_id 268
[ 0.011052] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/12 (session 268)
[ 0.011079] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa6e7bc0 (1-10.4) has parent 0x563aaa6e6360 (1-10) port 4
[ 0.011139] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-11 detached: 0
[ 0.011144] [000c280c] libusb: debug [linux_get_device_address] scan 1-11
[ 0.011166] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=7
[ 0.011171] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 7 session_id 263
[ 0.011178] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/7 (session 263)
[ 0.011217] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa699ae0 (1-11) has parent 0x563aaa6e7b10 (usb1) port 11
[ 0.011286] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-13 detached: 0
[ 0.011292] [000c280c] libusb: debug [linux_get_device_address] scan 1-13
[ 0.011315] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=10
[ 0.011319] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 10 session_id 266
[ 0.011323] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/10 (session 266)
[ 0.011346] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa6e6990 (1-13) has parent 0x563aaa6e7b10 (usb1) port 13
[ 0.011412] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-13.1 detached: 0
[ 0.011417] [000c280c] libusb: debug [linux_get_device_address] scan 1-13.1
[ 0.011440] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=14
[ 0.011444] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 14 session_id 270
[ 0.011447] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/14 (session 270)
[ 0.011471] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69a110 (1-13.1) has parent 0x563aaa6e6990 (1-13) port 1
[ 0.011533] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-14 detached: 0
[ 0.011538] [000c280c] libusb: debug [linux_get_device_address] scan 1-14
[ 0.011573] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=13
[ 0.011577] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 13 session_id 269
[ 0.011580] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/13 (session 269)
[ 0.011602] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69a1a0 (1-14) has parent 0x563aaa6e7b10 (usb1) port 14
[ 0.011661] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-5 detached: 0
[ 0.011665] [000c280c] libusb: debug [linux_get_device_address] scan 1-5
[ 0.011690] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=2
[ 0.011695] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 2 session_id 258
[ 0.011697] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/2 (session 258)
[ 0.011720] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69a230 (1-5) has parent 0x563aaa6e7b10 (usb1) port 5
[ 0.011778] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-6 detached: 0
[ 0.011783] [000c280c] libusb: debug [linux_get_device_address] scan 1-6
[ 0.011807] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=16
[ 0.011811] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 16 session_id 272
[ 0.011813] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/16 (session 272)
[ 0.011837] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69a9d0 (1-6) has parent 0x563aaa6e7b10 (usb1) port 6
[ 0.011895] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-9 detached: 0
[ 0.011900] [000c280c] libusb: debug [linux_get_device_address] scan 1-9
[ 0.011924] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=4
[ 0.011928] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 4 session_id 260
[ 0.011930] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/4 (session 260)
[ 0.011954] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69a500 (1-9) has parent 0x563aaa6e7b10 (usb1) port 9
[ 0.012015] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-9.3 detached: 0
[ 0.012020] [000c280c] libusb: debug [linux_get_device_address] scan 1-9.3
[ 0.012044] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=6
[ 0.012048] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 6 session_id 262
[ 0.012051] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/6 (session 262)
[ 0.012074] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69ac00 (1-9.3) has parent 0x563aaa69a500 (1-9) port 3
[ 0.012135] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-9.4 detached: 0
[ 0.012140] [000c280c] libusb: debug [linux_get_device_address] scan 1-9.4
[ 0.012164] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=8
[ 0.012168] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 8 session_id 264
[ 0.012170] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/8 (session 264)
[ 0.012194] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69aae0 (1-9.4) has parent 0x563aaa69a500 (1-9) port 4
[ 0.012258] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 1-9.4.1 detached: 0
[ 0.012263] [000c280c] libusb: debug [linux_get_device_address] scan 1-9.4.1
[ 0.012287] [000c280c] libusb: debug [linux_get_device_address] bus=1 dev=11
[ 0.012291] [000c280c] libusb: debug [linux_enumerate_device] busnum 1 devaddr 11 session_id 267
[ 0.012294] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 1/11 (session 267)
[ 0.012330] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69ae10 (1-9.4.1) has parent 0x563aaa69aae0 (1-9.4) port 1
[ 0.012389] [000c280c] libusb: debug [linux_get_device_address] getting address for device: usb2 detached: 0
[ 0.012394] [000c280c] libusb: debug [linux_get_device_address] scan usb2
[ 0.012418] [000c280c] libusb: debug [linux_get_device_address] bus=2 dev=1
[ 0.012422] [000c280c] libusb: debug [linux_enumerate_device] busnum 2 devaddr 1 session_id 513
[ 0.012424] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 2/1 (session 513)
[ 0.012505] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 2-1 detached: 0
[ 0.012510] [000c280c] libusb: debug [linux_get_device_address] scan 2-1
[ 0.012535] [000c280c] libusb: debug [linux_get_device_address] bus=2 dev=2
[ 0.012539] [000c280c] libusb: debug [linux_enumerate_device] busnum 2 devaddr 2 session_id 514
[ 0.012541] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 2/2 (session 514)
[ 0.012566] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69a710 (2-1) has parent 0x563aaa69bfd0 (usb2) port 1
[ 0.012625] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 2-5 detached: 0
[ 0.012630] [000c280c] libusb: debug [linux_get_device_address] scan 2-5
[ 0.012651] [000c280c] libusb: debug [linux_get_device_address] bus=2 dev=3
[ 0.012655] [000c280c] libusb: debug [linux_enumerate_device] busnum 2 devaddr 3 session_id 515
[ 0.012657] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 2/3 (session 515)
[ 0.012680] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69c1c0 (2-5) has parent 0x563aaa69bfd0 (usb2) port 5
[ 0.012742] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 2-5.1 detached: 0
[ 0.012747] [000c280c] libusb: debug [linux_get_device_address] scan 2-5.1
[ 0.012769] [000c280c] libusb: debug [linux_get_device_address] bus=2 dev=5
[ 0.012773] [000c280c] libusb: debug [linux_enumerate_device] busnum 2 devaddr 5 session_id 517
[ 0.012775] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 2/5 (session 517)
[ 0.012798] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69c0a0 (2-5.1) has parent 0x563aaa69c1c0 (2-5) port 1
[ 0.012859] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 2-5.4 detached: 0
[ 0.012864] [000c280c] libusb: debug [linux_get_device_address] scan 2-5.4
[ 0.012886] [000c280c] libusb: debug [linux_get_device_address] bus=2 dev=6
[ 0.012889] [000c280c] libusb: debug [linux_enumerate_device] busnum 2 devaddr 6 session_id 518
[ 0.012892] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 2/6 (session 518)
[ 0.012916] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69c130 (2-5.4) has parent 0x563aaa69c1c0 (2-5) port 4
[ 0.012974] [000c280c] libusb: debug [linux_get_device_address] getting address for device: 2-6 detached: 0
[ 0.012979] [000c280c] libusb: debug [linux_get_device_address] scan 2-6
[ 0.013001] [000c280c] libusb: debug [linux_get_device_address] bus=2 dev=4
[ 0.013005] [000c280c] libusb: debug [linux_enumerate_device] busnum 2 devaddr 4 session_id 516
[ 0.013009] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 2/4 (session 516)
[ 0.013031] [000c280c] libusb: debug [linux_get_parent_info] dev 0x563aaa69c2d0 (2-6) has parent 0x563aaa69bfd0 (usb2) port 6
[ 0.013089] [000c280c] libusb: debug [linux_get_device_address] getting address for device: usb3 detached: 0
[ 0.013094] [000c280c] libusb: debug [linux_get_device_address] scan usb3
[ 0.013118] [000c280c] libusb: debug [linux_get_device_address] bus=3 dev=1
[ 0.013122] [000c280c] libusb: debug [linux_enumerate_device] busnum 3 devaddr 1 session_id 769
[ 0.013126] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 3/1 (session 769)
[ 0.013199] [000c280c] libusb: debug [linux_get_device_address] getting address for device: usb4 detached: 0
[ 0.013205] [000c280c] libusb: debug [linux_get_device_address] scan usb4
[ 0.013227] [000c280c] libusb: debug [linux_get_device_address] bus=4 dev=1
[ 0.013230] [000c280c] libusb: debug [linux_enumerate_device] busnum 4 devaddr 1 session_id 1025
[ 0.013233] [000c280c] libusb: debug [linux_enumerate_device] allocating new device for 4/1 (session 1025)
[ 0.013428] [000c280c] libusb: warning [libusb_init] installing new context as implicit default
[ 0.013436] [000c280c] libusb: debug [libusb_get_device_list]
[ 0.013445] [000c280c] libusb: debug [discovered_devs_append] need to increase capacity
[ 0.013454] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 0:
idVendor = 0x1d6b
idProduct = 0x0003
bcdDevice = 0x0518
[ 0.013475] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 1:
idVendor = 0x1d6b
idProduct = 0x0002
bcdDevice = 0x0518
[ 0.013483] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 2:
idVendor = 0x174c
idProduct = 0x3074
bcdDevice = 0x0001
[ 0.013494] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 3:
idVendor = 0x0bda
idProduct = 0x0412
bcdDevice = 0x0119
[ 0.013506] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 4:
idVendor = 0x1e4e
idProduct = 0x7102
bcdDevice = 0x0100
[ 0.013519] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 5:
idVendor = 0x0bda
idProduct = 0x0411
bcdDevice = 0x0119
[ 0.013528] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 6:
idVendor = 0x0bda
idProduct = 0x0301
bcdDevice = 0x0124
[ 0.013537] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 7:
idVendor = 0x1d6b
idProduct = 0x0003
bcdDevice = 0x0518
[ 0.013546] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 8:
idVendor = 0x046d
idProduct = 0x082d
bcdDevice = 0x0011
[ 0.013557] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 9:
idVendor = 0x0bda
idProduct = 0x5412
bcdDevice = 0x0119
[ 0.013565] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 10:
idVendor = 0x0bda
idProduct = 0x5400
bcdDevice = 0x0107
[ 0.013575] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 11:
idVendor = 0x0bda
idProduct = 0x5411
bcdDevice = 0x0119
[ 0.013595] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 12:
idVendor = 0x067b
idProduct = 0x2303
bcdDevice = 0x0300
[ 0.013607] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 13:
idVendor = 0x046d
idProduct = 0xc21c
bcdDevice = 0x0203
[ 0.013621] [000c280c] libusb: debug [libusb_open] open 1.2
[ 0.013645] [000c280c] libusb: debug [usbi_add_event_source] add fd 7 events 4
[ 0.013655] [000c280c] libusb: debug [libusb_claim_interface] interface 0
[ 0.013671] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 14:
idVendor = 0x1b1c
idProduct = 0x1b14
bcdDevice = 0x0302
[ 0.013688] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 15:
idVendor = 0x1b1c
idProduct = 0x1b3b
bcdDevice = 0x0102
[ 0.013702] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 16:
idVendor = 0x0000
idProduct = 0x0000
bcdDevice = 0x3298
[ 0.013718] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 17:
idVendor = 0x1b1c
idProduct = 0x0c0b
bcdDevice = 0x000a
[ 0.013733] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 18:
idVendor = 0x1b1c
idProduct = 0x1b11
bcdDevice = 0x0308
[ 0.013751] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 19:
idVendor = 0x0ac8
idProduct = 0x3420
bcdDevice = 0x0413
[ 0.013765] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 20:
idVendor = 0x174c
idProduct = 0x2074
bcdDevice = 0x0001
[ 0.013782] [000c280c] libusb: debug [libusb_get_device_descriptor]
Checking index 21:
idVendor = 0x1d6b
idProduct = 0x0002
bcdDevice = 0x0518
[ 0.013801] [000c280c] libusb: debug [libusb_submit_transfer] transfer 0x563aaa6ce420
[ 0.013809] [000c280c] libusb: debug [submit_bulk_transfer] need 1 urbs for new transfer with length 256
[ 0.013829] [000c280c] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[ 0.013835] [000c280c] libusb: debug [handle_events] event sources modified, reallocating event data
[ 0.013843] [000c280c] libusb: debug [usbi_wait_for_events] poll() 3 fds with timeout in 60000ms
[ ==== Press/release key on G13 16 times here ==== ]
[ 7.643531] [000c280c] libusb: debug [usbi_wait_for_events] poll() returned 1
[ 7.643565] [000c280c] libusb: debug [reap_for_handle] urb type=1 status=0 transferred=256
[ 7.643575] [000c280c] libusb: debug [handle_bulk_completion] handling completion status 0 of bulk urb 1/1
[ 7.643584] [000c280c] libusb: debug [handle_bulk_completion] all URBs in transfer reaped --> complete!
[ 7.643590] [000c280c] libusb: debug [usbi_handle_transfer_completion] transfer 0x563aaa6ce420 has callback 0x7fa53bda89d0
[ 7.643597] [000c280c] libusb: debug [sync_transfer_cb] actual_length=256
[ 7.643613] [000c280c] libusb: debug [libusb_free_transfer] transfer 0x563aaa6ce420
nbytes: 256, keybits = [ 00 00 82 00 80 ]
[ 7.643636] [000c280c] libusb: debug [libusb_submit_transfer] transfer 0x563aaa6e1850
[ 7.643644] [000c280c] libusb: debug [submit_bulk_transfer] need 1 urbs for new transfer with length 256
[ 7.643665] [000c280c] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[ 7.643674] [000c280c] libusb: debug [usbi_wait_for_events] poll() 3 fds with timeout in 60000ms
^C
If you are working with a HID device, maybe you should consider using HIDAPI instead: https://github.com/libusb/libusb/wiki/FAQ#does-libusb-support-usb-hid-devices I don't know if that would solve this issue though.
The HID descriptor reported by the G13 is essentially meaningless, so it has to be parsed "by hand:"
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
0x09, 0x00, // Usage (0x00)
0xA1, 0x01, // Collection (Application)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x09, 0x01, // Usage (0x01)
0x85, 0x01, // Report ID (1)
0x95, 0x07, // Report Count (7)
0x75, 0x08, // Report Size (8)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x85, 0x03, // Report ID (3)
0x09, 0x02, // Usage (0x02)
0x96, 0xDF, 0x03, // Report Count (991)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0x07, // Report ID (7)
0x09, 0x03, // Usage (0x03)
0x95, 0x04, // Report Count (4)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0x04, // Report ID (4)
0x09, 0x04, // Usage (0x04)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0x05, // Report ID (5)
0x09, 0x05, // Usage (0x05)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0x06, // Report ID (6)
0x09, 0x06, // Usage (0x06)
0x96, 0x01, 0x01, // Report Count (257)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
// 61 bytes