Enumerating USB Devices - Obtaining All Availble Information

I’ve spent some time working with USB communications and I seem to be stuck. What I wish to do is have a block of code I can use to communicate with USB devices which works on XP, Vista and Win-7.

Currently I can enumerate all the USB devices attached to my machine and obtain the configuration descriptor , interface descriptor and endpoint descriptors. But the device descriptor escapes me? As many others I am relatively new to driver development and so I’m on the learning curve . I’ve downloaded the DDK and built up a few drivers, installed a few, played around with understanding the relavant registry entries. Read through every thing USB I could find on the web and in the last 2 months of this forum.

But I digress what I want to know for now is how to get a hold of the device descriptor without throwing out what I currently have working for a drastically different way of working with the USB. (I will get there eventually but I just want to put a close on my current enumeration test code before I move on to a straight forward WinUSB implementation of communication with my companies devices)

So currently I

// Get a handle for the Plug and Play node and request currently active USB devices
// Get a handle to the device information set by passing the device interface GUID
// that you defined in the INF
// In this case we are using the generic WinUSB GUID
// The function returns an HDEVINFO handle

PnPHandle := SetupDiGetClassDevs(@GUID, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);

AND THEN LOOP THROUGH INCREMENTING THE DEVICE NUMBER TILL IT NO LONGER WORKS

// Call SetupDiEnumDeviceInterfaces to enumerate the system?s device interfaces
// and obtain information on your device interface
// Pass the HDEVINFO handle from above, the device interface GUID, and a reference to
// the initialized SP_DEVICE_INTERFACE_DATA structure

Success := SetupDiEnumDeviceInterfaces(PnPHandle, nil, Guid, DeviceNumber, DeviceInterfaceData);

I GET THE SIZE OF THE BUFFER WHICH IS NEEDED

// Call SetupDiGetDeviceInterfaceDetail to get detailed data for the device interface.
// The information is returned in a SP_DEVICE_INTERFACE_DETAIL_DATA structure
// Because the size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure varies, you
// must first obtain the correct buffer size by calling SetupDiGetDeviceInterfaceDetail with
// the DeviceInterfaceDetailData parameter set to NULL
// The function returns the correct buffer size in the requiredlength parameter. Use that
// value to correctly allocate memory for a SP_DEVICE_INTERFACE_DETAIL_DATA
// structure

SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, nil, 0, BytesReturned, @DevData);

THEN I BUILD UP A LIST OF DEVICE PATHS

// Call SetupDiGetDeviceInterfaceDetail again and pass it a reference to the initialized
// structure. When the function returns, the structure contains detailed information about
// the interface

if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData,
FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData) then
begin
// The device path is in the SP_DEVICE_INTERFACE_DETAIL_DATA structure?s
// DevicePath member
ListOfUSBDevices.Add(PChar(@FunctionClassDeviceData.DevicePath));

SO AT THIS POINT I HAVE A LIST OF DEVICE PATHS LIKE:

‘\?\usb#vid_0930&pid_6545#001d92a85eaab911e3360016#{a5dcbf10-6530-11d2-901f-00c04fb951ed}’

// Get a handle to the USB device
handle := CreateFile(PChar(DeviceName),GENERIC_WRITE or GENERIC_READ,FILE_SHARE_WRITE or FILE_SHARE_READ, nil,OPEN_EXISTING,0,0);
// Safety First
if (handle = INVALID_HANDLE_VALUE) then exit;

// Figure out the magic number the device driver will respond to
FunctionNumber := CTL_CODE($22, 0, 0, 0);

// Query the Driver passing in the handle and function (Magic Number)
if Windows.DeviceIoControl(handle, FunctionNumber, @InBuffer, InSize, @InBuffer,OutSize, BytesReturned, nil) = true then
begin

then
this gives me my devices and I have obtained all the configuration, interface and endpoint information (not all shown here for brevity)

USB Devices Found = 5

1 Vendor(04D8) = Microchip, PID Product(000A) = Pic 18F AVB Box
HID


2 Vendor(0930) = Toshiba Product(6545) = 8G Memory Stick

Failure The request is not supported


3 Vendor(1448) = BioSystems Product(8278) = MultiPro

USB_CONFIGURATION_DESCRIPTOR
Descriptor Length = 9
Descriptor Type = 2
Total Length = 46
Interfaces = 1
ConfigID = 1
Description Index = 0
Attributes = 128
Max Power = 112


4 Vendor(413C) = Dell Computer Corp Product(2003) = Keyboard
HID


5 Vendor(413C) = Dell Computer Corp Product(3012) = Mouse
HID


so is it the case that I only need to figure out a new magic number to get the device descriptor

// This one came from the // IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR;
// and appears to work the same for the winusb driver

// FunctionNumber := 2228224;

or do I need to pass in some info to

Windows.DeviceIoControl

to get it to respond with the device descriptor

You wrote:

I’ve spent some time working with USB communications and I seem to be
stuck. What I wish to do is have a block of code I can use to
communicate with USB devices which works on XP, Vista and Win-7.

There is no generic way to do this. USB devices belong to different device classes (HID, Mass Storage, Video, Audio, Printer, etc.), and their device objects all respond to completely different sets of I/O requests.

Currently I can enumerate all the USB devices attached to my machine and
obtain the configuration descriptor , interface descriptor and endpoint
descriptors.

… all of which are part of the configuration descriptor…

But the device descriptor escapes me?

The programs that do this kind of thing, like “usbview”, do not talk to the device’s driver directly, because the driver speaks whatever language is required by the device class to which they belong. Instead, they talk to the hub driver BELOW the USB device, making semi-documented requests to read the descriptors.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

why not refer to USBView code ,enclosed in DDK ?

Thanks,
Tim and XieDong for your response.

I had thought I might be able to avoid throwing out my approach and not
having to cycle through the hubs like in USB View but it appears that
this may not be possible. I will continue to explore the USB View code
and look closer at the code

// Query the Driver passing in the handle and function (Magic Number)
if Windows.DeviceIoControl(handle, FunctionNumber, @InBuffer, InSize, @InBuffer,OutSize, BytesReturned, nil) = true then

Thanks again for your help

Just A few more points to throw out there

is it likely that at this point I am talking to the HUB low level driver
or the WinUSB driver ?

is thier any way to query the driver and find out what functions are
supported ?

The mechanism you’re using is fundamentally unsound. Give it up, and do it right – the way USBView does.

The best and most authoritative reply on this topic came a couple of years back from Glen Slick, one of the USB devs at Microsoft (and a very helpful guy to the community here on this list):

Sorry… but that’s the right answer.

Peter
OSR

xxxxx@osr.com wrote:

Give it up, and do it right – the way USBView does.

Thanks Peter

All roads lead to Rome I guess.

I think this is indefinitely the way I’m heading

replacing our older BulkUSb based USB communications with a simpler

WinUSB based communications. Hopefully allowing us to provide both a 32
bit (Which we have) and 64bit supported (Which we need)

communication with our devices for XP, Vista and Windows7.

> -----Original Message-----

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@osr.com
Sent: Tuesday, March 09, 2010 3:50 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Enumerating USB Devices - Obtaining All
Availble Information

It was already removed and it is Good Thing. WDK 7600.16385 contains
only WDF USB drivers.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

Frank Bishop wrote:

is it likely that at this point I am talking to the HUB low level
driver or the WinUSB driver ?

You are talking to the function driver for the device. It might be
WinUSB, if the device happens to use WinUSB for its driver. It’s not
the hub.

is thier any way to query the driver and find out what functions are
supported ?

No. Indeed, it’s quite possible that the driver file cannot be opened
at all from user mode.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.