libusb / hidapi

A Simple cross-platform library for communicating with HID devices
https://libusb.info/hidapi/
Other
1.67k stars 397 forks source link

Different feature report results for windows and linux #352

Closed presscot closed 2 years ago

presscot commented 2 years ago

On linux everything works fine and receives well results. ReportId from 1 to 254 works fine. Unfortunately, on windows only get results for Report from id 1 to 3. Report id 4 on linux returns correct results and the device responds. Unfortunately on windows the device does not respond and the result is incorrect. For example:

linux:

Opening device, vid/pid:0x0001/0x0000, usagePage/usage: 0/0
Device opened
Reading 128-byte feature report, report_id 4...read 22 bytes:
 16 03 55 00 50 00 53 00 20 00 4E 00 6F 00 20 00 41 00 63 00 6B 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Closing device

windows:

Opening device, vid/pid:0x0001/0x0000, usagePage/usage: 0/0
Device opened
Reading 128-byte feature report, report_id 4...read -1 bytes:
 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Closing device
$ usbhid-dump -m 0001:0000
003:076:000:DESCRIPTOR         1627334825.314075
 05 86 09 04 A1 01 05 84 09 1E A1 00 85 01 09 1F
 65 00 75 04 95 01 15 00 25 0F 65 00 B1 02 75 04
 95 01 B1 03 09 40 75 10 95 01 67 21 D1 F0 00 55
 07 15 00 26 FA 00 B1 02 09 42 75 10 95 01 66 01
 F0 55 00 15 00 25 3C B1 02 09 53 75 10 95 01 67
 21 D1 F0 00 55 07 15 00 26 FA 00 B1 02 09 54 75
 10 95 01 67 21 D1 F0 00 55 07 15 00 26 FA 00 B1
 02 09 FD 09 FE 09 FF 75 08 95 03 26 FF 00 65 00
 B1 00 C0 05 84 09 1E A1 00 85 02 09 1F 65 00 75
 04 95 01 15 00 25 0F 65 00 B1 02 95 01 75 04 B1
 03 09 40 75 10 95 01 67 21 D1 F0 00 55 07 15 00
 26 FA 00 B1 02 09 42 75 10 95 01 66 01 F0 55 00
 15 00 25 3C B1 02 09 43 75 10 95 01 66 21 D1 55
 07 15 00 27 FE FF 00 00 B1 02 09 44 95 01 75 10
 66 21 D1 55 07 15 00 27 FE FF 00 00 B1 02 09 56
 75 18 95 01 66 01 10 55 00 15 00 27 FE FF 00 00
 B1 02 09 57 75 18 95 01 66 01 10 55 00 15 00 27
 FE FF 00 00 B1 02 C0 05 84 09 10 A1 00 85 03 09
 11 65 00 75 04 95 01 15 00 25 0F 65 00 B1 02 75
 04 95 01 B1 03 09 02 A1 02 09 6D 09 61 75 01 95
 02 15 00 25 01 B1 02 75 06 95 01 B1 03 C0 09 30
 75 18 95 01 67 21 D1 F0 00 55 05 27 FE FF 00 00
 B1 02 09 36 75 10 95 01 67 01 00 01 00 27 FE FF
 00 00 B1 02 09 58 75 01 95 06 15 00 25 01 81 02
 75 02 95 01 81 03 09 58 75 01 95 04 15 00 25 01
 B1 02 75 04 95 01 B1 03 C0 05 84 09 16 A1 00 85
 04 09 17 75 04 95 01 15 00 25 0F 65 00 81 02 75
 04 95 01 81 03 09 1A A1 00 09 1B 09 1F 75 04 95
 02 15 00 25 0F 65 00 81 02 09 02 A1 02 09 61 75
 01 95 01 15 00 25 01 81 02 75 07 95 01 81 03 C0
 09 30 75 10 95 01 67 21 D1 F0 00 55 05 27 FE FF
 00 00 81 02 09 32 75 10 95 01 66 01 F0 55 05 27
 FE FF 00 00 81 02 C0 09 1C A1 00 85 05 09 1D 09
 1F 75 04 95 02 15 00 25 0F 65 00 81 02 09 30 75
 10 95 01 67 21 D1 F0 00 55 05 27 FE FF 00 00 81
 02 09 32 75 10 95 01 66 01 F0 55 05 27 FE FF 00
 00 81 02 09 35 75 10 95 01 15 00 26 FF 00 81 02
 09 02 A1 02 09 65 09 6E 09 6F 75 01 95 03 15 00
 25 01 65 00 81 02 75 05 95 01 81 03 C0 C0 C0 C0
