Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hid_error implementation for libusb #698

Merged
merged 10 commits into from
Oct 2, 2024
Merged

hid_error implementation for libusb #698

merged 10 commits into from
Oct 2, 2024

Conversation

Youw
Copy link
Member

@Youw Youw commented Sep 27, 2024

This is initial implementation.

  • hid_error is set correctly for most of the API functions;
  • refactored iconv routines - common code for utf16 and utf8 to wchar_t implementation;
  • hid_libusb_error to have libusb error code when possible;

Closes: #690
Fixes: #684

matheusmoreira and others added 8 commits September 7, 2024 15:31
Most if not all libusb functions return UTF-8 encoded data
but hidapi functions typically take and return wide character strings.
Adapt one of the existing algorithms in the code base into a general
conversion function.
Returns libusb error names and strings
converted to wide character strings.
Store libusb error code so it can be retrieved later.

Includes the original error code as well as a context-specific message
which the libusb documentation sometimes specifies for each function.
Code which uses those functions are meant to set the contextual message
whenever possible.

The code is initialized to a success state which implies no errors yet.
The contextual error message is initialized to NULL and is not freed
when the device is closed. It is meant to point at string literals.
Sets all error data, including an optional contextual error message
which is supposed to be a non-freeable constant string
such as a string literal.

Contextual error messages are meant to be used in the cases
the libusb documentation goes into detail as to what happened.
Passing NULL will produce a message with just the libusb_error_name
and the libusb_strerror results. Passing a string literal will produce
a message that contains the additional context in addition to the error
name and message.
Set error data when send_feature_report fails, including custom messages
for the situations especially outlined in the libusb documentation for
the libusb_control_transfer function.
Compute a formatted error string containing the libusb error name,
the error message as well as any contextual information.
Return NULL if there are no errors or if memory allocation failed.
@Youw Youw mentioned this pull request Sep 27, 2024
@Youw
Copy link
Member Author

Youw commented Sep 27, 2024

@mcuee if you could test this one as well - would be perfect.

@mcuee mcuee added the enhancement New feature or request label Sep 28, 2024
@mcuee
Copy link
Member

mcuee commented Sep 28, 2024

@mcuee if you could test this one as well - would be perfect.

Yes I will carry out the test later today.

@mcuee
Copy link
Member

mcuee commented Sep 29, 2024

First simple test -- looks good. Tested under Ubuntu Linux 20.04.

  1. git main:
mcuee@UbuntuSwift3 ~/build/hid/hidapi (master)$ sudo ./hidtest/hidtest-libusb 
hidapi test/example tool. Compiled with hidapi version 0.15.0, runtime version 0.15.0.
Compile-time version matches runtime version of hidapi.

Device Found
  type: 04d8 003f
  path: 3-3:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29, 
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81, 
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0, 
Device Found
  type: 1ea7 0064
  path: 3-1:1.0
  serial_number: (null)
  Manufacturer: (null)
  Product:      2.4G Mouse
  Release:      200
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (105 bytes)
0x06, 0xb5, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0xb5, 0x09, 
0x02, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x07, 
0x81, 0x02, 0x09, 0x02, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 
0x08, 0x95, 0x07, 0x91, 0x02, 0xc0, 0x05, 0x01, 0x09, 0x02, 
0xa1, 0x01, 0x85, 0x02, 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 
0x19, 0x01, 0x29, 0x08, 0x15, 0x00, 0x25, 0x01, 0x95, 0x08, 
0x75, 0x01, 0x81, 0x02, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 
0x16, 0x01, 0xf8, 0x26, 0xff, 0x07, 0x75, 0x0c, 0x95, 0x02, 
0x81, 0x06, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 
0x95, 0x01, 0x81, 0x06, 0x05, 0x0c, 0x0a, 0x38, 0x02, 0x95, 
0x01, 0x81, 0x06, 0xc0, 0xc0, 
Manufacturer String: Microchip Technology Inc.
Product String: Simple HID Device Demo
Serial Number String: (1033)   Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29, 
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81, 
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0, 
Device Found
  type: 04d8 003f
  path: 3-3:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x1 (0xff00)
  Bus type: 1 (USB)

Indexed String 1: Microchip Technology Inc.
Unable to send a feature report.
Unable to get a feature report: hid_error is not implemented yet
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
read() timeout
  1. This PR
mcuee@UbuntuSwift3 ~/build/hid/hidapi_pr698 (implement-hid-error)$ sudo ./hidtest/hidtest-libusb 
[sudo] password for mcuee: 
hidapi test/example tool. Compiled with hidapi version 0.15.0, runtime version 0.15.0.
Compile-time version matches runtime version of hidapi.

Device Found
  type: 04d8 003f
  path: 3-3:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29, 
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81, 
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0, 
Device Found
  type: 1ea7 0064
  path: 3-1:1.0
  serial_number: (null)
  Manufacturer: (null)
  Product:      2.4G Mouse
  Release:      200
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (105 bytes)
0x06, 0xb5, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0xb5, 0x09, 
0x02, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x07, 
0x81, 0x02, 0x09, 0x02, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 
0x08, 0x95, 0x07, 0x91, 0x02, 0xc0, 0x05, 0x01, 0x09, 0x02, 
0xa1, 0x01, 0x85, 0x02, 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 
0x19, 0x01, 0x29, 0x08, 0x15, 0x00, 0x25, 0x01, 0x95, 0x08, 
0x75, 0x01, 0x81, 0x02, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 
0x16, 0x01, 0xf8, 0x26, 0xff, 0x07, 0x75, 0x0c, 0x95, 0x02, 
0x81, 0x06, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 
0x95, 0x01, 0x81, 0x06, 0x05, 0x0c, 0x0a, 0x38, 0x02, 0x95, 
0x01, 0x81, 0x06, 0xc0, 0xc0, 
Manufacturer String: Microchip Technology Inc.
Product String: Simple HID Device Demo
Serial Number String: (1033)   Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29, 
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81, 
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0, 
Device Found
  type: 04d8 003f
  path: 3-3:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x1 (0xff00)
  Bus type: 1 (USB)

Indexed String 1: Microchip Technology Inc.
Unable to send a feature report.
Unable to get a feature report: hid_get_feature_report: (LIBUSB_ERROR_PIPE) Pipe erro
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
read() timeout

@mcuee
Copy link
Member

mcuee commented Sep 29, 2024

Tested under FreeBSD 14.1 and this PR is good as well.

mcuee@freebsd14:~/build/hidapi_pr698 $ sudo ./hidtest/hidtest
hidapi test/example tool. Compiled with hidapi version 0.15.0, runtime version 0.15.0.
Compile-time version matches runtime version of hidapi.

