c++libusbcd

libusb_open returns LIBUSB_ERROR_NOT_SUPPORTED on windows 10


OS: Windows 10 64bit

Compiler: MSVC 19 std:c++20

static linking

I have below code which just initialize and print some information about the device

#include "libusb.h"
#include <iostream>

int main()
{
  libusb_context* cntx{ nullptr };
  int status{ libusb_init(&cntx) };
  if (status != LIBUSB_SUCCESS)
  {
    std::cerr << libusb_strerror(status);
    return -1;
  }
  libusb_device** devices;
  ssize_t numberOfDevices{ libusb_get_device_list(cntx, &devices) };
  if (numberOfDevices <= 0)
  {
    std::cerr << "Device does NOT found\n";
    return -1;
  }
  std::cout << "Found " << numberOfDevices << " Devices\n";
  int index{ 0 };
  std::cout << std::hex;
  std::cout << "Device Address: " << +libusb_get_device_address(devices[index]) << '\n'
            << "Port Number: "    << +libusb_get_port_number(devices[index]) << '\n'
            << "Bus Number: "     << +libusb_get_bus_number(devices[index]) << '\n'
            << "Device Speed: ";
  switch (libusb_get_device_speed(devices[index])
  {
  case LIBUSB_SPEED_SUPER:      std::cout << "5Gb\n";     break;
  case LIBUSB_SPEED_SUPER_PLUS: std::cout << "10Gb\n";    break;
  case LIBUSB_SPEED_FULL:       std::cout << "12Mb\n";    break;
  case LIBUSB_SPEED_LOW:        std::cout << "1.5Mb\n";   break;
  case LIBUSB_SPEED_HIGH:       std::cout << "480Mb\n";   break;
  default:                      std::cout << "UNKNOWN\n"; break;
  }

so far so good, but when I want to open the (for example) devices[0], LIBUSB_ERROR_NOT_SUPPORTED will return:

  constexpr std::uint16_t VID{ 0x8086 };
  constexpr std::uint16_t PID{ 0x1D26 };
  libusb_device_handle* device{ nullptr };
  status = libusb_open(devices[index], &device);
  if (status)
  {
    std::cerr << "Can NOT open the device: " << libusb_strerror(status) << '\n';
    device = libusb_open_device_with_vid_pid(cntx, VID, PID);
    if (!device)
    { 
      std::cerr << "Can NOT open the device with VID & PID\n";
      return -1;
    }
  }
  std::cout << "Device opened\n";
  return 0;
}

neither works. btw, the device was programmed by a micro-programmer so I don't know about how he programmed it, my job is just to get data from the device.


Solution

  • libusb can enumerate all USB devices. But it can only open devices that have the WinUSB driver (or libusbK or libusb0) installed. WinUSB is the generic driver to interact directly with USB devices and their endpoints, without the need for implementing and providing your own device driver.

    This is appropriate if the device does not implement any of the standard USB protocols (mass storage, camera, audio, serial port etc.), for which Windows provides and loads standard drivers, and if the device does not come with its own driver that needs to be installed first.

    On Linux and macOS, this is a non-issue as USB devices without a dedicated driver are available to applications without any driver hassles.

    In order to install WinUSB, Zadig can be used. Make sure you select the correct device, which can be unplugged if a problem occurs. If the driver is replaced for a crucial device such a USB host controller, a keyboard etc., the PC might no longer boot.

    To automate the WinUSB installation, the device can implement additional USB control requests. There are two options: