[core] fix an enumeration issue and add support for ASUS UASP Turbo Mode

* Our detection for a match in the hash table, during USB enumeration, always
  pointed to the first hub when no match was found.
* Also, some USB mass storage devices (ASUS Turbo Mode devices, iPods) may
  have an additional driver inserted, which we now try to handle by looking
  up the grandparent.
* Thanks to NaoDarkness for helping investigate this
* Closes #513
This commit is contained in:
Pete Batard 2015-05-28 18:47:53 +01:00
parent 94e7e41082
commit ac213a16e9
5 changed files with 42 additions and 28 deletions

View File

@ -1,8 +1,9 @@
o Version 2.2 (2015.05.??)
Modernize the language selection button, courtesy of David Warner
Add keyboard accessibility, courtesy of David Warner
Add a clear indication of UEFI-CSM usage
Fix Rufus preventing Windows shutdown when idle
Add a clear indication of when UEFI-CSM is to be used
Fix an USB detection issue and add support for ASUS UASP Turbo Mode
Fix prevention of Windows shutdown when Rufus is idle
Improve UI on high DPI monitors
Other UI improvements and fixes

View File

@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 2.2.664"
CAPTION "Rufus 2.2.665"
FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
@ -157,7 +157,7 @@ END
IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 2.2.664"
CAPTION "Rufus 2.2.665"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
@ -283,7 +283,7 @@ END
IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 2.2.664"
CAPTION "Rufus 2.2.665"
FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
@ -415,7 +415,7 @@ END
IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 2.2.664"
CAPTION "Rufus 2.2.665"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
@ -671,8 +671,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,2,664,0
PRODUCTVERSION 2,2,664,0
FILEVERSION 2,2,665,0
PRODUCTVERSION 2,2,665,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -689,13 +689,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "2.2.664"
VALUE "FileVersion", "2.2.665"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2015 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "2.2.664"
VALUE "ProductVersion", "2.2.665"
END
END
BLOCK "VarFileInfo"

View File

@ -153,7 +153,7 @@ uint32_t htab_hash(char* str, htab_table* htab)
// existing hash
return idx;
}
// uprintf("hash collision ('%s' vs '%s')\n", str, htab_table[idx].str);
// uprintf("hash collision ('%s' vs '%s')\n", str, htab->table[idx].str);
// Second hash function, as suggested in [Knuth]
hval2 = 1 + hval % (htab->size - 2);

View File

