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

This commit is contained in:
Adam Honse
2026-07-01 21:25:09 -05:00
parent df0137c2b0
commit 387fed4f79
8 changed files with 240 additions and 38 deletions

View File

@@ -516,6 +516,73 @@ std::vector<i2c_smbus_info> NetworkClient::GetI2CBusInfo()
return(bus_info);
}
std::vector<USBDeviceInfo> NetworkClient::GetUSBDeviceInfo()
{
/*-----------------------------------------------------*\
| Send request |
\*-----------------------------------------------------*/
std::vector<USBDeviceInfo> device_info;
NetPacketHeader reply_hdr;
InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_GET_USB_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_USB_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++)
{
USBDeviceInfo device;
COPY_DATA_FIELD(data_ptr, response_data_ptr, device.vendor_id);
COPY_DATA_FIELD(data_ptr, response_data_ptr, device.product_id);
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);
device_info.push_back(device);
}
}
COPY_DATA_ERROR:
delete[] response_data_ptr;
response_data_ptr = NULL;
}
return(device_info);
}
/*---------------------------------------------------------*\
| DetectionManager functions |
\*---------------------------------------------------------*/
@@ -1588,6 +1655,7 @@ void NetworkClient::ListenThreadFunction()
case NET_PACKET_ID_GET_I2C_BUS_INFO:
case NET_PACKET_ID_GET_HID_DEVICE_INFO:
case NET_PACKET_ID_GET_USB_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

@@ -112,6 +112,7 @@ public:
\*-----------------------------------------------------*/
std::vector<HIDDeviceInfo> GetHIDDeviceInfo();
std::vector<i2c_smbus_info> GetI2CBusInfo();
std::vector<USBDeviceInfo> GetUSBDeviceInfo();
/*-----------------------------------------------------*\
| DetectionManager functions |

View File

@@ -118,6 +118,7 @@ enum
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_GET_USB_DEVICE_INFO = 122, /* Request list of USB device info */
NET_PACKET_ID_REQUEST_RESCAN_DEVICES = 140, /* Request rescan of devices */

View File

