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

New feature: Add driver name #1404

Closed
wants to merge 0 commits into from

Conversation

fabiensanglard
Copy link

@fabiensanglard fabiensanglard commented Dec 26, 2023

Fixes: #1225

@Youw Youw added enhancement New features API API changes labels Dec 26, 2023
libusb/os/linux_usbfs.c Outdated Show resolved Hide resolved
libusb/libusbi.h Outdated Show resolved Hide resolved
@@ -2293,6 +2293,7 @@ const struct windows_backend winusb_backend = {
winusb_cancel_transfer,
winusb_clear_transfer_priv,
winusb_copy_transfer_data,
"WinUSB",
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for the PR!
I think here I am not agreeing with you that this is the driver name. As far as I understand, UsbDK and WinUSB are 2 different Windows backenda. The "driver" as per Windows meaning is something else.
For WinUSB backed it can be WinUSB, but also libusbK or libusb0 (or something new in the future).

When the feature was presented in issue #1225 it clearly stated that for Windows the new API shall return one of those 3 for now, see: #1225 (comment).

Therefore I think that here we should have a function instead of a fixed string, in order to return actually loaded driver. Otherwise the feature makes less sense to me.

Thanks for considering this.

Copy link
Author

Choose a reason for hiding this comment

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

As far as I understand, UsbDK and WinUSB are 2 different Windows backend

Agreed.

For WinUSB backed it can be WinUSB, but also libusbK or libusb0 (or something new in the future).

Agreed but there are actually three types, resulting in eights APIs which can be tapped into:

  • Composite devices: dg_ssudbus, USBCCGP,
  • WinUsbX: libusbK, libusb0, WinUSB
  • HID: HIDUSB, MOUHID, KBDHID

However, these are per device APIs. So we can't return either of these names when driver name is requested for a backend because it could be any/many of them.

for Windows the new API shall return one of those 3 for now, see: #1225 (comment).

I don't think this list is accurate.

  • I think libusbK is a typo. @mcuee probably meant libusbdK.
  • There is no libusb-win32 support. We have pieces of code from libusb-win32 but that is neither a backend nor a supported API.
  • As for WinUSB, as you pointed, out it is a bad name. I took it from the translation unit but I shouldn't have.

My proposal for Windows is to keep libusbdK for the windows_backend defined in windows_usbdk.c. And use Per-Device-API (or Composite-WinUsbX-HID) for the windows_backend defined in windows_winusb.c

Copy link
Contributor

@sonatique sonatique Dec 27, 2023

Choose a reason for hiding this comment

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

Hello @fabiensanglard , thank you for your prompt reply. Yes, you're right, I wrote my comment too quickly: given the function prototype you chose (and correctly advertised in #1225 before doing your development), you cannot really return a driver name, since this only makes sens on a per device basis, and there is no device argument in your API.
However, given this "detail" that I didn't realize earlier, I am now in doubt about what additional information this work brings. It is more like getting the backend name (which is useful per se) and / or some hardcoded static driver name that is 1:1 with backend name.

So, I would suggest to either rename the function to "get_backend_name" or add a "libusb_device_handle *" parameter to the current "get_driver_name" function and implement it for returning the driver name under Windows.
But we need @mcuee opinion here as he's the one who first requested the feature.

Regarding libusbK: it really is libusK (not libusbdK): https://github.com/mcuee/libusbk
Regarding libusb-win32 aka libusb0.sys: it is supported via libusk.dll (not a driver but an user space lib) that interfaces in between libusb-1.0 and libusb0.sys (it provides a "WinUBS-like" API over libusb0.sys .

So well, @mcuee : do we want backend name or driver name (or both) ?

Copy link
Member

@mcuee mcuee Dec 28, 2023

Choose a reason for hiding this comment

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

My original intention: just the driver name and not the backend, as there is no extra info given by the backend.

Windows WinUSBx backend -- return WinUSB (WinUSB.dll --> WinUSB.sys), libusbK (libusbK.dll --> libusbK.sys) or libusb-win32 (libusbK.dll --> libusb0.sys) accordingly.

Windows USB HID backend -- return hidusb. As for USB HID Mouse and Keyboard, I am not so sure. libusb Windows can not do much with USB HID Mouse/Keyboard.

Windows USBDK backend -- return usbdk

Linux -- return usbfs
macOS -- return IOKit
BSDs -- return ugen

USB Composite Device is a tricky part. It was not really my intention to return USBCCGP (or dg_ssudbus as a special case for Samsung devices).

USB HUB is probably another tricky part.

Copy link
Member

Choose a reason for hiding this comment

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

It was more meaningful to get the backend name last time, at least for Windows.

Last time, it was possible to access devices using WinUSB driver through two ways.

  1. No libusbK.dll present
    libusb-1.0.dll --> WinUSB.dll --> WinUSB.sys
  2. With libusbK.dll present
    libusb-1.0.dll --> libusbK.dll --> WinUSB.dll --> WinUSB.sys

Now there is only one way, no matter the presence of libusbK.dll.
libusb-1.0.dll --> WinUSB.dll --> WinUSB.sys

Copy link
Member

@mcuee mcuee Dec 28, 2023

Choose a reason for hiding this comment

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

But after reading the info, maybe it is worth getting the backend name as well in the end to have more flexibilities. In the future, maybe there will be cases that there will be two ways to access a USB device (same device driver) using different backends.

Maybe it is good to provide two functions, one for the backend (os/backend) and the others for the driver name. Or return a structure with different members (os, backend, driver name).

Copy link
Member

Choose a reason for hiding this comment

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

Let's hear from @hjelmn and @tormodvolden as well for their opinions.

Copy link
Author

Choose a reason for hiding this comment

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

Based on both your feedback (@mcuee and @somatique) it seems what is needed is the driver name per device. For that I need to change the proposed API to:

const char* libusb_get_driver_name(struct libusb_device *device);

It would make sense to leverage the names in composite_driver_names, winusbx_driver_names, and hid_driver_names since they are already in the windows_usb_api_backend. If you don't like the values, maybe we can change them?

If you are both ok, I can update the CL.

Copy link
Contributor

@sonatique sonatique Dec 28, 2023

Choose a reason for hiding this comment

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

const char* libusb_get_driver_name(struct libusb_device *device);

In my opinion this is the best way to go.

It would make sense to leverage the names in composite_driver_names, winusbx_driver_names, and hid_driver_names since they are already in the windows_usb_api_backend. If you don't like the values, maybe we can change them?

I think current values are fine.
Thanks!

Copy link
Member

Choose a reason for hiding this comment

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

If you are both ok, I can update the CL.

Okay, please proceed. Thanks.

Hopefully @tormodvolden or @hjelmn would have some time later to review the proposal as well.

@mcuee
Copy link
Member

mcuee commented Dec 28, 2023

Example USB Composite Device:
Interface 0/1/2: USB Audio
Interface 4: USB HID --> only this interface is really useful for libusb.

So it seems to me the more useful is to get the driver used for an individual interface.

C:\work\libusb\libusb-1.0.27-rc1\build\v142\x64\Release> .\xusb 047f:c056
Using libusb v1.0.27.11848

Opening device 047F:C056...
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_1A86&PID_7523\C&1F76A113&0&2'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_24AE&PID_4057\C&1F76A113&0&3'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_5413\B&2EAF716D&0&3'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_0413\B&1637EEB3&0&3'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_413C&PID_B06E\B&2EAF716D&0&5'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_8087&PID_0AAA\5&E9F3E45&0&14'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842&MI_02\6&1BD5FF13&0&0002'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_5487\A&46F7C3F&0&2'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_58FD&MI_02\6&1E7CBC97&0&0002'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_24AE&PID_4057&MI_01\D&58BCC3D&0&0001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_24AE&PID_4057&MI_00\D&58BCC3D&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_0487\A&46F7C3F&0&4'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842&MI_03\6&1BD5FF13&0&0003'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_2717&PID_5013\5&E9F3E45&0&3'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_402E\200901010001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_047F&PID_C056&MI_03\6&360CBCF3&0&0003'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\ROOT_HUB30\4&36020D6F&0&0'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842\0123456789ABCD'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\ROOT_HUB30\9&AF4BBD4&0&0'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0B95&PID_772B\C1B13D'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\ROOT_HUB30\7&2452366F&0&0'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_402E&MI_00\D&E651DD6&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_047F&PID_C056\BB305534D79EBD418B6757528EAC0C19'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842&MI_00\6&1BD5FF13&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_8153\111000001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_413C&PID_B06F\C&1F76A113&0&5'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_047F&PID_C056&MI_00\6&360CBCF3&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_58FD&MI_00\6&1E7CBC97&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_05E3&PID_0608\5&E9F3E45&0&2'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842&MI_01\6&1BD5FF13&0&0001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_58FD\200901010001'

Reading device descriptor:
            length: 18
      device class: 0
               S/N: 3
           VID:PID: 047F:C056
         bcdDevice: 0210
   iMan:iProd:iSer: 1:2:3
          nb confs: 1

Reading BOS descriptor: libusb: warning [_hid_get_descriptor] unsupported
libusb: warning [_hid_get_descriptor] unsupported
libusb: error [composite_submit_control_transfer] no libusb supported interfaces to complete request
libusb: error [libusb_get_bos_descriptor] failed to read BOS (-5)
no descriptor

Reading first configuration descriptor:
              total length: 288
         descriptor length: 9
             nb interfaces: 4
              interface[0]: id = 0
interface[0].altsetting[0]: num endpoints = 0
   Class.SubClass.Protocol: 01.01.00
              interface[1]: id = 1
interface[1].altsetting[0]: num endpoints = 0
   Class.SubClass.Protocol: 01.02.00
interface[1].altsetting[1]: num endpoints = 1
   Class.SubClass.Protocol: 01.02.00
       endpoint[0].address: 81
           max packet size: 00C8
          polling interval: 01
              interface[2]: id = 2
interface[2].altsetting[0]: num endpoints = 0
   Class.SubClass.Protocol: 01.02.00
interface[2].altsetting[1]: num endpoints = 1
   Class.SubClass.Protocol: 01.02.00
       endpoint[0].address: 01
           max packet size: 00C0
          polling interval: 01
              interface[3]: id = 3
interface[3].altsetting[0]: num endpoints = 1
   Class.SubClass.Protocol: 03.00.00
       endpoint[0].address: 84
           max packet size: 0025
          polling interval: 01

Kernel driver attached for interface 0: (not supported)

Claiming interface 0...
   Failed (error -12) Operation not supported or unimplemented on this platform

Kernel driver attached for interface 1: (not supported)

Claiming interface 1...
   Failed (error -12) Operation not supported or unimplemented on this platform

Kernel driver attached for interface 2: (not supported)

Claiming interface 2...
   Failed (error -12) Operation not supported or unimplemented on this platform

Kernel driver attached for interface 3: (not supported)

Claiming interface 3...

Reading string descriptors:
   String (0x01): "Plantronics"
   String (0x02): "Plantronics Blackwire 3220 Series"
   String (0x03): "BB305534D79EBD418B6757528EAC0C19"

Reading OS string descriptor: no descriptor

Reading interface association descriptors (IADs) for first configuration:
    nb IADs: 0

Releasing interface 0...
Releasing interface 1...
Releasing interface 2...
Releasing interface 3...
Closing device...

Another USB Device: only Interface 0 is accessible by libusb Windows (USB HID interface).

C:\work\libusb\libusb-1.0.27-rc1\build\v142\x64\Release> .\xusb 03eb:2177
Using libusb v1.0.27.11848

Opening device 03EB:2177...
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_1A86&PID_7523\C&1F76A113&0&2'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_24AE&PID_4057\C&1F76A113&0&3'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_5413\B&2EAF716D&0&3'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_0413\B&1637EEB3&0&3'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_413C&PID_B06E\B&2EAF716D&0&5'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_8087&PID_0AAA\5&E9F3E45&0&14'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842&MI_02\6&1BD5FF13&0&0002'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_5487\A&46F7C3F&0&2'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_58FD&MI_02\6&1E7CBC97&0&0002'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_24AE&PID_4057&MI_01\D&58BCC3D&0&0001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_24AE&PID_4057&MI_00\D&58BCC3D&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_0487\A&46F7C3F&0&4'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842&MI_03\6&1BD5FF13&0&0003'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_2717&PID_5013\5&E9F3E45&0&3'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_402E\200901010001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_047F&PID_C056&MI_03\6&360CBCF3&0&0003'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\ROOT_HUB30\4&36020D6F&0&0'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842\0123456789ABCD'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\ROOT_HUB30\9&AF4BBD4&0&0'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\ROOT_HUB30\7&2452366F&0&0'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_402E&MI_00\D&E651DD6&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_03EB&PID_2177&MI_00\6&315E345F&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_047F&PID_C056\BB305534D79EBD418B6757528EAC0C19'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842&MI_00\6&1BD5FF13&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_8153\111000001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_413C&PID_B06F\C&1F76A113&0&5'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_047F&PID_C056&MI_00\6&360CBCF3&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_03EB&PID_2177\BUR200973052'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_58FD&MI_00\6&1E7CBC97&0&0000'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_03EB&PID_2177&MI_01\6&315E345F&0&0001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0A5C&PID_5842&MI_01\6&1BD5FF13&0&0001'
libusb: warning [get_guid] no DeviceInterfaceGUID registered for 'USB\VID_0BDA&PID_58FD\200901010001'

Reading device descriptor:
            length: 18
      device class: 239
               S/N: 3
           VID:PID: 03EB:2177
         bcdDevice: 0100
   iMan:iProd:iSer: 1:2:3
          nb confs: 1

Reading BOS descriptor: libusb: warning [_hid_get_descriptor] unsupported
libusb: warning [_hid_get_descriptor] unsupported
libusb: error [composite_submit_control_transfer] no libusb supported interfaces to complete request
libusb: error [libusb_get_bos_descriptor] failed to read BOS (-5)
no descriptor

Reading first configuration descriptor:
              total length: 107
         descriptor length: 9
             nb interfaces: 3
              interface[0]: id = 0
interface[0].altsetting[0]: num endpoints = 2
   Class.SubClass.Protocol: 03.00.00
       endpoint[0].address: 81
           max packet size: 0040
          polling interval: 01
       endpoint[1].address: 02
           max packet size: 0040
          polling interval: 01
              interface[1]: id = 1
interface[1].altsetting[0]: num endpoints = 1
   Class.SubClass.Protocol: 02.02.00
       endpoint[0].address: 84
           max packet size: 0040
          polling interval: 10
              interface[2]: id = 2
interface[2].altsetting[0]: num endpoints = 2
   Class.SubClass.Protocol: 0A.00.00
       endpoint[0].address: 83
           max packet size: 0200
          polling interval: 00
       endpoint[1].address: 05
           max packet size: 0200
          polling interval: 00

Kernel driver attached for interface 0: (not supported)

Claiming interface 0...

Kernel driver attached for interface 1: (not supported)

Claiming interface 1...
   Failed (error -12) Operation not supported or unimplemented on this platform

Kernel driver attached for interface 2: (not supported)

Claiming interface 2...
   Failed (error -12) Operation not supported or unimplemented on this platform

Reading string descriptors:
   String (0x01): "Microchip Technology Incorporated"
   String (0x02): "MPLAB PICkit 4 CMSIS-DAP"
   String (0x03): "BUR200973052"

Reading OS string descriptor: no descriptor

Reading interface association descriptors (IADs) for first configuration:
    nb IADs: 1
      IAD 0:
            bFirstInterface: 1
            bInterfaceCount: 2
             bFunctionClass: 02
          bFunctionSubClass: 02
          bFunctionProtocol: 00
                  iFunction: 5 (PICkit 4 Virtual COM Port)

Releasing interface 0...
Releasing interface 1...
Releasing interface 2...
Closing device...

@mcuee
Copy link
Member

mcuee commented Dec 28, 2023

When building using VS2019, the build failed. Appveryor MSVC build also failed.

PS C:\work\libusb\libusb_pr1404\msvc> msbuild -m -v:m -p:PlatformToolset=v142,Platform=x64,Configuration=Release .\libusb.sln
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

  core.c
  descriptor.c
  events_windows.c
  hotplug.c
  io.c
  strerror.c
  sync.c
  threads_windows.c
  windows_common.c
  windows_usbdk.c
  windows_winusb.c
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): error C2220: the following warning is treated as an er
ror [C:\work\libusb\libusb_pr1404\msvc\libusb_static.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): error C2220:         struct windows_context_priv *priv
 = usbi_get_context_priv(&usbi_backend); [C:\work\libusb\libusb_pr1404\msvc\libusb_static.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): error C2220:
                                      ^ [C:\work\libusb\libusb_pr1404\msvc\libusb_static.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): warning C4090: 'function': different 'const' qualifier
s [C:\work\libusb\libusb_pr1404\msvc\libusb_static.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): warning C4090:         struct windows_context_priv *pr
  getopt.c
  descriptor.c
  events_windows.c
  hotplug.c
  io.c
  strerror.c
  sync.c
  threads_windows.c
  windows_common.c
  windows_usbdk.c
  getopt1.c
  windows_winusb.c
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): error C2220: the following warning is treated as an er
ror [C:\work\libusb\libusb_pr1404\msvc\libusb_dll.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): error C2220:         struct windows_context_priv *priv
 = usbi_get_context_priv(&usbi_backend); [C:\work\libusb\libusb_pr1404\msvc\libusb_dll.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): error C2220:
                                      ^ [C:\work\libusb\libusb_pr1404\msvc\libusb_dll.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): warning C4090: 'function': different 'const' qualifier
