Skip to content

Add hidraw backend for FreeBSD #730

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

aokblast
Copy link

FreeBSD support hidraw in Kernel from 13.0.
By using libusb only, we can only see the HID device from usb. To address this, we implement hidraw backend for FreeBSD.

Just like Linux use libudev to handle usb specified HID stuff (like Manufacture), we use libusb to handle it.

Sponsored-by: FreeBSD Foundation

@aokblast
Copy link
Author

Currently, some stuff like the Report Descriptor parser and error registry routine are copied from Linux and I think they are platform independent. Can we create a common directory or hidraw directory in code then put them inside?

Have tested by the hidtest program.

@Youw Youw self-requested a review March 27, 2025 10:33
@Youw Youw added enhancement New feature or request bsd FreeBSD, NetBSD, OpenBSD, etc labels Mar 27, 2025
Copy link
Member

@Youw Youw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more comments

@aokblast aokblast force-pushed the use_hid_raw branch 4 times, most recently from 49a7a62 to 6e7a25a Compare March 27, 2025 14:16
@aokblast
Copy link
Author

Thanks for @Youw your review:).

Then, What is your opinion about this?

Currently, some stuff like the Report Descriptor parser and error registry routine are copied from Linux and I think they are platform independent. Can we create a common directory or hidraw directory in code then put them inside?

Have tested by the hidtest program.

@Youw
Copy link
Member

Youw commented Mar 27, 2025

Thanks for @Youw your review:).

Then, What is your opinion about this?

Currently, some stuff like the Report Descriptor parser and error registry routine are copied from Linux and I think they are platform independent. Can we create a common directory or hidraw directory in code then put them inside?
Have tested by the hidtest program.

I thinjk that is a good idea, but I don't think it really is nesessary to do so in scope of this PR.
There are really lots of stuff which I'd like to share among beckends, and I think it is going to be some refactoring after all.

@mcuee
Copy link
Member

mcuee commented Mar 28, 2025

Nice. This will address the following issue.

@aokblast
Copy link
Author

Oops. I forget we have udev-devd stuff. Maybe we should use udev also?

@Youw
Copy link
Member

Youw commented Mar 28, 2025

Oops. I forget we have udev-devd stuff. Maybe we should use udev also?

I lost context here. What for? Seem like you have all the functionality implemented already. Aren't you?

@aokblast
Copy link
Author

Oops. I forget we have udev-devd stuff. Maybe we should use udev also?

I lost context here. What for? Seem like you have all the functionality implemented already. Aren't you?

Yes, all functionality is fully implemented. I am just thinking if we should use libudev make hidapi more portable.

@mcuee
Copy link
Member

mcuee commented Mar 30, 2025

First test under FreeBSD 14.1 Release, under a physical machine (Chuwi mini PC, Intel J4125 CPU, 8GB RAM, 256GB SSD)

There are a few compiler warnings.

mcuee@freebsd14:~/build/hidapi_pr730 $ uname -a
FreeBSD freebsd14 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64

mcuee@freebsd14:~/build/hidapi_pr730 $ cc -v
FreeBSD clang version 18.1.5 (https://github.com/llvm/llvm-project.git llvmorg-18.1.5-0-g617a15a9eac9)
Target: x86_64-unknown-freebsd14.1
Thread model: posix
InstalledDir: /usr/bin

mcuee@freebsd14:~/build/hidapi_pr730 $ make
make  all-recursive
Making all in freebsd
  CC       hid.lo
hid.c:396:24: warning: passing 'uint8_t[255]' (aka 'unsigned char[255]') to parameter of type 'const char *' converts between pointers to integer types where one is of the unique plain 'char' type and the other is not [-Wpointer-sign]
  396 |                 mbstowcs(namebuffer, buffer, sizeof(namebuffer));
      |                                      ^~~~~~
/usr/include/stdlib.h:107:64: note: passing argument to parameter here
  107 | size_t   mbstowcs(wchar_t * __restrict , const char * __restrict, size_t);
      |                                                                 ^
hid.c:603:1: warning: non-void function does not return a value [-Wreturn-type]
  603 | }
      | ^
hid.c:937:7: warning: passing 'const char *' to parameter of type 'void *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
  937 |         free(dev->device_path);
      |              ^~~~~~~~~~~~~~~~
/usr/include/stdlib.h:101:18: note: passing argument to parameter here
  101 | void     free(void *);
      |                     ^
3 warnings generated.
  CCLD     libhidapi-hidraw.la
Making all in libusb
  CC       hid.lo
  CCLD     libhidapi-libusb.la
Making all in hidtest
  CC       test.o
  CCLD     hidtest-libusb
  CCLD     hidtest-hidraw

@aokblast
Copy link
Author

Fix it:). Forget to fix the warning.

@mcuee
Copy link
Member

