USB FLASH device enumeration question

I am attempting to use the SetupDiGetDeviceInterfaceDetail and IOCTL_USB
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX to walk the USB devices in a
system. Using the technique in USBView the USB controllers and hubs are
each enumerated. Information on each port of each hub with a connected
device gives the descriptors of that device.

I need to identify certain USB Flash drives based on their USB descriptors.
I will need to open the identified drives for read and write. I don’t see a
way to get a handle to the disk device (or a disk number or a drive letter)
from the enumeration of USB devices.

I can enumerate all disk drives but I don’t see how to match a particular
disk drive with a particular USB device.

How can I open specific flash devices?

Ed

>I can enumerate all disk drives but I don’t see how to match a particular disk drive with a particular

USB device.

  1. obtain the SetupDi handle of the disk devnode - Disk.sys FDO, UsbStor PDO.
  2. use CM_Get_Parent to obtain the CM/SetupDi handle of its parent - UsbStor FDO, UsbHub PDO.
  3. Use USB IOCTLs on the latter one.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Hi Max,

I do not see how this gets me closer to my solution. I missing how to use
the SetupDI… function and the USB IOCTLs to get a handle, unit number of
disk letter for the Flash Drives by issuing USB IOCTLS and SetupDI calls on
the ports of a hub device object.

I am already issuing the USB IOCTLs on the USB Hub. I get it by walking
through each USB host adapter and hub attached to the root and non-root
hubs. I call USB_NODE_CONNECTION_INFORMATION_EX (or
USB_NODE_CONNECTION_INFORMATION) on every port of each hub. I use the USB
Descriptors for the devices attached to downstream ports to find the USB
Flash drives, which are interesting.

IOCTL_USB_GET_NODE_CONNECTION_NAME returns the symbolic link name of the hub
attached to a downstream port. Is there an equivalent call or series of
calls to get the symbolic link name of non-Hub downstream devices (like my
flash drives)?

Ed

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Thursday, September 24, 2009 8:16 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] USB FLASH device enumeration question

I can enumerate all disk drives but I don’t see how to match a particular
disk drive with a particular
USB device.

  1. obtain the SetupDi handle of the disk devnode - Disk.sys FDO, UsbStor
    PDO.
  2. use CM_Get_Parent to obtain the CM/SetupDi handle of its parent - UsbStor
    FDO, UsbHub PDO.
  3. Use USB IOCTLs on the latter one.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> I do not see how this gets me closer to my solution. I missing how to use

the SetupDI… function and the USB IOCTLs to get a handle, unit number of

http://www.ureader.com/message/1018345.aspx


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

int _tmain(int argc, _TCHAR* argv)
{
int nRetCode = 0;

HANDLE Usbhandle;
HDEVINFO hDevHandle;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
DWORD required = 0;
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

int nBufferSize = 0;

SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

DWORD MemberIndex = 0;
BOOL Result;
// BAsed on the available Volume in the system it take the Handle. Check for multpule usb volume.
hDevHandle = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if(hDevHandle == INVALID_HANDLE_VALUE)
{
return 1;
}
else
{
BOOL bStart = false;
TCHAR *buffer = NULL;
PSP_DEVICE_INTERFACE_DETAIL_DATA devicedetailData;
buffer = (TCHAR*)malloc(sizeof(required));
do
{
Result = SetupDiEnumDeviceInfo(hDevHandle, MemberIndex, &devInfoData);

if(Result)
{
Result = SetupDiEnumDeviceInterfaces(hDevHandle, 0, &GUID_DEVINTERFACE_VOLUME,
MemberIndex, &deviceInterfaceData);
}

if(!Result)
{
SetupDiDestroyDeviceInfoList(hDevHandle);
/*delete buffer;*/ //here it is crashing why???
/*free(buffer);*/
buffer = NULL;
return 1;
}
MemberIndex++;

BOOL detailResult = FALSE;

if(!bStart)
{
// As per MSDN, Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a
// NULL DeviceInterfaceDetailData pointer, a DeviceInterfaceDetailDataSize of zero,
// and a valid RequiredSize variable. In response to such a call, this function returns
// the required buffer size at RequiredSize and fails with GetLastError returning
// ERROR_INSUFFICIENT_BUFFER.
// Allocate an appropriately sized buffer and call the function again to get the interface details.

SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, NULL, 0, &required, NULL);
devicedetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) buffer;
devicedetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
nBufferSize = required;
bStart = true;
}

detailResult = SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData,
devicedetailData, nBufferSize , &required, NULL);

_tprintf(L"Device Path = %s\n\n", devicedetailData->DevicePath);

if(detailResult)
{
Usbhandle = CreateFile(devicedetailData->DevicePath,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);

SendInquiry(Usbhandle);
}

if(!detailResult)
{
continue;
}
}while(Result);
}

return nRetCode;
}