@@ -1291,6 +1291,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo* client_info)
status = ProcessRequest_GetHIDDeviceInfo(client_info);
break;
case NET_PACKET_ID_GET_USB_DEVICE_INFO:
status = ProcessRequest_GetUSBDeviceInfo(client_info);
break;
/*-------------------------------------------------*\
| LogManager functions |
\*-------------------------------------------------*/
@@ -1773,6 +1777,90 @@ NetPacketStatus NetworkServer::ProcessRequest_GetI2CBusInfo(NetworkClientInfo* c
return(NET_PACKET_STATUS_OK);
}
NetPacketStatus NetworkServer::ProcessRequest_GetUSBDeviceInfo(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<USBDeviceInfo> device_info = ResourceManager::get()->GetUSBDeviceInfo();
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(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;
}
/*-----------------------------------------------------*\
| 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);
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;
}
NetPacketHeader reply_hdr;
InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_GET_USB_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_LogManager_ClearLogBuffer(NetworkClientInfo* client_info)
{
/*-----------------------------------------------------*\

View File

@@ -232,6 +232,7 @@ private:
NetPacketStatus ProcessRequest_GetHIDDeviceInfo(NetworkClientInfo* client_info);
NetPacketStatus ProcessRequest_GetI2CBusInfo(NetworkClientInfo* client_info);
NetPacketStatus ProcessRequest_GetUSBDeviceInfo(NetworkClientInfo* client_info);
NetPacketStatus ProcessRequest_LogManager_ClearLogBuffer(NetworkClientInfo* client_info);
NetPacketStatus ProcessRequest_LogManager_GetLogBuffer(NetworkClientInfo* client_info);

View File

@@ -377,6 +377,69 @@ std::vector<i2c_smbus_info> ResourceManager::GetI2CBusInfo()
}
}
std::vector<USBDeviceInfo> ResourceManager::GetUSBDeviceInfo()
{
if(IsLocalClient())
{
return(GetLocalClient()->GetUSBDeviceInfo());
}
else
{
std::size_t usb_device_count;
libusb_device** usb_devices;
std::vector<USBDeviceInfo> usb_info;
if(libusb_init(NULL) >= 0)
{
usb_device_count = libusb_get_device_list(NULL, &usb_devices);
for(std::size_t usb_device_idx = 0; usb_device_idx < usb_device_count; usb_device_idx++)
{
libusb_device_descriptor usb_desc;
libusb_device_handle* usb_handle;
if(libusb_get_device_descriptor(usb_devices[usb_device_idx], &usb_desc) >= 0)
{
USBDeviceInfo usb_device_info;
char usb_descriptor_buf[256];
usb_device_info.vendor_id = usb_desc.idVendor;
usb_device_info.product_id = usb_desc.idProduct;
if(libusb_open(usb_devices[usb_device_idx], &usb_handle) >= 0)
{
if(usb_desc.iSerialNumber)
{
libusb_get_string_descriptor_ascii(usb_handle, usb_desc.iSerialNumber, (unsigned char*)usb_descriptor_buf, sizeof(usb_descriptor_buf));
usb_device_info.serial_number.assign(usb_descriptor_buf);
}
if(usb_desc.iManufacturer)
{
libusb_get_string_descriptor_ascii(usb_handle, usb_desc.iManufacturer, (unsigned char*)usb_descriptor_buf, sizeof(usb_descriptor_buf));
usb_device_info.manufacturer_string.assign(usb_descriptor_buf);
}
if(usb_desc.iProduct)
{
libusb_get_string_descriptor_ascii(usb_handle, usb_desc.iProduct, (unsigned char*)usb_descriptor_buf, sizeof(usb_descriptor_buf));
usb_device_info.product_string.assign(usb_descriptor_buf);
}
libusb_close(usb_handle);
}
usb_info.push_back(usb_device_info);
}
}
libusb_free_device_list(usb_devices, 1);
}
return(usb_info);
}
}
LogManager* ResourceManager::GetLogManager()
{
return LogManager::get();

View File

@@ -50,6 +50,15 @@ typedef struct
std::string path;
} HIDDeviceInfo;
typedef struct
{
unsigned short vendor_id;
unsigned short product_id;
std::string serial_number;
std::string manufacturer_string;
std::string product_string;
} USBDeviceInfo;
class ResourceManager
{
public:
@@ -72,6 +81,7 @@ public:
std::vector<HIDDeviceInfo> GetHIDDeviceInfo();
std::vector<i2c_smbus_interface*>& GetI2CBuses();
std::vector<i2c_smbus_info> GetI2CBusInfo();
std::vector<USBDeviceInfo> GetUSBDeviceInfo();
PluginManagerInterface* GetPluginManager();
ProfileManager* GetProfileManager();
std::vector<RGBController*>& GetRGBControllers();

View File

@@ -74,55 +74,25 @@ int OpenRGBHardwareIDsDialog::show()
/*-----------------------------------------------------*\
| Add USB Devices |
\*-----------------------------------------------------*/
libusb_device** devices = nullptr;
QTreeWidgetItem* libusb_top = new QTreeWidgetItem(ui->HardwareIdsList, {"USB devices"});
std::vector<USBDeviceInfo> usb_device_info = ResourceManager::get()->GetUSBDeviceInfo();
QTreeWidgetItem* usb_top = new QTreeWidgetItem(ui->HardwareIdsList, {"USB devices"});
strings.push_back("\n[ USB devices ]");
int ret;
ret = libusb_init(NULL);
if(ret < 0)
for(USBDeviceInfo device_info : usb_device_info)
{
return 0;
}
char line[550];
ret = libusb_get_device_list(NULL, &devices);
snprintf(line, 550, "[%04X:%04X]", device_info.vendor_id, device_info.product_id);
new QTreeWidgetItem(usb_top, {line, QString::fromStdString(device_info.product_string), QString::fromStdString(device_info.manufacturer_string)});
if(ret < 0)
{
return 0;
}
int deviceCount = ret;
for(int i = 0; i < deviceCount; i++)
{
libusb_device* device = devices[i];
libusb_device_descriptor descriptor;
ret = libusb_get_device_descriptor(device, &descriptor);
if(ret < 0)
{
continue;
}
char line[512];
snprintf(line, 512, "%04X:%04X", descriptor.idVendor, descriptor.idProduct);
new QTreeWidgetItem(libusb_top, {line});
snprintf(line, 550, "[%04X:%04X] %s - %s", device_info.vendor_id, device_info.product_id, device_info.manufacturer_string.c_str(), device_info.product_string.c_str());
strings.push_back(line);
}
if(devices != nullptr)
{
libusb_free_device_list(devices, 1);
}
i2c_top->setExpanded(true);
hid_top->setExpanded(true);
libusb_top->setExpanded(true);
usb_top->setExpanded(true);
return this->exec();
}