libusb backend for Windows and macOS #319

Open
opened 2021-08-07 21:25:00 -05:00 by mcuee · 27 comments
mcuee commented 2021-08-07 21:25:00 -05:00 (Migrated from github.com)

As discussed in #61 , it may make sense to create a new libusb backend to remove some limitations of the native HID APIs under Windows. The users will need to use WinUSB driver to replace the native HID driver in order to make use of this (if using libusb HID backend, then the limitation still applies).

I am not so sure if there is any benefit to extend this to macOS, but it can be done as well with the latest kernel driver detaching function of libusb under macOS.

As discussed in #61 , it may make sense to create a new libusb backend to remove some limitations of the native HID APIs under Windows. The users will need to use WinUSB driver to replace the native HID driver in order to make use of this (if using libusb HID backend, then the limitation still applies). I am not so sure if there is any benefit to extend this to macOS, but it can be done as well with the latest kernel driver detaching function of libusb under macOS.
mcuee commented 2021-08-07 21:26:53 -05:00 (Migrated from github.com)

Reference discussion for macOS: https://github.com/libusb/libusb/pull/911

Reference discussion for macOS: https://github.com/libusb/libusb/pull/911
mcuee commented 2021-08-07 21:27:56 -05:00 (Migrated from github.com)

Quick hack for mac/hid.c
Codes from:
https://blog.albertarmea.com/post/47089939939/using-pthreadbarrier-on-mac-os-x

diff --git a/libusb/hid.c b/libusb/hid.c
index 0b8aa1e..cb4a1e2 100644
--- a/libusb/hid.c
+++ b/libusb/hid.c
@@ -112,6 +112,75 @@ static int pthread_barrier_wait(pthread_barrier_t *barrier)
 
 #endif
 
