79495589

Date: 2025-03-09 08:10:01
Score: 5
Natty:
Report link

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.

Reasons:
  • Blacklisted phrase (1): appreciated
  • Blacklisted phrase (1): Any help
  • RegEx Blacklisted phrase (3): Any help of sending the proper HID class report descriptor would be much appreciated
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: Christos