How is the guidProduct field of DIDEVICEINSTANCE generated - winapi

How does DirectInput generate the GUID for the guidProduct field in DIDEVICEINSTANCE? The documentation reads:
guidProduct
Unique identifier for the product. This identifier is established by the manufacturer of the device.
I am searching for a way to retrieve or synthesize the product GUID for a joystick without using DirectInput. I have successfully used RawInput to retrieve the device path and class GUID, but I have not yet found a way to retrieve the product GUID using RawInput and/or SetupDi* functions.
While searching, I noticed that MAKELONG(VID, PID) == guidProduct.Data1, which makes me hopeful that there is way to do what I want (DirectInput somehow does it, after all.)
Questions:
Is there an API to retrieve the product GUID for an HID (esp. joystick) device?
If not, does anyone know how DirectInput synthesizes this field? (The first fields combines VID and PID. What about the rest?)
Edit:
By hacking around the guidProduct field, I came across an interesting discovery. The product GUID for the P880 USB gamepad has the following format:
010906a3-0000-0000-0000-504944564944
The first 4 bytes are quite evidently the PID and VID for the controller. The last part of the GUID is common for all HID controllers in my possession. After a while it dawned on me - they are ASCII characters! The translation is:
010906a3-0000-0000-0000-504944564944
010906a3-0000-0000-0000- P I D V I D
PID_VID_-0000-0000-0000-'P I D"V I D'
I have verified this using the SDL2 game controller database, and it appears to hold! Of course, this does not cover bluetooth devices (such as the OUYA controller), which is only a minor issue for now.
Does anyone know how guidProduct is composed for bluetooth devices?

Related

How to identify a HID after it's moved to a different port on Windows

I'm on Windows and am trying to store calibration data for game controllers connected via USB and am trying to find a value which uniquely identifies them in a port independent way.
There is the HidD_GetSerialNumberString function but i've read here that it's uncommon for devices to have serial numbers and indeed when i try to read one f.e. from a PS4 controller HidD_GetSerialNumberString returns FALSE and GetLastError returns ERROR_INVALID_PARAMETER.
Is there any other data available which can be accessed to achieve this?
You can try to use instance ID for your HID device (call CM_Get_Device_Interface_Property with device interface path and DEVPKEY_Device_InstanceId property and use string after last & char). It should be unique and persistent per system restarts. But it is not guaranteed if serial number is not provided (in this case instance ID will be different if device is plugged into different usb port)...
More info on this here: https://stackoverflow.com/a/56885175/1795050

NFC sticker to launch website with unique URL

I can encoded an NFC Sticker with a website that will open when I tap it with a mobile phone. For the application I want to use it for I need to be able to expire that link so the user can't just save the URL and use it again. Basically I need to be able to put a random string in the URL that changes each time it gets scanned, such as www.mywebsite.com/TCHQ23, www.mywebsite.com/LQ8FT, ect.
Is this possible with a regular NFC sticker? If not, what kind of device would I use to make this happen? I know there are Arduino modules that can do this, but is there a simpler method or a ready made product that can act as an NFC but have the URL changed by a computer via a USB cable?
Thanks
NFC tags (some) have a feature called "Mirroring". You can mirror the read counter value to the URL, which gets incremented every time you tap it to reader i.e. Every time read command is called, the counter increases by 1. Tags like NTAG 213, NTAG 215 etc have that feature.
Update:
If your requirement is to get a portion of URL to to return random data and on a cheaper tag or sticker then I would suggest considering NTAG 213 tag, which is cost friendly and also have Mirroring feature supported.
If your URL data is http://www.abc#xyz.com then once the counter Mirroring is enabled (read counter must be enabled first) it will look something like
http://www.abc#xyz.com?000001
The last 6 digit value gets increased by value 1,every time a read command is invoked. (000002, 000003, 000004 and so on)
you can refer this link for more info
So your card/device has to present when read a NDEF record with a link in it (A "Well Known Type 1 with a record type definition of type U, etc), this will cause most phones to open a browser automatically
Some details on the Record type needed at https://www.oreilly.com/library/view/beginning-nfc/9781449324094/ch04.html
Most cards have the ability to store some static data, some have as #Adarsh Rotte says have counters, random number generators, crypto, password protection, mirroring (backup) of data, other functions but non of these will help as these custom functions and are card specific and don't / cannot present the data to match the NFC NDEF specification.
There is one type of card that can do this called JavaCard as these can run fully programmable Java Apps. These can be programmed to respond to NFC read request with the right NDEF measure where the URL can be generated on the fly.
There is a github repo with an example Java App to run on these cards that shows how to respond with and NDEF message at https://github.com/OpenJavaCard/openjavacard-ndef.
Watch out for https://github.com/OpenJavaCard/openjavacard-ndef/issues/10 if trying to use this, the default magic AID number is not the right one for NDEF and should be configured at the time you install the App on the Card.
This app emulates the behaviour of an NFC Type 4 spec card.
You would also need to customise it to have the right NDEF payload data with the right generated URL ending.
There are examples of the Card make/model supported by this App listed on the the github pages some are dual interface cards but there are some without the chip contacts and only NFC interface.
Generating the URL ending could be challenging or easy depending on level of security/validation you need.
Starting from a Random String which would be easy to fake because it has no level of validation, to a obfuscated counter, to a public key type encrypted counter.
There are also other solutions to generating the NDEF data with the right URL that don't use a Card and usually require there own power to run.
Some options:-
An Android phone can do what is call Host Card Emulation (HCE) which is very like what the JavaCard is doing, it is pretending to be a NFC Type 4 Card and the response it sends if fully programmable and could be the right type of NDEF message as per the JavaCard.
There are some "Card Reader" Devices that can be attach to a PC/Raspberry Pie via USB can also do HCE like the Android phone. e.g. https://www.acs.com.hk/en/products/342/acr1252u-usb-nfc-reader-iii-nfc-forum-certified-reader/ - this is well documented in the datasheets on how to do.
There are some other "Card Reader" modules that can connect via I2C to Arduino that can do HCE as well. (Technically most Arduino PN532 Chip's which are used in a lot of USB readers as well can do HCE but it is a bit undocumented on how to do it - see section 4 of https://www.nxp.com/docs/en/user-guide/141520.pdf)
There are some other chips that can act as static data NFC devices the also have an I2C interface to write the static data but allow a "pass through" mode to the I2C interface, again these tend to be NFC Type 4 but do some of the HCE type work for you.
e.g. the M24SR04-Y https://www.st.com/resource/en/datasheet/m24sr04-g.pdf can do it
So technically possible with a variety of methods but all not that simple to implement BUT not "Sticker" type format of NFC devices tend to be very simple NFC device as the format restricts the complexity of the hardware contained in them.

Getting unique device ID in Win8 app

I need to get an unique device identifier in Windows 8 application. I have few applications and I need to determine device ID that have one or more apps installed (e.g. a bonus for a gamer installing other game in the series). Using following methods provides me with per-app IDs which won't tell me that device have some other apps installed.
I've tried three different approaches but they all return different UDIDs on the same PC.
1) This was used before, since I needed unique id per app, now I need UDID, so it's predictably doesn't work for me:
GUID g;
std::string ret;
CoCreateGuid(&g);
Platform::Guid pg(g);
std::string udid = WStringToUTF8(pg.ToString()->Data());
2) I've tried EasClienDeviceInformation, which was suggested as a sure thing, but got different results for 2 apps on the same PC:
EasClientDeviceInformation^ info = ref new EasClientDeviceInformation;
ret = WStringToUTF8(info->Id.ToString()->Data());
3) And I've tried the commonly used way to get ASHWID, without any hope and it obviously shown different UDIDs:
auto token = Windows::System::Profile::HardwareIdentification::GetPackageSpecificToken(nullptr);
ret = WStringToUTF8(Windows::Security::Cryptography::CryptographicBuffer::EncodeToBase64String(token->Id)->Data());
_RPT1(_CRT_WARN, "TOKEN UDID IS %s \n", ret.c_str());
I know only about one option and it's to use MAC-address, but I'm not sure if it's a valid option. Users can have a PC where MAC-address could be changed or duplicated (I've heard of batches of chinese network adapters having the same address), or have a device without a network whatsoever (e.g. use a PC without a network adapter and connect to the internet using USB dongles).
So the questions are:
Did I do everything right, or I made a mistake that caused my examples to return wrong UDIDs?
Am I right to assume that MAC-address is the only viable way to get a trutfully unique per-device identifier? I could've been inattentive and missed some obvious way.
Am I wrong in my assumptions of MAC-address identification insecurities like those I've described above?
UPD: I also would like to know the right way for WP8, while we're on it.

Windows HID Device Name Format