mcuee commented Mar 30, 2025

Somehow hidtest-hidraw will seg fault with the Microchip Simple HID example.

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

Segmentation fault
mcuee@freebsd14:~/build/hidapi_pr730 $ 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: 04f2 0760
  path: 0-3:1.0
  serial_number: (null)
  Manufacturer: Chicony
  Product:      USB Keyboard
  Release:      100
  Interface:    0
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (65 bytes)
0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 
0x29, 0xe7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 
0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x03, 
0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, 0x02, 
0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06, 0x75, 0x08, 
0x15, 0x00, 0x26, 0xff, 0x00, 0x05, 0x07, 0x19, 0x00, 0x2a, 
0xff, 0x00, 0x81, 0x00, 0xc0, 
Device Found
  type: 04f2 0760
  path: 0-3:1.1
  serial_number: (null)
  Manufacturer: Chicony
  Product:      USB Keyboard
  Release:      100
  Interface:    1
  Usage (page): 0x0 (0x0)
  Bus type: 1 (USB)

  Report Descriptor: (127 bytes)
0x06, 0x01, 0x00, 0x09, 0x80, 0xa1, 0x01, 0x85, 0x01, 0x19, 
0x81, 0x29, 0x83, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 
0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 0xc0, 
0x05, 0x0c, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x03, 0x15, 0x00, 
0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x19, 0xb5, 0x29, 0xb8, 
0x09, 0xcd, 0x09, 0xe2, 0x09, 0xe9, 0x09, 0xea, 0x81, 0x02, 
0x0a, 0x83, 0x01, 0x0a, 0x8a, 0x01, 0x0a, 0x92, 0x01, 0x0a, 
0x94, 0x01, 0x0a, 0x21, 0x02, 0x1a, 0x23, 0x02, 0x2a, 0x25, 
0x02, 0x81, 0x02, 0x0a, 0x26, 0x02, 0x0a, 0x27, 0x02, 0x0a, 
0x2a, 0x02, 0x95, 0x03, 0x81, 0x02, 0x95, 0x05, 0x81, 0x01, 
0xc0, 0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x02, 
0x25, 0x01, 0x15, 0x00, 0x75, 0x01, 0x95, 0x08, 0x1a, 0xf1, 
0x00, 0x2a, 0xf8, 0x00, 0x81, 0x02, 0xc0, 
Device Found
  type: 1ea7 0064
  path: 0-4: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, 
Device Found
  type: 04d8 003f
  path: 0-2: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-2: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: hid_error is not implemented yet
Unable to get a feature report: hid_error is not implemented yet
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
read() timeout

@mcuee
Copy link
Member

mcuee commented Mar 30, 2025

Fix it:). Forget to fix the warning.

Thanks. The compiler warnings are gone.

The Segfault issue is still there though.

@aokblast aokblast force-pushed the use_hid_raw branch 2 times, most recently from 63cde91 to 26e3444 Compare April 3, 2025 16:14

