I am using Qt on windows platform.
i want to get and display vendor id and product id of a plugged usb device from my local system.
Below is my full source code to get the vendor id and product id from the usb device.
when i run the my qt application it does not throw me any errors .
so i plug the usb device into the system.
but my print statement displays the result as below
qDebug ()<<pDetData->DevicePath;
i get the result as 0x4
Whether i have any implementation mistakes in my source code ?
if so please guide me what i am doing wrong..
Have i missed out any other functions ?
Is it possible to get the vendor id and product id from the usb device based on my source code .( my implementation of the code ) ?
kindly find my source code below
static GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10L, 0x6530, 0x11D2,
{ 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
HANDLE hInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE,NULL,NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
if ( hInfo == INVALID_HANDLE_VALUE )
{
qDebug ()<<"invalid";
}
else
{
qDebug ()<<"valid handle";
SP_DEVINFO_DATA DeviceInfoData;
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
SP_INTERFACE_DEVICE_DATA Interface_Info;
Interface_Info.cbSize = sizeof(Interface_Info);
BYTE Buf[1024];
DWORD i;
DWORD InterfaceNumber= 0;
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd =
(PSP_DEVICE_INTERFACE_DETAIL_DATA) Buf;
for (i=0;SetupDiEnumDeviceInfo(hInfo,i,&DeviceInfoData);i++)
{
DWORD DataT;
LPTSTR buffer = NULL;
DWORD buffersize = 0;
while (!SetupDiGetDeviceRegistryProperty( hInfo,
&DeviceInfoData,
SPDRP_DEVICEDESC,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
// Change the buffer size.
if (buffer) LocalFree(buffer);
buffer = (LPTSTR)LocalAlloc(LPTR,buffersize);
}
else
{
// Insert error handling here.
break;
}
qDebug ()<<(TEXT("Device Number %i is: %s\n"),i, buffer);
if (buffer) LocalFree(buffer);
if ( GetLastError() != NO_ERROR
&& GetLastError() != ERROR_NO_MORE_ITEMS )
{
// Insert error handling here.
qDebug ()<<"return false";
}
InterfaceNumber = 0; // this just returns the first one, you can iterate on this
if (SetupDiEnumDeviceInterfaces(hInfo,
NULL,
&GUID_DEVINTERFACE_USB_DEVICE,
InterfaceNumber,
&Interface_Info))
{
printf("Got interface");
DWORD needed;
pspdidd->cbSize = sizeof(*pspdidd);
SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL;
DWORD dwDetDataSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)
+ 256;
SetupDiGetDeviceInterfaceDetail(hInfo,
&Interface_Info, pDetData,dwDetDataSize, NULL,
&DeviceInfoData);
qDebug ()<<pDetData->DevicePath;
//qDebug ()<<QString::fromWCharArray(pDetData->DevicePath);
}
else
{
printf("\nNo interface");
//ErrorExit((LPTSTR) "SetupDiEnumDeviceInterfaces");
if ( GetLastError() == ERROR_NO_MORE_ITEMS)
printf(", since there are no more items found.");
else
printf(", unknown reason.");
}
// Cleanup
SetupDiDestroyDeviceInfoList(hInfo);
qDebug ()<<"return true";
}
}
}
--------------- Edited to add: -----------------
Hi... the application comes and prints this
\?\usb#vid_04f2&pid_0111#5&1ba5a77f&0&2#{a5dcbf1 0-6530-11d2-901f-00c04fb951ed}
again it goes to while loop .... here it gets breaked in the else statement...
Qt Code:
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Change the buffer size.
if (buffer) LocalFree(buffer);
buffer = (LPTSTR)LocalAlloc(LPTR,buffersize);
} else {
qDebug ()<<"Here it quits the application";
// Insert error handling here. break;
}
Any ideas in this....
After this line:
SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL;
Add this:
DWORD dwDetDataSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA) + 256;
pDetData = (_SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc (dwDetDataSize);
pDetData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
After this line:
qDebug ()<<pDetData->DevicePath;
Add this:
free(pDetData);
But eventually you're going to have to read the docs for SetupDiGetDeviceInterfaceDetail()
. Do it, there are lots of functions that work like this, with pointers to variable-size structs.
-------- Edited to add: --------
You're really going about this the wrong way. I see you're following the advice you got here, and it's taken you down the wrong path. idVendor
and idProduct
can only be found in the USB_DEVICE_DESCRIPTOR
(MSDN).
It looks like you already know how to get the device handle (using CreateFile()
). After that, you call WinUsb_Initialize()
(MSDN). That gets you a WINUSB_INTERFACE_HANDLE
.
Once you have that handle, you want to call WinUsb_GetDescriptor()
(MSDN), with the DescriptorType
set to URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
. I can't test code now, but it will look something like this:
USB_DEVICE_DESCRIPTOR udd;
memset(&udd, 0, sizeof(udd));
ULONG LengthTransferred = 0;
WinUsb_GetDescriptor(
winusb_interface_handle, // returned by WinUsbInitialize
URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
0, // not sure if we need this
0x409, // not sure if we need this
&udd,
sizeof(udd),
&LengthTransferred);
After that, udd->idVendor
and udd->idProduct
should have what you want.
Microsoft used to supply sample code for all this in the DDK, and probably still does, but I don't have access to one.
---------- Edited to add: ----------
Daniel K writes that the code should really be:
USB_DEVICE_DESCRIPTOR udd;
memset(&udd, 0, sizeof(udd));
ULONG LengthTransferred = 0;
WinUsb_GetDescriptor(
winusb_interface_handle, // returned by WinUsbInitialize
USB_DEVICE_DESCRIPTOR_TYPE, // Daniel K's suggestion
0,
0x409, // asks for English
&udd,
sizeof(udd),
&LengthTransferred);
See the comments for further details.
An alternative is to obtain the hardwareID which includes the VID and PID.
Call SetupDiGetDeviceRegistryProperty with SPDRP_HARDWAREID like so:
wchar_t *hardwareID;
// First get requiredLength
SetupDiGetDeviceRegistryProperty(deviceInfoList, &deviceInfoData, SPDRP_HARDWAREID, NULL, NULL, 0, &requiredLength);
hardwareID = (wchar_t*)(new char[requiredLength]());
// Second call to populate hardwareID
SetupDiGetDeviceRegistryProperty(deviceInfoList, &deviceInfoData, SPDRP_HARDWAREID, NULL, (PBYTE)hardwareID, requiredLength, NULL);
// Display the string
qDebug() << "hardwareID =" << QString::fromWCharArray(hardwareID);
This will give you a string like USB\ROOT_HUB20&VID1002&PID4396&REV0000
which you can parse.
*Note: not all devices will have a VID and PID, such as non-USB devices.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With