s [C:\work\libusb\libusb_pr1404\msvc\libusb_dll.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): warning C4090:         struct windows_context_priv *pr
iv = usbi_get_context_priv(&usbi_backend); [C:\work\libusb\libusb_pr1404\msvc\libusb_dll.vcxproj]
C:\work\libusb\libusb_pr1404\libusb\os\windows_common.c(883,73): warning C4090:
                                        ^ [C:\work\libusb\libusb_pr1404\msvc\libusb_dll.vcxproj]
  getopt.vcxproj -> C:\work\libusb\libusb_pr1404\build\v142\x64\Release\getopt.lib

@mcuee
Copy link
Member

mcuee commented Dec 28, 2023

Warnings under MSYS2 mingw64:

os/windows_common.c: In function 'windows_get_backend_name':
os/windows_common.c:883:67: warning: passing argument 1 of 'usbi_get_context_priv' from incompatible pointer type [-Wincompatible-pointer-types]
  883 |         struct windows_context_priv *priv = usbi_get_context_priv(&usbi_backend);
      |                                                                   ^~~~~~~~~~~~~
      |                                                                   |
      |                                                                   const struct usbi_os_backend *

@mcuee
Copy link
Member

mcuee commented Dec 28, 2023

Strange that the example testlibusb caused seg-fault.

MINGW64 /c/work/libusb/libusb_pr1404
$ ./examples/testlibusb.exe
[timestamp] [threadID] facility level [function call] <message>
--------------------------------------------------------------------------------
[ 0.001042] [0000123c] libusb: debug [libusb_init_context] created default context
[ 0.001335] [0000123c] libusb: debug [libusb_init_context] libusb v1.0.27.11850-rc1
[ 0.001613] [0000123c] libusb: debug [usbi_add_event_source] add HANDLE 0000000000000094 events 0
[ 0.001866] [0000123c] libusb: debug [usbi_io_init] using timer for timeouts
[ 0.002072] [0000123c] libusb: debug [usbi_add_event_source] add HANDLE 000000000000009c events 0
[ 0.002201] [0000123c] libusb: debug [get_windows_version] Windows 10 64-bit
[ 0.002271] [0000123c] libusb: debug [htab_create] using 1021 entries hash table
[ 0.009625] [0000123c] libusb: info [winusbx_init] WinUSB DLL available (with isoch support)
[ 0.017150] [0000123c] libusb: debug [winusbx_init] libusbK DLL found, version: 3.1.0.0
[ 0.024100] [0000123c] libusb: error [load_usbdk_helper_dll] Failed to load UsbDkHelper.dll: [126] The specified module could not be found.
[ 0.024337] [0000123c] libusb: info [windows_init] UsbDk backend is not available
[ 0.025063] [00001090] libusb: debug [windows_iocp_thread] I/O completion thread started
Segmentation fault

