I have managed to make good progress with this. I switched to using a simple Microsoft Basic Optical Mouse:
// Microsoft Corp. Basic Optical Mouse
#define USB_VENDOR_ID 0x045e /* USB vendor ID used by the device */
#define USB_PRODUCT_ID 0x0084 /* USB product ID used by the device */
and the following code now works for the former mouse:
int main(void)
{
libusb_device **devs;
int r;
int numread;
ssize_t cnt;
int counter = 0;
// connect SIGINT to function sigint_handler() //
if (signal(SIGINT, sigint_handler) == SIG_ERR)
{
printf("ERROR: Cannot Connect to SIGINT!");
}
// Block SIGALRM in the main thread //
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
r = libusb_init(&ctx);
// r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0);
if (r < 0)
return r;
// libusb_set_option(ctx, LIBUSB_LOG_LEVEL_WARNING);
libusb_set_debug(ctx, 3); // debug level 3 //
cnt = libusb_get_device_list(ctx, &devs); // returns device list //
if (cnt < 0)
{
libusb_exit(NULL);
return (int) cnt;
}
print_devs(devs);
libusb_free_device_list(devs, 1);
// open device //
handle = libusb_open_device_with_vid_pid(ctx, USB_VENDOR_ID, USB_PRODUCT_ID);
if (!handle)
{
perror("device not found");
return 1;
}
// set auto detach/attach kernel driver //
r = libusb_set_auto_detach_kernel_driver(handle, 1); // enable = 1 //
printf("auto_detach result = %d\n", r);
// claim interface //
r = libusb_claim_interface(handle, 0);
if (r < 0)
{
fprintf(stderr, "usb_claim_interface error %d\n", r);
return 2;
}
printf("Interface claimed\n");
printf("Resetting Device\n");
r = libusb_reset_device(handle);
if (r < 0)
{
printf("ERROR %d resetting device!\n");
}
printf("*** Device Descriptor ***\n");
r = libusb_get_descriptor(handle, LIBUSB_DT_DEVICE, 0, desc_buffer, 1024);
dump_descriptor(r, desc_buffer, r);
//////////////////////////////////////////////////////
// allocate transfer of data IN (IN to host PC from USB-device)
transfer_in = libusb_alloc_transfer(1);
if (transfer_in == NULL)
{
printf("ERROR allocating usb transfer.\n");
}
// Note: in_buffer is where input data is written //
// libusb_fill_bulk_transfer(transfer_in, handle, USB_ENDPOINT_IN, in_buffer, LEN_IN_BUFFER, callback_in, NULL, 0); // NULL for no user data //
libusb_fill_interrupt_transfer(transfer_in, handle, USB_ENDPOINT_IN, in_buffer, 8, callback_in, NULL, 0); // NULL for no user data //
// submit next transfer //
r = libusb_submit_transfer(transfer_in);
if (r < 0)
{
printf("submit transter result = %d\n", r);
}
while (exitprogram == 0)
{
printf("exitprogram = %d\n", exitprogram);
// waiting //
// r = libusb_handle_events_completed(ctx, NULL);
r = libusb_handle_events(ctx);
if (r < 0)
{
printf("ERROR at events handling\n");
break;
}
}
printf("exitprogram = %d\n", exitprogram);
if (transfer_in)
{
r = libusb_cancel_transfer(transfer_in);
if (r == 0)
{
printf("transfer_in successfully cancelled.\n");
}
else
{
printf("ERROR cancelling transfer\n");
}
}
//////////////////////////////////////////////////////
// if you DONT release the interface, communication halts //
// release interface //
r = libusb_release_interface(handle, 0);
if (r < 0)
{
fprintf(stderr, "usb_release_interface error %d\n", r);
}
printf("Interface released\n");
// close device usb handle //
libusb_close(handle);
libusb_exit(ctx);
}
and in my callback function callback_in(), I dump the libusb_tranfer, i.e. transfer->status and the raw bytes received.
For the Microsoft mouse it all works well, and I get the following output, based on the mouse movement and buttons pressed:
...
LIBUSB_TRANSFER_COMPLETED
transfer flags = %b
transfer actual length = 8
0: transfer data = 4
1: transfer data = 0
2: transfer data = 255
3: transfer data = 0
4: transfer data = 4
5: transfer data = 0
6: transfer data = 255
7: transfer data = 0
exitprogram = 0
LIBUSB_TRANSFER_COMPLETED
transfer flags = %b
transfer actual length = 8
0: transfer data = 4
1: transfer data = 0
2: transfer data = 255
3: transfer data = 0
4: transfer data = 0
5: transfer data = 0
6: transfer data = 0
7: transfer data = 0
exitprogram = 0
...
The buffer size I use is 8, which is equal to the value of the maximum packet size of the USB Device descriptor, and in this case it works.
I am NOT sure what size of transfer to specify, but 8 works in this case.
When using difference mice, e.g. Logitech G5 Laser, or wireless Logitech mini mouse, instead of getting LIBUSB_TRANSFER_COMPLETED I get LIBUSB_TRANSFER_OVERFLOW, even if I use a HUGE buffer of 1024 bytes...
I looked up the USB HID document, but I am not sure HOW to send the proper control packet to configure other mice. On this webpage, https://www.usbmadesimple.co.uk/ums_5.htm it is explaned that you must send "an HID class report descriptor, which in this case informs the appropriate driver to expect to receive a 4 byte report of mouse events on its interrupt IN endpoint."
Any help of sending the proper HID class report descriptor would be much appreciated.