Device Found
  type: 04d8 003f
  path: 0-4:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29,
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81,
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0,
Manufacturer String: Microchip Technology Inc.
Product String: Simple HID Device Demo
Serial Number String: (1033  Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29,
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81,
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0,
Device Found
  type: 04d8 003f
  path: 0-4:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x1 (0xff00)
  Bus type: 1 (USB)

Indexed String 1: Microchip Technology Inc.
Unable to send a feature report.
Unable to get a feature report: hid_get_feature_report: (LIBUSB_ERROR_NO_DEVICE) No devic
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
read() timeout

@mcuee
Copy link
Member

mcuee commented Sep 29, 2024

hid_error is not used by hidapitester so I can not test using hidapitester as of now.

Anyway, it is good that git main and this PR works fine under FreeBSD 14.1 Release using hidapitester as well.

mcuee@freebsd14:~/build/hidapitester $ sudo ./hidapitester --vidpid 04d8/003f --open --send-output 0x00,0x80
Opening device, vid/pid: 0x04D8/0x003F
Writing output report of 64-bytes...wrote 64 bytes:
 00 80 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
mcuee@freebsd14:~/build/hidapitester $ sudo ./hidapitester --vidpid 04d8/003f --open --send-output 0x00,0x80
Opening device, vid/pid: 0x04D8/0x003F
Writing output report of 64-bytes...wrote 64 bytes:
 00 80 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

mcuee@freebsd14:~/build/hidapitester $ sudo ./hidapitester --vidpid 04d8/003f --open --send-output 0x00,0x81 --read-input
Opening device, vid/pid: 0x04D8/0x003F
Writing output report of 64-bytes...wrote 64 bytes:
 00 81 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
Reading up to 64-byte input report, 250 msec timeout...read 64 bytes:
 81 01 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

mcuee@freebsd14:~/build/hidapitester $ sudo ./hidapitester --vidpid 04d8/003f --open --get-report-descriptor
Opening device, vid/pid: 0x04D8/0x003F
Report Descriptor:
 06 00 FF 09 01 A1 01 19 01 29 40 15 01 25 40 75 08 95 40 81 00 19 01 29 40 91 00 C0
Closing device
mcuee@freebsd14:~/build/hidapitester $ sudo ./hidapitester --vidpid 04d8/003f --list-detail
04D8/003F: Microchip Technology Inc. - Simple HID Device Demo
  vendorId:      0x04D8
  productId:     0x003F
  usagePage:     0x0000
  usage:         0x0000
  serial_number: (null)
  interface:     0
  path: 0-4:1.0

mcuee@freebsd14:~/build/hidapitester $ sudo ./hidapitester --vidpid 04d8/003f --list-usages
04D8/003F / 0000/0000  Microchip Technology Inc. - Simple HID Device Demo

@mcuee
Copy link
Member

mcuee commented Sep 29, 2024

@Youw

I think this PR is good to go.

@Youw
Copy link
Member Author

Youw commented Sep 29, 2024

@matheusmoreira would you check as well?

@Youw
Copy link
Member Author

Youw commented Sep 29, 2024

Oh, from the logs I actually see one issue - looks like an error message is cut by one symbol:

Unable to get a feature report: hid_get_feature_report: (LIBUSB_ERROR_PIPE) Pipe erro

Unable to get a feature report: hid_get_feature_report: (LIBUSB_ERROR_NO_DEVICE) No devic

I'll double-check this one.

@Youw
Copy link
Member Author

Youw commented Sep 29, 2024

Now we should be good

@mcuee
Copy link
Member

mcuee commented Sep 30, 2024

Now we should be good

Yes it is good now.

mcuee@UbuntuSwift3 ~/build/hid/hidapi_pr698 (implement-hid-error)$ sudo ./hidtest/hidtest-libusb 
hidapi test/example tool. Compiled with hidapi version 0.15.0, runtime version 0.15.0.
Compile-time version matches runtime version of hidapi.

Device Found
  type: 04d8 003f
  path: 3-2.4:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29, 
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81, 
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0, 
Device Found
  type: 1ea7 0064
  path: 3-1:1.0
  serial_number: (null)
  Manufacturer: (null)
  Product:      2.4G Mouse
  Release:      200
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (105 bytes)
0x06, 0xb5, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0xb5, 0x09, 
0x02, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x07, 
0x81, 0x02, 0x09, 0x02, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 
0x08, 0x95, 0x07, 0x91, 0x02, 0xc0, 0x05, 0x01, 0x09, 0x02, 
0xa1, 0x01, 0x85, 0x02, 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 
0x19, 0x01, 0x29, 0x08, 0x15, 0x00, 0x25, 0x01, 0x95, 0x08, 
0x75, 0x01, 0x81, 0x02, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 
0x16, 0x01, 0xf8, 0x26, 0xff, 0x07, 0x75, 0x0c, 0x95, 0x02, 
0x81, 0x06, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 
0x95, 0x01, 0x81, 0x06, 0x05, 0x0c, 0x0a, 0x38, 0x02, 0x95, 
0x01, 0x81, 0x06, 0xc0, 0xc0, 
Manufacturer String: Microchip Technology Inc.
Product String: Simple HID Device Demo
Serial Number String: (1033)   Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29, 
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81, 
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0, 
Device Found
  type: 04d8 003f
  path: 3-2.4:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x1 (0xff00)
  Bus type: 1 (USB)

Indexed String 1: Microchip Technology Inc.
Unable to send a feature report.
Unable to get a feature report: hid_get_feature_report: (LIBUSB_ERROR_PIPE) Pipe error
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
read() timeout

@mcuee
Copy link
Member

mcuee commented Sep 30, 2024

It is also good under FreeBSD 14.1 release.

mcuee@freebsd14:~/build/hidapi_pr698 $ sudo ./hidtest/hidtest 
hidapi test/example tool. Compiled with hidapi version 0.15.0, runtime version 0.15.0.
Compile-time version matches runtime version of hidapi.

Device Found
  type: 04d8 003f
  path: 0-4:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29, 
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81, 
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0, 
Manufacturer String: Microchip Technology Inc.
Product String: Simple HID Device Demo
Unable to read serial number string
Serial Number String: (0) 
  Report Descriptor: (28 bytes)
0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x19, 0x01, 0x29, 
0x40, 0x15, 0x01, 0x25, 0x40, 0x75, 0x08, 0x95, 0x40, 0x81, 
0x00, 0x19, 0x01, 0x29, 0x40, 0x91, 0x00, 0xc0, 
Device Found
  type: 04d8 003f
  path: 0-4:1.0
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x1 (0xff00)
  Bus type: 1 (USB)

Indexed String 1: Microchip Technology Inc.
Unable to send a feature report.
Unable to get a feature report: hid_get_feature_report: (LIBUSB_ERROR_NO_DEVICE) No device
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
read() timeout

@matheusmoreira
Copy link

matheusmoreira commented Sep 30, 2024

Working for me as well on Arch Linux. The new function that just returns the libusb error code is perfect for my needs.

@Youw
Copy link
Member Author

Youw commented Sep 30, 2024

I assume you've tried the new hid_libusb_error?

@matheusmoreira
Copy link

Yeah. It's still incomplete but the feature report functions set the libusb error states which are what I need. Would you consider a similar error code based API for hid as well? It's much easier to use than strings.

@Youw
Copy link
Member Author

Youw commented Sep 30, 2024

Would you consider a similar error code based API for hid as well?

Not for v0.x, no.

It's much easier to use than strings.

HIDAPI was never designed to diagnose what went wrong, only an indication that something happened and as string for logging purpose only.

still incomplete

Can you elaborate? I've tried to cover all failure cases.

@matheusmoreira
Copy link

matheusmoreira commented Sep 30, 2024

It's just that I saw some TODO lines in the source code and assumed there were still failure cases left to cover. If they have all been handled then it looks good for merging as far as I can tell.

@Youw
Copy link
Member Author

Youw commented Sep 30, 2024

Ah those - right, still there. For the global state (hid_enumerate/hid_open/etc.).

@Youw
Copy link
Member Author

Youw commented Oct 1, 2024

This PR actually has non-obvious side-effect (related to #688).

Because with hid_error implementation, when calling hid_read concurently to other functions (e.g. hid_write) from different threads, in some cases (e.g. device disconnected) the error might be attempted to set in different threads causing a race-condition.
W/o hid_error implementation that de-facto wasn't an issue for libusb implementation.

@Youw Youw merged commit 3c24d0d into libusb-error Oct 2, 2024
21 checks passed
@Youw Youw deleted the implement-hid-error branch October 2, 2024 11:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants