diff options
Diffstat (limited to 'libusb/os/driver_install.c')
-rw-r--r-- | libusb/os/driver_install.c | 147 |
1 files changed, 147 insertions, 0 deletions
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, + ®_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, + ®_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 |