I’ve made this project using C++ and HIDAPI to interact with a dualsense controller.
#include <hidapi/hidapi.h>
#include <iostream>
#include <vector>
hid_device* find_device(unsigned short vendor_id, unsigned short product_id) {
struct hid_device_info* devices = hid_enumerate(0x0, 0x0);
hid_device* target_device = nullptr;
for (struct hid_device_info* cur = devices; cur != nullptr; cur = cur->next) {
if (cur->vendor_id == vendor_id && cur->product_id == product_id) {
std::wcout << L"Found device: " << cur->manufacturer_string
<< L" - " << cur->product_string << std::endl;
target_device = hid_open_path(cur->path);
break;
}
}
hid_free_enumeration(devices);
return target_device;
}
bool send_feature_report(hid_device* dev, unsigned char report_id, const std::vector<unsigned char>& data) {
std::vector<unsigned char> buffer(data.size() + 1);
buffer[0] = report_id;
std::copy(data.begin(), data.end(), buffer.begin() + 1);
return hid_send_feature_report(dev, buffer.data(), buffer.size()) >= 0;
}
std::vector<unsigned char> receive_feature_report(hid_device* dev, unsigned char report_id, size_t expected_length) {
std::vector<unsigned char> buffer(expected_length + 1, 0);
buffer[0] = report_id;
if (hid_get_feature_report(dev, buffer.data(), buffer.size()) < 0) {
return {};
}
return std::vector<unsigned char>(buffer.begin() + 1, buffer.end());
}
int nvstatus(hid_device* dev) {
send_feature_report(dev, 0x80, {3, 3});
auto response = receive_feature_report(dev, 0x81, 8);
if (response.size() < 4) return 2;
unsigned int ret = (response[0] << 24) | (response[1] << 16) | (response[2] << 8) | response[3];
return (ret == 0x03030201) ? 1 : (ret == 0x03030200) ? 0 : ret;
}
int main() {
const unsigned short vendor_id = 0x054C;
const unsigned short product_id = 0x0CE6;
hid_init();
hid_device* dev = find_device(vendor_id, product_id);
if (dev) {
int status = nvstatus(dev);
std::cout << "nvstatus: " << status << 'n';
hid_close(dev);
}
hid_exit();
}
hid_get_feature_report
fails because DeviceIoControl
returns an error. Here’s the relevant snippet from the HIDAPI library:
static int hid_get_report(hid_device *dev, DWORD report_type, unsigned char *data, size_t length)
{
BOOL res;
DWORD bytes_returned = 0;
OVERLAPPED ol;
memset(&ol, 0, sizeof(ol));
if (!data || !length) {
register_string_error(dev, L"Zero buffer/length");
return -1;
}
register_string_error(dev, NULL);
res = DeviceIoControl(dev->device_handle,
report_type,
data, (DWORD) length,
data, (DWORD) length,
&bytes_returned, &ol);
if (!res) {
if (GetLastError() != ERROR_IO_PENDING) {
/* DeviceIoControl() failed. Return error. */
register_winapi_error(dev, L"Get Input/Feature Report DeviceIoControl");
return -1;
}
}
/* Wait here until the write is done. This makes
hid_get_feature_report() synchronous. */
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
if (!res) {
/* The operation failed. */
register_winapi_error(dev, L"Get Input/Feature Report GetOverLappedResult");
return -1;
}
/* When numbered reports aren't used,
bytes_returned seem to include only what is actually received from the device
(not including the first byte with 0, as an indication "no numbered reports"). */
if (data[0] == 0x0) {
bytes_returned++;
}
return bytes_returned;
}
When the DeviceIoControl
call is made, it fails with the error:
Error Code: 0x00000057 (The parameter is incorrect)
The device is accessible, and I can use hid_open
without issues. Other HID operations (like sending reports) work fine.
Reference: deviceiocontrol
92half99 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2