diff --git a/NetworkClient.cpp b/NetworkClient.cpp index 4974e888d..fa5fbbf96 100644 --- a/NetworkClient.cpp +++ b/NetworkClient.cpp @@ -516,6 +516,73 @@ std::vector NetworkClient::GetI2CBusInfo() return(bus_info); } +std::vector NetworkClient::GetUSBDeviceInfo() +{ + /*-----------------------------------------------------*\ + | Send request | + \*-----------------------------------------------------*/ + std::vector 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 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: diff --git a/NetworkClient.h b/NetworkClient.h index c63f134ec..7528daecf 100644 --- a/NetworkClient.h +++ b/NetworkClient.h @@ -112,6 +112,7 @@ public: \*-----------------------------------------------------*/ std::vector GetHIDDeviceInfo(); std::vector GetI2CBusInfo(); + std::vector GetUSBDeviceInfo(); /*-----------------------------------------------------*\ | DetectionManager functions | diff --git a/NetworkProtocol.h b/NetworkProtocol.h index 5182d78b3..3f41c0629 100644 --- a/NetworkProtocol.h +++ b/NetworkProtocol.h @@ -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 */ diff --git a/NetworkServer.cpp b/NetworkServer.cpp index 4f62ffa74..e81c5504e 100644 --- a/NetworkServer.cpp +++ b/NetworkServer.cpp @@ -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 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) { /*-----------------------------------------------------*\ diff --git a/NetworkServer.h b/NetworkServer.h index 3725c766f..56b72919e 100644 --- a/NetworkServer.h +++ b/NetworkServer.h @@ -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); diff --git a/ResourceManager.cpp b/ResourceManager.cpp index 5c893f5d1..b67a080cd 100644 --- a/ResourceManager.cpp +++ b/ResourceManager.cpp @@ -377,6 +377,69 @@ std::vector ResourceManager::GetI2CBusInfo() } } +std::vector ResourceManager::GetUSBDeviceInfo() +{ + if(IsLocalClient()) + { + return(GetLocalClient()->GetUSBDeviceInfo()); + } + else + { + std::size_t usb_device_count; + libusb_device** usb_devices; + std::vector 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(); diff --git a/ResourceManager.h b/ResourceManager.h index 1cb409c53..b67b4d983 100644 --- a/ResourceManager.h +++ b/ResourceManager.h @@ -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 GetHIDDeviceInfo(); std::vector& GetI2CBuses(); std::vector GetI2CBusInfo(); + std::vector GetUSBDeviceInfo(); PluginManagerInterface* GetPluginManager(); ProfileManager* GetProfileManager(); std::vector& GetRGBControllers(); diff --git a/qt/OpenRGBHardwareIDsDialog/OpenRGBHardwareIDsDialog.cpp b/qt/OpenRGBHardwareIDsDialog/OpenRGBHardwareIDsDialog.cpp index f3a2426e4..6721f940e 100644 --- a/qt/OpenRGBHardwareIDsDialog/OpenRGBHardwareIDsDialog.cpp +++ b/qt/OpenRGBHardwareIDsDialog/OpenRGBHardwareIDsDialog.cpp @@ -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 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(); }