num_devs = libusb_get_device_list(global_usb_context, &list);
if (num_devs < 0) {
register_global_error_format("hid_find_device_handle_by_bus_and_port: %s", libusb_strerror(errno));
Copy link
Member

@Youw Youw Apr 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
register_global_error_format("hid_find_device_handle_by_bus_and_port: %s", libusb_strerror(errno));
register_global_error_format("hid_find_device_handle_by_bus_and_port: %s", libusb_strerror(error));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated my comment: should be error not errno

@Youw
Copy link
Member

Youw commented Apr 4, 2025

ignore Archlinux failure and revert your CI changes - not related to this PR - master is failing as well, I'll check

@aokblast
Copy link
Author

aokblast commented Apr 12, 2025

I am stupid. The get report and set report should return the actual length. @mcuee could you please help me test again?

@mcuee
Copy link
Member

mcuee commented Apr 13, 2025

Somehow it still does not work.

mcuee@freebsd14:~/build/hidapi_pr730 $ sudo ./hidtest/hidtest-hidraw 
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: 0925 1234
  path: /dev/hidraw1
  serial_number: (null)
  Manufacturer: CYPRESS
  Product:      CYPRESS EZ-USB FX2 HID USBHIDIO
  Release:      0
  Interface:    0
  Usage (page): 0x1 (0xffa0)
  Bus type: 1 (USB)

  Report Descriptor: (52 bytes)
0x06, 0xa0, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x02, 0xa1, 
0x00, 0x06, 0xa1, 0xff, 0x09, 0x03, 0x09, 0x04, 0x15, 0x80, 
0x25, 0x7f, 0x35, 0x00, 0x45, 0xff, 0x75, 0x08, 0x95, 0x80, 
0x81, 0x02, 0x09, 0x05, 0x09, 0x06, 0x15, 0x80, 0x25, 0x7f, 
0x35, 0x00, 0x45, 0xff, 0x75, 0x08, 0x95, 0x80, 0x91, 0x02, 
0xc0, 0xc0, 
Device Found
  type: 04f2 0760
  path: /dev/hidraw0
  serial_number: (null)
  Manufacturer: Chicony
  Product:      Chicony USB Keyboard
  Release:      100
  Interface:    1
  Usage (page): 0x80 (0x1)
  Bus type: 1 (USB)

  Report Descriptor: (127 bytes)
0x06, 0x01, 0x00, 0x09, 0x80, 0xa1, 0x01, 0x85, 0x01, 0x19, 
0x81, 0x29, 0x83, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 
0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 0xc0, 
0x05, 0x0c, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x03, 0x15, 0x00, 
0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x19, 0xb5, 0x29, 0xb8, 
0x09, 0xcd, 0x09, 0xe2, 0x09, 0xe9, 0x09, 0xea, 0x81, 0x02, 
0x0a, 0x83, 0x01, 0x0a, 0x8a, 0x01, 0x0a, 0x92, 0x01, 0x0a, 
0x94, 0x01, 0x0a, 0x21, 0x02, 0x1a, 0x23, 0x02, 0x2a, 0x25, 
0x02, 0x81, 0x02, 0x0a, 0x26, 0x02, 0x0a, 0x27, 0x02, 0x0a, 
0x2a, 0x02, 0x95, 0x03, 0x81, 0x02, 0x95, 0x05, 0x81, 0x01, 
0xc0, 0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x02, 
0x25, 0x01, 0x15, 0x00, 0x75, 0x01, 0x95, 0x08, 0x1a, 0xf1, 
0x00, 0x2a, 0xf8, 0x00, 0x81, 0x02, 0xc0, 
Device Found
  type: 04f2 0760
  path: /dev/hidraw0
  serial_number: (null)
  Manufacturer: Chicony
  Product:      Chicony USB Keyboard
  Release:      100
  Interface:    1
  Usage (page): 0x1 (0xc)
  Bus type: 1 (USB)

  Report Descriptor: (127 bytes)
0x06, 0x01, 0x00, 0x09, 0x80, 0xa1, 0x01, 0x85, 0x01, 0x19, 
0x81, 0x29, 0x83, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 
0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 0xc0, 
0x05, 0x0c, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x03, 0x15, 0x00, 
0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x19, 0xb5, 0x29, 0xb8, 
0x09, 0xcd, 0x09, 0xe2, 0x09, 0xe9, 0x09, 0xea, 0x81, 0x02, 
0x0a, 0x83, 0x01, 0x0a, 0x8a, 0x01, 0x0a, 0x92, 0x01, 0x0a, 
0x94, 0x01, 0x0a, 0x21, 0x02, 0x1a, 0x23, 0x02, 0x2a, 0x25, 
0x02, 0x81, 0x02, 0x0a, 0x26, 0x02, 0x0a, 0x27, 0x02, 0x0a, 
0x2a, 0x02, 0x95, 0x03, 0x81, 0x02, 0x95, 0x05, 0x81, 0x01, 
0xc0, 0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x02, 
0x25, 0x01, 0x15, 0x00, 0x75, 0x01, 0x95, 0x08, 0x1a, 0xf1, 
0x00, 0x2a, 0xf8, 0x00, 0x81, 0x02, 0xc0, 
Device Found
  type: 04f2 0760
  path: /dev/hidraw0
  serial_number: (null)
  Manufacturer: Chicony
  Product:      Chicony USB Keyboard
  Release:      100
  Interface:    1
  Usage (page): 0x1 (0xff00)
  Bus type: 1 (USB)

  Report Descriptor: (127 bytes)
0x06, 0x01, 0x00, 0x09, 0x80, 0xa1, 0x01, 0x85, 0x01, 0x19, 
0x81, 0x29, 0x83, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 
0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 0xc0, 
0x05, 0x0c, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x03, 0x15, 0x00, 
0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x19, 0xb5, 0x29, 0xb8, 
0x09, 0xcd, 0x09, 0xe2, 0x09, 0xe9, 0x09, 0xea, 0x81, 0x02, 
0x0a, 0x83, 0x01, 0x0a, 0x8a, 0x01, 0x0a, 0x92, 0x01, 0x0a, 
0x94, 0x01, 0x0a, 0x21, 0x02, 0x1a, 0x23, 0x02, 0x2a, 0x25, 
0x02, 0x81, 0x02, 0x0a, 0x26, 0x02, 0x0a, 0x27, 0x02, 0x0a, 
0x2a, 0x02, 0x95, 0x03, 0x81, 0x02, 0x95, 0x05, 0x81, 0x01, 
0xc0, 0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x02, 
0x25, 0x01, 0x15, 0x00, 0x75, 0x01, 0x95, 0x08, 0x1a, 0xf1, 
0x00, 0x2a, 0xf8, 0x00, 0x81, 0x02, 0xc0, 
unable to open device


mcuee@freebsd14:~/build/hidapitester $ sudo ./hidapitester_freebsd_libusb_pr730 --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128  --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
 80
Reading up to 129-byte input report, 250 msec timeout...read 64 bytes:
 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 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 00 00
 00
Closing device

mcuee@freebsd14:~/build/hidapitester $ sudo ./hidapitester_freebsd_hidraw_pr730 --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128  --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
 80
Reading up to 129-byte input report, 250 msec timeout...read 0 bytes:
Closing device

return -1;
}