+#ifdef __APPLE__
+
+#ifndef PTHREAD_BARRIER_H_
+#define PTHREAD_BARRIER_H_
+
+#include <pthread.h>
+#include <errno.h>
+
+typedef int pthread_barrierattr_t;
+typedef struct
+{
+    pthread_mutex_t mutex;
+    pthread_cond_t cond;
+    int count;
+    int tripCount;
+} pthread_barrier_t;
+
+
+int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
+{
+    if(count == 0)
+    {
+        errno = EINVAL;
+        return -1;
+    }
+    if(pthread_mutex_init(&barrier->mutex, 0) < 0)
+    {
+        return -1;
+    }
+    if(pthread_cond_init(&barrier->cond, 0) < 0)
+    {
+        pthread_mutex_destroy(&barrier->mutex);
+        return -1;
+    }
+    barrier->tripCount = count;
+    barrier->count = 0;
+
+    return 0;
+}
+
+int pthread_barrier_destroy(pthread_barrier_t *barrier)
+{
+    pthread_cond_destroy(&barrier->cond);
+    pthread_mutex_destroy(&barrier->mutex);
+    return 0;
+}
+
+int pthread_barrier_wait(pthread_barrier_t *barrier)
+{
+    pthread_mutex_lock(&barrier->mutex);
+    ++(barrier->count);
+    if(barrier->count >= barrier->tripCount)
+    {
+        barrier->count = 0;
+        pthread_cond_broadcast(&barrier->cond);
+        pthread_mutex_unlock(&barrier->mutex);
+        return 1;
+    }
+    else
+    {
+        pthread_cond_wait(&barrier->cond, &(barrier->mutex));
+        pthread_mutex_unlock(&barrier->mutex);
+        return 0;
+    }
+}
+
+#endif // PTHREAD_BARRIER_H_
+#endif // __APPLE__
+
 #ifdef __cplusplus
 extern "C" {
 #endif
Quick hack for mac/hid.c Codes from: https://blog.albertarmea.com/post/47089939939/using-pthreadbarrier-on-mac-os-x ``` diff --git a/libusb/hid.c b/libusb/hid.c index 0b8aa1e..cb4a1e2 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -112,6 +112,75 @@ static int pthread_barrier_wait(pthread_barrier_t *barrier) #endif +#ifdef __APPLE__ + +#ifndef PTHREAD_BARRIER_H_ +#define PTHREAD_BARRIER_H_ + +#include <pthread.h> +#include <errno.h> + +typedef int pthread_barrierattr_t; +typedef struct +{ + pthread_mutex_t mutex; + pthread_cond_t cond; + int count; + int tripCount; +} pthread_barrier_t; + + +int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) +{ + if(count == 0) + { + errno = EINVAL; + return -1; + } + if(pthread_mutex_init(&barrier->mutex, 0) < 0) + { + return -1; + } + if(pthread_cond_init(&barrier->cond, 0) < 0) + { + pthread_mutex_destroy(&barrier->mutex); + return -1; + } + barrier->tripCount = count; + barrier->count = 0; + + return 0; +} + +int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_lock(&barrier->mutex); + ++(barrier->count); + if(barrier->count >= barrier->tripCount) + { + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return 1; + } + else + { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +#endif // PTHREAD_BARRIER_H_ +#endif // __APPLE__ + #ifdef __cplusplus extern "C" { #endif ```
mcuee commented 2021-08-07 21:28:44 -05:00 (Migrated from github.com)

Quick hack for Makefile.macOS

###########################################
# Simple Makefile for HIDAPI test program
#
# Alan Ott
# Signal 11 Software
# 2010-06-01
###########################################

all: hidtest-libusb libs

libs: libhidapi-libusb.dylib

CC       ?= gcc
CFLAGS   ?= -Wall -g -fpic

LDFLAGS  ?= -Wall -g

COBJS_LIBUSB = hid.o
COBJS = $(COBJS_LIBUSB) ../hidtest/test.o
OBJS      = $(COBJS)
LIBS_USB  = `pkg-config libusb-1.0 --libs` -liconv -lpthread
LIBS      = $(LIBS_USB)
INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`


# Console Test Program
hidtest-libusb: $(COBJS)
	$(CC) $(LDFLAGS) $^ $(LIBS_USB) -o $@

# Shared Libs
libhidapi-libusb.dylib: $(COBJS_LIBUSB)
	$(CC) $(LDFLAGS) $(LIBS_USB) -shared -fpic -Wl,-install_name,$@.0 $^ -o $@

# Objects
$(COBJS): %.o: %.c
	$(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@


clean:
	rm -f $(OBJS) hidtest-libusb libhidapi-libusb.so ../hidtest/hidtest.o

.PHONY: clean libs
Quick hack for Makefile.macOS ``` ########################################### # Simple Makefile for HIDAPI test program # # Alan Ott # Signal 11 Software # 2010-06-01 ########################################### all: hidtest-libusb libs libs: libhidapi-libusb.dylib CC ?= gcc CFLAGS ?= -Wall -g -fpic LDFLAGS ?= -Wall -g COBJS_LIBUSB = hid.o COBJS = $(COBJS_LIBUSB) ../hidtest/test.o OBJS = $(COBJS) LIBS_USB = `pkg-config libusb-1.0 --libs` -liconv -lpthread LIBS = $(LIBS_USB) INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags` # Console Test Program hidtest-libusb: $(COBJS) $(CC) $(LDFLAGS) $^ $(LIBS_USB) -o $@ # Shared Libs libhidapi-libusb.dylib: $(COBJS_LIBUSB) $(CC) $(LDFLAGS) $(LIBS_USB) -shared -fpic -Wl,-install_name,$@.0 $^ -o $@ # Objects $(COBJS): %.o: %.c $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@ clean: rm -f $(OBJS) hidtest-libusb libhidapi-libusb.so ../hidtest/hidtest.o .PHONY: clean libs ```
mcuee commented 2021-08-08 00:31:54 -05:00 (Migrated from github.com)

Runlog for macOS with hidtest using the quick mod libusb backend.

hidapi_test/libusb on  master [!?] ❯ sudo ./hidtest-libusb 
hidapi test/example tool. Compiled with hidapi version 0.10.1, runtime version 0.10.1.
Compile-time version matches runtime version of hidapi.

Device Found
  type: 04d8 003f
  path: 0002:001e:00
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c52b
  path: 0002:000a:00
  serial_number: (null)
  Manufacturer: Logitech
  Product:      USB Receiver
  Release:      2410
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c52b
  path: 0002:000a:01
  serial_number: (null)
  Manufacturer: Logitech
  Product:      USB Receiver
  Release:      2410
  Interface:    1
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c52b
  path: 0002:000a:02
  serial_number: (null)
  Manufacturer: Logitech
  Product:      USB Receiver
  Release:      2410
  Interface:    2
  Usage (page): 0x0 (0x0)

Device Found
  type: 047f c025
  path: 0002:0008:03
  serial_number: CB13A3E40E8E47D6A40769C27E90A38E
  Manufacturer: Plantronics
  Product:      Plantronics C320-M
  Release:      135
  Interface:    3
  Usage (page): 0x0 (0x0)

Manufacturer String: Microchip Technology Inc.
Product String: Simple HID Device Demo
Serial Number String: (208) ?
Indexed String 1: Microchip Technology Inc.
Unable to send a feature report.
Unable to get a feature report.
hid_error is not implemented yetwaiting...
waiting...
waiting...
Unable to read()
Data read:
Runlog for macOS with hidtest using the quick mod libusb backend. ``` hidapi_test/libusb on  master [!?] ❯ sudo ./hidtest-libusb hidapi test/example tool. Compiled with hidapi version 0.10.1, runtime version 0.10.1. Compile-time version matches runtime version of hidapi. Device Found type: 04d8 003f path: 0002:001e:00 serial_number: (null) Manufacturer: Microchip Technology Inc. Product: Simple HID Device Demo Release: 2 Interface: 0 Usage (page): 0x0 (0x0) Device Found type: 046d c52b path: 0002:000a:00 serial_number: (null) Manufacturer: Logitech Product: USB Receiver Release: 2410 Interface: 0 Usage (page): 0x0 (0x0) Device Found type: 046d c52b path: 0002:000a:01 serial_number: (null) Manufacturer: Logitech Product: USB Receiver Release: 2410 Interface: 1 Usage (page): 0x0 (0x0) Device Found type: 046d c52b path: 0002:000a:02 serial_number: (null) Manufacturer: Logitech Product: USB Receiver Release: 2410 Interface: 2 Usage (page): 0x0 (0x0) Device Found type: 047f c025 path: 0002:0008:03 serial_number: CB13A3E40E8E47D6A40769C27E90A38E Manufacturer: Plantronics Product: Plantronics C320-M Release: 135 Interface: 3 Usage (page): 0x0 (0x0) Manufacturer String: Microchip Technology Inc. Product String: Simple HID Device Demo Serial Number String: (208) ? Indexed String 1: Microchip Technology Inc. Unable to send a feature report. Unable to get a feature report. hid_error is not implemented yetwaiting... waiting... waiting... Unable to read() Data read: ```
mcuee commented 2021-08-08 19:18:12 -05:00 (Migrated from github.com)

Under Windows, here is the output, with a quick mod of the following file.
https://gitlab.com/CalcProgrammer1/OpenRGB/-/blob/master/dependencies/hidapi/hidapi.c

I choose to use usbdk backend so that I do not need to replace the HID driver with WinUSB. And it may be able to find more devices like USB keyboard and mouse if they are present.

modified files and Windows 64bit binaries are included in the following zip file.
hidapi_libusb.zip

C:\work\hid\hidapi\libusb [master ≡ +7 ~1 -0 !]> .\hidtest-libusb.exe
hidapi test/example tool. Compiled with hidapi version 0.11.0, runtime version 0.10.1.
Compile-time version is different than runtime version of hidapi.
]nDevice Found
  type: 046d c534
  path: 0001:0008:00
  serial_number: (null)
  Manufacturer: Logitech
  Product:      USB Receiver
  Release:      2901
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c534
  path: 0001:0008:01
  serial_number: (null)
  Manufacturer: Logitech
  Product:      USB Receiver
  Release:      2901
  Interface:    1
  Usage (page): 0x0 (0x0)

Device Found
  type: 047f c056
  path: 0001:001d:03
  serial_number: D1CEC32927974D5F9BD6B2AEBF2EA8E3
  Manufacturer: Plantronics
  Product:      Plantronics Blackwire 3220 Series
  Release:      210
  Interface:    3
  Usage (page): 0x0 (0x0)

Device Found
  type: 04d8 003f
  path: 0001:001c:00
  serial_number: (null)
  Manufacturer: Microchip Technology Inc.
  Product:      Simple HID Device Demo
  Release:      2
  Interface:    0
  Usage (page): 0x0 (0x0)

Manufacturer String: Microchip Technology Inc.
Product String: Simple HID Device Demo
Serial Number String: (1033)
Indexed String 1: Microchip Technology Inc.
Unable to send a feature report.
Unable to get a feature report.
(null)Unable to write()
Error: (null)
Unable to write() (2)
waiting...
waiting...
waiting...
waiting...