@fabiensanglard
Copy link
Author

fabiensanglard commented Jan 6, 2024

PTAL (now the API retrieval is on a per device basis)

1/ @mcuee Do we have the instructions to setup MINGW64 so I can investigate the segfault?
2/ I tested it on Linux, Windows, and Mac. It works however, on Windows, the HID pass does not set api and sub_api so the names are not retrieved (moreover, many driver names are missing e.g: sensors). Composite and WinUSBX work as expected. I propose to merge this CL once reviewed and create a bug where we fix the HID sub_api issue to avoid making this PR too messy.

libusb/core.c Outdated Show resolved Hide resolved
libusb/libusbi.h Outdated Show resolved Hide resolved
libusb/libusb.h Outdated Show resolved Hide resolved
@mcuee
Copy link
Member

mcuee commented Jan 6, 2024

@fabiensanglard

MinGW development environment --> recommendation is to use MSYS2.
https://www.msys2.org/

There are multiple toolchains. The aim of libusb project is to support all of them (except msys).
https://www.msys2.org/docs/environments/

Currently libusb CI tests MSYS2 mingw64, clang32 and clang64 toolchain. I usually use only mingw64 and clang64 environment to carry out the tests.

Name Prefix Toolchain Architecture C Library C++ Library
MSYS /usr gcc x86_64 cygwin libstdc++
UCRT64 /ucrt64 gcc x86_64 ucrt libstdc++
CLANG64 /clang64 llvm x86_64 ucrt libc++
CLANGARM64 /clangarm64 llvm aarch64 ucrt libc++
CLANG32 /clang32 llvm i686 ucrt libc++
MINGW64 /mingw64 gcc x86_64 msvcrt libstdc++
MINGW32 /mingw32 gcc i686 msvcrt libstdc++

