Created
January 7, 2015 13:02
-
-
Save rakesh-gopal/9ac217aa218e32372eb4 to your computer and use it in GitHub Desktop.
List the USB devices connected
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
#include <windows.h> | |
#include <tchar.h> | |
#include <setupapi.h> | |
#include <initguid.h> | |
#include <stdio.h> | |
// This is the GUID for the USB device class | |
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, | |
0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); | |
// (A5DCBF10-6530-11D2-901F-00C04FB951ED) | |
int main() | |
{ | |
HDEVINFO hDevInfo; | |
SP_DEVICE_INTERFACE_DATA DevIntfData; | |
PSP_DEVICE_INTERFACE_DETAIL_DATA DevIntfDetailData; | |
SP_DEVINFO_DATA DevData; | |
DWORD dwSize, dwType, dwMemberIdx; | |
HKEY hKey; | |
BYTE lpData[1024]; | |
// We will try to get device information set for all USB devices that have a | |
// device interface and are currently present on the system (plugged in). | |
hDevInfo = SetupDiGetClassDevs( | |
&GUID_DEVINTERFACE_USB_DEVICE, NULL, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); | |
if (hDevInfo != INVALID_HANDLE_VALUE) | |
{ | |
// Prepare to enumerate all device interfaces for the device information | |
// set that we retrieved with SetupDiGetClassDevs(..) | |
DevIntfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); | |
dwMemberIdx = 0; | |
// Next, we will keep calling this SetupDiEnumDeviceInterfaces(..) until this | |
// function causes GetLastError() to return ERROR_NO_MORE_ITEMS. With each | |
// call the dwMemberIdx value needs to be incremented to retrieve the next | |
// device interface information. | |
SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_USB_DEVICE, | |
dwMemberIdx, &DevIntfData); | |
while(GetLastError() != ERROR_NO_MORE_ITEMS) | |
{ | |
// As a last step we will need to get some more details for each | |
// of device interface information we are able to retrieve. This | |
// device interface detail gives us the information we need to identify | |
// the device (VID/PID), and decide if it's useful to us. It will also | |
// provide a DEVINFO_DATA structure which we can use to know the serial | |
// port name for a virtual com port. | |
DevData.cbSize = sizeof(DevData); | |
// Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with | |
// a NULL DevIntfDetailData pointer, a DevIntfDetailDataSize | |
// of zero, and a valid RequiredSize variable. In response to such a call, | |
// this function returns the required buffer size at dwSize. | |
SetupDiGetDeviceInterfaceDetail( | |
hDevInfo, &DevIntfData, NULL, 0, &dwSize, NULL); | |
// Allocate memory for the DeviceInterfaceDetail struct. Don't forget to | |
// deallocate it later! | |
DevIntfDetailData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); | |
DevIntfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); | |
if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevIntfData, | |
DevIntfDetailData, dwSize, &dwSize, &DevData)) | |
{ | |
// Finally we can start checking if we've found a useable device, | |
// by inspecting the DevIntfDetailData->DevicePath variable. | |
// The DevicePath looks something like this: | |
// | |
// \\?\usb#vid_04d8&pid_0033#5&19f2438f&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed} | |
// | |
// The VID for Velleman Projects is always 10cf. The PID is variable | |
// for each device: | |
// | |
// ------------------- | |
// | Device | PID | | |
// ------------------- | |
// | K8090 | 8090 | | |
// | VMB1USB | 0b1b | | |
// ------------------- | |
// | |
// As you can see it contains the VID/PID for the device, so we can check | |
// for the right VID/PID with string handling routines. | |
if (NULL != _tcsstr((TCHAR*)DevIntfDetailData->DevicePath, _T("vid_10cf&pid_8090"))) | |
{ | |
// To find out the serial port for our K8090 device, | |
// we'll need to check the registry: | |
hKey = SetupDiOpenDevRegKey( | |
hDevInfo, | |
&DevData, | |
DICS_FLAG_GLOBAL, | |
0, | |
DIREG_DEV, | |
KEY_READ | |
); | |
dwType = REG_SZ; | |
dwSize = sizeof(lpData); | |
RegQueryValueEx(hKey, _T("PortName"), NULL, &dwType, lpData, &dwSize); | |
RegCloseKey(hKey); | |
// Eureka! | |
wprintf(_T("Found a device on port '%s'\n"), lpData); | |
} | |
} | |
HeapFree(GetProcessHeap(), 0, DevIntfDetailData); | |
// Continue looping | |
SetupDiEnumDeviceInterfaces( | |
hDevInfo, NULL, &GUID_DEVINTERFACE_USB_DEVICE, ++dwMemberIdx, &DevIntfData); | |
} | |
SetupDiDestroyDeviceInfoList(hDevInfo); | |
} | |
return 0; | |
} |
This gives me the error: undefined reference to `__imp_SetupDiGetClassDevsA' While compiling in Code::Blocks.
#pragma comment (lib, "Setupapi.lib")
GUID_DEVINTERFACE_USB_DEVICE
is defined in Usbiodef.h, no need to redefine it manually (https://learn.microsoft.com/en-us/windows-hardware/drivers/install/guid-devinterface-usb-device).
Otherwise this snippet works great, and for USB-to-serial converters allows you to query which COM port (if any) is associated with the USB device, which is amazing and I didn't think it was possible / so simple (relatively speaking).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This gives me the error: undefined reference to `__imp_SetupDiGetClassDevsA'
While compiling in Code::Blocks.