@ -128,7 +128,7 @@ BOOL GetUSBDevices(DWORD devnum)
{
// The first two are standard Microsoft drivers (including the Windows 8 UASP one).
// The rest are the vendor UASP drivers I know of so far - list may be incomplete!
const char* storage_name[] = { "USBSTOR", "UASPSTOR", "VUSBSTOR", "ETRONSTOR" };
const char* storage_name[] = { "USBSTOR", "UASPSTOR", "VUSBSTOR", "ETRONSTOR", "ASUSSTPT" };
const char* scsi_name = "SCSI";
const char* usb_speed_name[USB_SPEED_MAX] = { "USB", "USB 1.0", "USB 1.1", "USB 2.0", "USB 3.0" };
// Hash table and String Array used to match a Device ID with the parent hub's Device Interface Path
@ -141,20 +141,22 @@ BOOL GetUSBDevices(DWORD devnum)
SP_DEVINFO_DATA dev_info_data;
SP_DEVICE_INTERFACE_DATA devint_data;
PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data;
DEVINST parent_inst, device_inst;
DEVINST parent_inst, grandparent_inst, device_inst;
DWORD size, i, j, k, l, datatype, drive_index;
ULONG list_size[ARRAYSIZE(storage_name)] = { 0 }, full_list_size, ulFlags;
ULONG list_size[ARRAYSIZE(storage_name)] = { 0 }, list_start[ARRAYSIZE(storage_name)] = { 0 }, full_list_size, ulFlags;
HANDLE hDrive;
LONG maxwidth = 0;
int s, score, drive_number;
char drive_letters[27], *device_id, *devid_list = NULL, entry_msg[128];
char *label, *entry, buffer[MAX_PATH], str[128];
char *label, *entry, buffer[MAX_PATH], str[MAX_PATH], *method_str;
usb_device_props props;
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
StrArrayClear(&DriveID);
StrArrayClear(&DriveLabel);
StrArrayCreate(&dev_if_path, 128);
// Add a dummy for string index zero, as this is what non matching hashes will point to
StrArrayAdd(&dev_if_path, "");
device_id = (char*)malloc(MAX_PATH);
if (device_id == NULL)
@ -196,7 +198,6 @@ BOOL GetUSBDevices(DWORD devnum)
}
}
}
}
free(devint_detail_data);
}
@ -228,6 +229,7 @@ BOOL GetUSBDevices(DWORD devnum)
return FALSE;
}
for (s=0, i=0; s<ARRAYSIZE(storage_name); s++) {
list_start[s] = i;
if (list_size[s] > 1) {
if (CM_Get_Device_ID_ListA(storage_name[s], &devid_list[i], list_size[s], ulFlags) != CR_SUCCESS)
continue;
@ -249,6 +251,7 @@ BOOL GetUSBDevices(DWORD devnum)
dev_info_data.cbSize = sizeof(dev_info_data);
for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
memset(buffer, 0, sizeof(buffer));
method_str = "";
if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME,
&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %s\n", WindowsErrorString());
@ -281,17 +284,27 @@ BOOL GetUSBDevices(DWORD devnum)
&& (CM_Get_Child(&device_inst, parent_inst, 0) == CR_SUCCESS)
&& (device_inst == dev_info_data.DevInst) ) {
// If we're not dealing with the USBSTOR part of our list, then this is an UASP device
props.is_UASP = ((((uintptr_t)device_id)+2) >= ((uintptr_t)devid_list)+list_size[0]);
props.is_UASP = ((((uintptr_t)device_id)+2) >= ((uintptr_t)devid_list)+list_start[1]);
// Now get the properties of the device, and its Device ID, which we need to populate the properties
j = htab_hash(device_id, &htab_devid);
if (j > 0) {
GetUSBProperties(dev_if_path.String[(uint32_t)htab_devid.table[j].data], device_id, &props);
// If the hash didn't match a populated string in dev_if_path[] (htab_devid.table[j].data > 0),
// we might have an extra vendor driver in between (e.g. "ASUS USB 3.0 Boost Storage Driver"
// for UASP devices in ASUS "Turbo Mode" or "Apple Mobile Device USB Driver" for iPods)
// so try to see if we can match the grandparent.
if ( ((uint32_t)htab_devid.table[j].data == 0)
&& (CM_Get_Parent(&grandparent_inst, parent_inst, 0) == CR_SUCCESS)
&& (CM_Get_Device_IDA(grandparent_inst, str, MAX_PATH, 0) == CR_SUCCESS) ) {
device_id = str;
method_str = "[GP]";
j = htab_hash(device_id, &htab_devid);
}
if ((uint32_t)htab_devid.table[j].data > 0)
GetUSBProperties(dev_if_path.String[(uint32_t)htab_devid.table[j].data], device_id, &props);
// If the previous calls didn't succeed in getting the VID:PID, try from the device_id
// (This is for the case for USB media player devices, for instance)
// If previous calls still didn't succeed, try reading the VID:PID from the device_id
if ((props.vid == 0) && (props.pid == 0)) {
BOOL post_backslash = FALSE;
method_str = "[ID]";
for (j=0, k=0; (j<strlen(device_id))&&(k<2); j++) {
// The ID is in the form USB_VENDOR_BUSID\VID_xxxx&PID_xxxx\...
if (device_id[j] == '\\')
@ -305,12 +318,11 @@ BOOL GetUSBDevices(DWORD devnum)
}
}
}
}
}
}
if (props.is_VHD) {
uprintf("Found VHD device '%s'\n", buffer);
uprintf("Found VHD device '%s'", buffer);
} else {
if ((props.vid == 0) && (props.pid == 0)) {
if (is_SCSI) {
@ -324,8 +336,8 @@ BOOL GetUSBDevices(DWORD devnum)
}
if (props.speed >= USB_SPEED_MAX)
props.speed = 0;
uprintf("Found %s%s%s device '%s' (%s)\n", props.is_UASP?"UAS (":"",
usb_speed_name[props.speed], props.is_UASP?")":"", buffer, str);
uprintf("Found %s%s%s device '%s' (%s) %s\n", props.is_UASP?"UAS (":"",
usb_speed_name[props.speed], props.is_UASP?")":"", buffer, str, method_str);
if (props.is_LowerSpeed)
uprintf("NOTE: This device is an USB 3.0 device operating at lower speed...");
}

View File

@ -32,9 +32,9 @@ typedef struct usb_device_props {
uint32_t pid;
uint32_t speed;
uint32_t port;
BOOL is_UASP;
BOOL is_VHD;
BOOL is_LowerSpeed;
BOOLEAN is_UASP;
BOOLEAN is_VHD;
BOOLEAN is_LowerSpeed;
} usb_device_props;
/*
@ -94,6 +94,7 @@ DECLSPEC_IMPORT CONFIGRET WINAPI CM_Get_Device_ID_List_SizeA(PULONG pulLen, PCST
DECLSPEC_IMPORT CONFIGRET WINAPI CM_Get_Device_ID_ListA(PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags);
DECLSPEC_IMPORT CONFIGRET WINAPI CM_Locate_DevNodeA(PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags);
DECLSPEC_IMPORT CONFIGRET WINAPI CM_Get_Child(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags);
DECLSPEC_IMPORT CONFIGRET WINAPI CM_Get_Parent(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags);
DECLSPEC_IMPORT CONFIGRET WINAPI CM_Get_Sibling(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags);
// This last one is unknown from MinGW32 and needs to be fetched from the DLL
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_DevNode_Registry_PropertyA, (DEVINST, ULONG, PULONG, PVOID, PULONG, ULONG));