mirror of
https://github.com/aaru-dps/aaruremote.git
synced 2025-12-16 19:24:37 +00:00
Implement GetUsbData for win32.
This commit is contained in:
610
win32/usb.c
610
win32/usb.c
@@ -15,9 +15,588 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "usb.h"
|
||||
|
||||
#include "win32.h"
|
||||
|
||||
#include <SetupAPI.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <ntddstor.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <usbioctl.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user