From f03e4fd04951f24c30ed95ef073c3b1d3aa4383c Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Mon, 14 Jul 2025 12:39:15 -0500 Subject: [PATCH] Implement find_usb_serial_port for MacOS, switch HYTE CNVS implementation to serial-based --- .../HYTEMousematControllerDetect_MacOS.cpp | 89 ----------- .../HYTEMousematController_MacOS.cpp | 101 ------------ .../HYTEMousematController_MacOS.h | 39 ----- ...ousematControllerDetect_Windows_MacOS.cpp} | 6 +- .../HYTEMousematController_Windows_MacOS.cpp} | 6 +- .../HYTEMousematController_Windows_MacOS.h} | 4 +- .../RGBController_HYTEMousemat.h | 10 +- serial_port/find_usb_serial_port_macos.cpp | 148 +++++++++++++++++- serial_port/serial_port.cpp | 9 +- 9 files changed, 164 insertions(+), 248 deletions(-) delete mode 100644 Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematControllerDetect_MacOS.cpp delete mode 100644 Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematController_MacOS.cpp delete mode 100644 Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematController_MacOS.h rename Controllers/HYTEMousematController/{HYTEMousematController_Windows/HYTEMousematControllerDetect_Windows.cpp => HYTEMousematController_Windows_MacOS/HYTEMousematControllerDetect_Windows_MacOS.cpp} (95%) rename Controllers/HYTEMousematController/{HYTEMousematController_Windows/HYTEMousematController_Windows.cpp => HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.cpp} (95%) rename Controllers/HYTEMousematController/{HYTEMousematController_Windows/HYTEMousematController_Windows.h => HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.h} (88%) diff --git a/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematControllerDetect_MacOS.cpp b/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematControllerDetect_MacOS.cpp deleted file mode 100644 index 85a49112..00000000 --- a/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematControllerDetect_MacOS.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/*---------------------------------------------------------*\ -| HYTEMousematControllerDetect_MacOS.cpp | -| | -| Detector for HYTE mousemat (libusb implementation for | -| MacOS) | -| | -| Adam Honse (calcprogrammer1@gmail.com) 05 Aug 2024 | -| | -| This file is part of the OpenRGB project | -| SPDX-License-Identifier: GPL-2.0-only | -\*---------------------------------------------------------*/ - -#include -#include "Detector.h" -#include "RGBController_HYTEMousemat.h" - -/*-----------------------------------------------------*\ -| HYTE vendor ID | -\*-----------------------------------------------------*/ -#define HYTE_VID 0x3402 - -/*-----------------------------------------------------*\ -| HYTE CNVS product IDs | -\*-----------------------------------------------------*/ -#define HYTE_CNVS_HW_VER_1_PID 0x0B00 -#define HYTE_CNVS_HW_VER_2_PID 0x0B01 - -typedef struct -{ - unsigned short usb_vid; - unsigned short usb_pid; - unsigned char usb_interface; - const char * name; -} hyte_mousemat_device; - -#define HYTE_MOUSEMAT_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[ 0 ])) - -static const hyte_mousemat_device device_list[] = -{ - /*-----------------------------------------------------------------------------------------------------*\ - | Mousemats | - \*-----------------------------------------------------------------------------------------------------*/ - { HYTE_VID, HYTE_CNVS_HW_VER_1_PID, 0, "HYTE CNVS" }, - { HYTE_VID, HYTE_CNVS_HW_VER_2_PID, 0, "HYTE CNVS" }, -}; - -/******************************************************************************************\ -* * -* DetectHYTEMousematControllers * -* * -* Detect devices supported by the HyteMousemat driver * -* * -\******************************************************************************************/ - -void DetectHYTEMousematControllers() -{ - libusb_init(NULL); - - #ifdef _WIN32 - libusb_set_option(NULL, LIBUSB_OPTION_USE_USBDK); - #endif - - for(std::size_t device_idx = 0; device_idx < HYTE_MOUSEMAT_NUM_DEVICES; device_idx++) - { - libusb_device_handle * dev = libusb_open_device_with_vid_pid(NULL, device_list[device_idx].usb_vid, device_list[device_idx].usb_pid); - - //Look for HYTE CNVS - if(dev) - { - libusb_detach_kernel_driver(dev, 0); - libusb_claim_interface(dev, 0); - - HYTEMousematController * controller = new HYTEMousematController(dev); - RGBController_HYTEMousemat * rgb_controller = new RGBController_HYTEMousemat(controller); - rgb_controller->name = device_list[device_idx].name; - - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - } - -} /* DetectHYTEMousematControllers() */ - -REGISTER_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers); -/*---------------------------------------------------------------------------------------------------------*\ -| Entries for dynamic UDEV rules | -| | -| DUMMY_DEVICE_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers, 0x3402, 0x0B00 ) | -| DUMMY_DEVICE_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers, 0x3402, 0x0B01 ) | -\*---------------------------------------------------------------------------------------------------------*/ diff --git a/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematController_MacOS.cpp b/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematController_MacOS.cpp deleted file mode 100644 index 23c62d40..00000000 --- a/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematController_MacOS.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/*---------------------------------------------------------*\ -| HYTEMousematController_MacOS.cpp | -| | -| Driver for HYTE mousemat (libusb implementation for | -| MacOS) | -| | -| Adam Honse (calcprogrammer1@gmail.com) 05 Aug 2024 | -| | -| This file is part of the OpenRGB project | -| SPDX-License-Identifier: GPL-2.0-only | -\*---------------------------------------------------------*/ - -#include -#include -#include -#include "HYTEMousematController_MacOS.h" - -HYTEMousematController::HYTEMousematController(libusb_device_handle* dev_handle) -{ - dev = dev_handle; - - /*-----------------------------------------------------*\ - | Fill in location string with USB ID | - \*-----------------------------------------------------*/ - libusb_device_descriptor descriptor; - libusb_get_device_descriptor(libusb_get_device(dev_handle), &descriptor); - - std::stringstream location_stream; - location_stream << std::hex << std::setfill('0') << std::setw(4) << descriptor.idVendor << ":" << std::hex << std::setfill('0') << std::setw(4) << descriptor.idProduct; - location = location_stream.str(); -} - -HYTEMousematController::~HYTEMousematController() -{ - -} - -std::string HYTEMousematController::GetLocation() -{ - return(location); -} - -void HYTEMousematController::FirmwareAnimationControl(bool enabled) -{ - unsigned char serial_buf[4]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(serial_buf, 0, sizeof(serial_buf)); - - /*-----------------------------------------------------*\ - | Set up Firmware Animation Control packet | - \*-----------------------------------------------------*/ - serial_buf[0] = 0xFF; - serial_buf[1] = 0xDC; - serial_buf[2] = 0x05; - serial_buf[3] = enabled; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - libusb_bulk_transfer(dev, HYTE_CNVS_EP_OUT, serial_buf, sizeof(serial_buf), NULL, 1000); -} - -void HYTEMousematController::StreamingCommand(RGBColor* colors) -{ - unsigned char serial_buf[157]; - unsigned int max_brightness = 72; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(serial_buf, 0, sizeof(serial_buf)); - - /*-----------------------------------------------------*\ - | Set up Streaming packet | - \*-----------------------------------------------------*/ - serial_buf[0] = 0xFF; - serial_buf[1] = 0xEE; - serial_buf[2] = 0x02; - serial_buf[3] = 0x01; - serial_buf[4] = 0x00; - serial_buf[5] = 0x32; - serial_buf[6] = 0x00; - - /*-----------------------------------------------------*\ - | Copy in colors | - \*-----------------------------------------------------*/ - for(unsigned int color_idx = 0; color_idx < 50; color_idx++) - { - serial_buf[7 + (color_idx * 3)] = ( max_brightness * RGBGetGValue(colors[color_idx]) ) / 100; - serial_buf[8 + (color_idx * 3)] = ( max_brightness * RGBGetRValue(colors[color_idx]) ) / 100; - serial_buf[9 + (color_idx * 3)] = ( max_brightness * RGBGetBValue(colors[color_idx]) ) / 100; - } - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - libusb_bulk_transfer(dev, HYTE_CNVS_EP_OUT, serial_buf, sizeof(serial_buf), NULL, 1000); -} diff --git a/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematController_MacOS.h b/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematController_MacOS.h deleted file mode 100644 index 3d73cfbc..00000000 --- a/Controllers/HYTEMousematController/HYTEMousematController_MacOS/HYTEMousematController_MacOS.h +++ /dev/null @@ -1,39 +0,0 @@ -/*---------------------------------------------------------*\ -| HYTEMousematController_MacOS.h | -| | -| Driver for HYTE mousemat (libusb implementation for | -| MacOS) | -| | -| Adam Honse (calcprogrammer1@gmail.com) 05 Aug 2024 | -| | -| This file is part of the OpenRGB project | -| SPDX-License-Identifier: GPL-2.0-only | -\*---------------------------------------------------------*/ - -#pragma once - -#include -#include -#include "RGBController.h" - -/*---------------------------------------------------------*\ -| HYTE CNVS endpoint values | -\*---------------------------------------------------------*/ -#define HYTE_CNVS_EP_IN 0x81 -#define HYTE_CNVS_EP_OUT 0x01 - -class HYTEMousematController -{ -public: - HYTEMousematController(libusb_device_handle* dev_handle); - ~HYTEMousematController(); - - std::string GetLocation(); - - void FirmwareAnimationControl(bool enabled); - void StreamingCommand(RGBColor* colors); - -private: - libusb_device_handle* dev; - std::string location; -}; diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematControllerDetect_Windows.cpp b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematControllerDetect_Windows_MacOS.cpp similarity index 95% rename from Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematControllerDetect_Windows.cpp rename to Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematControllerDetect_Windows_MacOS.cpp index 2817e535..1a9ce35e 100644 --- a/Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematControllerDetect_Windows.cpp +++ b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematControllerDetect_Windows_MacOS.cpp @@ -1,8 +1,8 @@ /*---------------------------------------------------------*\ -| HYTEMousematControllerDetect_Windows.cpp | +| HYTEMousematControllerDetect_Windows_MacOS.cpp | | | | Detector for HYTE mousemat (Serial implementation for | -| Windows) | +| Windows and MacOS) | | | | Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | | | @@ -12,7 +12,7 @@ #include #include "Detector.h" -#include "HYTEMousematController_Windows.h" +#include "HYTEMousematController_Windows_MacOS.h" #include "RGBController_HYTEMousemat.h" #include "find_usb_serial_port.h" diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematController_Windows.cpp b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.cpp similarity index 95% rename from Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematController_Windows.cpp rename to Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.cpp index c9ece09a..8a641d79 100644 --- a/Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematController_Windows.cpp +++ b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.cpp @@ -1,8 +1,8 @@ /*---------------------------------------------------------*\ -| HYTEMousematController_Windows.cpp | +| HYTEMousematController_Windows_MacOS.cpp | | | | Driver for HYTE mousemat (Serial implementation for | -| Windows) | +| Windows and MacOS) | | | | Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | | | @@ -10,7 +10,7 @@ | SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "HYTEMousematController_Windows.h" +#include "HYTEMousematController_Windows_MacOS.h" HYTEMousematController::HYTEMousematController(char* port) { diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematController_Windows.h b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.h similarity index 88% rename from Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematController_Windows.h rename to Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.h index d000b3ec..2488c694 100644 --- a/Controllers/HYTEMousematController/HYTEMousematController_Windows/HYTEMousematController_Windows.h +++ b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.h @@ -1,8 +1,8 @@ /*---------------------------------------------------------*\ -| HYTEMousematController_Windows.h | +| HYTEMousematController_Windows_MacOS.h | | | | Driver for HYTE mousemat (Serial implementation for | -| Windows) | +| Windows and MacOS) | | | | Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | | | diff --git a/Controllers/HYTEMousematController/RGBController_HYTEMousemat.h b/Controllers/HYTEMousematController/RGBController_HYTEMousemat.h index 1db361ca..c4c58a00 100644 --- a/Controllers/HYTEMousematController/RGBController_HYTEMousemat.h +++ b/Controllers/HYTEMousematController/RGBController_HYTEMousemat.h @@ -12,12 +12,16 @@ #pragma once #include "RGBController.h" -#ifdef _WIN32 -#include "HYTEMousematController_Windows.h" -#else + +#if defined(_WIN32) || defined(__APPLE__) +#include "HYTEMousematController_Windows_MacOS.h" +#endif + +#ifdef __linux__ #include "HYTEMousematController_Linux.h" #endif + enum { HYTE_CNVS_MODE_DIRECT = 0, /* Direct (streaming) mode */ diff --git a/serial_port/find_usb_serial_port_macos.cpp b/serial_port/find_usb_serial_port_macos.cpp index d87415f3..2ca50c6d 100644 --- a/serial_port/find_usb_serial_port_macos.cpp +++ b/serial_port/find_usb_serial_port_macos.cpp @@ -10,6 +10,35 @@ #include "find_usb_serial_port.h" +std::string exec(const char* cmd) +{ + char buffer[128]; + std::string result = ""; + FILE* pipe = popen(cmd, "r"); + + if(!pipe) + { + throw std::runtime_error("popen() failed!"); + } + + try + { + while(fgets(buffer, sizeof(buffer), pipe) != NULL) + { + result += buffer; + } + } + catch(...) + { + pclose(pipe); + throw; + } + + pclose(pipe); + + return result; +} + /*---------------------------------------------------------------------*\ | | | find_usb_serial_port | @@ -24,12 +53,121 @@ | | \*---------------------------------------------------------------------*/ -std::vector find_usb_serial_port(unsigned short /*vid*/, unsigned short /*pid*/) +std::vector find_usb_serial_port(unsigned short vid, unsigned short pid) { - std::vector ret_vector; + /*-----------------------------------------------------*\ + | Strings to search for in ioreg output | + \*-----------------------------------------------------*/ + #define IO_CALLOUT_STR "\"IOCalloutDevice\" =" + #define ID_VENDOR_STR "\"idVendor\" = " + #define ID_PRODUCT_STR "\"idProduct\" = " - /*-----------------------------------------------------------------*\ - | TODO: Implement for MacOS | - \*-----------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Return variables | + \*-----------------------------------------------------*/ + std::vector ret_vector; + std::string * tmp_string; + + /*-----------------------------------------------------*\ + | Execute command to list USB devices | + | | + | Top level entry lines in ioreg output start with | + | "+-o". Start the string with an extra newline so | + | that we can search for "\n+-0" to identify only hits | + | at the beginning of a line. | + \*-----------------------------------------------------*/ + std::string out_string = "\n" + exec("ioreg -r -c IOUSBHostDevice -l"); + + /*-----------------------------------------------------*\ + | Append desired VID and PID to search strings | + \*-----------------------------------------------------*/ + std::string vid_string = ID_VENDOR_STR + std::to_string(vid); + std::string pid_string = ID_PRODUCT_STR + std::to_string(pid); + + /*-----------------------------------------------------*\ + | Start position counter at 0 | + \*-----------------------------------------------------*/ + std::size_t pos = 0; + + /*-----------------------------------------------------*\ + | Loop through ioreg output, loop exits when "\n+-o" | + | string cannot be found. | + \*-----------------------------------------------------*/ + while(1) + { + /*-------------------------------------------------*\ + | Variables to store positions in string | + \*-------------------------------------------------*/ + std::size_t next_pos; + std::size_t vid_pos; + std::size_t pid_pos; + + /*-------------------------------------------------*\ + | Search for the next 2 iterations of "\n+-o" so | + | that we can check if hits are in between them | + \*-------------------------------------------------*/ + pos = out_string.find("\n+-o", pos); + next_pos = out_string.find("\n+-o", pos + 1); + + /*-------------------------------------------------*\ + | Search for the vendor and product ID strings in | + | and verify that they are between pos and next_pos | + \*-------------------------------------------------*/ + vid_pos = out_string.find(vid_string, pos); + pid_pos = out_string.find(pid_string, pos); + + /*-------------------------------------------------*\ + | Verify that VID/PID matches are within this | + | device block by checking that their positions are | + | less than next_pos. If next_pos is invalid, | + | this is the last block, in which case check if | + | VID/PID positions are valid. | + \*-------------------------------------------------*/ + if(((vid_pos < next_pos) && (pid_pos < next_pos)) || ((pos == std::string::npos) && (vid_pos != std::string::npos) && (pid_pos != std::string::npos))) + { + /*---------------------------------------------*\ + | Variables to store positions in string | + \*---------------------------------------------*/ + std::size_t dev_pos; + std::size_t start_pos; + std::size_t end_pos; + + /*---------------------------------------------*\ + | Look for the IO callout device tag and then | + | get the start and end positions of its value | + \*---------------------------------------------*/ + dev_pos = out_string.find(IO_CALLOUT_STR, pos + 1); + start_pos = out_string.find("\"", dev_pos + sizeof(IO_CALLOUT_STR)) + 1; + end_pos = out_string.find("\"\n", start_pos); + + /*---------------------------------------------*\ + | Ensure the IO callout device tag is within | + | this device's section | + \*---------------------------------------------*/ + if(dev_pos < next_pos) + { + tmp_string = new std::string(out_string.substr(start_pos, end_pos-start_pos)); + ret_vector.push_back(tmp_string); + } + } + + /*-------------------------------------------------*\ + | If we've reached the end of the string, break out | + | of the loop | + \*-------------------------------------------------*/ + if(pos == std::string::npos) + { + break; + } + + /*-------------------------------------------------*\ + | Increment position | + \*-------------------------------------------------*/ + pos++; + } + + /*-----------------------------------------------------*\ + | Return vector of detected strings | + \*-----------------------------------------------------*/ return(ret_vector); } diff --git a/serial_port/serial_port.cpp b/serial_port/serial_port.cpp index c2b3b20a..72ca7509 100644 --- a/serial_port/serial_port.cpp +++ b/serial_port/serial_port.cpp @@ -460,6 +460,8 @@ bool serial_port::serial_open() | Configure baud rate | \*-----------------------------------------*/ ioctl(file_descriptor, IOSSIOSPEED, &baud_rate); + + printf("Port opened fd %d", file_descriptor); #endif /*-----------------------------------------------------*\ @@ -595,9 +597,10 @@ int serial_port::serial_write(char * buffer, int length) \*-----------------------------------------------------*/ #ifdef __APPLE__ int byteswritten; - tcdrain(file_descriptor); - byteswritten = write(file_descriptor, buffer, length); - tcdrain(file_descriptor); + printf("serial write fd %d", file_descriptor); + printf("tcdrain %d\r\n",tcdrain(file_descriptor)); + printf("write %d\r\n", byteswritten = write(file_descriptor, buffer, length)); + printf("tcdrain %d\r\n", tcdrain(file_descriptor)); return byteswritten; #endif