C:\work\hid\hidapi\libusb [master ≡ +7 ~1 -0 !]> .\hidtest-libusb.exe
hidapi test/example tool. Compiled with hidapi version 0.11.0, runtime version 0.10.1.
Compile-time version is different than runtime version of hidapi.
]nDevice Found
  type: 413c b06e
  path: 0003:0007:00
  serial_number: (null)
  Manufacturer: (null)
  Product:
  Release:      101
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c534
  path: 0001:0002:00
  serial_number: (null)
  Manufacturer: Logitech
  Product:      USB Receiver
  Release:      2901
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c534
  path: 0001:0002:01
  serial_number: (null)
  Manufacturer: Logitech
  Product:      USB Receiver
  Release:      2901
  Interface:    1
  Usage (page): 0x0 (0x0)

Device Found
  type: 047f c056
  path: 0003:001c:03
  serial_number: D1CEC32927974D5F9BD6B2AEBF2EA8E3
  Manufacturer: Plantronics
  Product:      Plantronics Blackwire 3220 Series
  Release:      210
  Interface:    3
  Usage (page): 0x0 (0x0)

Device Found
  type: 413c 2107
  path: 0003:000d:00
  serial_number: (null)
  Manufacturer: DELL
  Product:      Dell USB Entry Keyboard
  Release:      178
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 413c b06f
  path: 0003:000a:00
  serial_number: (null)
  Manufacturer: (null)
  Product:
  Release:      101
  Interface:    0
  Usage (page): 0x0 (0x0)

Device Found
  type: 046d c077
  path: 0003:000e:00
  serial_number: (null)
  Manufacturer: Logitech
  Product:      USB Optical Mouse
  Release:      7200
  Interface:    0
  Usage (page): 0x0 (0x0)

unable to open device
Under Windows, here is the output, with a quick mod of the following file. https://gitlab.com/CalcProgrammer1/OpenRGB/-/blob/master/dependencies/hidapi/hidapi.c I choose to use usbdk backend so that I do not need to replace the HID driver with WinUSB. And it may be able to find more devices like USB keyboard and mouse if they are present. modified files and Windows 64bit binaries are included in the following zip file. [hidapi_libusb.zip](https://github.com/libusb/hidapi/files/6966596/hidapi_libusb.zip) ``` C:\work\hid\hidapi\libusb [master ≡ +7 ~1 -0 !]> .\hidtest-libusb.exe hidapi test/example tool. Compiled with hidapi version 0.11.0, runtime version 0.10.1. Compile-time version is different than runtime version of hidapi. ]nDevice Found type: 046d c534 path: 0001:0008:00 serial_number: (null) Manufacturer: Logitech Product: USB Receiver Release: 2901 Interface: 0 Usage (page): 0x0 (0x0) Device Found type: 046d c534 path: 0001:0008:01 serial_number: (null) Manufacturer: Logitech Product: USB Receiver Release: 2901 Interface: 1 Usage (page): 0x0 (0x0) Device Found type: 047f c056 path: 0001:001d:03 serial_number: D1CEC32927974D5F9BD6B2AEBF2EA8E3 Manufacturer: Plantronics Product: Plantronics Blackwire 3220 Series Release: 210 Interface: 3 Usage (page): 0x0 (0x0) Device Found type: 04d8 003f path: 0001:001c:00 serial_number: (null) Manufacturer: Microchip Technology Inc. Product: Simple HID Device Demo Release: 2 Interface: 0 Usage (page): 0x0 (0x0) Manufacturer String: Microchip Technology Inc. Product String: Simple HID Device Demo Serial Number String: (1033) Indexed String 1: Microchip Technology Inc. Unable to send a feature report. Unable to get a feature report. (null)Unable to write() Error: (null) Unable to write() (2) waiting... waiting... waiting... waiting... ``` ``` C:\work\hid\hidapi\libusb [master ≡ +7 ~1 -0 !]> .\hidtest-libusb.exe hidapi test/example tool. Compiled with hidapi version 0.11.0, runtime version 0.10.1. Compile-time version is different than runtime version of hidapi. ]nDevice Found type: 413c b06e path: 0003:0007:00 serial_number: (null) Manufacturer: (null) Product: Release: 101 Interface: 0 Usage (page): 0x0 (0x0) Device Found type: 046d c534 path: 0001:0002:00 serial_number: (null) Manufacturer: Logitech Product: USB Receiver Release: 2901 Interface: 0 Usage (page): 0x0 (0x0) Device Found type: 046d c534 path: 0001:0002:01 serial_number: (null) Manufacturer: Logitech Product: USB Receiver Release: 2901 Interface: 1 Usage (page): 0x0 (0x0) Device Found type: 047f c056 path: 0003:001c:03 serial_number: D1CEC32927974D5F9BD6B2AEBF2EA8E3 Manufacturer: Plantronics Product: Plantronics Blackwire 3220 Series Release: 210 Interface: 3 Usage (page): 0x0 (0x0) Device Found type: 413c 2107 path: 0003:000d:00 serial_number: (null) Manufacturer: DELL Product: Dell USB Entry Keyboard Release: 178 Interface: 0 Usage (page): 0x0 (0x0) Device Found type: 413c b06f path: 0003:000a:00 serial_number: (null) Manufacturer: (null) Product: Release: 101 Interface: 0 Usage (page): 0x0 (0x0) Device Found type: 046d c077 path: 0003:000e:00 serial_number: (null) Manufacturer: Logitech Product: USB Optical Mouse Release: 7200 Interface: 0 Usage (page): 0x0 (0x0) unable to open device ```
mcuee commented 2021-08-11 02:42:54 -05:00 (Migrated from github.com)

Of course, it is also possible not to use usbdk, just comment out the following line in hid.c.

		//libusb_set_option(NULL, LIBUSB_OPTION_USE_USBDK);

hidapi_libusb2.zip

