diff --git a/win32/CMakeLists.txt b/win32/CMakeLists.txt
index 408ef72..85bfaa6 100644
--- a/win32/CMakeLists.txt
+++ b/win32/CMakeLists.txt
@@ -41,8 +41,8 @@ if (HAVE_SDCMDD)
add_definitions(-DHAS_SDCMDD)
endif ()
-set(PLATFORM_SOURCES "win32.h" network.c hello.c "win32.c" list_devices.c ata.c device.c ieee1394.c pcmcia.c scsi.c sdhci.c usb.c ntioctl.h)
+set(PLATFORM_SOURCES "win32.h" network.c hello.c "win32.c" list_devices.c ata.c device.c ieee1394.c pcmcia.c scsi.c sdhci.c usb.h usb.c ntioctl.h)
add_executable(dicremote ${PLATFORM_SOURCES})
-target_link_libraries(dicremote dicremotecore ws2_32 iphlpapi version)
\ No newline at end of file
+target_link_libraries(dicremote dicremotecore ws2_32 iphlpapi version setupapi cfgmgr32)
\ No newline at end of file
diff --git a/win32/usb.c b/win32/usb.c
index 2d95829..edafa5c 100644
--- a/win32/usb.c
+++ b/win32/usb.c
@@ -15,9 +15,588 @@
* along with this program. If not, see .
*/
+#include "usb.h"
+
#include "win32.h"
+#include
+#include
+#include
#include
+#include
+#include
+
+#ifndef DIGCF_PRESENT
+#define DIGCF_PRESENT 0x00000002
+#endif
+#ifndef DIGCF_DEVICEINTERFACE
+#define DIGCF_DEVICEINTERFACE 0x00000010
+#endif
+
+UsbController_t* GetHostControllers(DWORD* length)
+{
+ GUID hostGuid = GUID_DEVINTERFACE_USB_HOST_CONTROLLER;
+ HDEVINFO h;
+ UsbController_t* hostlist;
+ UsbController_t* host;
+ DWORD i;
+ BOOL success;
+ SP_DEVICE_INTERFACE_DATA dia;
+ SP_DEVINFO_DATA da;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA didd;
+ DWORD nRequiredSize = 0;
+ DWORD N_BYTES = USB_BUFFER_SIZE;
+ DWORD requiredSize;
+ DWORD regType;
+ CHAR ptrBuf[USB_BUFFER_SIZE];
+
+ *length = 0;
+
+ didd = malloc(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + USB_BUFFER_SIZE);
+
+ hostlist = malloc(sizeof(UsbController_t) * 64);
+ if(!hostlist) return NULL;
+
+ memset(hostlist, 0, sizeof(UsbController_t) * 64);
+
+ // We start at the "root" of the device tree and look for all
+ // devices that match the interface GUID of a Hub Controller
+ h = SetupDiGetClassDevs(&hostGuid, 0, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+
+ if(h == INVALID_HANDLE_VALUE) return NULL;
+
+ i = 0;
+
+ do
+ {
+ host = &hostlist[*length];
+ memset(host, 0, sizeof(UsbController_t));
+ host->ControllerIndex = i;
+
+ // create a Device Interface Data structure
+ memset(&dia, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
+ dia.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ // start the enumeration
+ success = SetupDiEnumDeviceInterfaces(h, NULL, &hostGuid, i, &dia);
+ if(success)
+ {
+ // build a DevInfo Data structure
+ memset(&da, 0, sizeof(SP_DEVINFO_DATA));
+ da.cbSize = sizeof(SP_DEVINFO_DATA);
+ // build a Device Interface Detail Data structure
+ memset(didd, 0, USB_BUFFER_SIZE + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA));
+ didd->cbSize = 4 + sizeof(TCHAR);
+
+ // now we can get some more detailed information
+ nRequiredSize = 0;
+ if(SetupDiGetDeviceInterfaceDetail(h, &dia, didd, N_BYTES, &nRequiredSize, &da))
+ {
+ strncpy(host->ControllerDevicePath, didd->DevicePath, USB_BUFFER_SIZE);
+
+ // get the Device Description and DriverKeyName
+ requiredSize = 0;
+ regType = REG_SZ;
+
+ if(SetupDiGetDeviceRegistryProperty(
+ h, &da, SPDRP_DEVICEDESC, ®Type, (PBYTE)ptrBuf, USB_BUFFER_SIZE, &requiredSize))
+ strncpy(host->ControllerDeviceDesc, ptrBuf, USB_BUFFER_SIZE);
+ if(SetupDiGetDeviceRegistryProperty(
+ h, &da, SPDRP_DRIVER, ®Type, (PBYTE)ptrBuf, USB_BUFFER_SIZE, &requiredSize))
+ strncpy(host->ControllerDriverKeyName, ptrBuf, USB_BUFFER_SIZE);
+ }
+
+ (*length)++;
+ }
+
+ i++;
+ } while(success);
+
+ SetupDiDestroyDeviceInfoList(h);
+
+ return hostlist;
+}
+
+DWORD GetDeviceNumberWithHandle(HANDLE handle)
+{
+ STORAGE_DEVICE_NUMBER sdn;
+ DWORD ans = -1;
+ DWORD k = 0;
+
+ if(DeviceIoControl(handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(STORAGE_DEVICE_NUMBER), &k, NULL))
+ { ans = (sdn.DeviceType << 8) + sdn.DeviceNumber; }
+
+ return ans;
+}
+
+DWORD GetDeviceNumber(char* devicePath)
+{
+ DWORD len = strlen(devicePath);
+ HANDLE h;
+ DWORD ans = -1;
+
+ if(devicePath[len - 1] == '\\') devicePath[len - 1] = 0;
+
+ h = CreateFile(devicePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if(h != INVALID_HANDLE_VALUE)
+ {
+ ans = GetDeviceNumberWithHandle(h);
+ CloseHandle(h);
+ }
+
+ return ans;
+}
+
+UsbHub_t* GetRootHub(UsbController_t* controller)
+{
+ HANDLE h, h2;
+ UsbHub_t* root;
+ PUSB_ROOT_HUB_NAME hubName;
+ DWORD nBytes;
+ DWORD k = 0;
+ USB_NODE_INFORMATION nodeInfo;
+
+ root = malloc(sizeof(UsbHub_t));
+ hubName = malloc(sizeof(USB_ROOT_HUB_NAME) + USB_BUFFER_SIZE - 1);
+
+ if(!root) return NULL;
+
+ root->HubIsRootHub = TRUE;
+ strncpy(root->HubDeviceDesc, "Root Hub", 8);
+
+ // Open a handle to the Host Controller
+ h = CreateFile(controller->ControllerDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if(h == INVALID_HANDLE_VALUE) return root;
+
+ memset(&hubName, 0, sizeof(USB_ROOT_HUB_NAME) + USB_BUFFER_SIZE - 1);
+ nBytes = sizeof(USB_ROOT_HUB_NAME) + USB_BUFFER_SIZE - 1;
+
+ // get the Hub Name
+ if(DeviceIoControl(h, IOCTL_USB_GET_ROOT_HUB_NAME, &hubName, nBytes, &hubName, nBytes, &k, NULL))
+ { snprintf(root->HubDevicePath, USB_BUFFER_SIZE, "\\\\.\\%ws", hubName->RootHubName); }
+
+ // TODO: Get DriverKeyName for Root Hub
+
+ // Now let's open the Hub (based upon the HubName we got above)
+ h2 = CreateFile(root->HubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ if(h2 != INVALID_HANDLE_VALUE)
+ {
+ memset(&nodeInfo, 0, sizeof(USB_NODE_INFORMATION));
+ nodeInfo.NodeType = UsbHub;
+
+ nBytes = sizeof(USB_NODE_INFORMATION);
+
+ // get the Hub Information
+ if(DeviceIoControl(h2, IOCTL_USB_GET_NODE_INFORMATION, &nodeInfo, nBytes, &nodeInfo, nBytes, &k, NULL))
+ {
+ root->HubIsBusPowered = nodeInfo.u.HubInformation.HubIsBusPowered;
+ root->HubPortCount = nodeInfo.u.HubInformation.HubDescriptor.bNumberOfPorts;
+ }
+
+ CloseHandle(h2);
+ }
+
+ free(hubName);
+ CloseHandle(h);
+ return root;
+}
+
+UsbPort_t* GetHubPorts(UsbHub_t* hub, DWORD* length)
+{
+ UsbPort_t* portList;
+ UsbPort_t* port;
+ HANDLE h;
+ USB_NODE_CONNECTION_INFORMATION_EX nodeConnection;
+ DWORD nBytes;
+ DWORD k = 0;
+ DWORD i;
+
+ *length = 0;
+
+ if(hub == NULL) return NULL;
+
+ h = CreateFile(hub->HubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if(h == INVALID_HANDLE_VALUE) return NULL;
+
+ portList = malloc(sizeof(UsbPort_t) * hub->HubPortCount);
+
+ if(!portList) return NULL;
+
+ for(i = 1; i <= hub->HubPortCount; i++)
+ {
+ nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION_EX);
+ memset(&nodeConnection, 0, nBytes);
+ nodeConnection.ConnectionIndex = i;
+ k = 0;
+
+ if(!DeviceIoControl(h,
+ IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
+ &nodeConnection,
+ nBytes,
+ &nodeConnection,
+ nBytes,
+ &k,
+ NULL))
+ continue;
+
+ // load up the USBPort class
+ port = &portList[*length];
+
+ port->PortPortNumber = i;
+ strncpy(port->PortHubDevicePath, hub->HubDevicePath, USB_BUFFER_SIZE);
+ port->PortStatus = nodeConnection.ConnectionStatus;
+ port->PortSpeed = nodeConnection.Speed;
+ port->PortIsDeviceConnected = nodeConnection.ConnectionStatus == DeviceConnected;
+ port->PortIsHub = nodeConnection.DeviceIsHub;
+ memcpy(&port->PortDeviceDescriptor, &nodeConnection.DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
+
+ // add it to the list
+ (*length)++;
+ }
+
+ CloseHandle(h);
+ return portList;
+}
+
+UsbDevice_t* GetPortDevice(UsbPort_t* port)
+{
+ UsbDevice_t* device;
+ HANDLE h;
+ DWORD nBytesReturned;
+ DWORD nBytes = USB_BUFFER_SIZE + sizeof(USB_DESCRIPTOR_REQUEST) + sizeof(USB_STRING_DESCRIPTOR);
+ PUSB_DESCRIPTOR_REQUEST request;
+ PUSB_STRING_DESCRIPTOR descriptor;
+ DWORD k;
+
+ if(port == NULL || port->PortIsDeviceConnected) return NULL;
+
+ device = malloc(sizeof(UsbDevice_t));
+ request = malloc(nBytes);
+
+ if(!device) return NULL;
+
+ memset(device, 0, sizeof(UsbDevice_t));
+
+ // Copy over some values from the Port class
+ device->PortNumber = port->PortPortNumber;
+ strncpy(device->HubDevicePath, port->PortHubDevicePath, USB_BUFFER_SIZE);
+ memcpy(&device->DeviceDescriptor, &port->PortDeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
+
+ // Open a handle to the Hub device
+ h = CreateFile(port->PortHubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ if(h == INVALID_HANDLE_VALUE) return device;
+
+ // The iManufacturer, iProduct and iSerialNumber entries in the
+ // Device Descriptor are really just indexes. So, we have to
+ // request a String Descriptor to get the values for those strings.
+ if(port->PortDeviceDescriptor.iManufacturer > 0)
+ {
+ memset(request, 0, nBytes);
+
+ request->ConnectionIndex = port->PortPortNumber;
+ request->SetupPacket.wIndex = 0x409;
+ request->SetupPacket.wValue = ((USB_STRING_DESCRIPTOR_TYPE << 8) + port->PortDeviceDescriptor.iManufacturer);
+ request->SetupPacket.wLength = nBytes - sizeof(USB_DESCRIPTOR_REQUEST);
+
+ // Use an IOCTL call to request the String Descriptor
+ if(DeviceIoControl(
+ h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, request, nBytes, request, nBytes, &k, NULL))
+ {
+ // The location of the string descriptor is immediately after
+ // the Request structure. Because this location is not "covered"
+ // by the structure allocation, we're forced to zero out this
+ // chunk of memory by using the StringToHGlobalAuto() hack above
+ descriptor = (PUSB_STRING_DESCRIPTOR)(request + sizeof(USB_DESCRIPTOR_REQUEST));
+ snprintf(device->Manufacturer, USB_BUFFER_SIZE, "%ws", descriptor->bString);
+ }
+ }
+ if(port->PortDeviceDescriptor.iProduct > 0)
+ {
+ memset(request, 0, nBytes);
+
+ request->ConnectionIndex = port->PortPortNumber;
+ request->SetupPacket.wIndex = 0x409;
+ request->SetupPacket.wValue = ((USB_STRING_DESCRIPTOR_TYPE << 8) + port->PortDeviceDescriptor.iProduct);
+ request->SetupPacket.wLength = nBytes - sizeof(USB_DESCRIPTOR_REQUEST);
+
+ // Use an IOCTL call to request the String Descriptor
+ if(DeviceIoControl(
+ h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, request, nBytes, request, nBytes, &k, NULL))
+ {
+ // The location of the string descriptor is immediately after
+ // the Request structure. Because this location is not "covered"
+ // by the structure allocation, we're forced to zero out this
+ // chunk of memory by using the StringToHGlobalAuto() hack above
+ descriptor = (PUSB_STRING_DESCRIPTOR)(request + sizeof(USB_DESCRIPTOR_REQUEST));
+ snprintf(device->Product, USB_BUFFER_SIZE, "%ws", descriptor->bString);
+ }
+ }
+ if(port->PortDeviceDescriptor.iSerialNumber > 0)
+ {
+ memset(request, 0, nBytes);
+
+ request->ConnectionIndex = port->PortPortNumber;
+ request->SetupPacket.wIndex = 0x409;
+ request->SetupPacket.wValue = ((USB_STRING_DESCRIPTOR_TYPE << 8) + port->PortDeviceDescriptor.iSerialNumber);
+ request->SetupPacket.wLength = nBytes - sizeof(USB_DESCRIPTOR_REQUEST);
+
+ // Use an IOCTL call to request the String Descriptor
+ if(DeviceIoControl(
+ h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, request, nBytes, request, nBytes, &k, NULL))
+ {
+ // The location of the string descriptor is immediately after
+ // the Request structure. Because this location is not "covered"
+ // by the structure allocation, we're forced to zero out this
+ // chunk of memory by using the StringToHGlobalAuto() hack above
+ descriptor = (PUSB_STRING_DESCRIPTOR)(request + sizeof(USB_DESCRIPTOR_REQUEST));
+ snprintf(device->SerialNumber, USB_BUFFER_SIZE, "%ws", descriptor->bString);
+ }
+ }
+
+ // build a request for configuration descriptor
+ memset(request, 0, nBytes);
+
+ request->ConnectionIndex = port->PortPortNumber;
+ request->SetupPacket.wIndex = 0;
+ request->SetupPacket.wValue = ((USB_STRING_DESCRIPTOR_TYPE << 8));
+ request->SetupPacket.wLength = nBytes - sizeof(USB_DESCRIPTOR_REQUEST);
+
+ // Use an IOCTL call to request the String Descriptor
+ if(DeviceIoControl(
+ h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, request, nBytes, request, nBytes, &nBytesReturned, NULL))
+ {
+ if(nBytesReturned > USB_BUFFER_SIZE) nBytesReturned = USB_BUFFER_SIZE;
+
+ memcpy(&device->BinaryDeviceDescriptors, request + sizeof(USB_DESCRIPTOR_REQUEST), nBytesReturned);
+ device->BinaryDeviceDescriptorsLength = nBytesReturned;
+ }
+
+ free(request);
+ CloseHandle(h);
+ return device;
+}
+
+UsbHub_t* GetPortHub(UsbPort_t* port)
+{
+ UsbHub_t* hub;
+ HANDLE h, h2;
+ PUSB_NODE_CONNECTION_NAME nodeName;
+ DWORD nBytes;
+ DWORD k = 0;
+ USB_NODE_INFORMATION nodeInfo;
+ UsbDevice_t* device;
+
+ nodeName = malloc(sizeof(USB_NODE_CONNECTION_NAME) + USB_BUFFER_SIZE - 1);
+
+ if(port == NULL || port->PortIsHub || nodeName == NULL) return NULL;
+
+ hub = malloc(sizeof(UsbHub_t));
+
+ if(!hub) return NULL;
+
+ hub->HubIsRootHub = FALSE;
+ strncpy(hub->HubDeviceDesc, "External Hub", 12);
+
+ // Open a handle to the Host Controller
+ h = CreateFile(port->PortHubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ if(h == INVALID_HANDLE_VALUE)
+ {
+ free(nodeName);
+ return hub;
+ }
+
+ // Get the DevicePath for downstream hub
+ nBytes = sizeof(USB_NODE_CONNECTION_NAME) + USB_BUFFER_SIZE - 1;
+ memset(nodeName, 0, nBytes);
+ nodeName->ConnectionIndex = port->PortPortNumber;
+ k = 0;
+
+ // Use an IOCTL call to request the Node Name
+ if(DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_NAME, nodeName, nBytes, nodeName, nBytes, &k, NULL))
+ { snprintf(hub->HubDevicePath, USB_BUFFER_SIZE, "\\\\.\\%ws", nodeName->NodeName); }
+
+ // Now let's open the Hub (based upon the HubName we got above)
+ h2 = CreateFile(hub->HubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if(h2 != INVALID_HANDLE_VALUE)
+ {
+ memset(&nodeInfo, 0, sizeof(USB_NODE_INFORMATION));
+ nodeInfo.NodeType = UsbHub;
+ nBytes = sizeof(USB_NODE_INFORMATION);
+ k = 0;
+
+ // get the Hub Information
+ if(DeviceIoControl(h2, IOCTL_USB_GET_NODE_INFORMATION, &nodeInfo, nBytes, &nodeInfo, nBytes, &k, NULL))
+ {
+ hub->HubIsBusPowered = nodeInfo.u.HubInformation.HubIsBusPowered;
+ hub->HubPortCount = nodeInfo.u.HubInformation.HubDescriptor.bNumberOfPorts;
+ }
+
+ CloseHandle(h2);
+ }
+
+ // Fill in the missing Manufacture, Product, and SerialNumber values
+ // values by just creating a Device instance and copying the values
+ device = GetPortDevice(port);
+ if(device != NULL)
+ {
+ strncpy(hub->InstanceId, device->InstanceId, USB_BUFFER_SIZE);
+ strncpy(hub->Manufacturer, device->Manufacturer, USB_BUFFER_SIZE);
+ strncpy(hub->Product, device->Product, USB_BUFFER_SIZE);
+ strncpy(hub->SerialNumber, device->SerialNumber, USB_BUFFER_SIZE);
+ strncpy(hub->DriverKey, device->DriverKey, USB_BUFFER_SIZE);
+ free(device);
+ }
+
+ CloseHandle(h);
+ return hub;
+}
+
+static void SearchHubInstanceId(UsbHub_t* hub, UsbDevice_t** foundDevice, const char* instanceId)
+{
+ UsbPort_t* portList;
+ DWORD portCount = 0;
+ DWORD i;
+ UsbDevice_t* device;
+ UsbHub_t* childHub;
+ *foundDevice = NULL;
+
+ if(hub == NULL) return;
+
+ portList = GetHubPorts(hub, &portCount);
+
+ if(portList == NULL || portCount == 0) return;
+
+ for(i = 0; i < portCount; i++)
+ {
+ if(portList[i].PortIsHub)
+ {
+ childHub = GetPortHub(&portList[i]);
+
+ if(childHub == NULL) continue;
+
+ SearchHubInstanceId(childHub, foundDevice, instanceId);
+
+ free(childHub);
+ }
+ else
+ {
+ if(!portList[i].PortIsDeviceConnected) continue;
+
+ device = GetPortDevice(&portList[i]);
+ if(device == NULL || strncmp(device->InstanceId, instanceId, USB_BUFFER_SIZE) != 0) continue;
+
+ *foundDevice = device;
+ break;
+ }
+ }
+
+ free(portList);
+}
+
+UsbDevice_t* FindDeviceByInstanceId(const char* instanceId)
+{
+ UsbController_t* controllers;
+ DWORD controllers_len = 0;
+ DWORD i;
+ UsbDevice_t* foundDevice = NULL;
+
+ controllers = GetHostControllers(&controllers_len);
+
+ if(controllers == NULL || controllers_len == 0) return NULL;
+
+ for(i = 0; i < controllers_len; i++)
+ {
+ SearchHubInstanceId(GetRootHub(&controllers[i]), &foundDevice, instanceId);
+ if(foundDevice != NULL) break;
+ }
+
+ return foundDevice;
+}
+
+UsbDevice_t* FindDeviceNumber(DWORD devNum, GUID diskGuid)
+{
+ HDEVINFO h;
+ BOOL success;
+ DWORD i = 0;
+ SP_DEVICE_INTERFACE_DATA dia;
+ SP_DEVINFO_DATA da;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA didd;
+ DWORD nRequiredSize = 0;
+ DWORD N_BYTES = USB_BUFFER_SIZE;
+ DEVINST ptrPrevious;
+ PSTR instanceId = malloc(N_BYTES);
+ UsbDevice_t* foundDevice = NULL; // TODO: Determine type
+
+ didd = malloc(USB_BUFFER_SIZE + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA));
+ if(instanceId) return NULL;
+
+ memset(instanceId, 0, N_BYTES);
+
+ // We start at the "root" of the device tree and look for all
+ // devices that match the interface GUID of a disk
+ h = SetupDiGetClassDevs(&diskGuid, 0, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+
+ if(h != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ // create a Device Interface Data structure
+ memset(&dia, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
+ dia.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ // start the enumeration
+ success = SetupDiEnumDeviceInterfaces(h, NULL, &diskGuid, i, &dia);
+ if(success)
+ {
+ // build a DevInfo Data structure
+ memset(&da, 0, sizeof(SP_DEVINFO_DATA));
+ da.cbSize = sizeof(SP_DEVINFO_DATA);
+
+ // build a Device Interface Detail Data structure
+ memset(didd, 0, USB_BUFFER_SIZE + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA));
+ didd->cbSize = 4 + sizeof(TCHAR);
+
+ // now we can get some more detailed information
+ nRequiredSize = 0;
+
+ if(SetupDiGetDeviceInterfaceDetail(h, &dia, didd, N_BYTES, &nRequiredSize, &da))
+ if(GetDeviceNumber(didd->DevicePath) == devNum)
+ {
+ // current InstanceID is at the "USBSTOR" level, so we
+ // need up "move up" one level to get to the "USB" level
+ CM_Get_Parent(&ptrPrevious, da.DevInst, 0);
+
+ // Now we get the InstanceID of the USB level device
+ memset(instanceId, 0, N_BYTES);
+ CM_Get_Device_ID(ptrPrevious, instanceId, N_BYTES, 0);
+ }
+ }
+
+ i++;
+ } while(success);
+
+ SetupDiDestroyClassImageList(h);
+ }
+
+ // Did we find an InterfaceID of a USB device?
+ if(strlen(instanceId) > 0 && strncmp(instanceId, "USB\\", 3) == 0) foundDevice = FindDeviceByInstanceId(instanceId);
+
+ free(didd);
+ return foundDevice;
+}
+
+UsbDevice_t* FindDrivePath(Win32DeviceContext* ctx, GUID deviceGuid)
+{
+ // We start by getting the unique DeviceNumber of the given
+ // DriveLetter. We'll use this later to find a matching
+ // DevicePath "symbolic name"
+ DWORD devNum = GetDeviceNumber(ctx->handle);
+ return devNum < 0 ? NULL : FindDeviceNumber(devNum, deviceGuid);
+}
uint8_t Win32GetUsbData(void* device_ctx,
uint16_t* desc_len,
@@ -28,10 +607,33 @@ uint8_t Win32GetUsbData(void* device_ctx,
char* product,
char* serial)
{
- Win32DeviceContext* ctx = device_ctx;
+ Win32DeviceContext* ctx = device_ctx;
+ UsbDevice_t* device = NULL;
+ GUID floppyGuid = GUID_DEVINTERFACE_FLOPPY;
+ GUID tapeGuid = GUID_DEVINTERFACE_TAPE;
+ GUID diskGuid = GUID_DEVINTERFACE_DISK;
+ GUID cdromGuid = GUID_DEVINTERFACE_CDROM;
+ GUID guids[4] = {floppyGuid, cdromGuid, diskGuid, tapeGuid};
+ int i;
if(!ctx) return -1;
- // TODO: Implement
- return -1;
-}
+ for(i = 0; i < 4; i++)
+ {
+ device = FindDrivePath(ctx, guids[i]);
+
+ if(device != NULL) break;
+ }
+
+ if(device == NULL) return 0;
+
+ memcpy(descriptors, device->BinaryDeviceDescriptors, device->BinaryDeviceDescriptorsLength);
+ *desc_len = device->BinaryDeviceDescriptorsLength;
+ *id_vendor = device->DeviceDescriptor.idVendor;
+ *id_product = device->DeviceDescriptor.idProduct;
+ strncpy(manufacturer, device->Manufacturer, 256);
+ strncpy(product, device->Product, 256);
+ strncpy(serial, device->SerialNumber, 256);
+
+ return 1;
+}
\ No newline at end of file
diff --git a/win32/usb.h b/win32/usb.h
new file mode 100644
index 0000000..000bd92
--- /dev/null
+++ b/win32/usb.h
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the DiscImageChef Remote Server.
+ * Copyright (c) 2019 Natalia Portillo.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define USB_BUFFER_SIZE 2048
+
+#include
+#include
+#include
+
+#ifndef GUID_DEVINTERFACE_USB_HOST_CONTROLLER
+#define GUID_DEVINTERFACE_USB_HOST_CONTROLLER \
+ { \
+ 0x3abf6f2d, 0x71c4, 0x462a, { 0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27 } \
+ }
+#endif
+
+typedef struct
+{
+ DWORD ControllerIndex;
+ CHAR ControllerDevicePath[USB_BUFFER_SIZE];
+ CHAR ControllerDeviceDesc[USB_BUFFER_SIZE];
+ CHAR ControllerDriverKeyName[USB_BUFFER_SIZE];
+} UsbController_t;
+
+typedef struct
+{
+ CHAR InstanceId[USB_BUFFER_SIZE];
+ CHAR Manufacturer[USB_BUFFER_SIZE];
+ CHAR Product[USB_BUFFER_SIZE];
+ CHAR SerialNumber[USB_BUFFER_SIZE];
+ CHAR DriverKey[USB_BUFFER_SIZE];
+ DWORD PortNumber;
+ USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+ CHAR HubDevicePath[USB_BUFFER_SIZE];
+ CHAR BinaryDeviceDescriptors[USB_BUFFER_SIZE];
+ DWORD BinaryDeviceDescriptorsLength;
+} UsbDevice_t;
+
+typedef struct
+{
+ BOOL HubIsRootHub;
+ CHAR HubDeviceDesc[USB_BUFFER_SIZE];
+ CHAR HubDevicePath[USB_BUFFER_SIZE];
+ BOOL HubIsBusPowered;
+ UCHAR HubPortCount;
+ CHAR InstanceId[USB_BUFFER_SIZE];
+ CHAR Manufacturer[USB_BUFFER_SIZE];
+ CHAR Product[USB_BUFFER_SIZE];
+ CHAR SerialNumber[USB_BUFFER_SIZE];
+ CHAR DriverKey[USB_BUFFER_SIZE];
+} UsbHub_t;
+
+typedef struct
+{
+ DWORD PortPortNumber;
+ CHAR PortHubDevicePath[USB_BUFFER_SIZE];
+ DWORD PortStatus;
+ UCHAR PortSpeed;
+ BOOL PortIsDeviceConnected;
+ BOOL PortIsHub;
+ USB_DEVICE_DESCRIPTOR PortDeviceDescriptor;
+} UsbPort_t;
\ No newline at end of file