2025-03-18 17:40:39 +01:00
|
|
|
#include "global.h"
|
|
|
|
|
#include "HidDevice.h"
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
|
2025-03-22 17:28:21 +01:00
|
|
|
HidDevice::HidDevice(int vid, int pid, int interfaceNum, bool autoReconnection, bool nonBlockingWrite) :
|
2025-03-19 10:22:20 +01:00
|
|
|
vid{ vid },
|
|
|
|
|
pid{ pid },
|
|
|
|
|
interfaceNum{ interfaceNum },
|
2025-03-22 17:28:21 +01:00
|
|
|
autoReconnection{autoReconnection},
|
|
|
|
|
nonBlockingWrite{nonBlockingWrite}
|
2025-03-18 17:40:39 +01:00
|
|
|
{
|
|
|
|
|
bool result = TryConnect();
|
|
|
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
|
|
2025-03-22 17:28:21 +01:00
|
|
|
LOG->Warn("HID device with VID/PID %04x/%04x not found.", vid, pid);
|
2025-03-18 17:40:39 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
2025-03-19 10:22:20 +01:00
|
|
|
foundOnce = true;
|
2025-03-18 17:40:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HidDevice::~HidDevice()
|
|
|
|
|
{
|
2025-03-19 10:22:20 +01:00
|
|
|
Close();
|
2025-03-18 17:40:39 +01:00
|
|
|
hid_exit();
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 21:38:27 +01:00
|
|
|
void HidDevice::Close()
|
|
|
|
|
{
|
|
|
|
|
hid_close(handle);
|
|
|
|
|
handle = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-19 10:22:20 +01:00
|
|
|
bool HidDevice::Open(const char* path)
|
2025-03-18 21:38:27 +01:00
|
|
|
{
|
|
|
|
|
handle = hid_open_path(path);
|
|
|
|
|
|
2025-03-22 17:28:21 +01:00
|
|
|
if(nonBlockingWrite)
|
|
|
|
|
hid_set_nonblocking(handle, 1);
|
|
|
|
|
|
2025-03-22 13:03:48 -05:00
|
|
|
if(handle)
|
|
|
|
|
LOG->Info("HidDevice opened %04x:%04x:%d by path %s", vid, pid, interfaceNum, path);
|
|
|
|
|
|
2025-03-18 21:38:27 +01:00
|
|
|
return handle != nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 17:40:39 +01:00
|
|
|
bool HidDevice::TryConnect()
|
|
|
|
|
{
|
2025-03-19 10:22:20 +01:00
|
|
|
char* path = GetPath(vid, pid, interfaceNum);
|
|
|
|
|
|
2025-03-18 21:38:27 +01:00
|
|
|
if (path == nullptr)
|
|
|
|
|
return false;
|
2025-03-18 17:40:39 +01:00
|
|
|
|
2025-03-19 10:22:20 +01:00
|
|
|
return Open(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool HidDevice::CheckConnection()
|
|
|
|
|
{
|
|
|
|
|
if (IsConnected())
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (!autoReconnection || !foundOnce)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return TryConnect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const wchar_t* HidDevice::GetError()
|
|
|
|
|
{
|
|
|
|
|
return hid_read_error(handle);
|
2025-03-18 17:40:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool HidDevice::IsConnected() {
|
2025-03-18 21:38:27 +01:00
|
|
|
return handle != nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-22 17:28:21 +01:00
|
|
|
bool HidDevice::FoundOnce()
|
|
|
|
|
{
|
|
|
|
|
return foundOnce;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 21:38:27 +01:00
|
|
|
char* HidDevice::GetPath(int vid, int pid, int interfaceNumber)
|
|
|
|
|
{
|
|
|
|
|
struct hid_device_info* devs, * cur_dev;
|
|
|
|
|
|
|
|
|
|
devs = hid_enumerate(vid, pid);
|
|
|
|
|
cur_dev = devs;
|
|
|
|
|
|
|
|
|
|
if (devs && cur_dev)
|
|
|
|
|
{
|
|
|
|
|
// Look for the desired devices by iterating connected ones
|
|
|
|
|
while (cur_dev)
|
|
|
|
|
{
|
|
|
|
|
if (cur_dev->vendor_id == vid &&
|
|
|
|
|
cur_dev->product_id == pid)
|
|
|
|
|
{
|
|
|
|
|
if (interfaceNumber == -1)
|
|
|
|
|
{
|
|
|
|
|
return cur_dev->path;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(cur_dev->interface_number == interfaceNumber)
|
|
|
|
|
return cur_dev->path;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cur_dev = cur_dev->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
2025-03-18 17:40:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HidDevice::Read(unsigned char* data, size_t length)
|
|
|
|
|
{
|
2025-03-19 10:22:20 +01:00
|
|
|
if (!CheckConnection())
|
2025-03-18 17:40:39 +01:00
|
|
|
return;
|
2025-03-19 10:22:20 +01:00
|
|
|
int result = hid_read(handle, data, length);
|
2025-03-18 17:40:39 +01:00
|
|
|
|
2025-03-19 10:22:20 +01:00
|
|
|
if (result == -1)
|
|
|
|
|
{
|
2025-03-22 17:28:21 +01:00
|
|
|
LOG->Warn("HID device with VID/PID %04x/%04x read failed. Fail reason %ls", vid, pid, GetError());
|
2025-03-19 10:22:20 +01:00
|
|
|
}
|
2025-03-18 17:40:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HidDevice::Write(const unsigned char* data, size_t length)
|
|
|
|
|
{
|
2025-03-19 10:22:20 +01:00
|
|
|
if (!CheckConnection())
|
2025-03-18 17:40:39 +01:00
|
|
|
return;
|
2025-03-22 13:03:48 -05:00
|
|
|
|
2025-03-18 21:38:27 +01:00
|
|
|
int result = hid_write(handle, data, length);
|
|
|
|
|
|
|
|
|
|
if (result != length)
|
2025-03-19 10:22:20 +01:00
|
|
|
{
|
2025-03-22 17:28:21 +01:00
|
|
|
LOG->Warn("HID device with VID/PID %04x/%04x write failed. Fail reason %ls", vid, pid, GetError());
|
2025-03-18 21:38:27 +01:00
|
|
|
Close();
|
2025-03-19 10:22:20 +01:00
|
|
|
}
|
2025-03-18 17:40:39 +01:00
|
|
|
}
|