Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

WinUSB - iterating devices to get serial numbers.

1,005 views
Skip to first unread message

Jake

unread,
Dec 7, 2009, 7:35:01 PM12/7/09
to
Scene: Multiple devices with the same GUID attached to a machine. They
report serial numbers and that is a known-working configuration. As I
understand it, the proper way to iterate serial numbers is basically:

1. SetupDiGetClassDevs with the GUID then iterate:
1.a. getDevicePath(n++)
1.b. hDev = CreateFile()
1.c. hUsb = WinUsb_Initialize(hDev)
1.d. WinUsb_GetDescriptor(hUsb)

This works fine. However, a problem occurs when one of these devices is
then opened (or shall I say, left open because the calls above actually
"open" the device). The NEXT time the above block is called, the device that
is open cannot be opened again.

The call in 1. Lists all the devices.
The call in 1.a. also succeeds.
The call in 1.b. fails. It returns an INVALID_HANDLE_VALUE and the last
error is ERROR_ACCESS_DENIED.

The CreateFile was called with GENERIC_WRITE|GENERIC_READ and
FILE_SHARE_WRITE|FILE_SHARE_READ.

Is there an alternate way to iterate serial numbers of attached devices that
does not require them to be opened? Or is there an alternate way to open the
device which does not prevent access to iterate them.

Tim Roberts

unread,
Dec 8, 2009, 12:32:36 AM12/8/09
to
Jake <Ja...@discussions.microsoft.com> wrote:
>
>Scene: Multiple devices with the same GUID attached to a machine. They
>report serial numbers and that is a known-working configuration. As I
>understand it, the proper way to iterate serial numbers is basically:
>
>1. SetupDiGetClassDevs with the GUID then iterate:
>1.a. getDevicePath(n++)
>1.b. hDev = CreateFile()
>1.c. hUsb = WinUsb_Initialize(hDev)
>1.d. WinUsb_GetDescriptor(hUsb)
>...

>Is there an alternate way to iterate serial numbers of attached devices that
>does not require them to be opened? Or is there an alternate way to open the
>device which does not prevent access to iterate them.

For devices with serial numbers, the device path you get in 1.a will
persist -- it will be the same after a reboot. I suggest that you cache
the mappings when you are able to. So:

getDevicePath(n++)
If device path exists in a registry key that you manage:
Read serial number from registry
Else
CreateFile / WinUsb_Initialize / WinUsb_GetDescriptor
Save serial number in registry

It is possible to extract the serial number from the device path, but
that's undocumented, so you'll go to hell for doing it.

What are you doing with the serial numbers? It's not usually used to
identify specific instances.
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Jake

unread,
Dec 9, 2009, 11:22:02 PM12/9/09
to
> For devices with serial numbers, the device path you get in 1.a will
> persist -- it will be the same after a reboot. I suggest that you cache
> the mappings when you are able to. So:
>
> getDevicePath(n++)
> If device path exists in a registry key that you manage:
> Read serial number from registry
> Else
> CreateFile / WinUsb_Initialize / WinUsb_GetDescriptor
> Save serial number in registry

Tim--

Thanks for the response. I'm trying to actually iterate through *connected*
devices, so storing them in registry keys isn't exactly what I'm looking for.
In particular, this action is done in an API and not within the application,
so it would be awkward to work through a registry situation.

> It is possible to extract the serial number from the device path, but
> that's undocumented, so you'll go to hell for doing it.

Hm. That's unfortunate, because I think that's exactly what I'd like to do.
Is there an API that allows the (proper / blessed) extraction of the serial
number from the path?

> What are you doing with the serial numbers? It's not usually used to
> identify specific instances.

I am using it to identify specific instances. I'm curious why you say it is
not usually used to do so -- what other method would be used? Identifiers
may be stored on the device itself -- those are set by the user. But I have
the same problem. In fact, it gets a little more hairy this way because the
serial number retrieval is more "primal" in USB land and doesn't require
certain communication with the device.

Jake

Tim Roberts

unread,
Dec 10, 2009, 12:53:09 AM12/10/09
to
Jake <Ja...@discussions.microsoft.com> wrote:
>
>Thanks for the response. I'm trying to actually iterate through *connected*
>devices, so storing them in registry keys isn't exactly what I'm looking for.

Yes, I think it IS what you're looking for. The getDevicePath call is only
going to return to you the device path for connected devices. As long as
you remember the device-path-to-serial-number mapping the first time you
see a device path you haven't seen before, it should do exactly what you
want.

>In particular, this action is done in an API and not within the application,
>so it would be awkward to work through a registry situation.

I don't really see what that has to do with it. The registry APIs work the
same from a DLL or from an EXE.

>> It is possible to extract the serial number from the device path, but
>> that's undocumented, so you'll go to hell for doing it.
>
>Hm. That's unfortunate, because I think that's exactly what I'd like to do.
>Is there an API that allows the (proper / blessed) extraction of the serial
>number from the path?

No, but if you print out each of the device paths you see, I think it will
only take you about 10 seconds to figure out where the serial number is.

>I am using it to identify specific instances. I'm curious why you say it is
>not usually used to do so -- what other method would be used?

It's unusual to WANT to identify specific instances. That's my point. For
most devices, if I have serial number 18 and serial number 74 plugged in, I
don't do anything any different than if I have serial number 19 and serial
number 75. If I have 6 web cameras, I want to be able to address each one,
but I don't care which SPECIFIC camera each one is.

What kind of devices are these?

Pavel A.

unread,
Dec 10, 2009, 12:07:51 PM12/10/09
to
"Tim Roberts" <ti...@probo.com> wrote in message
news:pn21i5d8ndaku4hn2...@4ax.com...
.................

> It's unusual to WANT to identify specific instances. That's my point.
> For
> most devices, if I have serial number 18 and serial number 74 plugged in,
> I
> don't do anything any different than if I have serial number 19 and serial
> number 75. If I have 6 web cameras, I want to be able to address each
> one,
> but I don't care which SPECIFIC camera each one is.

This may be needed for association of the instances with data
stored somewhere else.
For example, USB network adapter has associated configuration (dhcp and so
on)
which is stored in the tcpip registry branch, away from the driver PnP reg.
keys.
An adapter with the serial number is associated with it's existing config,
no matter where it is attached.

If the OP has this need, it can be addressed in exactly same way:
the software detects a new instance, it assigns it a unique "configuration
id"
and uses it as a key to link to it's own data.

Regards,
P.

Jake

unread,
Dec 22, 2009, 9:22:02 PM12/22/09
to

"Tim Roberts" wrote:
> number 75. If I have 6 web cameras, I want to be able to address each one,
> but I don't care which SPECIFIC camera each one is.
>
> What kind of devices are these?

(annoyed that I'm not getting automatic emails when responses are posted)

Using your example, you would want to if these cameras were part of a motion
capture setup and had specific locations tied to them. Or, simplifying, just
a left and right for a stereo setup.

I guess I don't see why any of the details of the implementation
requirements really matters here.

I'm just trying to iterate serial numbers while a device is already "open"
within WinUSB. This should certainly be possible and, if not, I think it
represents a bug somewhere, or at least a deficiency.

I know that it is possible using a different driver implementation that I've
used in the past, so it may simply be a known deficiency in WinUSB, but it
would be nice to see that written somewhere. And it would be nice to have
that deficiency resolved.

How do we elevate something like this using one of our "MSDN incidents" ?
I've never used one, but this seems like the right time since no one from MS
is chiming in here.

David Craig

unread,
Dec 22, 2009, 10:28:19 PM12/22/09
to
1. MSDN managed newsgroups are going away. The latest from MSDN says the
forums will be the only supported free place to get answers in 2 days.
2. As has been asked many times in the past, what do you plan to do with
the serial number? Why can't 1, 2, 3, etc. be used? What happens if they
replace the device and all serial numbers change?

I don't know much if anything about USB cameras except I like my MS 5000 and
gave my daughter the MS 6000 that I thought had inferior video quality when
compared with the 5000. My new notebook will have a camera at the top of
the screen, so I can use the MS 5000 when the laptop is closed and an
external monitor/KVM is being used.

I do see a need on one of my systems to know the serial number, but it also
happens to be printed on the Seagate HD as well. It has failed and since
that box has six of those drives in it, the serial number is useful. Maybe
that could apply in your case, but I have never seen the serial number given
on a webcam where you can read it from the label.

"Jake" <Ja...@discussions.microsoft.com> wrote in message
news:34673D26-9F62-4B8E...@microsoft.com...

Pavel A.

unread,
Dec 22, 2009, 10:26:02 PM12/22/09
to
"Jake" <Ja...@discussions.microsoft.com> wrote in message
news:34673D26-9F62-4B8E...@microsoft.com...

> How do we elevate something like this using one of our "MSDN incidents" ?


> I've never used one, but this seems like the right time since no one from
> MS
> is chiming in here.

Log on to the msdn site, then click on Support Incidents link in the MSDN
Subscriptions box on the right side,
or Online concierge chat.

Good luck,
--pa

Tim Roberts

unread,
Dec 22, 2009, 10:46:26 PM12/22/09
to
Jake <Ja...@discussions.microsoft.com> wrote:

>
>"Tim Roberts" wrote:
>>
>> What kind of devices are these?
>
>(annoyed that I'm not getting automatic emails when responses are posted)

Hmmm; I use the newsgroup interface. It's hard for me to imagine a worse
interface for technical exchanges than a web forum.

>I guess I don't see why any of the details of the implementation
>requirements really matters here.

You're right, of course. It's just that we often find people asking
specific implementation questions trying to solve problems in an out of
ordinary way, when in fact there is a well-supported mechanism to reach the
same end. This leads me to ask seemingly annoying questions.

>I'm just trying to iterate serial numbers while a device is already "open"
>within WinUSB. This should certainly be possible and, if not, I think it
>represents a bug somewhere, or at least a deficiency.

It's not a bug, it's a feature. WinUSB creates its device object as
"exclusive", so each instance can only be opened by one app at a time. This
is certainly documented. You will never be able to read the serial number
USING WINUSB while another app has the device open.

Did you do as I suggested, and dump the device path filenames during your
iteration? Did you not find the serial numbers embedded in the device
filename in an easy-to-parse way? That doesn't require opening the device
at all.

>I know that it is possible using a different driver implementation that I've
>used in the past, so it may simply be a known deficiency in WinUSB, but it
>would be nice to see that written somewhere. And it would be nice to have
>that deficiency resolved.

It is documented.

>How do we elevate something like this using one of our "MSDN incidents" ?
>I've never used one, but this seems like the right time since no one from MS
>is chiming in here.

Well, a support incident isn't going to help, because WinUSB is working as
designed. If you need a capability that WinUSB does not provide, then your
fallback situation is to write your own driver. WinUSB, after all, is just
a convenience for applications where its model fits the problem space.

Jake

unread,
Dec 23, 2009, 10:04:01 PM12/23/09
to
Tim--

Well, I was hoping to avoid a full-on explanation because it really is
irrelevant to the problem at hand. But I'm not hiding anything. First, a
few other things to address:

1. I was not able to see the serial number in the device path names. Just
the PID, VID, and a GUID which isn't the GUID from the INF file. Perhaps
something associated with WinUSB.

2. Regarding the incident, yes, I was afraid of that. Most of the forms for
incidents seem to indicate we're posting bugs with something. I'm really
looking for a solution that may or may not be documented somewhere.

3. You're right that OPENING a device should be exclusive. However, I'm not
trying to open the device. I just want to query the serial numbers of all
attached devices. This should not require opening a device with WinUSB. The
serial number query can occur without a bound interface.

Now... the irrelevant details.

This is an API for a very custom, very niche device. It can be used in any
number of applications from industrial control to image capture. It's not
your typical keyboard, mouse, webcam, etc.

It isn't uncommon to have multiple of these devices attached to different
machinery. The device allows storage of a user-managed ID. For the camera
example, let's say those IDs are "Camera 1", "Camera 2", and "Camera 3".
Query of the device ID requires communication with the device outside the
simple USB queries like interfaces, serial numbers, PID/VID, etc.

Therefore, I accept that query of the device ID will require WinUSB to bind
a handle. Fair enough. I encourage this behavior! It prevents two apps (or
even the same app) from trying to communicate with the device. This can
really muck with the state of the device.

But the end user should be able to iterate all attached devices of this
PID/VID pair and get their serial number even if a device is "open".

In fact, this driver was migrated from the (horrible) Cypress API for their
USB devices. But even that API allowed serial number query for devices that
are active.

I recognize that a simple solution is to just require the end-user to
iterate devices before establishing any communication. But since this is an
update to an existing API, it should support the legacy operation. Both in
terms of customer support and in terms of my understanding of the "theory"
behind it. It was done before (my thinking goes...) it simply MUST be
possible.

Even if I need to do this external to the WinUSB stuff, I'm happy to do so.
It might require a few more lines of code, but it should be possible, right?

...I used to use the newsgroup interfaces to all this stuff to. I suppose
I've just drifted with the tides. Haven't used a newsgroup interface for
several years now. Funny, it was my migration to Windows that changed all
that. And now I'm getting grief for it on a Windows newsgroup. :) ...


"Tim Roberts" wrote:

> .
>

David Craig

unread,
Dec 23, 2009, 10:43:54 PM12/23/09
to
I am sure you know this, but:

1. Any query requires that some device driver have a device object exposing
a physical device, maybe just one function if multiple ones exist.

2. Some stacks expose some functionality via IoCtls and/or WMI. In these
cases a driver, frequently from Microsoft, does all the stuff in 1.

You can get a rather nice WMI query utility in source form to see what is
available. It was/is called WmiTest and it may require some changes to work
properly and Visual Studio to compile.

You may have to do a lot of research and reverse engineering to see what the
USB stack will expose to you. I am certain that it will query the device
for that descriptor if it exists.


"Jake" <Ja...@discussions.microsoft.com> wrote in message

news:E5B33D3A-CE41-459E...@microsoft.com...

Maxim S. Shatskih

unread,
Dec 23, 2009, 10:49:35 PM12/23/09
to
> It isn't uncommon to have multiple of these devices attached to different
> machinery. The device allows storage of a user-managed ID. For the camera
> example, let's say those IDs are "Camera 1", "Camera 2", and "Camera 3".

I think you can use SetupDi APIs instead of WinUSB to query such strings.

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

Pavel A.

unread,
Dec 23, 2009, 11:16:02 PM12/23/09
to
"Jake" <Ja...@discussions.microsoft.com> wrote in message
news:E5B33D3A-CE41-459E...@microsoft.com...

..................


> 1. I was not able to see the serial number in the device path names. Just
> the PID, VID, and a GUID which isn't the GUID from the INF file. Perhaps
> something associated with WinUSB.
>

...................


> It isn't uncommon to have multiple of these devices attached to different
> machinery. The device allows storage of a user-managed ID. For the
> camera
> example, let's say those IDs are "Camera 1", "Camera 2", and "Camera 3".
> Query of the device ID requires communication with the device outside the
> simple USB queries like interfaces, serial numbers, PID/VID, etc.

It looks that there IDs have nothing to do with the so called "USB serial
numbers".
They sit in some other string descriptors, or maybe not in string
descriptors at all.
If these devices have no unique "USB serial numbers", there is no obvious
solution.

Regards,
--pa

Jake

unread,
Dec 24, 2009, 12:34:01 AM12/24/09
to
Pavel--

The question (how to get serial numbers) is predicated on each device having
a unique USB serial number.

The existence of the IDs is ancillary, just as the specific usage of serial
numbers is ancillary.

I think it might do to revisit the original post here since perhaps we've
lost sight of the goal...

1. Multiple USB devices with the same GUID (and PID/VID). These have unique
USB serial numbers and report them in the proper way.

2. I'm using WinUSB for the communication API, but would like to request the
serial numbers of these devices -- EVEN IF a device is "open" within WinUSB.

3. I don't care if I use WinUSB (WinUSB_GetDescriptor) or some other method
to query the serial numbers.

Jake

unread,
Dec 24, 2009, 12:35:02 AM12/24/09
to
Maxim--

Thanks. I'll take a peek through the SetupDi to see if something rings out.

"Maxim S. Shatskih" wrote:

> .
>

Pavel A.

unread,
Dec 24, 2009, 6:08:47 PM12/24/09
to
If your devices had serial numbers, they shoud be clearly visible
somewhere in the device path, as Tim suggested.
--pa

"Jake" <Ja...@discussions.microsoft.com> wrote in message

news:AC0D1B8F-3872-4FA6...@microsoft.com...

Jake

unread,
Dec 24, 2009, 11:26:01 PM12/24/09
to
Pavel--

Hm. They do... And I don't... I wonder if I'm doing something wrong?

Will they just print, as usual? Here is an example string I'm getting:
\\?\usb#vid_XXXX&pid_YYYY#5&595e2b2&0&2#{7a1a3eb2-9c2c-47be-be55-ff3332a722fd}

VID and PID have been replaced, but the remainder is verbatim.

Pavel A.

unread,
Dec 25, 2009, 2:54:46 AM12/25/09
to
"Jake" <Ja...@discussions.microsoft.com> wrote in message
news:DB9A65A2-2C3B-4EC1...@microsoft.com...

> Pavel--
>
> Hm. They do... And I don't... I wonder if I'm doing something wrong?
>
> Will they just print, as usual? Here is an example string I'm getting:
> \\?\usb#vid_XXXX&pid_YYYY#5&595e2b2&0&2#{7a1a3eb2-9c2c-47be-be55-ff3332a722fd}
>
> VID and PID have been replaced, but the remainder is verbatim.

Hi Jake,

If only my memory serves, when the serial number is present,
it should be contained verbatim in the above string, somewhere between the
vid & pid part and the {guid}.

Regards,
--pa

Jake

unread,
Dec 25, 2009, 4:58:01 PM12/25/09
to
Pavel--

Interesting. Perhaps this is something MS has already changed or perhaps
the WinUSB driver doesn't add this to the device path.

This is on Vista 32-bit.

And, although you don't seem to believe me, the serial number is present and
fully verified on Windows, Linux, and Mac OS X as a real "honest to goodness"
USB serial number. I've got about 5 yrs of production behind this particular
device to prove that out, and every single USB "snoop" or inspection utility
shows the serial number reliably.

0 new messages