$ lsusb -vd 0001:0000

Bus 003 Device 067: ID 0001:0000 Fry's Electronics MEC0003
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x0001 Fry's Electronics
  idProduct          0x0000 
  bcdDevice            1.00
  iManufacturer           1 MEC
  iProduct                2 MEC0003
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0022
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.00
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     624
         Report Descriptors: 
           ** UNAVAILABLE **
      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              10
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

Please help me. I have a ready-made application written in the Electron running on linux, but unfortunately the principals only depend on the windows version.

Cheers Patryk

JoergAtGithub commented 2 years ago

According to the attached Report Descriptor, there is only an input report with ID 4, but not an feature report with this ID.

Therefore the response on Windows seems to be the correct one.

Which backend do you use on Linux, hidraw or libusb? I wonder why Linux does not return a proper error here.

You should use hid_get_feature_report for report 1-3 of this device, and hid_get_input_report or hid_read for report 4 & 5 of this device.

Youw commented 2 years ago

I wonder why Linux does not return a proper error here

As far as I know, Windows is the only backend that checks requested reports with HID descriptor. WinAPI validates all report requests.

Maybe macOS and hidraw does something similar (at least those backends could do so - it is up to OS implementation).

Libusb definitely doesn't perform any validations. HIDAPI just sends corresponding USB requests to the device, and device may choose to handle those, even if HID descriptor doesn't contain the information about the requested report.

presscot commented 2 years ago

Fist of all Thank You @JoergAtGithub and @Youw for response.

I want to connect to the device via node-hid based on hidapi. However, I did some tests using different libraries, here are the results:

On Ubuntu 20.04:

On Windows10:

Example for libusb 1.0.24:

unsigned char reportId  = 4;

rc = libusb_init(&context);  // return LIBUSB_SUCCESS
count = libusb_get_device_list(context, &devs);
// foreach and select device
rc = libusb_open(device, &dev_handle); // return LIBUSB_SUCCESS
rc = libusb_claim_interface(dev_handle, 0); // return LIBUSB_SUCCESS

rc = libusb_control_transfer(
    dev_handle,
    LIBUSB_ENDPOINT_IN + LIBUSB_REQUEST_TYPE_CLASS + LIBUSB_RECIPIENT_INTERFACE,
    0x01,
    reportId + (0x03 << 8),
    0,
    buf, size, 5000);
// return -1 LIBUSB_ERROR_IO; for id higher or equal than 4, works well for ID 1,2,3

Example for libusb-win32-1.2.6.0:

usb_init();
usb_find_busses();
usb_find_devices();
// foreach and select device
dev_handle = usb_open(dev);
usb_claim_interface(dev_handle, 0);

ret = usb_control_msg(
    dev_handle,
    USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
    0x01,
    reportId + (0x03 << 8),
    0,
    buf, size, 5000);
// works with each reportId and returns length of response

Installing additional drivers for libusb-win32-1.2.6.0 is problematic so i would like to use hidapi or libusb. Therefore, I would like to ask you for help if it is possible to skip the descriptor checking when sending a feature report, or if is possible to introduce a corrected descriptor in fly. Is the only option to stay with libusb-win32?

Thank you in advance for your help!!

JoergAtGithub commented 2 years ago

You must use the correct API commands in your code! These are hid_get_feature_report for report 1-3 of this device, and hid_get_input_report (or hid_read) for report 4 & 5 of this device.

presscot commented 2 years ago

You must use the correct API commands in your code! These are hid_get_feature_report for report 1-3 of this device, and hid_get_input_report (or hid_read) for report 4 & 5 of this device.

I forgot to write that I also tested the hid_get_feature_report functions, unfortunately without success. Besides, there is a lot of functionality in feature report ID higher than 6. I just think the descryptor is invalid.

Youw commented 2 years ago

skip the descriptor checking

That check is performed by Windows HID driver, not by HIDAPI - so it is not possible.

if is possible to introduce a corrected descriptor in fly

Not possible - not supported by HID standard, nor by any of the driver/implementation.


If you need "different reports" depending on some current state of the device - use a single report, and write your own protocol on top of it. E.g.: byte[0] - fixed report ID, byte[1] - your "dynamic report ID" (other bytes - additional payload, if needed).

mcuee commented 2 years ago

Closing this as there are no further updates.