Of course, it is also possible not to use usbdk, just comment out the following line in hid.c. ``` //libusb_set_option(NULL, LIBUSB_OPTION_USE_USBDK); ``` [hidapi_libusb2.zip](https://github.com/libusb/hidapi/files/6966661/hidapi_libusb2.zip)
Youw commented 2021-08-12 03:37:02 -05:00 (Migrated from github.com)

Instead of using "hacks" to make it functional I'd rather suggest to refactor libusb backend of HIDAPI and switch to C11 instead of using POSIX/pthread API.
That way we will have a clean implementation compliant with the C Standard.

Thoughts?

Instead of using "hacks" to make it functional I'd rather suggest to refactor libusb backend of HIDAPI and switch to C11 instead of using POSIX/pthread API. That way we will have a _clean_ implementation compliant with the C Standard. Thoughts?
mcuee commented 2021-08-12 04:08:14 -05:00 (Migrated from github.com)

Yes, that will be great.

Haha, my hack is just a quick demo to show that it is possible.

Yes, that will be great. Haha, my hack is just a quick demo to show that it is possible.
mcuee commented 2021-08-26 21:52:11 -05:00 (Migrated from github.com)

In order for your USB HID device to be found by the libusb backend (hidapi_libusb2.zip), there are two possibilities.

Take note this is only applicable to device listed under Windows Device Manager as "Human Interface Devices" --> "USB Input Device". Keyboard/mouse and Bluetooth/I2C/SPI HID devices are not supported.

  1. keep using the default kernel HID driver, then it has same (actually more) limitation as HIDAPI with the normal Windows HID API backend. But it is not recommended to use libusb HID backend because of all the limitations. So we recommend you to use HIDAPI instead.

https://github.com/libusb/libusb/wiki/Windows#known-restrictions
HID keyboards and mice cannot be accessed using the native HID driver as Windows reserves exclusive access to them.
Multiple HID top level collections are currently not supported (only the first top level collection will be used).

  1. change the USB HID driver to WinUSB. In that case, certain limitations will be lifted. For example, now you can use control transfer to get the HID report descriptors.
In order for your USB HID device to be found by the libusb backend (hidapi_libusb2.zip), there are two possibilities. Take note this is only applicable to device listed under Windows Device Manager as "Human Interface Devices" --> "USB Input Device". Keyboard/mouse and Bluetooth/I2C/SPI HID devices are not supported. 1) keep using the default kernel HID driver, then it has same (actually more) limitation as HIDAPI with the normal Windows HID API backend. But it is not recommended to use libusb HID backend because of all the limitations. So we recommend you to use HIDAPI instead. https://github.com/libusb/libusb/wiki/Windows#known-restrictions HID keyboards and mice cannot be accessed using the native HID driver as Windows reserves exclusive access to them. Multiple HID top level collections are currently not supported (only the first top level collection will be used). 2) change the USB HID driver to WinUSB. In that case, certain limitations will be lifted. For example, now you can use control transfer to get the HID report descriptors.
mcuee commented 2021-08-26 21:58:19 -05:00 (Migrated from github.com)

hidapi_libusb.zip uses the USBDK backend of the libusb, so it may be able to find more devices than hidapi_libusb2.zip. For example, it may be able to find some USB mice/keyboards. But it requires the installation of usbdk. libusb usbdk backend may be less stable than using WinUSB backend.
https://github.com/daynix/UsbDk/releases

hidapi_libusb.zip uses the USBDK backend of the libusb, so it may be able to find more devices than hidapi_libusb2.zip. For example, it may be able to find some USB mice/keyboards. But it requires the installation of usbdk. libusb usbdk backend may be less stable than using WinUSB backend. https://github.com/daynix/UsbDk/releases
mcuee commented 2021-08-30 20:46:05 -05:00 (Migrated from github.com)

64bit Windows binary with hidapitester here (not using usbdk). libusb-1.0.dll is a mod version of 1.0.24.11650 with pull request libusb/libusb#986 to fix the Windows HID backend issue.
https://github.com/mcuee/hidapitester/releases/tag/v8610dc6

64bit Windows binary with hidapitester here (not using usbdk). libusb-1.0.dll is a mod version of 1.0.24.11650 with pull request libusb/libusb#986 to fix the Windows HID backend issue. https://github.com/mcuee/hidapitester/releases/tag/v8610dc6
mcuee commented 2023-02-24 21:26:39 -06:00 (Migrated from github.com)

nstead of using "hacks" to make it functional I'd rather suggest to refactor libusb backend of HIDAPI and switch to C11 instead of using POSIX/pthread API. That way we will have a clean implementation compliant with the C Standard.

@Youw

Since I do not know much about pthread and C++11 threading, and since ChatGPT is now popular, I asked ChatGPT to do the job.

Unfortuantely ChatGPT is not able to finish the full conversion and always got stuck.

(Edit: delete the code as it is not good).

> nstead of using "hacks" to make it functional I'd rather suggest to refactor libusb backend of HIDAPI and switch to C11 instead of using POSIX/pthread API. That way we will have a clean implementation compliant with the C Standard. @Youw Since I do not know much about pthread and C++11 threading, and since ChatGPT is now popular, I asked ChatGPT to do the job. Unfortuantely ChatGPT is not able to finish the full conversion and always got stuck. (Edit: delete the code as it is not good).
Youw commented 2023-02-25 02:16:26 -06:00 (Migrated from github.com)

Loool :)
Writing it in C++11 would be even easier, for sure)

Loool :) Writing it in C++11 would be even easier, for sure)
mcuee commented 2023-02-25 04:13:31 -06:00 (Migrated from github.com)

Loool :) Writing it in C++11 would be even easier, for sure)

Glad to hear that.

Interestingly I ask ChatGPT to convert the simple libusb stress_mt.c pthread based test codes to C++11 threading and it has no problems. But the result codes do not work under WIndows but work under Linux. Maybe libusb Windows has some issues under stress.

https://github.com/libusb/libusb/blob/master/tests/stress_mt.c

However, if I ask it to convert into C11, the result codes do not even compile since MinGW does not support C11 <threads>.

> Loool :) Writing it in C++11 would be even easier, for sure) Glad to hear that. Interestingly I ask ChatGPT to convert the simple libusb `stress_mt.c` pthread based test codes to C++11 threading and it has no problems. But the result codes do not work under WIndows but work under Linux. Maybe libusb Windows has some issues under stress. https://github.com/libusb/libusb/blob/master/tests/stress_mt.c * https://github.com/libusb/libusb/issues/1128#issuecomment-1445044575 However, if I ask it to convert into C11, the result codes do not even compile since MinGW does not support C11 `<threads>`. * https://github.com/libusb/libusb/issues/1128#issuecomment-1445046039
Youw commented 2023-02-25 05:57:33 -06:00 (Migrated from github.com)

MinGW does not support C11

That's a bummer :(
I never actually used C11 threads. I only assumed, that compilers that have C++11 threads would have C implementation as well...

Writing an entire backend in C++ has many proc and cons. One of the most important ones - dependency on C++ Standard library.
And I'm pretty sure there will be some part of the (C) community that will not support such huge change as switching from C to C++.

But maybe, having an experimental (additional, not replacement) C++ port of libusb backend of HIDAPI - should be a "fun project" at least.
And I'm not talking about "just replacing pthreads with C++11 threads". I'm talking of taking a full advantage of Modern C++ (yes - that is a "thing").

