From 3e1bb7b66c9cc22924dba539310a3c01af5440cc Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Tue, 7 Jul 2026 17:00:51 -0500 Subject: [PATCH] Add network packet for requesting USB serial ports --- Documentation/OpenRGBSDK.md | 28 +++++++++++++ NetworkClient.cpp | 67 +++++++++++++++++++++++++++++++ NetworkClient.h | 1 + NetworkProtocol.h | 1 + NetworkServer.cpp | 80 +++++++++++++++++++++++++++++++++++++ NetworkServer.h | 1 + ResourceManager.cpp | 2 +- 7 files changed, 179 insertions(+), 1 deletion(-) diff --git a/Documentation/OpenRGBSDK.md b/Documentation/OpenRGBSDK.md index bb30cc720..4fba9a713 100644 --- a/Documentation/OpenRGBSDK.md +++ b/Documentation/OpenRGBSDK.md @@ -63,6 +63,7 @@ The following IDs represent different SDK commands. Each ID packet has a certai | 121 | [NET_PACKET_ID_GET_HID_DEVICE_INFO](#net_packet_id_get_hid_device_info) | Request list of HID device info | 6 | | 122 | [NET_PACKET_ID_GET_USB_DEVICE_INFO](#net_packet_id_get_usb_device_info) | Request list of USB device info | 6 | | 123 | [NET_PACKET_ID_GET_SERIAL_PORTS](#net_packet_id_get_serial_ports) | Request list of serial ports | 6 | +| 124 | [NET_PACKET_ID_GET_USB_SERIAL_PORTS](#net_packet_id_get_usb_serial_ports) | Request list of USB serial port info | 6 | | 140 | [NET_PACKET_ID_REQUEST_RESCAN_DEVICES](#net_packet_id_request_rescan_devices) | Request server to rescan devices | 5 | | 150 | [NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST](#net_packet_id_profilemanager_get_profile_list) | Get profile list | 2 | | 151 | [NET_PACKET_ID_PROFILEMANAGER_SAVE_PROFILE](#net_packet_id_profilemanager_save_profile) | Save current configuration in a new profile | 2 | @@ -482,6 +483,33 @@ The server responds with a data block containing serial port information. | 2 | unsigned short | port_string_size | 6 | Length of port string, including null termination | | port_string_size | char[port_string_size] | port_string | 6 | Port string value, including null termination | +## NET_PACKET_ID_GET_USB_SERIAL_PORTS + +### Request [Size: 0] + +The client uses this ID to request a list of USB serial port device info from the server. The request contains no data. This request should only be used if the server sets the NET_SERVER_FLAG_SUPPORTS_DEVICE_INFO flag. + +### Response [Size: Variable] + +The server responds with a data block containing USB serial port information. + +| Size | Format | Name | Protocol Version | Description | +| -------- | ------------------------------- | -------------- | ---------------- | ------------------------------------------------------------------------------------------ | +| 4 | unsigned int | data_size | 6 | Size of all data in packet | +| 4 | unsigned int | port_count | 6 | Number of USB serial port entries | +| Variable | Serial Port Data[port_count] | port_data | 6 | See [Serial Port Data](#usb-serial-port-data) block format table. Repeat port_count times | + +### USB Serial Port Data + +| Size | Format | Name | Protocol Version | Description | +| -------------- | ------------------------------- | -------------- | ---------------- | ------------------------------------------------------------------------------------------ | +| 2 | unsigned short | vendor_id | 6 | USB vendor ID | +| 2 | unsigned short | product_id | 6 | USB product ID | +| 2 | unsigned short | port_path_size | 6 | Length of port path string, including null termination | +| port_path_size | char[port_path_size] | port_path | 6 | Port path string value, including null termination | +| 2 | unsigned short | usb_path_size | 6 | Length of port path string, including null termination | +| usb_path_size | char[usb_path_size] | usb_path | 6 | USB path string value, including null termination | + ## NET_PACKET_ID_REQUEST_RESCAN_DEVICES ### Client Only [Size: 0] diff --git a/NetworkClient.cpp b/NetworkClient.cpp index e72575b84..98fa554c8 100644 --- a/NetworkClient.cpp +++ b/NetworkClient.cpp @@ -655,6 +655,72 @@ std::vector NetworkClient::GetUSBDeviceInfo() return(device_info); } +std::vector NetworkClient::GetUSBSerialPorts() +{ + /*-----------------------------------------------------*\ + | Send request | + \*-----------------------------------------------------*/ + std::vector device_info; + NetPacketHeader reply_hdr; + + if(GetSupportsDeviceInfoAPI()) + { + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_GET_USB_SERIAL_PORTS, 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_SERIAL_PORTS && 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++) + { + SerialDeviceInfo 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 port_path_size; + COPY_DATA_FIELD(data_ptr, response_data_ptr, port_path_size); + COPY_STRING_FIELD(data_ptr, response_data_ptr, port_path_size, device.port_path); + + unsigned short usb_path_size; + COPY_DATA_FIELD(data_ptr, response_data_ptr, usb_path_size); + COPY_STRING_FIELD(data_ptr, response_data_ptr, usb_path_size, device.usb_path); + + device_info.push_back(device); + } + } + + COPY_DATA_ERROR: + delete[] response_data_ptr; + response_data_ptr = NULL; + } + } + + return(device_info); +} + /*---------------------------------------------------------*\ | DetectionManager functions | \*---------------------------------------------------------*/ @@ -1729,6 +1795,7 @@ void NetworkClient::ListenThreadFunction() case NET_PACKET_ID_GET_HID_DEVICE_INFO: case NET_PACKET_ID_GET_USB_DEVICE_INFO: case NET_PACKET_ID_GET_SERIAL_PORTS: + case NET_PACKET_ID_GET_USB_SERIAL_PORTS: 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 ed2f37c83..090879d66 100644 --- a/NetworkClient.h +++ b/NetworkClient.h @@ -115,6 +115,7 @@ public: std::vector GetI2CBusInfo(); std::vector GetSerialPorts(); std::vector GetUSBDeviceInfo(); + std::vector GetUSBSerialPorts(); /*-----------------------------------------------------*\ | DetectionManager functions | diff --git a/NetworkProtocol.h b/NetworkProtocol.h index e32da5a39..ae56edf36 100644 --- a/NetworkProtocol.h +++ b/NetworkProtocol.h @@ -121,6 +121,7 @@ enum 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_GET_SERIAL_PORTS = 123, /* Request list of serial ports */ + NET_PACKET_ID_GET_USB_SERIAL_PORTS = 124, /* Request list of USB serial port info */ NET_PACKET_ID_REQUEST_RESCAN_DEVICES = 140, /* Request rescan of devices */ diff --git a/NetworkServer.cpp b/NetworkServer.cpp index c334dea4e..02a57f9ae 100644 --- a/NetworkServer.cpp +++ b/NetworkServer.cpp @@ -1300,6 +1300,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo* client_info) status = ProcessRequest_GetSerialPorts(client_info); break; + case NET_PACKET_ID_GET_USB_SERIAL_PORTS: + status = ProcessRequest_GetUSBSerialPorts(client_info); + break; + /*-------------------------------------------------*\ | LogManager functions | \*-------------------------------------------------*/ @@ -1926,6 +1930,82 @@ NetPacketStatus NetworkServer::ProcessRequest_GetUSBDeviceInfo(NetworkClientInfo return(NET_PACKET_STATUS_OK); } +NetPacketStatus NetworkServer::ProcessRequest_GetUSBSerialPorts(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()->GetUSBSerialPorts(); + + 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].port_path.c_str()) + 1; + data_size += sizeof(unsigned short); + data_size += (unsigned int)strlen(device_info[device_idx].usb_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); + + unsigned short port_path_size = (unsigned short)strlen(device_info[device_idx].port_path.c_str()) + 1; + memcpy(data_ptr, &port_path_size, sizeof(port_path_size)); + data_ptr += sizeof(port_path_size); + memcpy(data_ptr, device_info[device_idx].port_path.c_str(), port_path_size); + data_ptr += port_path_size; + + unsigned short usb_path_size = (unsigned short)strlen(device_info[device_idx].usb_path.c_str()) + 1; + memcpy(data_ptr, &usb_path_size, sizeof(usb_path_size)); + data_ptr += sizeof(usb_path_size); + memcpy(data_ptr, device_info[device_idx].usb_path.c_str(), usb_path_size); + data_ptr += usb_path_size; + } + + NetPacketHeader reply_hdr; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_GET_USB_SERIAL_PORTS, 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 cebd653c9..9c60991e1 100644 --- a/NetworkServer.h +++ b/NetworkServer.h @@ -234,6 +234,7 @@ private: NetPacketStatus ProcessRequest_GetI2CBusInfo(NetworkClientInfo* client_info); NetPacketStatus ProcessRequest_GetSerialPorts(NetworkClientInfo* client_info); NetPacketStatus ProcessRequest_GetUSBDeviceInfo(NetworkClientInfo* client_info); + NetPacketStatus ProcessRequest_GetUSBSerialPorts(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 17e9e56b9..107b04f64 100644 --- a/ResourceManager.cpp +++ b/ResourceManager.cpp @@ -394,7 +394,7 @@ std::vector ResourceManager::GetUSBSerialPorts() { if(IsLocalClient()) { - return(find_usb_serial_ports()); + return(GetLocalClient()->GetUSBSerialPorts()); } else {