There are various ways to retrieve the Windows "Device Name" of a HID device, GetRawInputDeviceInfo with RIDI_DEVICENAME being one way to do it.
Given the example name:
\?\HID#VID_FEED&PID_DEAD#6&3559c8ea&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}
I'm wondering if there is any documentation whatsoever on what is what in this string?
\?\HID#VID_AAAA&PID_BBBB#C&DDDDDD&E&FFFF#{GUID}
So the obvious ones are A(VID), B(PID) and the GUID on the end. What I'm wondering is what EXACTLY are C, D, E and F?
It seems that C and D are unique even if you plug in two of the exact same HID devices which is great for my problem, but I'd feel more comfortable if I could know exactly how this is determined on a per OS basis, or at least that it follows some known format.
I have been googling like a madman trying to figure this out, am I missing something obvious?
Thanks in advance
According to a similar MSDN post, the value represents a unique device instance ID:
the device instance ID is unique and constant for the physical
location the device is plugged into, but it is also opaque and should
not be parsed. that means it can be used for string comparison, but
not for interpretation.
It is actually device interface instance id (symbolic link name). And yes, its unique and persists across system restart. Some details also here.
You can use CM_Get_Device_Interface_Property or SetupDiGetDeviceInterfaceProperty on interface instance id with DEVPKEY_Device_InstanceId to get device instance id (one device can have multiple interfaces).
In your example - you have a HID device. Its device id format is described here.
Info on general USB devices id format is here.
After you have device instance id you can use CM_Get_DevNode_Property or SetupDiGetDeviceProperty with DEVPKEY_NAME to get localized friendly name of a device (which is shown in Device Manager).
To sum up:
\\?\HID#VID_203A&PID_FFFC&MI_01#7&2de99099&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd} - is device interface id (also referred as "device interface path" or "device name" in docs). This is path in virtual device file system.
{378de44c-56ef-11d1-bc8c-00a0c91405dd} - device interface class guid (GUID_DEVINTERFACE_MOUSE in this case. It determines which IOCTLs can be called on this device. IOCTL_MOUSE_QUERY_ATTRIBUTES in this case)
HID\VID_203A&PID_FFFC&MI_01\7&2de99099&0&0000 - is device instance id
NOTE: exact device interface id format is not documented, each device interface can generate file name it want. I don't recommend you to parse it - it could be changed in later Windows version, better aquire device instance id - it is documents at least.

Multiple mice on OS X

I am developing an OS X application that is supposed to take input from two mice. I want to read the motion of each mouse independently. What would be the best way to do this?
If that is not possible, is there a way to disable/enable either of the mice programmatically?
The HID Class Device Interface is definitely what you need. There are basically two steps:
First you need to find the mouse devices. To do this you need to construct a matching dictionary and then search the IO Registry with it. There is some sample code here, you will need to add some additional elements to the dictionary so you just get the mice instead of the all HID devices on the system. Something like this should do the trick:
// Set up a matching dictionary to search the I/O Registry by class
// name for all HID class devices`
hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);
// Add key for device usage page - 0x01 for "Generic Desktop"
UInt32 usagePage = 0x01;
CFNumberRef usagePageRef = ::CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &usagePage );
::CFDictionarySetValue( hidMatchDictionary, CFSTR( kIOHIDPrimaryUsagePageKey ), usagePageRef );
::CFRelease( usagePageRef );
// Add key for device usage - 0x02 for "Mouse"
UInt32 usage = 0x02;
CFNumberRef usageRef = ::CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &usage );
::CFDictionarySetValue( hidMatchDictionary, CFSTR( kIOHIDPrimaryUsageKey ), usageRef );
::CFRelease( usageRef );
You then need to listen to the X/Y/button queues from the devices you found above. This sample code should point you in the right direction. Using the callbacks is much more efficient than polling!
The HID code looks much more complex than it is - it's made rather "wordy" by the CF stuff.
It looks like the HID Manager is what you're looking for.
You're going to want to check out the I/O Kit and HID (Human Interface Device) manager stuff.
HID manager is part of I/O Kit, so looking into there might be useful. There are two APIs for HID management, the older API is a bit more painful and then you have the new 10.5 and above API which is a bit more comfortable.
Important thing to understand is this isn't going to probably be just a quick fix, it may take some significant work to get it running. If you can assume you'll have 10.5 or better installed, using the Leopard API will definitely help.
Also; depending on how you accomplish what you're doing, may be important for you to hide the mouse cursor as it may still move a lot even if you're receiving the information from both mice. If your application grabs the screen, I'd use CoreGraphics to disable the cursor and just draw my own.
You might also consider finding a wrapper for one of these APIs, an example can be found in this question.
Unless you can force one of the mice to not be dealt with as a mouse, both will continue to control the pointer. However, you can use IOKit to write a custom USB HID driver to allow your app to read from one or both of the mice (although this would probably interfere with using them as normal mice). Building Customized User Client Drivers for USB Devices would be a good place to start for how to interact directly with USB mice.
You could look at the USB/PS-2 device interrupt.
Even if you don't want to rewrite a so called driver, it could be usefull since all the mice send their data through.
You could also check this page that could give some hints http://multicursor-wm.sourceforge.net/
maybe it's a solution for you to use usb->rsr232 converter and go by reading the serial port by yourself ?

Resources