@mcuee
Copy link
Member

mcuee commented Jan 6, 2024

@fabiensanglard

As for review of this PR, I think @tormodvolden and @hjelmn will need to take a look, probably after libusb-1.0.27 release.

@mcuee
Copy link
Member

mcuee commented Jan 6, 2024

@fabiensanglard

Your latest commit is good -- no more compiler warnings and no more crash using MSYS2 mingw64 toolchain and test under Windows 11.

MINGW64 /c/work/libusb/libusb_pr1404
$ ./examples/testlibusb.exe
Dev (bus 2, device 1): 05E3 - 0612 speed: 5G driver:
Dev (bus 2, device 2): 05E3 - 0749 speed: 5G driver:
Dev (bus 1, device 3): 8087 - 0026 speed: 12M driver:
Dev (bus 1, device 4): 1EA7 - 0064 speed: 12M driver: HIDUSB
  Product:                   2.4G Mouse
Dev (bus 1, device 2): 04F2 - B6DD speed: 480M driver: USBCCGP
Dev (bus 1, device 5): 1C7A - 0575 speed: 480M driver: WinUSB
Dev (bus 1, device 0): 8086 - A0ED speed: 5G driver:
Dev (bus 1, device 1): 05E3 - 0610 speed: 480M driver:
Dev (bus 1, device 6): 03EB - 2177 speed: 480M driver: USBCCGP
  Manufacturer:              Microchip Technology Incorporated
  Product:                   MPLAB PICkit 4 CMSIS-DAP
Dev (bus 2, device 0): 8086 - 9A13 speed: 5G driver:

@mcuee
Copy link
Member

mcuee commented Jan 6, 2024

@fabiensanglard

Idealy it would be even better to zoom into the interfaces of USB Composite Device like PICKit 4.

Example output from Linux usbutils (lsusb -t)