bytes_written = write(dev->device_handle, data, length);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strip leading zero for unnumbered reports. See write section of FreeBSD hidraw(4) man.
Don't forget to account for this byte in return value.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HIDRAW_GET_REPORT and HIDRAW_SET_REPORT callers should strip leading zero for unnumbered reports too

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wulf7 are you sure?
I believe this entire implementation should be about hidraw, not uhid, and according to https://man.freebsd.org/cgi/man.cgi?hidraw(4)

In the hidraw mode, the first byte should be set to 0 and the report data itself should begin at the second byte.

I.e. - no strip.

if (hid_get_name_from_mib(mib, items, name_buffer, sizeof(name_buffer)) == 0)
return -1;

return sscanf(name_buffer, "dev.hidraw.%d", &result) == 1 ? result : -1;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you may add "dev.uhid.%d" nodes here too as they are compatible with hidraw(4) in uhid mode on binary level.

FreeBSD support hidraw in Kernel from 13.0.
By using libusb only, we can only see the HID device from usb.
To address this, we implement hidraw backend for FreeBSD.

Just like Linux use libudev to handle usb specified HID stuff (like
Manufacture), we use libusb to handle it.

Sponsored-by: FreeBSD Foundation
Sponsored-by: Framework Laptop. Inc
@aokblast
Copy link
Author

Sorry about the confusing code. I would like to clarify first that I think using hidraw mode is better for supporting non-usb hid device (e.g. iichid). I clean up the code so that there is hidraw mode only.

@wulf7
Copy link

wulf7 commented Apr 14, 2025

uhid mode supports non-USB HID devices too. Both modes are comparable.

@Youw
Copy link
Member

Youw commented Apr 14, 2025

If they are compatible, then what point of using both?

HIDAPI is intended to be as thin wrapper as possible for HID device drivers (libusb backend is a different story, of course), with uniform API across platforms.
The way I see it - hidraw mode has simpler and more alike API for HIDAPI to be used as is, when uhid requires additional tracking of current operational mode and handling report IDs in some cases.

Do I miss something about uhid worth mentioning in this scope?

@wulf7
Copy link

wulf7 commented Apr 14, 2025

They are comparable but not compatible.

uhid API may be used with old uhid(4) driver.
hidraw API is simpler for implementation and may reuse existing Linux support code.

FreeBSD hidraw(4) supports both. Choose one you prefer but do not mix them.

@wulf7
Copy link

wulf7 commented Apr 14, 2025

Sorry about the confusing code. I would like to clarify first that I think using hidraw mode is better for supporting non-usb hid device (e.g. iichid). I clean up the code so that there is hidraw mode only.

Now after switching to hidraw mode, it is better to replace all remaining HIDRAW_* ioctls with HIDIOC* ones.
The only exception may be HIDRAW_GET_DEVICEINFO as it provides device serial number which is unavailable through hidraw API

@wulf7
Copy link

wulf7 commented Apr 14, 2025

Ooops. FreeBSD hidraw API is outdated. It misses HIDIOCSOUTPUT and HIDIOCGINPUT ioctls.
Although it is easy to implement them, they won`t hit the tree until FreeBSD 14.3 or even 14.4.
So, the uhid API is the only option for 14.2 and earlier.

@mcuee
Copy link
Member

mcuee commented Apr 14, 2025

Ooops. FreeBSD hidraw API is outdated. It misses HIDIOCSOUTPUT and HIDIOCGINPUT ioctls. Although it is easy to implement them, they won`t hit the tree until FreeBSD 14.3 or even 14.4. So, the uhid API is the only option for 14.2 and earlier.

Hmm, what about FreeBSD 15.0-Current? Does it have the two IOCTLs you mentioned?

@aokblast is indeed using FreeBSD 15.0-Current for testing.

@wulf7
Copy link

wulf7 commented Apr 15, 2025

Hmm, what about FreeBSD 15.0-Current? Does it have the two IOCTLs you mentioned?

Not yet. I made a patch with both ioctls(). It is only compile tested. I'll commit after one has tested it.

hidraw.patch.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bsd FreeBSD, NetBSD, OpenBSD, etc enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants