How to query the serial number of a UVC camera? - usb

I have two UVC cameras in a stereoscopic setup, controlled with a C++ MediaFoundation app. I need to uniquely identify them in order to assign left and right to each physical device. This camera model has a unique serial number in the USB descriptor. However I can't seem to find a way to get the serial number while enumerating using MediaFoundation.
The MF enumeration order of these cameras is not reliably in port order; 95% of the time, camera 1 is enumerated before camera 2, while on some machines, we get camera 2 before camera 1. So finding the serial number is very important.
Things I've tried:
MediaFoundation doesn't seem to provide a direct way to get the serial number at all
By querying the MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK attribute, you can get a USB symbolic link. The docs say this can be used to call SetupDiOpenDeviceInterface however this doesn't seem to be usable to get the serial number (or the USB descriptor) either.
WinUSB can be used to open some USB devices in a generic manner, so the USB descriptor might be accessible, but this method fails on these cameras also, after passing the handle from CreateFile.
IOCTL the lowest level method, apparently you can send a IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX to the hub device, with a port index, and it will return the descriptor from which you should be able to get the serial number. No idea how to get the hub device and port index from only the symlink though.
Related, but unresolved: How to get hardware ID when enumerating with Windows Media Foundation
I do not wish to reimplement half of the USBView example and enumerate the entire USB world just to get some specific info for a device for which I already have a handle.
Some symbolic links for USB devices can be parsed to extract the serial number, however in the case of composite devices (all the devices in question here) the symbolic link has the &MI_00# style format and does not contain the serial number in the symlink string. So it cannot simply be parsed out.
More generally, the Setup and related APIs in Win32 seem to make it easy to get information such as manufacturer, friendly name, and all sorts of other info. But serial number is conspicuously absent.
So how do you get the serial number associated with a MediaFoundation device instance?

You can do camera identification by USB port connection (Root-Hub-Port identifiers are the same if you don't connect new USB cards or hubs to the system)

Unfortunately StackOverflow doesn't give to attach images (I don't have good enough reputation).
I'll try to show data from debugger:
There is list of my available cameras
+Integrated_Webcam/R1.H2.P4/VID_1BCF&PID_2284&MI_00;
+HBVCAM FHD CAMERA/R4.H2.P4/VID_058F&PID_3821&MI_00;
+HD USB Camera/R5.H2.P5/VID_05A3&PID_9230&MI_00;
+Integrated_Webcam/R5.H2.P6/VID_1BCF&PID_2284&MI_00;
+Logitech HD Webcam C270/R1.H2.P1/VID_046D&PID_0825&MI_00;
Each string consists of Friendly camera name, Rx.Hx.Px camera connection port indexes, (i.e. Controller number"R"-Hub number"H"-Port number"P") and VID-PID-MI presentation string(vendor id, product id and interface number).
1st and 4th cameras are the same, but have different RHP indexes. These indexes I do use for camera identification.
I did USB enumerator which provides these indexes (I did this on the base of Microsoft USBView.exe application which is provided with sources in Windows SDK).
[1]: https://i.stack.imgur.com/6SQcS.png

Usually simple USB cameras (web cameras) doesn't have serial number or something like serial number is encoded inside USB instance ID. More expensive cameras have special drivers and you can read SN by driver.
I see only one way to know, what camera I do use now - by attached USB port. This port is unique... if you don't connect additional hubs or not insert additional USB interface cards in computer. There is USB enumeration process which provides Controller(Root)-Hub-Port enumeration indexes. I do use these indexes for camera identification.
Look on this dialog: you see 5 strings with 5 USB cameras descriptors. Each descriptor consists of "Friendly Camera Name", 3 enumeration indexes (Rx.Hx.Px) and camera vendor ID and product ID (VID and PID).
If I put different camera to the same port, my program will use this different camera. If several cameras of the same type are connected, I do differ between cameras by RHP indexes. For example, the first and the fourth camera in list are the same, but they have different
enter image description here

Related

USB hub and the identification of positions

I need to attach 8 devices of the same kind (RFID readers) to the 8 positions of the USB hub. I need to recognize which reader is not plugged-in. I also need to know which exact device sends the data (based on the physical location)
I am aware of "a path" related to an USB plug. However, I am still a newbie in the topic. Are the positions at the USB hub numbered always the same way, or are the numbers in the path assigned based on when the USB device is plugged in? In other words, can I tell whether a specific position at the USB hub is connected or not? Can I reliably determine which device sends the data based on the communication path?

Retrieve mount point of WPD device

I've worked with WPD API for a while now, and I seem to run in to problem after problem.
Once I fix one problem, something else pops up. But hey, that's life.
I've been trying to determine if a WPD device is a storage device or a phone or whatever.
Turns out, devices such as iPhone are not set to be recognized as a phone, but instead as a generic device in terms of WPD_DEVICE_TYPE.
But, it is presented to Windows as a storage device.
When connecting external harddrives, SD memory card readers and other more conventional storage devices, they are recognized by the WPD API as well, but ehy that also get a dedicated mount point in Windows.
If I connect an external harddrive, it will have one functional category object, and the value of that object will be the path of that drive, say E:.
Nice. Great!
So my question is: How can I somehow read if the WPD device has a mountpoint?
Sure the functional object indicates that it has one, but is it possible that there could be an indicational value which states that a mount point is available?
Check the device Ids, here's an example how they differ:
\\?\swd#wpdbusenum#_??_usbstor#disk&ven_usb&prod_flash_disk&rev_1100#aa04012700007404&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}#{6ac27878-a6fa-4155-ba85-f98f491d4f33
vs.
USBSTOR\DISK&VEN_USB&PROD_FLASH_DISK&REV_1100\AA04012700007404&0
The upper one is the Id gathered from PortableDeviceManagerClass (first step to create an PortableDevice object), the lower one I've just read from the Device Manager, but it should be easily retrievable with one of these solutions:
How do I get a Unique Identifier for a Device within Windows 10 Universal?
https://sourceforge.net/projects/sharpdevelop/files/SharpUSBLib/

Choosing a GPS to read position from VB.net 2010? Which one I should buy?

I'm trying to build a device to read the current GPS coordinates. The device will include a small computer inside running Windows 7.
I'm looking for a usb GPS to connect it to the computer and be able to read the GPS coordinates from my VB.net 2010 program. Of course, here the most important thing is what hardware I need to accomplish that. Suggest me some GPS models.
Do I need only a GPS receptor or do I need even more hardware?
In addition to jcibar's answer:
For Bluetooth GPS or most USB devices you probably don't even have to set the classic RS232 communication settings like "baud rate". It will just work, whatever baud rate you set.
Look at the "Ports (COM & LPT)" list of the Windows Device Manager - One of the "COM" devices listed should be the GPS receiver and it many times includes a description that indicates what it is.
E.g. on my Win7 x64 notebook I have a "Sierra Wireless Gobi 2000 HS-USB NMEA 9001 (COM8)" port, which is the notebook's built-in GPS. It will just start communicating the moment I open the port:
17.09.2013 10:12:01.890 [RX] - $GPGSA,A,1,,,,,,,,,,,,,,,*1E<CR><LF>
$GPGSV,4,1,16,10,,,,21,,,,20,,,,32,,,*7A<CR><LF>
$GPGSV,4,2,16,31,,,,30,,,,29,,,,28,,,*78<CR><LF>
$GPGSV,4,3,16,27,,,,26,,,,25,,,,24,,,*79<CR><LF>
$GPGSV,4,4,16,23,,,,22,,,,19,,,,18,,,*7E<CR><LF>
$GPGGA,,,,,,0,,,,,,,,*66<CR><LF>
$PQXFI,,,,,,,,,,*56<CR><LF>
$GPVTG,,T,,M,,N,,K,N*2C<CR><LF>
$GPRMC,,V,,,,,,,,,,N*53<CR><LF>
You can use any serial COM port / RS232 logger to test this.
You can use any GPS (USB, Bluetooth) that provides a RS232-level serial interface (serial port). The GPS will create a virtual serial port (e.g. COM13) that you can use in your VB.net program to read serial data (NMEA frames tipically at 4800 bauds).
For instance, for USB you could use something like this: Haicom HI-206USB.

USB host recognition

I'm developing an embedded USB device which needs to be available to two different hosts.
The first is a normal PC, where it will be used as a MSC (mass storage) device, and the second is a specific hardware which the USB device needs to comunicate with a CDC profile.
during the enumeration, the USB device send descriptor table where it declares its capabilities.
Is there a way in the enumeration process to know to which host the device was connected to ?
The simplest solution perhaps would be to implement a "USB Composite Device", where the single device presented both the MSC and CDC class interfaces simultaneously. The host PC would see both interfaces, but you could simply leave one unused. The "specific hardware" would probably simply ignore the MSC class if it had no support for it.

Is an ASHWID guaranteed to uniquely identify a device?

We want to use a unique device identifier in a Windows 8 Metro app and the recommendation is an ASHWID, documented here:
http://msdn.microsoft.com/en-us/library/windows/apps/jj553431.aspx
I'm struggling to see how this can possibly be guaranteed unique. The format includes two bytes per hardware component, of which the most uniquely identifiable are MAC address and hard disk serial number. But just two bytes for those values really doesn't seem like enough.
If the bytes used are anything other than the least significant digits (the rightmost, as a human reads them) are taken, then two identical laptops adjacent on the production line would probably have the same ASHWIDs. The MACs and drive serials would likely be adjacent.
So, I guess the crux of my question really is how many devices have to be produced with the same CPU type and memory configuration before you're likely hit a duplicate. Seems like the same sort of problem as the Birthday Paradox, so I found a calculator for that and plugged in the numbers :)
With one MAC address and one hard disk with a two-byte identifier each, you have about 4 billion permutations. Once you've allocated just 6,000 of them, it's roughly 50/50 that you've got two the same.
(go to http://jeff.aaron.ca/cgi-bin/birthday and plug in "6563" and "4294967296" for the actual calculation).
So this really doesn't seem very unique at all. Am I right in being ultra-sceptical of this identifier, or am I missing something really significant?
No, the ASHWID is not guaranteed to uniquely identify a device. At work, I've seen dozens of daily collisions where one monthly is our tolerance.
Further, the ASHWID might frequently change for the same device -- since Windows 8 will often run on laptops that might add a docking station, USB thumb-drive, or a plug-in Bluetooth adapter. The best use of the ASHWID is for verifying that a user has only installed your app to a limited number of devices, and you do that by parsing the ASHWID and selectively comparing it to previously-seen ASHWIDs from that user.
As for a unique hardware identifier, I suggest an MD5 digest of a string containing multiple components, of which some components of the ASHWID can play a part.
You might randomly generate a large number (64+ bits) and store that (eg in the registry). And of course the user's login name/ID should be unique to that user, if you want something else to include in a hash. You also need to consider what you want to do if the user clones an OS install, or replaces the HD after a drive failure.
Back in the Windows Desktop world, I used the MachineGuid registry key and the serial number of the boot device, but I'm fighting to get access to that info in a Windows Store app. If you have access, MachineGuid is in HKLM\SOFTWARE\Microsoft\Cryptography, which MS guarantees to be unique. The serial number of the boot device ::GetVolumeInformationW(::SHGetFolderPathW(~),~) will be fairly unique but only 32 bits.
From the article:
The ASHWID provides a strong binding between the app/package and the
device by representing several individual hardware characteristics. In
order to protect user privacy, the ASHWID varies from app to app.
Unless the underlying hardware has changed, two calls from the same
app will result in identical ASHWIDs. However, the ASHWID changes if
the hardware profile of the device changes, such as when the user
unplugs a USB Bluetooth adapter. The back-end cloud service can verify
the ASHWID and compare it with previously reported values. Though the
ASHWID varies, it can be parsed to detect if the variance was simply
due to a minor change such as an addition of memory to the system. The
level of tolerance for variance is up to the implementation of the
back-end cloud service.
The ASHWID is made up of 9 components:
CPU ID of the processor
Size of the memory
Serial number of the disk device
Network adapter (NIC MAC address - first instance)
Audio adapter
Docking station
Bluetooth address
Mobile broadband device ID
BIOS
CPU ID is only unique to processor model, but NIC MAC Address should be very unique. Having said that, MAC addresses can be cloned and USB NICs can be moved from device to device. So, while I guess it's possible for two devices to have the same ASHWID, it's very unlikely. What's most challenging in using this ID is the fact that hardware can change. It's up to the service to decide which parts of the ASHWID they allow to change and which parts the do not (acceptable variance). The article itself provides guidance on that.