Я использую QT на платформе окон.
я хочу получить и отобразить идентификатор поставщика и идентификатор продукта включенного USB-устройства от моей локальной системы.
Ниже мой полный исходный код для получения идентификатора поставщика и идентификатора продукта от USB-устройства.
когда я запускаю свое спокойное приложение, оно не бросает меня никакие ошибки.
таким образом, я включаю USB-устройство в систему.
но мой оператор печати отображает результат как ниже
qDebug ()<<pDetData->DevicePath;
я получаю результат как 0x4
Есть ли у меня какие-либо ошибки реализации в моем исходном коде?
раз так ведите меня, что я делаю неправильно..
Я пропустил какие-либо другие функции?
Действительно ли возможно получить идентификатор поставщика и идентификатор продукта от USB-устройства на основе моего исходного кода. (моя реализация кода)?
любезно см. ниже мой исходный код
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";
}
}
}
---------------Отредактированный для добавления:-----------------
Привет... приложение появляется и печатает это
\? \usb#vid_04f2&pid_0111#5&1ba5a77f&0&2# {a5dcbf1 0-6530-11d2-901f-00c04fb951ed}
снова это переходит к циклу с условием продолжения.... здесь это еще вкладывает breaked оператор...
Спокойный код:
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;
}
Любые идеи в этом....
После этой строки:
SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL;
Добавьте это:
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);
После этой строки:
qDebug ()<<pDetData->DevicePath;
Добавьте это:
free(pDetData);
Но в конечном итоге вам придется прочитать документацию для SetupDiGetDeviceInterfaceDetail()
. Сделайте это, есть много функций, которые работают подобным образом, с указателями на структуры переменного размера.
-------- Отредактировано для добавления: --------
Вы действительно идете к этому неправильным путем. Я вижу, что вы следуете совету, который вы получили здесь, и это привело вас по неправильному пути. idVendor
и idProduct
можно найти только в USB_DEVICE_DESCRIPTOR
(MSDN).
Похоже, вы уже знаете, как получить хэндл устройства (используя CreateFile()
). После этого вы вызываете WinUsb_Initialize()
(MSDN). В результате вы получаете WINUSB_INTERFACE_HANDLE
.
Как только вы получили этот хэндл, вы должны вызвать WinUsb_GetDescriptor()
(MSDN), с DescriptorType
, установленным в URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
. Я не могу проверить код сейчас, но он будет выглядеть примерно так:
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);
После этого, udd->idVendor
и udd->idProduct
должны иметь то, что вы хотите.
Раньше Microsoft поставляла примеры кода для всего этого в DDK, и, возможно, до сих пор поставляет, но у меня нет доступа к ним.
---------- Отредактировано для добавления: ----------
Daniel K пишет, что на самом деле код должен быть таким:
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);
Более подробную информацию смотрите в комментариях.
Вы перечисляете "интерфейс" устройства. Интерфейсы не имеют VID или PID - это делают экземпляры устройств. Я не уверен, перечисляете ли вы интерфейсы, чтобы сузить круг интересующих вас устройств, потому что это ошибка.
Если вы просто перечисляете экземпляры устройств, то вы можете вызвать SetupDiGetDeviceProperty с DEVPKEY_Device_HardwareIds, а затем перечислить полученный аппаратный идентификатор для VID и PID.
Если вы специально используете интерфейсы устройств, то вам нужно один раз вызвать SetupDiGetDeviceInterfaceDetail с параметром NULL PSP_DEVICE_INTERFACE_DETAIL и действительным указателем requiredSize, чтобы получить необходимый размер памяти для выделения, выделить эту память и затем снова вызвать функцию. В этом вызове последним параметром будет структура SP_DEVINFO_DATA, которую после получения можно использовать в вызове SetupDiGetDeviceProperty, как я упоминал выше.