I am a beginner with USB and libusb.
I am looking for libusb 1.0 code, capable of reading data from a usb mouse.
I have found some relevant code online, e.g. .c, but does not work for my purpose.
As explained here , the mouse does not receive data.
I am also attaching the code here for convenience:
int main(void)
{
libusb_device **devs;
int r;
int numread;
ssize_t cnt;
int counter = 0;
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_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
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 //
// r = libusb_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");
// 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, 1, callback_in, NULL, 1); // NULL for no user data, 1 is TIMEOUT //
// submit next transfer //
r = libusb_submit_transfer(transfer_in);
if (r < 0)
{
printf("submit transter result = %d\n", r);
}
// 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);
printf("WAITING...\n");
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");
}
}
// close device usb handle //
libusb_close(handle);
libusb_exit(ctx);
return 0;
}
and the callback and signal handlers are as follows:
// called when data for in_buffer is AVAILABLE //
void callback_in(struct libusb_transfer *transfer)
{
switch (transfer->status)
{
case LIBUSB_TRANSFER_COMPLETED:
{
// Success here, data transfered are inside
// xfr->buffer
// and the length is
// xfr->actual_length
printf("LIBUSB_TRANSFER_COMPLETED\n");
break;
}
case LIBUSB_TRANSFER_CANCELLED:
{
printf("LIBUSB_TRANSFER_CANCELLED\n");
break;
}
case LIBUSB_TRANSFER_NO_DEVICE:
{
printf("LIBUSB_TRANSFER_NO_DEVICE\n");
break;
}
case LIBUSB_TRANSFER_TIMED_OUT:
{
printf("LIBUSB_TRANSFER_TIMED_OUT\n");
break;
}
case LIBUSB_TRANSFER_ERROR:
{
printf("LIBUSB_TRANSFER_ERROR\n");
break;
}
case LIBUSB_TRANSFER_STALL:
{
printf("LIBUSB_TRANSFER_STALL\n");
break;
}
case LIBUSB_TRANSFER_OVERFLOW:
{
printf("LIBUSB_TRANSFER_OVERFLOW\n");
break;
}
break;
}
printf("transfer flags = %b\n", transfer->flags)
printf("transfer actual length = %d\n", transfer->actual_length);
printf("transfer data = %d\n", *(transfer->buffer + 0));
totalbytes = totalbytes + transfer->actual_length;
// submit next transfer //
libusb_submit_transfer(transfer_in);
}
// *** sigint_handler *** //
// note that the SIGINT interupts the main thread //
void sigint_handler(int signo)
{
write(fileno(stderr), "\nCtrl-C Interrupt Detected.\n", 28);
exitprogram = 1;
}
What happens is that I don't get ANY interrupt transfers from USB at all, only callback timeouts.
Any help is much appreciated!!!
I am a beginner with USB and libusb.
I am looking for libusb 1.0 code, capable of reading data from a usb mouse.
I have found some relevant code online, e.g. https://github/Mathias-L/STM32F4-libusb-example/blob/master/async.c, but does not work for my purpose.
As explained here https://github/libusb/libusb/discussions/1613, the mouse does not receive data.
I am also attaching the code here for convenience:
int main(void)
{
libusb_device **devs;
int r;
int numread;
ssize_t cnt;
int counter = 0;
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_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
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 //
// r = libusb_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");
// 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, 1, callback_in, NULL, 1); // NULL for no user data, 1 is TIMEOUT //
// submit next transfer //
r = libusb_submit_transfer(transfer_in);
if (r < 0)
{
printf("submit transter result = %d\n", r);
}
// 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);
printf("WAITING...\n");
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");
}
}
// close device usb handle //
libusb_close(handle);
libusb_exit(ctx);
return 0;
}
and the callback and signal handlers are as follows:
// called when data for in_buffer is AVAILABLE //
void callback_in(struct libusb_transfer *transfer)
{
switch (transfer->status)
{
case LIBUSB_TRANSFER_COMPLETED:
{
// Success here, data transfered are inside
// xfr->buffer
// and the length is
// xfr->actual_length
printf("LIBUSB_TRANSFER_COMPLETED\n");
break;
}
case LIBUSB_TRANSFER_CANCELLED:
{
printf("LIBUSB_TRANSFER_CANCELLED\n");
break;
}
case LIBUSB_TRANSFER_NO_DEVICE:
{
printf("LIBUSB_TRANSFER_NO_DEVICE\n");
break;
}
case LIBUSB_TRANSFER_TIMED_OUT:
{
printf("LIBUSB_TRANSFER_TIMED_OUT\n");
break;
}
case LIBUSB_TRANSFER_ERROR:
{
printf("LIBUSB_TRANSFER_ERROR\n");
break;
}
case LIBUSB_TRANSFER_STALL:
{
printf("LIBUSB_TRANSFER_STALL\n");
break;
}
case LIBUSB_TRANSFER_OVERFLOW:
{
printf("LIBUSB_TRANSFER_OVERFLOW\n");
break;
}
break;
}
printf("transfer flags = %b\n", transfer->flags)
printf("transfer actual length = %d\n", transfer->actual_length);
printf("transfer data = %d\n", *(transfer->buffer + 0));
totalbytes = totalbytes + transfer->actual_length;
// submit next transfer //
libusb_submit_transfer(transfer_in);
}
// *** sigint_handler *** //
// note that the SIGINT interupts the main thread //
void sigint_handler(int signo)
{
write(fileno(stderr), "\nCtrl-C Interrupt Detected.\n", 28);
exitprogram = 1;
}
What happens is that I don't get ANY interrupt transfers from USB at all, only callback timeouts.
Any help is much appreciated!!!
Share Improve this question asked Mar 6 at 14:54 ChristosChristos 1 2 |1 Answer
Reset to default 0I 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.
lsusb
can help with that. – Tim Roberts Commented Mar 6 at 19:11