Files
itgmania212121/src/archutils/Common/HidDevice.cpp
T

193 lines
3.8 KiB
C++
Raw Normal View History

2025-03-18 17:40:39 +01:00
#include "global.h"
#include "HidDevice.h"
#include "RageLog.h"
2025-03-25 10:17:43 +01:00
HidDevice::HidDevice(int vid, const std::vector<int> pids, int interfaceNum, bool autoReconnection, bool nonBlockingRead) :
vid{ vid },
pids{ pids },
interfaceNum{ interfaceNum },
autoReconnection{ autoReconnection },
2025-03-25 10:17:43 +01:00
nonBlockingRead{ nonBlockingRead }
2025-03-18 17:40:39 +01:00
{
bool result = TryConnect();
if (!result)
{
2025-03-25 10:17:43 +01:00
LOG->Warn("HidDevice with vendor_id %04x and pids %s - %d not found", vid, GetPidsString(pids).c_str(), interfaceNum);
2025-03-18 17:40:39 +01:00
}
else
foundOnce = true;
2025-03-18 17:40:39 +01:00
}
2025-03-25 10:17:43 +01:00
HidDevice::HidDevice(int vid, int pid, int interfaceNum, bool autoReconnection, bool nonBlockingRead) :
HidDevice(vid, make_pids(pid, 1), interfaceNum, autoReconnection, nonBlockingRead)
{
}
2025-03-18 17:40:39 +01:00
HidDevice::~HidDevice()
{
Close();
2025-03-18 17:40:39 +01:00
hid_exit();
}
void HidDevice::Close()
{
hid_close(handle);
handle = nullptr;
2025-03-25 10:17:43 +01:00
foundDeviceInfo.vid = 0;
foundDeviceInfo.pid = 0;
foundDeviceInfo.interfaceNum = 0;
foundDeviceInfo.path = nullptr;
}
bool HidDevice::Open(const char* path)
{
handle = hid_open_path(path);
2025-03-25 10:17:43 +01:00
if(nonBlockingRead)
hid_set_nonblocking(handle, 1);
2025-03-22 13:03:48 -05:00
if(handle)
2025-03-25 10:17:43 +01:00
LOG->Info("HidDevice %04x:%04x: %d opened by path %s", foundDeviceInfo.vid, foundDeviceInfo.pid, foundDeviceInfo.interfaceNum, foundDeviceInfo.path);
2025-03-22 13:03:48 -05:00
return handle != nullptr;
}
2025-03-18 17:40:39 +01:00
bool HidDevice::TryConnect()
{
2025-03-25 10:17:43 +01:00
GetDeviceInfo(vid, pids, interfaceNum, &foundDeviceInfo);
2025-03-25 10:17:43 +01:00
if (foundDeviceInfo.path == nullptr)
return false;
2025-03-18 17:40:39 +01:00
2025-03-25 10:17:43 +01:00
return Open(foundDeviceInfo.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() {
return handle != nullptr;
}
bool HidDevice::FoundOnce()
{
return foundOnce;
}
const RString HidDevice::GetPidsString(const std::vector<int> pids)
{
RString pidsString;
char pid[5] = { 0 };
size_t size = pids.size();
for (size_t i = 0; i < size; ++i)
{
sprintf(pid, "%04X", pids[i]);
pidsString += pid;
if (i != size - 1)
pidsString += ",";
}
return pidsString;
}
2025-03-25 10:17:43 +01:00
void HidDevice::GetDeviceInfo(int vid, const std::vector<int> pids, int interfaceNumber, HidDeviceInfo* device_info)
{
2025-03-25 10:17:43 +01:00
bool found{ false };
struct hid_device_info* devs, * cur_dev;
size_t size = pids.size();
devs = hid_enumerate(vid, 0);
cur_dev = devs;
if (devs && cur_dev)
{
// Look for the desired devices by iterating connected ones
while (cur_dev)
{
for (int i = 0; i < size; i++)
{
if (cur_dev->vendor_id == vid &&
cur_dev->product_id == pids[i])
{
if (interfaceNumber == -1)
{
2025-03-25 10:17:43 +01:00
found = true;
break;
}
else
{
if (cur_dev->interface_number == interfaceNumber)
2025-03-25 10:17:43 +01:00
{
found = true;
break;
}
}
}
}
2025-03-25 22:09:00 +01:00
if (found)
break;
cur_dev = cur_dev->next;
}
}
2025-03-25 10:17:43 +01:00
if (found && cur_dev != nullptr)
{
device_info->vid = cur_dev->vendor_id;
device_info->pid = cur_dev->product_id;
device_info->interfaceNum = cur_dev->interface_number;
device_info->path = cur_dev->path;
}
2025-03-18 17:40:39 +01:00
}
int HidDevice::Read(unsigned char* data, size_t length)
2025-03-18 17:40:39 +01:00
{
if (!CheckConnection())
2025-03-25 10:17:43 +01:00
return NotConnected;
int result = hid_read(handle, data, length);
2025-03-18 17:40:39 +01:00
2025-03-25 10:17:43 +01:00
if (result == -1)
{
2025-03-25 10:17:43 +01:00
LOG->Warn("HidDevice %04x:%04x: %d read failed. Fail reason %ls", foundDeviceInfo.vid, foundDeviceInfo.pid, foundDeviceInfo.interfaceNum, GetError());
Close();
}
return result;
2025-03-18 17:40:39 +01:00
}
2025-03-25 10:17:43 +01:00
HidResults HidDevice::Write(const unsigned char* data, size_t length)
{
if (!CheckConnection())
return NotConnected;
int result = hid_write(handle, data, length);
if (result != length)
{
LOG->Warn("HidDevice %04x:%04x: %d write failed. Fail reason %ls", foundDeviceInfo.vid, foundDeviceInfo.pid, foundDeviceInfo.interfaceNum, GetError());
Close();
return OperationFailed;
}
return Success;
}