> MinGW does not support C11 That's a bummer :( I never actually used C11 threads. I only assumed, that compilers that have C++11 threads would have C implementation as well... Writing an entire backend in C++ has many proc and cons. One of the most important ones - dependency on C++ Standard library. And I'm pretty sure there will be some part of the (C) community that will not support such huge change as switching from C to C++. But _maybe_, having an experimental (additional, not replacement) C++ port of libusb backend of HIDAPI - should be a "fun project" at least. And I'm not talking about "just replacing pthreads with C++11 threads". I'm talking of taking a full advantage of _Modern C++_ (yes - that is a "thing").
mcuee commented 2023-02-26 18:12:22 -06:00 (Migrated from github.com)

FYI: Apple clang does not support C11 threading either.

Ref:
https://stackoverflow.com/questions/16244153/clang-c11-threads-h-not-found

FYI: Apple clang does not support C11 threading either. Ref: https://stackoverflow.com/questions/16244153/clang-c11-threads-h-not-found
mcuee commented 2023-05-11 03:02:01 -05:00 (Migrated from github.com)

I think in the end, this is not an important work (not much real use in reality) and therefore I will close it for now.

I think in the end, this is not an important work (not much real use in reality) and therefore I will close it for now.
mcuee commented 2023-05-13 21:07:29 -05:00 (Migrated from github.com)

Re-open as a low priority item.

Re-open as a low priority item.
mcuee commented 2024-10-25 09:19:29 -05:00 (Migrated from github.com)

From #706, comment by mandar1jn.

I'm working on a program which would benefit from using the libusb backend of hidapi due to needing the ability to send control transfers. I was wondering if the libusb backend is available on windows. Libusb works on windows, but the build instructions never mention how to or if it's even possible and I had no luck getting it to compile myself.

From #706, comment by mandar1jn. > I'm working on a program which would benefit from using the libusb backend of hidapi due to needing the ability to send control transfers. I was wondering if the libusb backend is available on windows. Libusb works on windows, but the build instructions never mention how to or if it's even possible and I had no luck getting it to compile myself.
mandar1jn commented 2024-10-25 09:33:26 -05:00 (Migrated from github.com)

I'll add some context to this: I'm working with skylanders portals which are HID devices, but they recieve commands over control transfers, something you wouldn't normally do for an HID device, but what can you do about it. My current code uses hidapi with a workaround to get the device handle from hidapi and manually runs the required win32 functions, but I'd prefer to use libusb (I can still extract the libusb handle from what I saw) and then use that functionality to send control transfers, and maybe utilize the hotplug functionality

I'll add some context to this: I'm working with skylanders portals which are HID devices, but they recieve commands over control transfers, something you wouldn't normally do for an HID device, but what can you do about it. My current code uses hidapi with a workaround to get the device handle from hidapi and manually runs the required win32 functions, but I'd prefer to use libusb (I can still extract the libusb handle from what I saw) and then use that functionality to send control transfers, and maybe utilize the hotplug functionality
Youw commented 2024-11-21 06:36:41 -06:00 (Migrated from github.com)

Right now there is no official support of libusb backend for Windows or macOS, but there steps has been made towards that direction with the help of the community.
You may try in scope of your project (or even contribute if you feel like it) to define the HIDAPI thread abstraction for libusb and define the HIDAPI_THREAD_MODEL_INCLUDE pointing to that implementation.
See https://github.com/libusb/hidapi/pull/582/files for details.

Right now there is no official support of libusb backend for Windows or macOS, but there steps has been made towards that direction with the help of the community. You may try in scope of your project (or even contribute if you feel like it) to define the HIDAPI thread abstraction for libusb and define the `HIDAPI_THREAD_MODEL_INCLUDE` pointing to that implementation. See https://github.com/libusb/hidapi/pull/582/files for details.
mcuee commented 2025-04-01 00:30:18 -05:00 (Migrated from github.com)

Quick hack for hidapitester to use libusb backend under Windows.

$ make -f Makefile.libusb
gcc -I/mingw64/include/libusb-1.0 -I ../hidapi/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" -c ../hidapi/libusb/hid.c -o ../hidapi/libusb/hid.o
gcc -I/mingw64/include/libusb-1.0 -I ../hidapi/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" -c hidapitester.c -o hidapitester.o
gcc -I/mingw64/include/libusb-1.0 -I ../hidapi/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" ../hidapi/libusb/hid.o hidapitester.o -o hidapitester.exe -lsetupapi -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lusb-1.0 -liconv -pthread

$ diff -u Makefile Makefile.libusb
--- Makefile    2024-03-15 09:35:53.615624700 +0800
+++ Makefile.libusb     2025-04-01 13:27:29.504891700 +0800
@@ -57,8 +57,11 @@
   CC = gcc
 endif

-LIBS += -lsetupapi -Wl,--enable-auto-import -static-libgcc -static-libstdc++
-OBJS = $(HIDAPI_DIR)/windows/hid.o
+CFLAGS += -I/mingw64/include/libusb-1.0
+
+LIBS += -lsetupapi -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lusb-1.0 -liconv
+OBJS = $(HIDAPI_DIR)/libusb/hid.o
 EXE=.exe

 endif

$ cp hidapitester.exe hidapitester_libusb_git.exe

C:\work\libusb\hidapi [master ≡ +10 ~2 -0 !]> git diff
diff --git a/libusb/hid.c b/libusb/hid.c
index d2ceef5..728ee17 100644
--- a/libusb/hid.c
+++ b/libusb/hid.c
@@ -34,8 +34,8 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/utsname.h>
+//#include <sys/ioctl.h>
+//#include <sys/utsname.h>
 #include <fcntl.h>
 #include <wchar.h>

C:\work\libusb\hidapitester [main ≡ +5 ~0 -0 !]> .\hidapitester_libusb_git.exe --vidpid 0925:1234 --open --buflen 3 -l 3 --send-output 0,1,2  --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 3-bytes...wrote 4 bytes:
 00 01 02
Reading up to 3-byte input report, 250 msec timeout...read 3 bytes:
 01 02 00
