summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/lsusb.c10
-rw-r--r--libusb/os/driver_install.c147
-rw-r--r--libusb/os/driver_install.h17
-rw-r--r--libusb/os/windows_usb.c34
-rw-r--r--libusb/os/windows_usb.h24
-rw-r--r--libusb_2008.sln32
6 files changed, 224 insertions, 40 deletions
diff --git a/examples/lsusb.c b/examples/lsusb.c
index 58d58fe..6b815d4 100644
--- a/examples/lsusb.c
+++ b/examples/lsusb.c
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <libusb/libusb.h>
+#include <libusb/os/driver_install.h>
static void print_devs(libusb_device **devs)
{
@@ -50,6 +51,15 @@ main(void)
libusb_device **devs;
int r;
ssize_t cnt;
+ struct driver_info *drv_info;
+
+ drv_info = list_driverless();
+ for (; drv_info != NULL; drv_info = drv_info->next) {
+ printf("%s\n", drv_info->desc);
+ printf(" %s\n", drv_info->vid);
+ printf(" %s\n", drv_info->pid);
+ printf(" %s\n", drv_info->mi);
+ }
r = libusb_init(NULL);
if (r < 0)
diff --git a/libusb/os/driver_install.c b/libusb/os/driver_install.c
new file mode 100644
index 0000000..3c80901
--- /dev/null
+++ b/libusb/os/driver_install.c
@@ -0,0 +1,147 @@
+#if defined(_MSC_VER)
+#include <config_msvc.h>
+#else
+#include <config.h>
+#endif
+#include <windows.h>
+#include <setupapi.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <process.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <objbase.h> // for GUID ops. requires libole32.a
+
+#include "libusbi.h"
+#include "windows_usb.h"
+#include "driver_install.h"
+
+char* guid_to_string(const GUID guid)
+{
+ static char guid_string[MAX_GUID_STRING_LENGTH];
+
+ sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ (unsigned int)guid.Data1, guid.Data2, guid.Data3,
+ guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
+ guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+ return guid_string;
+}
+
+void free_di(struct driver_info *start)
+{
+ struct driver_info *tmp;
+ while(start != NULL) {
+ tmp = start;
+ start = start->next;
+ free(tmp);
+ }
+}
+
+struct driver_info* list_driverless(void)
+{
+ unsigned i, j;
+ struct libusb_context *ctx = NULL;
+ DWORD size, reg_type, install_state;
+ CONFIGRET r;
+ HDEVINFO dev_info;
+ SP_DEVINFO_DATA dev_info_data;
+ SP_DEVICE_INTERFACE_DETAIL_DATA *dev_interface_details = NULL;
+ char *sanitized_short = NULL;
+ char *prefix[3] = {"VID_", "PID_", "MI_"};
+// char *designation[3] = {"VendorID", "ProductID", "InterfaceID"};
+ char *token;
+ char path[MAX_PATH_LENGTH];
+ char desc[MAX_DESC_LENGTH];
+ struct driver_info *ret = NULL, *cur = NULL, *drv_info;
+
+ // List all connected USB devices
+ dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
+ if (dev_info == INVALID_HANDLE_VALUE) {
+ return NULL;
+ }
+
+ // Find the ones that are driverless
+ for (i = 0; ; i++)
+ {
+ safe_free(sanitized_short);
+
+ dev_info_data.cbSize = sizeof(dev_info_data);
+ if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
+ break;
+ }
+
+ if ( (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_INSTALL_STATE,
+ &reg_type, (BYTE*)&install_state, 4, &size))
+ && (size != 4) ) {
+ usbi_warn(ctx, "could not detect installation state of driver for %d: %s",
+ i, windows_error_str(0));
+ continue;
+ }
+ if (install_state != InstallStateFailedInstall) {
+ continue;
+ }
+
+ if ( (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_DEVICEDESC,
+ &reg_type, (BYTE*)desc, MAX_KEY_LENGTH, &size)) ) {
+ usbi_warn(ctx, "could not read device description for %d: %s",
+ i, windows_error_str(0));
+ continue;
+ }
+
+ r = CM_Get_Device_ID(dev_info_data.DevInst, path, MAX_PATH_LENGTH, 0);
+ if (r != CR_SUCCESS) {
+ usbi_err(ctx, "could not retrieve simple path for device %d: CR error %d",
+ i, r);
+ continue;
+ }
+ sanitized_short = sanitize_path(path);
+ if (sanitized_short == NULL) {
+ usbi_err(ctx, "could not sanitize path for device %d", i);
+ continue;
+ }
+ usbi_dbg("Driverless USB device (%d): %s", i, sanitized_short);
+// usbi_dbg(" DeviceName = \"%s\"", desc);
+
+ drv_info = calloc(1, sizeof(struct driver_info));
+ if (drv_info == NULL) {
+ free_di(ret);
+ return NULL;
+ }
+ if (cur == NULL) {
+ ret = drv_info;
+ } else {
+ cur->next = drv_info;
+ }
+ cur = drv_info;
+
+ safe_strcpy(drv_info->desc, sizeof(drv_info->desc), desc);
+
+ token = strtok (sanitized_short, "#&");
+ while(token != NULL) {
+ for (j = 0; j < 3; j++) {
+ if (safe_strncmp(token, prefix[j], strlen(prefix[j])) == 0) {
+ switch(j) {
+ case 0:
+ safe_strcpy(drv_info->vid, sizeof(drv_info->vid), token);
+ break;
+ case 1:
+ safe_strcpy(drv_info->pid, sizeof(drv_info->pid), token);
+ break;
+ case 2:
+ safe_strcpy(drv_info->mi, sizeof(drv_info->mi), token);
+ break;
+ default:
+ usbi_err(ctx, "unexpected case");
+ break;
+ }
+ }
+ }
+ token = strtok (NULL, "#&");
+ }
+ CoCreateGuid(&drv_info->dev_guid);
+
+// usbi_dbg(" DeviceGUID = \"%s\"", guid_to_string(drv_info->dev_guid));
+ }
+ return ret;
+} \ No newline at end of file
diff --git a/libusb/os/driver_install.h b/libusb/os/driver_install.h
new file mode 100644
index 0000000..f1703b3
--- /dev/null
+++ b/libusb/os/driver_install.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <windows.h>
+#define MAX_DESC_LENGTH 128
+
+struct driver_info {
+ struct driver_info *next;
+ char desc[MAX_DESC_LENGTH];
+ char vid[9];
+ char pid[9];
+ char mi[6];
+ GUID dev_guid;
+};
+
+struct driver_info *list_driverless(void);
+char* guid_to_string(const GUID guid);
+
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index e48db35..3723239 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -106,6 +106,18 @@ static int composite_abort_control(struct usbi_transfer *itransfer);
static int composite_reset_device(struct libusb_device_handle *dev_handle);
static int composite_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size);
+// http://msdn.microsoft.com/en-us/library/bb663109.aspx
+// http://msdn.microsoft.com/en-us/library/bb663093.aspx
+#if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER)
+const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} };
+#endif
+#if !defined(GUID_DEVINTERFACE_USB_DEVICE)
+const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
+#endif
+const GUID CLASS_GUID_UNSUPPORTED = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x57, 0xDA} };
+const GUID CLASS_GUID_HID = { 0x745A17A0, 0x74D3, 0x11D0, {0xB6, 0xFE, 0x00, 0xA0, 0xC9, 0x0F, 0x57, 0xDA} };
+const GUID CLASS_GUID_LIBUSB_WINUSB = { 0x78A1C341, 0x4539, 0x11D3, {0xB8, 0x8D, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71} };
+const GUID CLASS_GUID_COMPOSITE = { 0x36FC9E60, 0xC465, 0x11cF, {0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };
// Global variables
struct windows_hcd_priv* hcd_root = NULL;
@@ -161,24 +173,11 @@ static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2) {
return false;
}
-#if 0
-static char* guid_to_string(const GUID guid)
-{
- static char guid_string[MAX_GUID_STRING_LENGTH];
-
- sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
- (unsigned int)guid.Data1, guid.Data2, guid.Data3,
- guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
- guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
- return guid_string;
-}
-#endif
-
/*
* Converts a windows error to human readable string
* uses retval as errorcode, or, if 0, use GetLastError()
*/
-static char *windows_error_str(uint32_t retval)
+char *windows_error_str(uint32_t retval)
{
static char err_string[ERR_BUFFER_SIZE];
@@ -208,7 +207,7 @@ static char err_string[ERR_BUFFER_SIZE];
* Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes.
* Return an allocated sanitized string or NULL on error.
*/
-static char* sanitize_path(const char* path)
+char* sanitize_path(const char* path)
{
const char root_prefix[] = "\\\\.\\";
size_t j, size, root_size;
@@ -1001,6 +1000,7 @@ enum libusb_hid_report_type {
continue;
}
CLSIDFromString(guid_string_w, &guid);
+//usbi_dbg("GUID: %s", guid_to_string(guid));
// identical device interface GUIDs are not supposed to happen, but are a real possibility
// => check and ignore duplicates
@@ -1033,7 +1033,7 @@ enum libusb_hid_report_type {
dev_interface_details = get_interface_details(ctx, &dev_info, &dev_info_data, guid, i);
if (dev_interface_details == NULL)
break;
-
+usbi_dbg("%s", dev_interface_details->DevicePath);
// HID devices (and possibly other classes) have an extra indirection
// for an USB path we can recognize
if (j == HID_DEVICE_INTERFACE_GUID_INDEX) {
@@ -1264,6 +1264,8 @@ static int set_device_paths(struct libusb_context *ctx, struct discovered_devs *
uint8_t api;
bool found;
+// list_driverless(ctx);
+
// TODO (v1.5): MI_## automated driver installation
guid = GUID_DEVINTERFACE_USB_DEVICE;
for (i = 0; ; i++)
diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h
index cd74e22..b11b318 100644
--- a/libusb/os/windows_usb.h
+++ b/libusb/os/windows_usb.h
@@ -82,6 +82,8 @@ inline void upperize(char* str) {
for (i=0; i<strlen(str); i++)
str[i] = (char)toupper((int)str[i]);
}
+extern char* sanitize_path(const char* path);
+extern char *windows_error_str(uint32_t retval);
#define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_USB_DEVICES 256
@@ -100,16 +102,6 @@ inline void upperize(char* str) {
// Additional return code for HID operations that completed synchronously
#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1)
-// http://msdn.microsoft.com/en-us/library/bb663109.aspx
-// http://msdn.microsoft.com/en-us/library/bb663093.aspx
-#if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER)
-const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} };
-#endif
-#if !defined(GUID_DEVINTERFACE_USB_DEVICE)
-const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
-#endif
-
-
/*
* Multiple USB API backend support
*/
@@ -119,11 +111,6 @@ const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0
#define USB_API_HID 3
#define USB_API_MAX 4
-const GUID CLASS_GUID_UNSUPPORTED = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x57, 0xDA} };
-const GUID CLASS_GUID_HID = { 0x745A17A0, 0x74D3, 0x11D0, {0xB6, 0xFE, 0x00, 0xA0, 0xC9, 0x0F, 0x57, 0xDA} };
-const GUID CLASS_GUID_LIBUSB_WINUSB = { 0x78A1C341, 0x4539, 0x11D3, {0xB8, 0x8D, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71} };
-const GUID CLASS_GUID_COMPOSITE = { 0x36FC9E60, 0xC465, 0x11cF, {0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };
-
struct windows_usb_api_backend {
const uint8_t id;
const GUID *class_guid; // The Class GUID (for fallback in case the driver name cannot be read)
@@ -386,6 +373,13 @@ typedef enum _USB_HUB_NODE {
UsbMIParent
} USB_HUB_NODE;
+typedef enum _DEVICE_INSTALL_STATE {
+ InstallStateInstalled,
+ InstallStateNeedsReinstall,
+ InstallStateFailedInstall,
+ InstallStateFinishInstall
+} DEVICE_INSTALL_STATE, *PDEVICE_INSTALL_STATE;
+
CMAPI CONFIGRET WINAPI CM_Get_Parent(
/*OUT*/ PDEVINST pdnDevInst,
/*IN*/ DEVINST dnDevInst,
diff --git a/libusb_2008.sln b/libusb_2008.sln
index e2421f9..04c2e15 100644
--- a/libusb_2008.sln
+++ b/libusb_2008.sln
@@ -1,11 +1,12 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0", "libusb-static_2008.vcproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (static)", "libusb-static_2008.vcproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0 (dll)", "libusb-dll_2008.vcproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsusb", "examples\lsusb_2008.vcproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}"
ProjectSection(ProjectDependencies) = postProject
+ {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9} = {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187}
EndProjectSection
EndProject
@@ -14,6 +15,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xusb", "examples\xusb_2008.
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver-install", "driver-install_2008.vcproj", "{9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -30,14 +33,10 @@ Global
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.Build.0 = Release|Win32
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64
- {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.ActiveCfg = Debug|Win32
- {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.Build.0 = Debug|Win32
- {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.ActiveCfg = Debug|x64
- {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.Build.0 = Debug|x64
- {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.ActiveCfg = Release|Win32
- {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.Build.0 = Release|Win32
- {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.ActiveCfg = Release|x64
- {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.Build.0 = Release|x64
+ {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|Win32.ActiveCfg = Debug|Win32
+ {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
+ {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|Win32.ActiveCfg = Release|Win32
+ {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.ActiveCfg = Debug|Win32
{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.Build.0 = Debug|Win32
{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.ActiveCfg = Debug|x64
@@ -46,6 +45,21 @@ Global
{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.Build.0 = Release|Win32
{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.ActiveCfg = Release|x64
{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.Build.0 = Release|x64
+ {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|Win32.Build.0 = Debug|Win32
+ {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.ActiveCfg = Debug|x64
+ {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Debug|x64.Build.0 = Debug|x64
+ {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.ActiveCfg = Release|Win32
+ {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|Win32.Build.0 = Release|Win32
+ {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.ActiveCfg = Release|x64
+ {3F3138D0-7AB7-4268-9BF3-1A3EA5503A11}.Release|x64.Build.0 = Release|x64
+ {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Debug|Win32.Build.0 = Debug|Win32
+ {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Debug|x64.ActiveCfg = Debug|Win32
+ {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|Win32.ActiveCfg = Release|Win32
+ {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|Win32.Build.0 = Release|Win32
+ {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|x64.ActiveCfg = Release|x64
+ {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE