Add network request for requesting list of HID devices in local client mode

This commit is contained in:
Adam Honse
2026-07-01 17:49:07 -05:00
parent 7c059fa3e3
commit df0137c2b0
8 changed files with 257 additions and 16 deletions

View File

@@ -387,6 +387,81 @@ void NetworkClient::RegisterNetworkClientCallback(NetworkClientCallback new_call
/*---------------------------------------------------------*\
| Device Info Functions |
\*---------------------------------------------------------*/
std::vector<HIDDeviceInfo> NetworkClient::GetHIDDeviceInfo()
{
/*-----------------------------------------------------*\
| Send request |
\*-----------------------------------------------------*/
std::vector<HIDDeviceInfo> device_info;
NetPacketHeader reply_hdr;
InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_GET_HID_DEVICE_INFO, 0);
send_in_progress.lock();
send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL);
send_in_progress.unlock();
/*-----------------------------------------------------*\
| Wait for response |
\*-----------------------------------------------------*/
std::unique_lock<std::mutex> wait_lock(waiting_on_response_mutex);
waiting_on_response_cv.wait(wait_lock);
/*-----------------------------------------------------*\
| Parse response into device list |
\*-----------------------------------------------------*/
if(response_header.pkt_id == NET_PACKET_ID_GET_HID_DEVICE_INFO && response_data_ptr != NULL)
{
unsigned int device_count = 0;
unsigned char* data_ptr = response_data_ptr;
unsigned int& data_size = response_header.pkt_size;
unsigned int data_size_pkt;
COPY_DATA_FIELD(data_ptr, response_data_ptr, data_size_pkt);
if(data_size_pkt == data_size)
{
COPY_DATA_FIELD(data_ptr, response_data_ptr, device_count);
for(unsigned int device_idx = 0; device_idx < device_count; device_idx++)
{
HIDDeviceInfo device;
COPY_DATA_FIELD(data_ptr, response_data_ptr, device.vendor_id);
COPY_DATA_FIELD(data_ptr, response_data_ptr, device.product_id);
COPY_DATA_FIELD(data_ptr, response_data_ptr, device.release_number);
COPY_DATA_FIELD(data_ptr, response_data_ptr, device.usage_page);
COPY_DATA_FIELD(data_ptr, response_data_ptr, device.usage);
COPY_DATA_FIELD(data_ptr, response_data_ptr, device.interface_number);
unsigned short serial_number_size;
COPY_DATA_FIELD(data_ptr, response_data_ptr, serial_number_size);
COPY_STRING_FIELD(data_ptr, response_data_ptr, serial_number_size, device.serial_number);
unsigned short manufacturer_string_size;
COPY_DATA_FIELD(data_ptr, response_data_ptr, manufacturer_string_size);
COPY_STRING_FIELD(data_ptr, response_data_ptr, manufacturer_string_size, device.manufacturer_string);
unsigned short product_string_size;
COPY_DATA_FIELD(data_ptr, response_data_ptr, product_string_size);
COPY_STRING_FIELD(data_ptr, response_data_ptr, product_string_size, device.product_string);
unsigned short path_size;
COPY_DATA_FIELD(data_ptr, response_data_ptr, path_size);
COPY_STRING_FIELD(data_ptr, response_data_ptr, path_size, device.path);
device_info.push_back(device);
}
}
COPY_DATA_ERROR:
delete[] response_data_ptr;
response_data_ptr = NULL;
}
return(device_info);
}
std::vector<i2c_smbus_info> NetworkClient::GetI2CBusInfo()
{
/*-----------------------------------------------------*\
@@ -425,7 +500,7 @@ std::vector<i2c_smbus_info> NetworkClient::GetI2CBusInfo()
for(unsigned int bus_idx = 0; bus_idx < bus_count; bus_idx++)
{
i2c_smbus_info bus;
i2c_smbus_info bus;
COPY_DATA_FIELD(data_ptr, response_data_ptr, bus);
@@ -1512,6 +1587,7 @@ void NetworkClient::ListenThreadFunction()
break;
case NET_PACKET_ID_GET_I2C_BUS_INFO:
case NET_PACKET_ID_GET_HID_DEVICE_INFO:
case NET_PACKET_ID_LOGMANAGER_GET_LOG_LEVEL:
case NET_PACKET_ID_PROFILEMANAGER_DOWNLOAD_PROFILE:
case NET_PACKET_ID_PROFILEMANAGER_GET_ACTIVE_PROFILE:

View File

@@ -17,6 +17,7 @@
#include <thread>
#include <condition_variable>
#include "i2c_smbus.h"
#include "ResourceManager.h"
#include "RGBController.h"
#include "NetworkProtocol.h"
#include "net_port.h"
@@ -109,6 +110,7 @@ public:
/*-----------------------------------------------------*\
| Device Info Functions |
\*-----------------------------------------------------*/
std::vector<HIDDeviceInfo> GetHIDDeviceInfo();
std::vector<i2c_smbus_info> GetI2CBusInfo();
/*-----------------------------------------------------*\

View File

@@ -117,6 +117,7 @@ enum
NET_PACKET_ID_DETECTION_COMPLETE = 103, /* Indicate to clients that detection completed */
NET_PACKET_ID_GET_I2C_BUS_INFO = 120, /* Request list of I2C bus info */
NET_PACKET_ID_GET_HID_DEVICE_INFO = 121, /* Request list of HID device info */
NET_PACKET_ID_REQUEST_RESCAN_DEVICES = 140, /* Request rescan of devices */

View File

@@ -1287,6 +1287,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo* client_info)
status = ProcessRequest_GetI2CBusInfo(client_info);
break;
case NET_PACKET_ID_GET_HID_DEVICE_INFO:
status = ProcessRequest_GetHIDDeviceInfo(client_info);
break;
/*-------------------------------------------------*\
| LogManager functions |
\*-------------------------------------------------*/
@@ -1616,6 +1620,114 @@ NetPacketStatus NetworkServer::ProcessRequest_RescanDevices()
return(NET_PACKET_STATUS_OK);
}
NetPacketStatus NetworkServer::ProcessRequest_GetHIDDeviceInfo(NetworkClientInfo* client_info)
{
/*-----------------------------------------------------*\
| Require local client for this packet |
\*-----------------------------------------------------*/
if(!client_info->client_is_local_client)
{
return(NET_PACKET_STATUS_ERROR_NOT_ALLOWED);
}
std::vector<HIDDeviceInfo> device_info = ResourceManager::get()->GetHIDDeviceInfo();
unsigned int data_size = 0;
unsigned int device_count = (unsigned int)device_info.size();
/*-----------------------------------------------------*\
| Calculate data size |
\*-----------------------------------------------------*/
data_size += sizeof(data_size);
data_size += sizeof(device_count);
for(unsigned int device_idx = 0; device_idx < device_count; device_idx++)
{
data_size += sizeof(device_info[device_idx].vendor_id);
data_size += sizeof(device_info[device_idx].product_id);
data_size += sizeof(device_info[device_idx].release_number);
data_size += sizeof(device_info[device_idx].usage_page);
data_size += sizeof(device_info[device_idx].usage);
data_size += sizeof(device_info[device_idx].interface_number);
data_size += sizeof(unsigned short);
data_size += (unsigned int)strlen(device_info[device_idx].serial_number.c_str()) + 1;
data_size += sizeof(unsigned short);
data_size += (unsigned int)strlen(device_info[device_idx].manufacturer_string.c_str()) + 1;
data_size += sizeof(unsigned short);
data_size += (unsigned int)strlen(device_info[device_idx].product_string.c_str()) + 1;
data_size += sizeof(unsigned short);
data_size += (unsigned int)strlen(device_info[device_idx].path.c_str()) + 1;
}
/*-----------------------------------------------------*\
| Copy in data |
\*-----------------------------------------------------*/
unsigned char* data_buf = new unsigned char[data_size];
unsigned char* data_ptr = data_buf;
memcpy(data_ptr, &data_size, sizeof(data_size));
data_ptr += sizeof(data_size);
memcpy(data_ptr, &device_count, sizeof(device_count));
data_ptr += sizeof(device_count);
for(unsigned int device_idx = 0; device_idx < device_count; device_idx++)
{
memcpy(data_ptr, &device_info[device_idx].vendor_id, sizeof(device_info[device_idx].vendor_id));
data_ptr += sizeof(device_info[device_idx].vendor_id);
memcpy(data_ptr, &device_info[device_idx].product_id, sizeof(device_info[device_idx].product_id));
data_ptr += sizeof(device_info[device_idx].product_id);
memcpy(data_ptr, &device_info[device_idx].release_number, sizeof(device_info[device_idx].release_number));
data_ptr += sizeof(device_info[device_idx].release_number);
memcpy(data_ptr, &device_info[device_idx].usage_page, sizeof(device_info[device_idx].usage_page));
data_ptr += sizeof(device_info[device_idx].usage_page);
memcpy(data_ptr, &device_info[device_idx].usage, sizeof(device_info[device_idx].usage));
data_ptr += sizeof(device_info[device_idx].usage);
memcpy(data_ptr, &device_info[device_idx].interface_number, sizeof(device_info[device_idx].interface_number));
data_ptr += sizeof(device_info[device_idx].interface_number);
unsigned short serial_number_size = (unsigned short)strlen(device_info[device_idx].serial_number.c_str()) + 1;
memcpy(data_ptr, &serial_number_size, sizeof(serial_number_size));
data_ptr += sizeof(serial_number_size);
memcpy(data_ptr, device_info[device_idx].serial_number.c_str(), serial_number_size);
data_ptr += serial_number_size;
unsigned short manufacturer_string_size = (unsigned short)strlen(device_info[device_idx].manufacturer_string.c_str()) + 1;
memcpy(data_ptr, &manufacturer_string_size, sizeof(manufacturer_string_size));
data_ptr += sizeof(manufacturer_string_size);
memcpy(data_ptr, device_info[device_idx].manufacturer_string.c_str(), manufacturer_string_size);
data_ptr += manufacturer_string_size;
unsigned short product_string_size = (unsigned short)strlen(device_info[device_idx].product_string.c_str()) + 1;
memcpy(data_ptr, &product_string_size, sizeof(product_string_size));
data_ptr += sizeof(product_string_size);
memcpy(data_ptr, device_info[device_idx].product_string.c_str(), product_string_size);
data_ptr += product_string_size;
unsigned short path_size = (unsigned short)strlen(device_info[device_idx].path.c_str()) + 1;
memcpy(data_ptr, &path_size, sizeof(path_size));
data_ptr += sizeof(path_size);
memcpy(data_ptr, device_info[device_idx].path.c_str(), path_size);
data_ptr += path_size;
}
NetPacketHeader reply_hdr;
InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_GET_HID_DEVICE_INFO, data_size);
send_in_progress.lock();
send(client_info->client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL);
send(client_info->client_sock, (char *)data_buf, reply_hdr.pkt_size, MSG_NOSIGNAL);
send_in_progress.unlock();
return(NET_PACKET_STATUS_OK);
}
NetPacketStatus NetworkServer::ProcessRequest_GetI2CBusInfo(NetworkClientInfo* client_info)
{
/*-----------------------------------------------------*\

View File

@@ -230,6 +230,7 @@ private:
NetPacketStatus ProcessRequest_ClientString(NetworkClientInfo* client_info, unsigned int data_size, unsigned char* data_ptr);
NetPacketStatus ProcessRequest_RescanDevices();
NetPacketStatus ProcessRequest_GetHIDDeviceInfo(NetworkClientInfo* client_info);
NetPacketStatus ProcessRequest_GetI2CBusInfo(NetworkClientInfo* client_info);
NetPacketStatus ProcessRequest_LogManager_ClearLogBuffer(NetworkClientInfo* client_info);

View File

@@ -24,10 +24,17 @@
#include "ProfileManager.h"
#include "LogManager.h"
#include "SettingsManager.h"
#include "StringUtils.h"
#include "NetworkClient.h"
#include "NetworkServer.h"
#include "filesystem.h"
/*---------------------------------------------------------*\
| Put these last to avoid some include order issues |
\*---------------------------------------------------------*/
#include <hidapi.h>
#include <libusb.h>
#ifdef __linux__
#include <sys/resource.h>
#endif
@@ -308,6 +315,43 @@ unsigned short ResourceManager::GetDefaultServerPort()
return(default_server_port);
}
std::vector<HIDDeviceInfo> ResourceManager::GetHIDDeviceInfo()
{
if(IsLocalClient())
{
return(GetLocalClient()->GetHIDDeviceInfo());
}
else
{
hid_device_info* hid_devices;
std::vector<HIDDeviceInfo> hid_info;
hid_devices = hid_enumerate(0,0);
while(hid_devices)
{
HIDDeviceInfo hid_device_info;
hid_device_info.vendor_id = hid_devices->vendor_id;
hid_device_info.product_id = hid_devices->product_id;
hid_device_info.release_number = hid_devices->release_number;
hid_device_info.usage_page = hid_devices->usage_page;
hid_device_info.usage = hid_devices->usage;
hid_device_info.interface_number = hid_devices->interface_number;
hid_device_info.serial_number = StringUtils::wchar_to_string(hid_devices->serial_number);
hid_device_info.manufacturer_string = StringUtils::wchar_to_string(hid_devices->manufacturer_string);
hid_device_info.product_string = StringUtils::wchar_to_string(hid_devices->product_string);
hid_device_info.path = hid_devices->path;
hid_info.push_back(hid_device_info);
hid_devices = hid_devices->next;
}
return(hid_info);
}
}
std::vector<i2c_smbus_interface*> & ResourceManager::GetI2CBuses()
{
return DetectionManager::get()->GetI2CBuses();

View File

@@ -36,6 +36,20 @@ class ProfileManager;
class RGBController;
class SettingsManager;
typedef struct
{
unsigned short vendor_id;
unsigned short product_id;
unsigned short release_number;
unsigned short usage_page;
unsigned short usage;
int interface_number;
std::string serial_number;
std::string manufacturer_string;
std::string product_string;
std::string path;
} HIDDeviceInfo;
class ResourceManager
{
public:
@@ -55,6 +69,7 @@ public:
std::string GetDefaultServerHost();
unsigned short GetDefaultServerPort();
LogManager* GetLogManager();
std::vector<HIDDeviceInfo> GetHIDDeviceInfo();
std::vector<i2c_smbus_interface*>& GetI2CBuses();
std::vector<i2c_smbus_info> GetI2CBusInfo();
PluginManagerInterface* GetPluginManager();

View File

@@ -55,30 +55,20 @@ int OpenRGBHardwareIDsDialog::show()
/*-----------------------------------------------------*\
| Add HID Devices |
\*-----------------------------------------------------*/
hid_device_info* hid_devices = NULL;
hid_devices = hid_enumerate(0,0);
hid_device_info* current_hid_device;
current_hid_device = hid_devices;
std::vector<HIDDeviceInfo> hid_device_info = ResourceManager::get()->GetHIDDeviceInfo();
QTreeWidgetItem* hid_top = new QTreeWidgetItem(ui->HardwareIdsList, {"HID Devices"});
strings.push_back("\n[ HID Devices ]");
while(current_hid_device)
for(HIDDeviceInfo device_info : hid_device_info)
{
const char* manu_name = StringUtils::wchar_to_char(current_hid_device->manufacturer_string);
const char* prod_name = StringUtils::wchar_to_char(current_hid_device->product_string);
char line[550];
snprintf(line, 550, "[%04X:%04X U=%04X P=0x%04X I=%d]", current_hid_device->vendor_id, current_hid_device->product_id, current_hid_device->usage, current_hid_device->usage_page, current_hid_device->interface_number);
new QTreeWidgetItem(hid_top, {line, prod_name, manu_name});
snprintf(line, 550, "[%04X:%04X U=%04X P=0x%04X I=%d]", device_info.vendor_id, device_info.product_id, device_info.usage, device_info.usage_page, device_info.interface_number);
new QTreeWidgetItem(hid_top, {line, QString::fromStdString(device_info.product_string), QString::fromStdString(device_info.manufacturer_string)});
snprintf(line, 550, "[%04X:%04X U=%04X P=0x%04X I=%d] %s - %s", current_hid_device->vendor_id, current_hid_device->product_id, current_hid_device->usage, current_hid_device->usage_page, current_hid_device->interface_number, manu_name, prod_name);
snprintf(line, 550, "[%04X:%04X U=%04X P=0x%04X I=%d] %s - %s", device_info.vendor_id, device_info.product_id, device_info.usage, device_info.usage_page, device_info.interface_number, device_info.manufacturer_string.c_str(), device_info.product_string.c_str());
strings.push_back(line);
current_hid_device = current_hid_device->next;
}
/*-----------------------------------------------------*\