Closing device
Quick hack for hidapitester to use libusb backend under Windows. ``` $ make -f Makefile.libusb gcc -I/mingw64/include/libusb-1.0 -I ../hidapi/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" -c ../hidapi/libusb/hid.c -o ../hidapi/libusb/hid.o gcc -I/mingw64/include/libusb-1.0 -I ../hidapi/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" -c hidapitester.c -o hidapitester.o gcc -I/mingw64/include/libusb-1.0 -I ../hidapi/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" ../hidapi/libusb/hid.o hidapitester.o -o hidapitester.exe -lsetupapi -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lusb-1.0 -liconv -pthread $ diff -u Makefile Makefile.libusb --- Makefile 2024-03-15 09:35:53.615624700 +0800 +++ Makefile.libusb 2025-04-01 13:27:29.504891700 +0800 @@ -57,8 +57,11 @@ CC = gcc endif -LIBS += -lsetupapi -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -OBJS = $(HIDAPI_DIR)/windows/hid.o +CFLAGS += -I/mingw64/include/libusb-1.0 + +LIBS += -lsetupapi -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lusb-1.0 -liconv +OBJS = $(HIDAPI_DIR)/libusb/hid.o EXE=.exe endif $ cp hidapitester.exe hidapitester_libusb_git.exe C:\work\libusb\hidapi [master ≡ +10 ~2 -0 !]> git diff diff --git a/libusb/hid.c b/libusb/hid.c index d2ceef5..728ee17 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -34,8 +34,8 @@ #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/utsname.h> +//#include <sys/ioctl.h> +//#include <sys/utsname.h> #include <fcntl.h> #include <wchar.h> C:\work\libusb\hidapitester [main ≡ +5 ~0 -0 !]> .\hidapitester_libusb_git.exe --vidpid 0925:1234 --open --buflen 3 -l 3 --send-output 0,1,2 --read-input Opening device, vid/pid: 0x0925/0x1234 Writing output report of 3-bytes...wrote 4 bytes: 00 01 02 Reading up to 3-byte input report, 250 msec timeout...read 3 bytes: 01 02 00 Closing device ```
mcuee commented 2025-04-01 04:05:32 -05:00 (Migrated from github.com)

PR #728 almost works under Windows but there is one extra byte written and read.

C:\work\libusb\hidapitester [main ≡ +5 ~0 -0 !]> .\hidapitester_git.exe --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 128 bytes:
 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
 00
Closing device

C:\work\libusb\hidapitester [main ≡ +6 ~0 -0 !]> .\hidapitester_libusb_pr728.exe --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 130 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 129 bytes:
 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
 00
Closing device
PR #728 almost works under Windows but there is one extra byte written and read. ``` C:\work\libusb\hidapitester [main ≡ +5 ~0 -0 !]> .\hidapitester_git.exe --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 128 bytes: 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 00 Closing device C:\work\libusb\hidapitester [main ≡ +6 ~0 -0 !]> .\hidapitester_libusb_pr728.exe --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 130 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 129 bytes: 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 00 Closing device ```
Youw commented 2025-04-01 04:09:26 -05:00 (Migrated from github.com)

So you've replaced a standard HID driver with WinUSB one to perform this test?

So you've replaced a standard HID driver with WinUSB one to perform this test?
mcuee commented 2025-04-01 05:10:47 -05:00 (Migrated from github.com)

So you've replaced a standard HID driver with WinUSB one to perform this test?

No, the above test was using libusb-1.0 Windows HID backend.

$ ldd hidapitester_libusb_pr728.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7fffd2810000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffd18f0000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffcff40000)
        msvcrt.dll => /c/WINDOWS/System32/msvcrt.dll (0x7fffd1e80000)
        libiconv-2.dll => /c/work/libusb/hidapitester/libiconv-2.dll (0x7fff93cc0000)
        libwinpthread-1.dll => /c/work/libusb/hidapitester/libwinpthread-1.dll (0x7fffca600000)
        libusb-1.0.dll => /c/work/libusb/hidapitester/libusb-1.0.dll (0x70980000)
        USER32.dll => /c/WINDOWS/System32/USER32.dll (0x7fffd1cc0000)
        win32u.dll => /c/WINDOWS/System32/win32u.dll (0x7fffcf950000)
        GDI32.dll => /c/WINDOWS/System32/GDI32.dll (0x7fffd27a0000)
        gdi32full.dll => /c/WINDOWS/System32/gdi32full.dll (0x7fffd03c0000)
        msvcp_win.dll => /c/WINDOWS/System32/msvcp_win.dll (0x7fffd0320000)
        ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffcf980000

If I switch to WinUSB driver, it does not work, matching the testing result I had with PR #728 under Linux and FreeBSD.

C:\work\libusb\hidapitester [main ≡ +6 ~0 -0 !]> .\hidapitester_libusb_pr728.exe --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
> So you've replaced a standard HID driver with WinUSB one to perform this test? No, the above test was using libusb-1.0 Windows HID backend. ``` $ ldd hidapitester_libusb_pr728.exe ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7fffd2810000) KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffd18f0000) KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffcff40000) msvcrt.dll => /c/WINDOWS/System32/msvcrt.dll (0x7fffd1e80000) libiconv-2.dll => /c/work/libusb/hidapitester/libiconv-2.dll (0x7fff93cc0000) libwinpthread-1.dll => /c/work/libusb/hidapitester/libwinpthread-1.dll (0x7fffca600000) libusb-1.0.dll => /c/work/libusb/hidapitester/libusb-1.0.dll (0x70980000) USER32.dll => /c/WINDOWS/System32/USER32.dll (0x7fffd1cc0000) win32u.dll => /c/WINDOWS/System32/win32u.dll (0x7fffcf950000) GDI32.dll => /c/WINDOWS/System32/GDI32.dll (0x7fffd27a0000) gdi32full.dll => /c/WINDOWS/System32/gdi32full.dll (0x7fffd03c0000) msvcp_win.dll => /c/WINDOWS/System32/msvcp_win.dll (0x7fffd0320000) ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffcf980000 ``` If I switch to WinUSB driver, it does not work, matching the testing result I had with PR #728 under Linux and FreeBSD. ``` C:\work\libusb\hidapitester [main ≡ +6 ~0 -0 !]> .\hidapitester_libusb_pr728.exe --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 ```
mcuee commented 2025-04-01 08:04:00 -05:00 (Migrated from github.com)

So you've replaced a standard HID driver with WinUSB one to perform this test?

@Youw

But it will work if I test with the default fx2hid FW (two bytes input/output report loopback), if I switch the driver to WinUSB. So I will say the current libusb codes kind of work under Windows even though it will suffer the same issue as #274.

You can see that libusb mod works in this case while unmodifed hidapitester will not work since it only works with Windows HID driver.

Of course my mod is a quick hack -- needs proper changes to the code, auto-tools script and CMake files.

And it may need further work to remove the dependanices to libiconv as well.

