diff --git a/Controllers/SinowealthController/RGBController_SinowealthGMOW.cpp b/Controllers/SinowealthController/RGBController_SinowealthGMOW.cpp new file mode 100644 index 00000000..90ac164b --- /dev/null +++ b/Controllers/SinowealthController/RGBController_SinowealthGMOW.cpp @@ -0,0 +1,204 @@ +/*-------------------------------------------*\ +| RGBController_GMOW.cpp | +| | +| Support for the Glorious Model O Wireless | +| | +| Matt Silva (thesilvanator) 05/2022 | +\*-------------------------------------------*/ + +/**------------------------------------------------------------------*\ + @name Sinowealth Glorious Model O Wireless + @type USB + @save :white_check_mark: + @direct :x: + @effects :white_check_mark: + @detectors DetectSinowealthMouse + @comment +\*-------------------------------------------------------------------*/ + +#include "RGBController_SinowealthGMOW.h" + +RGBController_GMOW::RGBController_GMOW(SinowealthGMOWController* controller_ptr) +{ + controller = controller_ptr; + + name = "Sinowealth Device"; + type = DEVICE_TYPE_MOUSE; + description = "Sinowealth Device"; + location = controller->GetLocation(); + serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); + + mode Off; + Off.name = "Off"; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + Off.value = GMOW_MODE_OFF; + modes.push_back(Off); + + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + RainbowWave.speed_min = GMOW_SPEED1_MIN; + RainbowWave.speed = GMOW_SPEED1_MID; + RainbowWave.speed_max = GMOW_SPEED1_MAX; + RainbowWave.direction = MODE_DIRECTION_UP; + RainbowWave.color_mode = MODE_COLORS_NONE; + RainbowWave.brightness_min = GMOW_BRIGHTNESS_MIN; + RainbowWave.brightness = GMOW_BRIGHTNESS_MID; + RainbowWave.brightness_max = GMOW_BRIGHTNESS_MAX; + RainbowWave.value = GMOW_MODE_RAINBOW_WAVE; + modes.push_back(RainbowWave); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.speed_min = GMOW_SPEED1_MIN; + SpectrumCycle.speed = GMOW_SPEED1_MID; + SpectrumCycle.speed_max = GMOW_SPEED1_MAX; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.brightness_min = GMOW_BRIGHTNESS_MIN; + SpectrumCycle.brightness = GMOW_BRIGHTNESS_MID; + SpectrumCycle.brightness_max = GMOW_BRIGHTNESS_MAX; + SpectrumCycle.value = GMOW_MODE_SPECTRUM_CYCLE; + modes.push_back(SpectrumCycle); + + mode CustomBreathing; + CustomBreathing.name = "Custom Breathing"; + CustomBreathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + CustomBreathing.speed_min = GMOW_SPEED1_MIN; + CustomBreathing.speed = GMOW_SPEED1_MID; + CustomBreathing.speed_max = GMOW_SPEED1_MAX; + CustomBreathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + CustomBreathing.colors_min = 2; + CustomBreathing.colors_max = 7; + CustomBreathing.brightness_min = GMOW_BRIGHTNESS_MIN; + CustomBreathing.brightness = GMOW_BRIGHTNESS_MID; + CustomBreathing.brightness_max = GMOW_BRIGHTNESS_MAX; + CustomBreathing.value = GMOW_MODE_CUSTOM_BREATHING; + CustomBreathing.colors.resize(7); + modes.push_back(CustomBreathing); + + mode Static; + Static.name = "Static"; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.brightness_min = GMOW_BRIGHTNESS_MIN; + Static.brightness = GMOW_BRIGHTNESS_MID; + Static.brightness_max = GMOW_BRIGHTNESS_MAX; + Static.value = GMOW_MODE_STATIC; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = GMOW_SPEED1_MIN; + Breathing.speed = GMOW_SPEED1_MID; + Breathing.speed_max = GMOW_SPEED1_MAX; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.brightness_min = GMOW_BRIGHTNESS_MIN; + Breathing.brightness = GMOW_BRIGHTNESS_MID; + Breathing.brightness_max = GMOW_BRIGHTNESS_MAX; + Breathing.value = GMOW_MODE_BREATHING; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Tail; + Tail.name = "Tail"; + Tail.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Tail.speed_min = GMOW_SPEED1_MIN; + Tail.speed = GMOW_SPEED1_MID; + Tail.speed_max = GMOW_SPEED1_MAX; + Tail.color_mode = MODE_COLORS_NONE; + Tail.brightness_min = GMOW_BRIGHTNESS_MIN; + Tail.brightness = GMOW_BRIGHTNESS_MID; + Tail.brightness_max = GMOW_BRIGHTNESS_MAX; + Tail.value = GMOW_MODE_TAIL; + modes.push_back(Tail); + + mode Rave; + Rave.name = "Rave"; + Rave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Rave.speed_min = GMOW_SPEED2_MIN; + Rave.speed = GMOW_SPEED2_MID; + Rave.speed_max = GMOW_SPEED2_MAX; + Rave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Rave.colors_min = 1; + Rave.colors_max = 2; + Rave.brightness_min = GMOW_BRIGHTNESS_MIN; + Rave.brightness = GMOW_BRIGHTNESS_MID; + Rave.brightness_max = GMOW_BRIGHTNESS_MAX; + Rave.value = GMOW_MODE_RAVE; + Rave.colors.resize(2); + modes.push_back(Rave); + + mode Wave; + Wave.name = "Wave"; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Wave.speed_min = GMOW_SPEED2_MIN; + Wave.speed = GMOW_SPEED2_MID; + Wave.speed_max = GMOW_SPEED2_MAX; + Wave.color_mode = MODE_COLORS_NONE; + Wave.brightness_min = GMOW_BRIGHTNESS_MIN; + Wave.brightness = GMOW_BRIGHTNESS_MID; + Wave.brightness_max = GMOW_BRIGHTNESS_MAX; + Wave.value = GMOW_MODE_WAVE; + modes.push_back(Wave); + + SetupZones(); +} + +RGBController_GMOW::~RGBController_GMOW() +{ + delete controller; +} + +void RGBController_GMOW::SetupZones() +{ + +} + +void RGBController_GMOW::ResizeZone(int zone, int new_size) +{ + +} + +void RGBController_GMOW::DeviceUpdateLEDs() +{ + +} + +void RGBController_GMOW::UpdateZoneLEDs(int zone) +{ + +} + +void RGBController_GMOW::UpdateSingleLED(int led) +{ + +} + +void RGBController_GMOW::SetCustomMode() +{ + active_mode = GMOW_MODE_STATIC; +} +void RGBController_GMOW::SetMode() +{ + +} + +void RGBController_GMOW::DeviceUpdateMode() +{ + mode curr = modes[active_mode]; + controller->SetMode(active_mode, curr.speed,curr.brightness, curr.brightness, curr.colors.data(), curr.colors.size()); +} + +void RGBController_GMOW::DeviceSaveMode() +{ + +} diff --git a/Controllers/SinowealthController/RGBController_SinowealthGMOW.h b/Controllers/SinowealthController/RGBController_SinowealthGMOW.h new file mode 100644 index 00000000..2332ddd2 --- /dev/null +++ b/Controllers/SinowealthController/RGBController_SinowealthGMOW.h @@ -0,0 +1,32 @@ +/*-------------------------------------------*\ +| RGBController_GMOW.h | +| | +| Support for the Glorious Model O Wireless | +| | +| Matt Silva (thesilvanator) 05/2022 | +\*-------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SinowealthGMOWController.h" + +class RGBController_GMOW : public RGBController +{ +public: + RGBController_GMOW(SinowealthGMOWController* sinowealth_ptr); + ~RGBController_GMOW(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + void SetCustomMode(); + void DeviceUpdateMode(); + void SetMode(); + void DeviceSaveMode(); + +private: + SinowealthGMOWController* controller; +}; diff --git a/Controllers/SinowealthController/SinowealthControllerDetect.cpp b/Controllers/SinowealthController/SinowealthControllerDetect.cpp index fa362acb..9e777362 100644 --- a/Controllers/SinowealthController/SinowealthControllerDetect.cpp +++ b/Controllers/SinowealthController/SinowealthControllerDetect.cpp @@ -3,22 +3,26 @@ #include "SinowealthController1007.h" #include "SinowealthKeyboardController.h" #include "SinowealthKeyboard16Controller.h" +#include "SinowealthGMOWController.h" #include "RGBController.h" #include "RGBController_Sinowealth.h" #include "RGBController_Sinowealth1007.h" #include "RGBController_SinowealthKeyboard.h" #include "RGBController_SinowealthKeyboard16.h" +#include "RGBController_SinowealthGMOW.h" #include #include "LogManager.h" -#define SINOWEALTH_VID 0x258A +#define SINOWEALTH_VID 0x258A -#define Glorious_Model_O_PID 0x0036 -#define Glorious_Model_D_PID 0x0033 -#define Everest_GT100_PID 0x0029 -#define ZET_FURY_PRO_PID 0x1007 -#define Fl_Esports_F11_PID 0x0049 -#define RGB_KEYBOARD_0016PID 0x0016 +#define Glorious_Model_O_PID 0x0036 +#define Glorious_Model_OW_PID1 0x2022 // wireless +#define Glorious_Model_OW_PID2 0x2011 // when connected via cable +#define Glorious_Model_D_PID 0x0033 +#define Everest_GT100_PID 0x0029 +#define ZET_FURY_PRO_PID 0x1007 +#define Fl_Esports_F11_PID 0x0049 +#define RGB_KEYBOARD_0016PID 0x0016 /******************************************************************************************\ * * @@ -49,7 +53,7 @@ int GetDeviceCount(hid_device_info* info, unsigned int &device_count_total, unsi { hid_device_info* info_temp = info; - while (info_temp) + while(info_temp) { if (info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID && info_temp->product_id == info->product_id // NON-constant @@ -63,7 +67,7 @@ int GetDeviceCount(hid_device_info* info, unsigned int &device_count_total, unsi /*----------------------------------------------------------------------*\ | If we have an expected number and what's left is a multiple of it | \*----------------------------------------------------------------------*/ - if (device_count_expected == 0 || device_count_total % device_count_expected == 0) + if(device_count_expected == 0 || device_count_total % device_count_expected == 0) { return true; } @@ -92,7 +96,7 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c | 3. If remaining amount is a multiple of expected amount - we're on the first collection of one | | of connected devices, and proceed with finding expected reports | \*-----------------------------------------------------------------------------------------------*/ - if (!GetDeviceCount(info, device_count_total, device_count_expected)) + if(!GetDeviceCount(info, device_count_total, device_count_expected)) { LOG_DEBUG("[%s] Detection stage skipped - devices left %d (expected %d) ", name.c_str(), device_count_total, device_count_expected); reports.clear(); @@ -117,7 +121,7 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c bool report_found = false; device = hid_open_path(info_temp->path); - if (!device) + if(!device) { LOG_ERROR("[%s] Couldn't open path \"HID: %s\", do we have enough permissions?", name.c_str(), info_temp->path); reports.clear(); @@ -129,7 +133,7 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c /*-----------------------------------------------------------*\ | We shouldn't do any checks if device is already found | \*-----------------------------------------------------------*/ - if (report->device != nullptr) continue; + if(report->device != nullptr) continue; memset(tmp_buf, 0x00, sizeof(tmp_buf)); tmp_buf[0] = report->id; @@ -138,7 +142,7 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c | If we need to send a command before requesting data, send it and flag the report | | (DON'T TRY TO CREATE MORE THAN 1 EXPECTED REPORT SENDING COMMANDS) | \*--------------------------------------------------------------------------------------*/ - if (report->cmd_buf != nullptr && report->cmd_device == nullptr) + if(report->cmd_buf != nullptr && report->cmd_device == nullptr) { if (hid_send_feature_report(device, report->cmd_buf, report->cmd_size) > -1) { @@ -151,12 +155,12 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c /*------------------------------------------------------*\ | Now we try to request data for expected feature report | \*------------------------------------------------------*/ - if (report->cmd_buf == nullptr || report->cmd_device != nullptr) + if(report->cmd_buf == nullptr || report->cmd_device != nullptr) { /*---------------------------------------------------------------------------*\ | If device actually responds to expected report ID, set a flag | \*---------------------------------------------------------------------------*/ - if (hid_get_feature_report(device, tmp_buf, report->size) > -1) + if(hid_get_feature_report(device, tmp_buf, report->size) > -1) { device_count++; report_found = true; @@ -170,7 +174,7 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c | If it doesn't - make sure to close it! | | Don't close if restart flag is set because we found cmd_dev | \*-----------------------------------------------------------*/ - if (!report_found && !restart_flag) hid_close(device); + if(!report_found && !restart_flag) hid_close(device); } info_temp = restart_flag ? info : info_temp->next; @@ -182,17 +186,17 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c | with the same VID & PID | | (I don't care how unlikely it is, we must be prepared for everything) | \*-------------------------------------------------------------------------*/ - if (device_count == reports.size()) info_temp = nullptr; + if(device_count == reports.size()) info_temp = nullptr; } /*-----------------------------------------------------------*\ | If we found less devices than expected - sad, lets clean up | \*-----------------------------------------------------------*/ - if (device_count < reports.size()) + if(device_count < reports.size()) { for (expected_report* report: reports) { - if (report->device != nullptr) + if(report->device != nullptr) { hid_close(report->device); } @@ -217,24 +221,58 @@ void DetectSinowealthMouse(hid_device_info* info, const std::string& name) expected_reports* reports = new expected_reports(); RGBController *rgb_controller; - if (pid == ZET_FURY_PRO_PID) + if(pid == ZET_FURY_PRO_PID) { reports->emplace_back(new expected_report(0x04, 59)); - if (!DetectUsages(info, name, 5, *reports)) return; + if(!DetectUsages(info, name, 5, *reports)) return; SinowealthController1007* controller = new SinowealthController1007(reports->at(0)->device, info->path); - rgb_controller = new RGBController_Sinowealth1007(controller); + rgb_controller = new RGBController_Sinowealth1007(controller); + + } + /*-------------------------------------------------------------------------*\ + | When the GMOW is connected only via the wireless dongle, only one | + | device shows up (PID=2022), and RGB packets go to that device. | + | Same for when it is only plugged in via a cable but not a dongle (except | + | the device is PID=2011). However, when both are plugged in, packets | + | should only go to the cable connected device | + \*-------------------------------------------------------------------------*/ + else if(pid == Glorious_Model_OW_PID1) // if dongle + { + LOG_DEBUG("[%s] Detected connection via wireless dongle", name.c_str()); + hid_device_info* start = hid_enumerate(SINOWEALTH_VID,0); + hid_device_info* curr = start; + + while(curr) + { + if(curr->product_id == Glorious_Model_OW_PID2) + { + return; + } + curr = curr->next; + } + + hid_device *dev = hid_open_path(info->path); + SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_DONGLE_CONNECTED); + rgb_controller = new RGBController_GMOW(controller); + } + else if(pid == Glorious_Model_OW_PID2) + { + LOG_DEBUG("[%s] Detected connection via USB cable", name.c_str()); + hid_device *dev = hid_open_path(info->path); + SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_CABLE_CONNECTED); + rgb_controller = new RGBController_GMOW(controller); } else { unsigned char command[6] = {0x05, 0x11, 0x00, 0x00, 0x00, 0x00}; reports->emplace_back(new expected_report(0x04, 520, command, sizeof(command))); - if (!DetectUsages(info, name, 3, *reports)) return; + if(!DetectUsages(info, name, 3, *reports)) return; SinowealthController* controller = new SinowealthController(reports->at(0)->device, reports->at(0)->cmd_device, info->path); - rgb_controller = new RGBController_Sinowealth(controller); + rgb_controller = new RGBController_Sinowealth(controller); } rgb_controller->name = name; @@ -247,18 +285,48 @@ void DetectSinowealthMouse(hid_device_info* info, const std::string& name) { RGBController *rgb_controller; - if (pid == ZET_FURY_PRO_PID) + if(pid == ZET_FURY_PRO_PID) { SinowealthController1007* controller = new SinowealthController1007(dev, info->path); rgb_controller = new RGBController_Sinowealth1007(controller); rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } + /*-------------------------------------------------------------------------*\ + | See above where USE_HID_USAGE is true for explanation of the detection | + | process for the GMOW | + \*-------------------------------------------------------------------------*/ + else if(pid == Glorious_Model_OW_PID1) // if dongle + { + LOG_DEBUG("[%s] Detected connection via wireless dongle", name.c_str()); + hid_device_info* start = hid_enumerate(SINOWEALTH_VID,0); + hid_device_info* curr = start; + + while(curr) + { + if(curr->product_id == Glorious_Model_OW_PID2) + { + return; + } + curr = curr->next; + } + + hid_device *dev = hid_open_path(info->path); + SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_DONGLE_CONNECTED); + rgb_controller = new RGBController_GMOW(controller); + } + else if(pid == Glorious_Model_OW_PID2) + { + LOG_DEBUG("[%s] Detected connection via USB cable", name.c_str()); + hid_device *dev = hid_open_path(info->path); + SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_CABLE_CONNECTED); + rgb_controller = new RGBController_GMOW(controller); + } else { SinowealthController* controller = new SinowealthController(dev, dev, info->path); rgb_controller = new RGBController_Sinowealth(controller); - rgb_controller->name = name; + rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -272,12 +340,12 @@ void DetectSinowealthKeyboard(hid_device_info* info, const std::string& name) expected_reports* reports = new expected_reports(); RGBController *rgb_controller; - if (pid == RGB_KEYBOARD_0016PID) + if(pid == RGB_KEYBOARD_0016PID) { unsigned char command[6] = {0x05, 0x83, 0x00, 0x00, 0x00, 0x00}; reports->emplace_back(new expected_report(0x06, 1032, command, sizeof(command))); - if (!DetectUsages(info, name, 3, *reports)) return; + if(!DetectUsages(info, name, 3, *reports)) return; SinowealthKeyboard16Controller* controller = new SinowealthKeyboard16Controller(reports->at(0)->cmd_device, reports->at(0)->device, info->path, name); rgb_controller = new RGBController_SinowealthKeyboard16(controller); @@ -287,7 +355,7 @@ void DetectSinowealthKeyboard(hid_device_info* info, const std::string& name) unsigned char command[6] = {0x05, 0x83, 0xB6, 0x00, 0x00, 0x00}; reports->emplace_back(new expected_report(0x06, 1032, command, sizeof(command))); - if (!DetectUsages(info, name, 3, *reports)) return; + if(!DetectUsages(info, name, 3, *reports)) return; SinowealthKeyboardController* controller = new SinowealthKeyboardController(reports->at(0)->cmd_device, reports->at(0)->device, info->path); rgb_controller = new RGBController_SinowealthKeyboard(controller); @@ -319,17 +387,23 @@ void DetectSinowealthKeyboard(hid_device_info* info, const std::string& name) } #ifdef USE_HID_USAGE -REGISTER_HID_DETECTOR_P("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 0xFF00); -REGISTER_HID_DETECTOR_P("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 0xFF00); -REGISTER_HID_DETECTOR_P("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 0xFF00); -REGISTER_HID_DETECTOR_IPU("ZET Fury Pro", DetectSinowealthMouse, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_P("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 0xFF00); +REGISTER_HID_DETECTOR_P("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 0xFF00); +REGISTER_HID_DETECTOR_P("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 0xFF00); +REGISTER_HID_DETECTOR_IPU("ZET Fury Pro", DetectSinowealthMouse, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID1, 0xFFFF, 0x0000); +REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID2, 0xFFFF, 0x0000); + //REGISTER_HID_DETECTOR_P("FL ESPORTS F11", DetectSinowealthKeyboard, SINOWEALTH_VID, Fl_Esports_F11_PID, 0xFF00); //REGISTER_HID_DETECTOR_P("Sinowealth Keyboard", DetectSinowealthKeyboard, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 0xFF00); #else -REGISTER_HID_DETECTOR_I("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 1); -REGISTER_HID_DETECTOR_I("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 1); -REGISTER_HID_DETECTOR_I("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 1); -REGISTER_HID_DETECTOR_I("ZET Fury Pro", DetectSinowealthMouse, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1); +REGISTER_HID_DETECTOR_I("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 1); +REGISTER_HID_DETECTOR_I("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 1); +REGISTER_HID_DETECTOR_I("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 1); +REGISTER_HID_DETECTOR_I("ZET Fury Pro", DetectSinowealthMouse, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1); +REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID1, 2); +REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID2, 2); + //REGISTER_HID_DETECTOR_I("FL ESPORTS F11", DetectSinowealthKeyboard, SINOWEALTH_VID, Fl_Esports_F11_PID, 1); //REGISTER_HID_DETECTOR_I("Sinowealth Keyboard", DetectSinowealthKeyboard, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 1); #endif diff --git a/Controllers/SinowealthController/SinowealthGMOWController.cpp b/Controllers/SinowealthController/SinowealthGMOWController.cpp new file mode 100644 index 00000000..c8b454cc --- /dev/null +++ b/Controllers/SinowealthController/SinowealthGMOWController.cpp @@ -0,0 +1,236 @@ +/*-------------------------------------------*\ +| SinowealthGMOWController.cpp | +| | +| Support for the Glorious Model O Wireless | +| | +| Matt Silva (thesilvanator) 05/2022 | +\*-------------------------------------------*/ + +#include "SinowealthGMOWController.h" +#include +#include + +#include + +SinowealthGMOWController::SinowealthGMOWController(hid_device* dev_handle, char *_path, int _type) +{ + dev = dev_handle; + location = _path; + + memset(mode_packet,0x00, GMOW_PACKET_SIZE); + mode_packet[0x03] = 0x02; + mode_packet[0x05] = 0x02; + mode_packet[0x07] = 0x01; + mode_packet[0x08] = 0xFF; + + memset(wired_packet,0x00, GMOW_PACKET_SIZE); + wired_packet[0x03] = 0x02; + wired_packet[0x04] = 0x02; + wired_packet[0x05] = 0x02; + wired_packet[0x06] = 0x02; + wired_packet[0x07] = 0x01; + + memcpy(less_packet, wired_packet, GMOW_PACKET_SIZE); + less_packet[0x07] = 0x00; + + type = _type; +} + +SinowealthGMOWController::~SinowealthGMOWController() +{ + hid_close(dev); +} + +std::string SinowealthGMOWController::GetLocation() +{ + return("HID: " + location); +} + +std::string SinowealthGMOWController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + std::wstring return_wstring = serial_string; + std::string return_string(return_wstring.begin(), return_wstring.end()); + + return(return_string); +} + +std::string SinowealthGMOWController::GetFirmwareVersion() +{ + using namespace std::chrono_literals; + + unsigned char buf_send[GMOW_PACKET_SIZE] = {0}; + unsigned char buf_receive[GMOW_PACKET_SIZE] = {0}; + + if(type == GMOW_CABLE_CONNECTED) + { + buf_send[0x03] = 0x02; + } + + buf_send[0x04] = 0x03; + buf_send[0x06] = 0x81; + + hid_send_feature_report(dev,buf_send, GMOW_PACKET_SIZE); + + std::this_thread::sleep_for(50ms); + + hid_get_feature_report(dev,buf_receive,GMOW_PACKET_SIZE); + + char str[128] = {0}; + snprintf(str,128,"%d.%d.%d.%d", buf_receive[7], + buf_receive[8], + buf_receive[9], + buf_receive[10]); + + return std::string(str); +} + +void SinowealthGMOWController::SetMode(unsigned char mode, + unsigned char speed, + unsigned char wired_brightness, + unsigned char less_brightness, + RGBColor* color_buf, + unsigned char color_count) +{ + using namespace std::chrono_literals; + + unsigned char mode_buff[GMOW_PACKET_SIZE]; + memcpy(mode_buff, mode_packet, GMOW_PACKET_SIZE); + mode_buff[0x09] = mode; + + unsigned char wired_buff[GMOW_PACKET_SIZE]; + memcpy(wired_buff, wired_packet, GMOW_PACKET_SIZE); + wired_buff[0x08] = wired_brightness; + + unsigned char less_buff[GMOW_PACKET_SIZE]; + memcpy(less_buff, less_packet, GMOW_PACKET_SIZE); + less_buff[0x08] = less_brightness; + + + switch (mode) + { + case GMOW_MODE_RAINBOW_WAVE: + mode_buff[0x04] = 0x05; + mode_buff[0x0B] = speed; + break; + case GMOW_MODE_SPECTRUM_CYCLE: + mode_buff[0x04] = 0x05; + mode_buff[0x0B] = speed; + mode_buff[0x0C] = 0xFF; + break; + case GMOW_MODE_CUSTOM_BREATHING: + { + mode_buff[0x04] = color_count * 3 + 5; + mode_buff[0x0B] = speed; + + for(unsigned int i = 0; i < color_count; i++) + { + unsigned char r = (char)RGBGetRValue(color_buf[i]); + unsigned char g = (char)RGBGetGValue(color_buf[i]); + unsigned char b = (char)RGBGetBValue(color_buf[i]); + + if(r == 0x00 && g == 0x00 && b == 0x00) + { + r = 0x01; + } + + mode_buff[0x0C + 3*i + 0] = r; + mode_buff[0x0C + 3*i + 1] = g; + mode_buff[0x0C + 3*i + 2] = b; + } + + } + break; + case GMOW_MODE_STATIC: + { + mode_buff[0x04] = 0x05; + mode_buff[0x0B] = 0x09; // rate is replaced with 9 + + unsigned char r = (char)RGBGetRValue(color_buf[0]); + unsigned char g = (char)RGBGetGValue(color_buf[0]); + unsigned char b = (char)RGBGetBValue(color_buf[0]); + + if(r == 0 && g == 0 && b == 0) + { + r = 1; + } + + mode_buff[0x0C] = r; + mode_buff[0x0D] = g; + mode_buff[0x0E] = b; + } + break; + case GMOW_MODE_BREATHING: + { + mode_buff[0x04] = 0x08; + mode_buff[0x0B] = speed; + + unsigned char r = (char)RGBGetRValue(color_buf[0]); + unsigned char g = (char)RGBGetGValue(color_buf[0]); + unsigned char b = (char)RGBGetBValue(color_buf[0]); + + if(r == 0 && g == 0 && b == 0) + { + r = 1; + } + + mode_buff[0x0C] = r; + mode_buff[0x0D] = g; + mode_buff[0x0E] = b; + } + break; + case GMOW_MODE_TAIL: + mode_buff[0x04] = 0x05; + mode_buff[0x0B] = speed; + break; + case GMOW_MODE_RAVE: + { + mode_buff[0x04] = color_count * 3 + 5; + mode_buff[0x0B] = speed; + + for(unsigned int i = 0; i < color_count; i++) { + unsigned char r = (char)RGBGetRValue(color_buf[i]); + unsigned char g = (char)RGBGetGValue(color_buf[i]); + unsigned char b = (char)RGBGetBValue(color_buf[i]); + + if(r == 0 && g == 0 && b == 0) + { + r = 1; + } + + mode_buff[0x0C + 3*i + 0] = r; + mode_buff[0x0C + 3*i + 1] = g; + mode_buff[0x0C + 3*i + 2] = b; + } + } + break; + case GMOW_MODE_WAVE: + mode_buff[0x04] = 0x05; + mode_buff[0x0B] = speed; + break; + case GMOW_MODE_OFF: + mode_buff[0x04] = 0x05; + mode_buff[0x0B] = 0x09; + break; + default: + break; + } + + std::this_thread::sleep_for(50ms); + hid_send_feature_report(dev, mode_buff, GMOW_PACKET_SIZE); + + std::this_thread::sleep_for(50ms); + hid_send_feature_report(dev, wired_buff, GMOW_PACKET_SIZE); + + std::this_thread::sleep_for(50ms); + hid_send_feature_report(dev, less_buff, GMOW_PACKET_SIZE); + + +} \ No newline at end of file diff --git a/Controllers/SinowealthController/SinowealthGMOWController.h b/Controllers/SinowealthController/SinowealthGMOWController.h new file mode 100644 index 00000000..9a2294e3 --- /dev/null +++ b/Controllers/SinowealthController/SinowealthGMOWController.h @@ -0,0 +1,82 @@ +/*-------------------------------------------*\ +| SinowealthGMOWController.h | +| | +| Support for the Glorious Model O Wireless | +| | +| Matt Silva (thesilvanator) 05/2022 | +\*-------------------------------------------*/ + +#include "RGBController.h" +#include +#include + +#pragma once + +#define GMOW_PACKET_SIZE 64 + 1 + +enum +{ + GMOW_MODE_OFF = 0x00, + GMOW_MODE_RAINBOW_WAVE = 0x01, + GMOW_MODE_SPECTRUM_CYCLE = 0x02, + GMOW_MODE_CUSTOM_BREATHING = 0x03, + GMOW_MODE_STATIC = 0x04, + GMOW_MODE_BREATHING = 0x05, + GMOW_MODE_TAIL = 0x06, + GMOW_MODE_RAVE = 0x07, + GMOW_MODE_WAVE = 0x08, +}; + +enum +{ + GMOW_SPEED1_MIN = 0x14, + GMOW_SPEED1_MID = 0x0B, + GMOW_SPEED1_MAX = 0x01, + + GMOW_SPEED2_MIN = 0xC8, + GMOW_SPEED2_MID = 0x6E, + GMOW_SPEED2_MAX = 0x0A, +}; + + +enum +{ + GMOW_BRIGHTNESS_MIN = 0x00, + GMOW_BRIGHTNESS_MID = 0x7F, + GMOW_BRIGHTNESS_MAX = 0xFF, +}; + +enum +{ + GMOW_CABLE_CONNECTED, + GMOW_DONGLE_CONNECTED +}; + + +class SinowealthGMOWController +{ +public: + SinowealthGMOWController(hid_device* dev_handle, char *_path, int type); + ~SinowealthGMOWController(); + + std::string GetLocation(); + std::string GetSerialString(); + + void SetMode(unsigned char mode, + unsigned char speed, + unsigned char wired_brightness, + unsigned char less_brightness, + RGBColor* color_buf, + unsigned char color_count); + + std::string GetFirmwareVersion(); + +private: + hid_device* dev; + unsigned char mode_packet[GMOW_PACKET_SIZE]; + unsigned char wired_packet[GMOW_PACKET_SIZE]; + unsigned char less_packet[GMOW_PACKET_SIZE]; + + std::string location; + int type; +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index 2ca37d17..1992ae5f 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -529,10 +529,12 @@ HEADERS += Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.h \ Controllers/SinowealthController/SinowealthController.h \ Controllers/SinowealthController/SinowealthController1007.h \ + Controllers/SinowealthController/SinowealthGMOWController.h \ Controllers/SinowealthController/SinowealthKeyboardController.h \ Controllers/SinowealthController/SinowealthKeyboard16Controller.h \ Controllers/SinowealthController/RGBController_Sinowealth.h \ Controllers/SinowealthController/RGBController_Sinowealth1007.h \ + Controllers/SinowealthController/RGBController_SinowealthGMOW.h \ Controllers/SinowealthController/RGBController_SinowealthKeyboard.h \ Controllers/SinowealthController/RGBController_SinowealthKeyboard16.h \ Controllers/SonyGamepadController/SonyDualSenseController.h \ @@ -1069,11 +1071,13 @@ SOURCES += Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.cpp \ Controllers/SinowealthController/SinowealthController.cpp \ Controllers/SinowealthController/SinowealthController1007.cpp \ + Controllers/SinowealthController/SinowealthGMOWController.cpp \ Controllers/SinowealthController/SinowealthKeyboardController.cpp \ Controllers/SinowealthController/SinowealthKeyboard16Controller.cpp \ Controllers/SinowealthController/SinowealthControllerDetect.cpp \ Controllers/SinowealthController/RGBController_Sinowealth.cpp \ Controllers/SinowealthController/RGBController_Sinowealth1007.cpp \ + Controllers/SinowealthController/RGBController_SinowealthGMOW.cpp \ Controllers/SinowealthController/RGBController_SinowealthKeyboard.cpp \ Controllers/SinowealthController/RGBController_SinowealthKeyboard16.cpp \ Controllers/SonyGamepadController/SonyDualSenseController.cpp \