mcuee@UbuntuSwift3 ~/build/libusb/libusb_git (master)$ lsusb 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 007: ID 05e3:0612 Genesys Logic, Inc. Hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 003: ID 1ea7:0064 SHARKOON Technologies GmbH 2.4G Mouse
Bus 003 Device 004: ID 04f2:b6dd Chicony Electronics Co., Ltd HD User Facing
Bus 003 Device 005: ID 1c7a:0575 LighTuning Technology Inc. EgisTec EH575
Bus 003 Device 006: ID 8087:0026 Intel Corp. 
Bus 003 Device 019: ID 05e3:0610 Genesys Logic, Inc. 4-port hub
Bus 003 Device 020: ID 03eb:2177 Atmel Corp. MPLAB PICkit 4 CMSIS-DAP
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

mcuee@UbuntuSwift3 ~/build/libusb/libusb_git (master)$ lsusb -t
/:  Bus 001.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/1p, 480M
/:  Bus 002.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/4p, 10000M
    |__ Port 001: Dev 007, If 0, Class=Hub, Driver=hub/4p, 5000M
/:  Bus 003.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/12p, 480M
    |__ Port 002: Dev 019, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 002: Dev 020, If 0, Class=Human Interface Device, Driver=usbhid, 480M
        |__ Port 002: Dev 020, If 1, Class=Communications, Driver=cdc_acm, 480M
        |__ Port 002: Dev 020, If 2, Class=CDC Data, Driver=cdc_acm, 480M
    |__ Port 003: Dev 003, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 005: Dev 004, If 0, Class=Video, Driver=uvcvideo, 480M
    |__ Port 005: Dev 004, If 1, Class=Video, Driver=uvcvideo, 480M
    |__ Port 007: Dev 005, If 0, Class=Vendor Specific Class, Driver=[none], 480M
    |__ Port 010: Dev 006, If 0, Class=Wireless, Driver=btusb, 12M
    |__ Port 010: Dev 006, If 1, Class=Wireless, Driver=btusb, 12M
/:  Bus 004.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/4p, 10000M

@fabiensanglard
Copy link
Author

If we want to get the driver name for each interface, we will return values like usbhid, btusb, xhci_hcd/1p, hub. This is different from the original requirements from issue #1225 where

Linux -- return usbfs 

@mcuee
Copy link
Member

mcuee commented Jan 7, 2024

If we want to get the driver name for each interface, we will return values like usbhid, btusb, xhci_hcd/1p, hub. This is different from the original requirements from issue #1225 where

Linux -- return usbfs 

I understand your point but I feel it will be more useful, at least for USB Composite Devices under Windows and Linux.

I think you may want to pause and let's hear from @tormodvolden and @hjelmn before continue the efforts.

libusb/os/windows_usbdk.c Outdated Show resolved Hide resolved
libusb/os/windows_winusb.c Outdated Show resolved Hide resolved
libusb/os/openbsd_usb.c Outdated Show resolved Hide resolved
Comment on lines 186 to 188
printf("Dev (bus %u, device %u): %04X - %04X speed: %s driver: %s\n",
libusb_get_bus_number(dev), libusb_get_device_address(dev),
desc.idVendor, desc.idProduct, speed, libusb_get_driver_name(dev));
Copy link
Member

@Youw Youw Jan 10, 2024

Choose a reason for hiding this comment

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