I will also need to test under macOS.

PS C:\work\libusb\hidapitester> .\hidapitester_libusb_pr728.exe --vidpid 0925:1234 --open --buflen 3 -l 3 --send-output 0,1,2  --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 3-bytes...wrote 3 bytes:
 00 01 02
Reading up to 3-byte input report, 250 msec timeout...read 2 bytes:
 01 02 00
Closing device

PS C:\work\libusb\hidapitester> .\hidapitester.exe --vidpid 0925:1234 --open --buflen 3 -l 3 --send-output 0,1,2  --read-input

PS C:\work\libusb\hidapitester> .\hidapitester_git.exe --vidpid 0925:1234 --open --buflen 3 -l 3 --send-output 0,1,2  --read-input
Opening device, vid/pid: 0x0925/0x1234
Error on send: no device opened.
Error on read: no device opened.

BTW, I am not so sure where I introduce the dependancy to libwinpthread-1.dll. It would be good to remove the dependancy as well. The default Windows version (using native Windows HID API) does not have those dependancies.

$ make -f Makefile_pr728_libusb
gcc -I/ucrt64/include/libusb-1.0 -I ../hidapi_pr728/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" -c ../hidapi_pr728/libusb/hid.c -o ../hidapi_pr728/libusb/hid.o
gcc -I/ucrt64/include/libusb-1.0 -I ../hidapi_pr728/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" -c hidapitester.c -o hidapitester.o
gcc -I/ucrt64/include/libusb-1.0 -I ../hidapi_pr728/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" ../hidapi_pr728/libusb/hid.o hidapitester.o -o hidapitester.exe -lsetupapi -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lusb-1.0 -liconv

$ cp hidapitester.exe hidapitester_libusb_pr728

$ ldd ./hidapitester_libusb_git.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000)
        ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000)
        libiconv-2.dll => /c/work/libusb/hidapitester/libiconv-2.dll (0x7fff6ea70000)
        libwinpthread-1.dll => /c/work/libusb/hidapitester/libwinpthread-1.dll (0x7fffa5d50000)
        libusb-1.0.dll => /c/work/libusb/hidapitester/libusb-1.0.dll (0x7fff839d0000)

$ ldd ./hidapitester_libusb_pr728.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000)
        ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000)
        libiconv-2.dll => /c/work/libusb/hidapitester/libiconv-2.dll (0x7fff6ea70000)
        libwinpthread-1.dll => /c/work/libusb/hidapitester/libwinpthread-1.dll (0x7fffa5d50000)
        libusb-1.0.dll => /c/work/libusb/hidapitester/libusb-1.0.dll (0x7fff839d0000)

$ ldd hidapitester_git.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000)
        ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000)

$ ldd hidapitester_git.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000)
        ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000)

$ ldd hidapitester_winapi_pr728.exe
        ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000)
        KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000)
        KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000)
        ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000)

My mod of hidapitester Makefiles and the binaries (MSYS2 uscrt64 build).

hidapitester_git.zip

> So you've replaced a standard HID driver with WinUSB one to perform this test? @Youw But it will work if I test with the default fx2hid FW (two bytes input/output report loopback), if I switch the driver to WinUSB. So I will say the current libusb codes kind of work under Windows even though it will suffer the same issue as #274. You can see that libusb mod works in this case while unmodifed hidapitester will not work since it only works with Windows HID driver. Of course my mod is a quick hack -- needs proper changes to the code, auto-tools script and CMake files. And it may need further work to remove the dependanices to libiconv as well. I will also need to test under macOS. ``` PS C:\work\libusb\hidapitester> .\hidapitester_libusb_pr728.exe --vidpid 0925:1234 --open --buflen 3 -l 3 --send-output 0,1,2 --read-input Opening device, vid/pid: 0x0925/0x1234 Writing output report of 3-bytes...wrote 3 bytes: 00 01 02 Reading up to 3-byte input report, 250 msec timeout...read 2 bytes: 01 02 00 Closing device PS C:\work\libusb\hidapitester> .\hidapitester.exe --vidpid 0925:1234 --open --buflen 3 -l 3 --send-output 0,1,2 --read-input PS C:\work\libusb\hidapitester> .\hidapitester_git.exe --vidpid 0925:1234 --open --buflen 3 -l 3 --send-output 0,1,2 --read-input Opening device, vid/pid: 0x0925/0x1234 Error on send: no device opened. Error on read: no device opened. ``` BTW, I am not so sure where I introduce the dependancy to libwinpthread-1.dll. It would be good to remove the dependancy as well. The default Windows version (using native Windows HID API) does not have those dependancies. ``` $ make -f Makefile_pr728_libusb gcc -I/ucrt64/include/libusb-1.0 -I ../hidapi_pr728/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" -c ../hidapi_pr728/libusb/hid.c -o ../hidapi_pr728/libusb/hid.o gcc -I/ucrt64/include/libusb-1.0 -I ../hidapi_pr728/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" -c hidapitester.c -o hidapitester.o gcc -I/ucrt64/include/libusb-1.0 -I ../hidapi_pr728/hidapi -DHIDAPITESTER_VERSION=\"""v0.5""\" ../hidapi_pr728/libusb/hid.o hidapitester.o -o hidapitester.exe -lsetupapi -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lusb-1.0 -liconv $ cp hidapitester.exe hidapitester_libusb_pr728 $ ldd ./hidapitester_libusb_git.exe ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000) KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000) KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000) ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000) libiconv-2.dll => /c/work/libusb/hidapitester/libiconv-2.dll (0x7fff6ea70000) libwinpthread-1.dll => /c/work/libusb/hidapitester/libwinpthread-1.dll (0x7fffa5d50000) libusb-1.0.dll => /c/work/libusb/hidapitester/libusb-1.0.dll (0x7fff839d0000) $ ldd ./hidapitester_libusb_pr728.exe ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000) KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000) KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000) ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000) libiconv-2.dll => /c/work/libusb/hidapitester/libiconv-2.dll (0x7fff6ea70000) libwinpthread-1.dll => /c/work/libusb/hidapitester/libwinpthread-1.dll (0x7fffa5d50000) libusb-1.0.dll => /c/work/libusb/hidapitester/libusb-1.0.dll (0x7fff839d0000) $ ldd hidapitester_git.exe ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000) KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000) KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000) ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000) $ ldd hidapitester_git.exe ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000) KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000) KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000) ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000) $ ldd hidapitester_winapi_pr728.exe ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffff05c0000) KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fffefba0000) KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fffede00000) ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7fffee290000) ``` My mod of hidapitester Makefiles and the binaries (MSYS2 uscrt64 build). [hidapitester_git.zip](https://github.com/user-attachments/files/19551606/hidapitester_git.zip)
mcuee commented 2025-04-02 18:34:03 -05:00 (Migrated from github.com)

