I need to detect when a gamepad is plugged in for my game (I'm not using a higher-level input API for reasons), how can I do this? I've already enumerated all HID devices and opened files on them (except keyboard, mouse ofc) and can get all the info on the device, but what info do I want? What value(s) will tell me right away that this is an xbox controller, for example, and where are these values?
My code for enumerating over the devices (very messy atm :p):
DWORD required_size = 0, determined_size;
SP_DEVICE_INTERFACE_DATA device_interface_data;
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data;
HANDLE current_device;
PHIDP_PREPARSED_DATA preparsed_data;
WCHAR product_string[128];
for (int i = 0; ; ++i) /* Enumerate HID devices */
{
rv = SetupDiEnumDeviceInterfaces(device_enumeration, NULL, &interface_guid, i, &device_interface_data); /* Does the actual enumeration,
each time we increase index i
to get the next device */
error = GetLastError();
if (error == ERROR_NO_MORE_ITEMS) /* If there are no more devices, break */
break;
else if (!rv && error != ERROR_NO_MORE_ITEMS) /* Otherwise, we have a legit error */
{
cr_print_error(GetLastError());
return EXIT_FAILURE;
}
SetupDiGetDeviceInterfaceDetail(device_enumeration, &device_interface_data, NULL, 0, &required_size, NULL); /* Probing call only to get buffer size,
so error code (122) ignored */
/* Allocate new device detail struct using buffer size we obtained */
determined_size = required_size;
device_interface_detail_data = cr_safe_malloc(required_size);
device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
/* Get detailed info about device */
rv = SetupDiGetDeviceInterfaceDetail(device_enumeration, &device_interface_data, device_interface_detail_data, determined_size, &required_size, NULL);
if (!rv)
{
cr_print_error(GetLastError());
return EXIT_FAILURE;
}
cr_printf("FOUNDD DEVICE: %s\n\n", device_interface_detail_data->DevicePath);
current_device = cr_open_device(device_interface_detail_data->DevicePath);
if (!current_device && GetLastError() == ERROR_ACCESS_DENIED)
goto Done;
cr_printf("OPENED DEVICE: %s\n\n", device_interface_detail_data->DevicePath);
preparsed_data = HidD_GetPreparsedData(current_device, &preparsed_data);
if (!preparsed_data)
{
cr_print_error(GetLastError());
return EXIT_FAILURE;
}
HidD_GetProductString(current_device, product_string, sizeof(product_string));
cr_printf("PRODUCT STRING: %S\n\n", product_string);
HidD_FreePreparsedData(&preparsed_data);
DeleteFile(device_interface_detail_data->DevicePath);
Done:
cr_safe_free(&device_interface_detail_data);
}
SetupDiDestroyDeviceInfoList(device_enumeration);
As you can see I've found the product string, which tells me what the device actually is, but maybe comparing product strings is not the best way to do PnP?