Thank you for sending this but I see a few problems on the surface of this
code:

  1. The routine SendInquiry(UsbHandle) is undefined
  2. Memory for the pointer buffer is allocated with malloc(sizeof (required))
    required is a DWORD. buffer later cast to a
    PSP_DEVICE_INTERFACE_DETAIL_DATA structure. The size of
    SP_DEVICE_INTERFACE_ETAIL_DATA is not the same as the size of a DWORD.
  3. after allocating buffer (with the value of required set to 0) the value
    of buffer is set to the required buffersize and passed to
    SetupDiGetDriverInterfaceDetal as the size of buffer. There is no
    allocation for buffer after the size needed is known.

Ed

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, September 28, 2009 2:22 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] USB FLASH device enumeration question

int _tmain(int argc, _TCHAR* argv)
{
int nRetCode = 0;

HANDLE Usbhandle;
HDEVINFO hDevHandle;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
DWORD required = 0;
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

int nBufferSize = 0;

SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

DWORD MemberIndex = 0;
BOOL Result;
// BAsed on the available Volume in the system it take the
Handle. Check for multpule usb volume.
hDevHandle = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if(hDevHandle == INVALID_HANDLE_VALUE)
{
return 1;
}
else
{
BOOL bStart = false;
TCHAR *buffer = NULL;
PSP_DEVICE_INTERFACE_DETAIL_DATA devicedetailData;
buffer = (TCHAR*)malloc(sizeof(required));
do
{
Result = SetupDiEnumDeviceInfo(hDevHandle,
MemberIndex, &devInfoData);

if(Result)
{
Result =
SetupDiEnumDeviceInterfaces(hDevHandle, 0, &GUID_DEVINTERFACE_VOLUME,
MemberIndex, &deviceInterfaceData);
}

if(!Result)
{
SetupDiDestroyDeviceInfoList(hDevHandle);
/*delete buffer;*/ //here it is crashing why???
/*free(buffer);*/
buffer = NULL;
return 1;
}
MemberIndex++;

BOOL detailResult = FALSE;

if(!bStart)
{
// As per MSDN, Get the required buffer size. Call
SetupDiGetDeviceInterfaceDetail with a
// NULL DeviceInterfaceDetailData pointer, a
DeviceInterfaceDetailDataSize of zero,
// and a valid RequiredSize variable. In response to such a
call, this function returns
// the required buffer size at RequiredSize and fails with
GetLastError returning
// ERROR_INSUFFICIENT_BUFFER.
// Allocate an appropriately sized buffer and call the
function again to get the interface details.

SetupDiGetDeviceInterfaceDetail(hDevHandle,
&deviceInterfaceData, NULL, 0, &required, NULL);
devicedetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) buffer;
devicedetailData->cbSize =
sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
nBufferSize = required;
bStart = true;
}

detailResult = SetupDiGetDeviceInterfaceDetail(hDevHandle,
&deviceInterfaceData,
devicedetailData, nBufferSize , &required, NULL);

_tprintf(L"Device Path = %s\n\n", devicedetailData->DevicePath);

if(detailResult)
{
Usbhandle =
CreateFile(devicedetailData->DevicePath,

GENERIC_READ|GENERIC_WRITE,

FILE_SHARE_READ|FILE_SHARE_WRITE,

NULL, OPEN_EXISTING, 0, NULL);

SendInquiry(Usbhandle);
}

if(!detailResult)
{
continue;
}
}while(Result);
}

return nRetCode;
}


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Raj
void SendInquiry(HANDLE FileHandle)
{
typedef struct
{
SCSI_PASS_THROUGH Spt;
BYTE Sense[18];
BYTE Data[96];
} INFO;
INFO Info = {0};
DWORD ReturnLen;

Info.Spt.Length = sizeof(Info.Spt);
Info.Spt.SenseInfoLength = sizeof(Info.Sense);
Info.Spt.DataTransferLength = sizeof(Info.Data);
Info.Spt.SenseInfoOffset = offsetof(INFO, Sense);
Info.Spt.DataBufferOffset = offsetof(INFO, Data);
Info.Spt.TimeOutValue = 30;
Info.Spt.DataIn = SCSI_IOCTL_DATA_IN;
Info.Spt.CdbLength = 6;
Info.Spt.Cdb[0] = 0x12; // inquiry opcode
Info.Spt.Cdb[1] = 0x00;
Info.Spt.Cdb[2] = 0x00;
Info.Spt.Cdb[3] = 0x00;
Info.Spt.Cdb[4] = sizeof(Info.Data);
Info.Spt.Cdb[5] = 0x00;

if (DeviceIoControl(FileHandle, IOCTL_SCSI_PASS_THROUGH,
&Info, sizeof(Info), &Info, sizeof(Info),
&ReturnLen, FALSE))
{
char ch[1] ={0};
puts(“success”);
// get data buffer in to a char array
//ch[0] = (Info.Data[i]);
}
else
printf(“ioctl failed. Error=%u\n”, GetLastError());
}