But it will work if I test with the default fx2hid FW (two bytes input/output report loopback), if I switch the driver to WinUSB. So I will say the current libusb codes kind of work under Windows even though it will suffer the same issue as https://github.com/libusb/hidapi/issues/274.

Same if I use my mod of Jan Axelson's USB PIC Generic HID example, mentioned here. Both hidapi git and PR #728 work fine, basically with report IDs for input/output reports and feature reports.

Using WinUSB driver and not native Windows HID driver in the following tests.

PS C:\work\hid\hidapitester_bin>  .\hidapitester_libusb_git.exe --vidpid 0925:7001 --open -l 3 --send-output 2,8,9 --read-input 1
Opening device, vid/pid: 0x0925/0x7001
Writing output report of 3-bytes...wrote 3 bytes:
 02 08 09
Reading up to 3-byte input report, 250 msec timeout...read 3 bytes:
 01 08 09
Closing device

PS C:\work\hid\hidapitester_bin>  .\hidapitester_libusb_pr728.exe --vidpid 0925:7001 --open -l 3 --send-output 2,8,9 --read-input 1
Opening device, vid/pid: 0x0925/0x7001
Writing output report of 3-bytes...wrote 3 bytes:
 02 08 09
Reading up to 3-byte input report, 250 msec timeout...read 3 bytes:
 01 08 09
Closing device

PS C:\work\hid\hidapitester_bin>  .\hidapitester_libusb_git.exe --vidpid 0925:7001 --open -l 3 --send-feature 3,6,7 --read-feature 4
Opening device, vid/pid: 0x0925/0x7001
Writing 3-byte feature report...wrote 3 bytes:
 03 06 07
Reading 3-byte feature report, report_id 4...read 3 bytes:
 04 06 07
Closing device

PS C:\work\hid\hidapitester_bin>  .\hidapitester_libusb_pr728.exe --vidpid 0925:7001 --open -l 3 --send-feature 3,6,7 --read-feature 4
Opening device, vid/pid: 0x0925/0x7001
Writing 3-byte feature report...wrote 3 bytes:
 03 06 07
Reading 3-byte feature report, report_id 4...read 3 bytes:
 04 06 07
Closing device

Switch back to Windows HID driver and use hidapi git. This is just to prove the FW is working.

PS C:\work\hid\hidapitester_bin>  .\hidapitester_git.exe --vidpid 0925:7001 --open --buflen 3 -l 3 --send-output 2,1,2 --read-input
Opening device, vid/pid: 0x0925/0x7001
Writing output report of 3-bytes...wrote 3 bytes:
 02 01 02
Reading up to 3-byte input report, 250 msec timeout...read 3 bytes:
 01 01 02
Closing device

PS C:\work\hid\hidapitester_bin>  .\hidapitester_git.exe --vidpid 0925:7001 --open --buflen 3 -l 3 --send-feature 3,7,8 --read-feature 4
Opening device, vid/pid: 0x0925/0x7001
Writing 3-byte feature report...wrote 3 bytes:
 03 07 08
Reading 3-byte feature report, report_id 4...read 3 bytes:
 04 07 08
Closing device
> But it will work if I test with the default fx2hid FW (two bytes input/output report loopback), if I switch the driver to WinUSB. So I will say the current libusb codes kind of work under Windows even though it will suffer the same issue as https://github.com/libusb/hidapi/issues/274. Same if I use my mod of Jan Axelson's USB PIC Generic HID example, mentioned here. Both hidapi git and PR #728 work fine, basically with report IDs for input/output reports and feature reports. * https://github.com/libusb/hidapi/issues/478#issuecomment-1546890931 Using WinUSB driver and not native Windows HID driver in the following tests. ``` PS C:\work\hid\hidapitester_bin> .\hidapitester_libusb_git.exe --vidpid 0925:7001 --open -l 3 --send-output 2,8,9 --read-input 1 Opening device, vid/pid: 0x0925/0x7001 Writing output report of 3-bytes...wrote 3 bytes: 02 08 09 Reading up to 3-byte input report, 250 msec timeout...read 3 bytes: 01 08 09 Closing device PS C:\work\hid\hidapitester_bin> .\hidapitester_libusb_pr728.exe --vidpid 0925:7001 --open -l 3 --send-output 2,8,9 --read-input 1 Opening device, vid/pid: 0x0925/0x7001 Writing output report of 3-bytes...wrote 3 bytes: 02 08 09 Reading up to 3-byte input report, 250 msec timeout...read 3 bytes: 01 08 09 Closing device PS C:\work\hid\hidapitester_bin> .\hidapitester_libusb_git.exe --vidpid 0925:7001 --open -l 3 --send-feature 3,6,7 --read-feature 4 Opening device, vid/pid: 0x0925/0x7001 Writing 3-byte feature report...wrote 3 bytes: 03 06 07 Reading 3-byte feature report, report_id 4...read 3 bytes: 04 06 07 Closing device PS C:\work\hid\hidapitester_bin> .\hidapitester_libusb_pr728.exe --vidpid 0925:7001 --open -l 3 --send-feature 3,6,7 --read-feature 4 Opening device, vid/pid: 0x0925/0x7001 Writing 3-byte feature report...wrote 3 bytes: 03 06 07 Reading 3-byte feature report, report_id 4...read 3 bytes: 04 06 07 Closing device ``` Switch back to Windows HID driver and use hidapi git. This is just to prove the FW is working. ``` PS C:\work\hid\hidapitester_bin> .\hidapitester_git.exe --vidpid 0925:7001 --open --buflen 3 -l 3 --send-output 2,1,2 --read-input Opening device, vid/pid: 0x0925/0x7001 Writing output report of 3-bytes...wrote 3 bytes: 02 01 02 Reading up to 3-byte input report, 250 msec timeout...read 3 bytes: 01 01 02 Closing device PS C:\work\hid\hidapitester_bin> .\hidapitester_git.exe --vidpid 0925:7001 --open --buflen 3 -l 3 --send-feature 3,7,8 --read-feature 4 Opening device, vid/pid: 0x0925/0x7001 Writing 3-byte feature report...wrote 3 bytes: 03 07 08 Reading 3-byte feature report, report_id 4...read 3 bytes: 04 07 08 Closing device ```
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-libusb/hidapi#319
No description provided.