regarding tabs vs spaces - here is a very interesting case:
the file uses tabs for aligning, but the consequent alignment of multiline statement/expression should use spaces, since the first line "refix" is a fixed-width printf(:

Suggested change
printf("Dev (bus %u, device %u): %04X - %04X speed: %s driver: %s\n",
libusb_get_bus_number(dev), libusb_get_device_address(dev),
desc.idVendor, desc.idProduct, speed, libusb_get_driver_name(dev));
printf("Dev (bus %u, device %u): %04X - %04X speed: %s driver: %s\n",
libusb_get_bus_number(dev), libusb_get_device_address(dev),
desc.idVendor, desc.idProduct, speed, libusb_get_driver_name(dev));

and the original author of these suggested that consequent lines should be aligned regardless of the "tab size" configuration in the viewer/IDE

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 from my side

@mcuee
Copy link
Member

mcuee commented Jan 11, 2024

Latest git commit is still good under Windows, if we just use the original proposal, to return the relevant driver name of a device (not down to an interface).

MINGW64 /c/work/libusb/libusb_drivername
$ ./examples/testlibusb.exe
Dev (bus 2, device 7): 05E3 - 0612 speed: 5G driver:
Dev (bus 2, device 8): 05E3 - 0749 speed: 5G driver:
Dev (bus 1, device 5): 8087 - 0026 speed: 12M driver:
Dev (bus 1, device 25): 1EA7 - 0064 speed: 12M driver: HIDUSB
  Product:                   2.4G Mouse
Dev (bus 1, device 3): 04F2 - B6DD speed: 480M driver: USBCCGP
Dev (bus 1, device 4): 1C7A - 0575 speed: 480M driver: WinUSB
Dev (bus 1, device 0): 8086 - A0ED speed: 5G driver:
Dev (bus 1, device 26): 05E3 - 0610 speed: 480M driver:
Dev (bus 1, device 27): 03EB - 2177 speed: 480M driver: USBCCGP
  Manufacturer:              Microchip Technology Incorporated
  Product:                   MPLAB PICkit 4 CMSIS-DAP
Dev (bus 2, device 0): 8086 - 9A13 speed: 5G driver:

@fabiensanglard
Copy link
Author

fabiensanglard commented Jan 13, 2024

Ok, I am pausing the feature until @tormodvolden and @hjelmn can take a look. I will just summarize for them the latest status.

The requirement of the feature evolved over the review. It seems what is the most useful according to @mcuee is to have two functions. One to retrieve backend info. And one to retrieve the driver name for a given (device, interface). That means I can split the PR into two.

One would add to the APi:

// Return info about the backend. e.g.: "linux with udev"
const char* libusb_get_backend_info();

The other would add the following API:

// Retrieve the driver bound to an interface by the OS (if any). e.g. (linux): usbhid, btusb, xhci_hcd/1p, hub, usbfs.
const char* libusb_get_driver_name(libusb_device *dev, uint8_t interface_index);
void  libusb_free_driver_name(const char* driver_name);

@mcuee
Copy link
Member

mcuee commented Feb 15, 2024

@tormodvolden and @hjelmn

Just wondering if you can review the proposal here. Thanks.

@mcuee
Copy link
Member

mcuee commented Feb 15, 2024

Tested under macOS.

I know we say macOS should return IOKit as the driver name. However, it should only for those without kernel driver attached. I am not so sure it is a good idea to return IOKit blindly.

@hjelmn and @tormodvolden
Please comment as well.

mcuee@mcuees-Mac-mini libusb_pr1404 % ./examples/testlibusb 
Dev (bus 3, device 14): 0BDA - 0413 speed: 5G driver: IOKit
  Manufacturer:              Dell Inc.
  Product:                   Dell dock
Dev (bus 3, device 13): 0BDA - 8153 speed: 5G driver: IOKit
  Manufacturer:              Realtek
  Product:                   USB 10/100/1000 LAN
Dev (bus 3, device 12): 0BDA - 0487 speed: 10G driver: IOKit
  Manufacturer:              Dell Inc.
  Product:                   Dell dock
Dev (bus 3, device 8): 0BDA - 402E speed: 480M driver: IOKit
  Manufacturer:              Generic
  Product:                   USB Audio
Dev (bus 3, device 7): 413C - B06F speed: 480M driver: IOKit
  Product:                   Dell dock
Dev (bus 3, device 6): 413C - B06E speed: 480M driver: IOKit
  Product:                   Dell dock
Dev (bus 3, device 5): 0BDA - 5413 speed: 480M driver: IOKit
  Manufacturer:              Dell Inc.
  Product:                   Dell dock
Dev (bus 3, device 1): 0BDA - 5487 speed: 480M driver: IOKit
  Manufacturer:              Dell Inc.
  Product:                   Dell dock
Dev (bus 2, device 11): 05E3 - 0749 speed: 5G driver: IOKit
  Manufacturer:              Generic
  Product:                   USB3.0 Card Reader
Dev (bus 2, device 10): 1915 - 1025 speed: 12M driver: IOKit
  Manufacturer:              ZY.Ltd
  Product:                   ZY Control Mic
Dev (bus 2, device 9): 046D - C52B speed: 12M driver: IOKit
  Manufacturer:              Logitech
  Product:                   USB Receiver
Dev (bus 2, device 8): 1A40 - 0201 speed: 480M driver: IOKit
  Product:                   USB 2.0 Hub [MTT]
Dev (bus 2, device 7): 0AC8 - 3420 speed: 480M driver: IOKit
  Manufacturer:              Vimicro Corp.
  Product:                   PROLiNK PCC3220
Dev (bus 2, device 6): 1A40 - 0201 speed: 480M driver: IOKit
  Product:                   USB 2.0 Hub [MTT]
Dev (bus 2, device 5): 0BDA - 5411 speed: 480M driver: IOKit
  Manufacturer:              Generic
  Product:                   4-Port USB 2.0 Hub
Dev (bus 2, device 3): 0BDA - 0411 speed: 5G driver: IOKit
  Manufacturer:              Generic
  Product:                   4-Port USB 3.0 Hub
Dev (bus 2, device 2): 0BDA - 0411 speed: 5G driver: IOKit
  Manufacturer:              Generic
  Product:                   4-Port USB 3.0 Hub
Dev (bus 2, device 1): 0BDA - 5411 speed: 480M driver: IOKit
  Manufacturer:              Generic
  Product:                   4-Port USB 2.0 Hub
mcuee@mcuees-Mac-mini libusb_pr1404 % ./examples/listdevs 
0bda:0413 (bus 3, device 14) path: 4.3 driver: 'IOKit'
0bda:8153 (bus 3, device 13) path: 4.4 driver: 'IOKit'
0bda:0487 (bus 3, device 12) path: 4 driver: 'IOKit'
0bda:402e (bus 3, device 8) path: 2.3.4 driver: 'IOKit'
413c:b06f (bus 3, device 7) path: 2.3.5 driver: 'IOKit'
413c:b06e (bus 3, device 6) path: 2.5 driver: 'IOKit'
0bda:5413 (bus 3, device 5) path: 2.3 driver: 'IOKit'
0bda:5487 (bus 3, device 1) path: 2 driver: 'IOKit'
05e3:0749 (bus 2, device 11) path: 6.1.2 driver: 'IOKit'
1915:1025 (bus 2, device 10) path: 2.4.5.6 driver: 'IOKit'
046d:c52b (bus 2, device 9) path: 2.4.7 driver: 'IOKit'
1a40:0201 (bus 2, device 8) path: 2.4.5 driver: 'IOKit'
0ac8:3420 (bus 2, device 7) path: 2.1.1 driver: 'IOKit'
1a40:0201 (bus 2, device 6) path: 2.4 driver: 'IOKit'
0bda:5411 (bus 2, device 5) path: 2.1 driver: 'IOKit'
0bda:0411 (bus 2, device 3) path: 6.1 driver: 'IOKit'
0bda:0411 (bus 2, device 2) path: 6 driver: 'IOKit'
0bda:5411 (bus 2, device 1) path: 2 driver: 'IOKit'

@sonatique
Copy link
Contributor

sonatique commented Mar 4, 2024

@fabiensanglard @mcuee @tormodvolden : I recently made some Windows-only libusb-1.0 dev on my side in order to get per device driver information using SetupDiEnumDriverInfo. We can get description (kind of device name) and provider (kind of manufacturer) strings as well as date and version. This correspond to DriverDesc, ProviderName, DriverDate and DriverVersion that you'll find under Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{Your GUID}\YourNumber .
I needed this to verify a given device was using the latest version of its driver.

The way I did is that I added call to SetupDiEnumDriverInfo during enumeration, when dev object is created and stored relevant information in new fields of winusb_device_priv which I can later retrieve via a new libusb API function.

Of course this is quite Windows specific but I wonder whether there might be an interested to complement this PR with some version (or other, provider maybe) information got from SetupDiEnumDriverInfo.

@mcuee
Copy link
Member

mcuee commented Mar 5, 2024

@sonatique

Looks like an interesting idea to me. Windows is anyway one of the main focus of this PR.

@fabiensanglard
Copy link
Author

Thanks @sonatique this is precious. When I was researching it, I found getting the Linux driver name to be trivial but the Window side of things very complicated. Your Windows expertise is a relief!

It looks like SetupDiEnumDriverInfo gives us access to a SP_DRVINFO_DATA_V2_A . However there is no driver name in it. Am I missing something?

@sonatique
Copy link
Contributor

@fabiensanglard Thanks for your reply. As far as I know (not being an expert myself) we can use SetupDiEnumDriverInfoA that fills a SP_DRVINFO_DATA_A and and SetupDiGetDriverInfoDetailA that fills a SP_DRVINFO_DETAIL_DATA_A .
Some information are redundant among the two.

You're right, there is no "driver name" with the meaning of giving you the driver filename, like libusb0.sys or libusbK.sys because, I guess, this is not what is considered to be relevant by Windows (after all you can always rename this file and repackage it). The more relevant data is what is to be found in (signed) INF file. Moreover in recent version of Windows driver files are stored into "DriverStore" folder upon installation and their name is modified to be unique per INF file / device type.

Before this, a single libsub0.sys (for instance) would be installed in System32/Driver for all devices to use. If someone would update this file, all device would automatically use it, even if their related application would not support some aspects of it.

So, well, instead of "driver name" with SetupDiEnumDriverInfoA you get a "Description" (basically the name of the device as registered in the INF file), a "Provider", typically the company who signed/made the INF, but could also be "libusb-win32" when using directly what is provided by libsub-win32 developers. Then, most important thing for my own use: the driver "Version" (4 words), typically something like 1.3.0.2 or 1.4.0.0, and the associated date.
With SetupDiGetDriverInfoDetailA you additionally get the INF file name and the "hardware ID" (some kind of unique string, typically made of VID and PID + other things.

I think that when developing an application for a device, if you face the problem of needing to known the driver version, it is because you may be compatible with some versions and not with others. In this case you'll refer to then "Provider" then check the "Version" (you may support multiple Provider / Version pairs) and you'll have to know the Provider in advance. This is what is closer to "driver name", as far as I understand.

@tormodvolden
Copy link
Contributor

Did you mean to rebase here? There are no commits left.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API API changes enhancement New features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Return kernel driver name -- New API
6 participants