diff --git a/Controllers/LaviewTechnologyController/LaviewTechnologyController/LaviewTechnologyController.cpp b/Controllers/LaviewTechnologyController/LaviewTechnologyController/LaviewTechnologyController.cpp new file mode 100644 index 00000000..bf4321ac --- /dev/null +++ b/Controllers/LaviewTechnologyController/LaviewTechnologyController/LaviewTechnologyController.cpp @@ -0,0 +1,102 @@ +/*---------------------------------------------------------*\ +| LaviewTechnologyController.cpp | +| | +| Driver for Laview Tech. mice, including Glorious | +| | +| Kosta A (kostaarvanitis) 27 Oct 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-or-later | +\*---------------------------------------------------------*/ + +#include +#include +#include "LogManager.h" +#include "LaviewTechnologyController.h" +#include "StringUtils.h" + +LaviewTechnologyController::LaviewTechnologyController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name) +{ + device = dev_handle; + location = dev_info->path; + name = dev_name; + version = dev_info->release_number; + vendor = StringUtils::wstring_to_string(dev_info->manufacturer_string); + serial = StringUtils::wstring_to_string(dev_info->serial_number); +} + +LaviewTechnologyController::~LaviewTechnologyController() +{ + hid_close(device); +} + +std::string LaviewTechnologyController::GetLocation() +{ + return("HID: " + location); +} + +std::string LaviewTechnologyController::GetName() +{ + return(name); +} + +std::string LaviewTechnologyController::GetVendor() +{ + return(vendor); +} + +std::string LaviewTechnologyController::GetSerialNumber() +{ + return(serial); +} + +std::string LaviewTechnologyController::GetFirmwareVersion() +{ + return std::to_string(version); +} + +void LaviewTechnologyController::SetMode(unsigned int mode, unsigned int brightness, unsigned int speed, RGBColor* color) +{ + uint8_t buf[LAVIEW_TECHNOLOGY_REPORT_SIZE]; + memset(buf, 0x00, sizeof(buf)); + + buf[0] = 0xA1; + buf[1] = 0x0C; + buf[5] = 0x01; // Profile + + buf[16] = mode; + buf[56] = std::clamp(0u, brightness, 64u); + buf[58] = std::clamp(0u, speed, 64u); + buf[60] = 0; // Set for some modes??? + + switch (mode) + { + case LAVIEW_TECHNOLOGY_MODE_STATIC: + case LAVIEW_TECHNOLOGY_MODE_BREATHING: + buf[17] = RGBGetRValue(color[0]); + buf[18] = RGBGetGValue(color[0]); + buf[19] = RGBGetBValue(color[0]); + break; + default: + /*----------------------------------------------------------------*\ + | For these reports we inject the default color scheme into the | + | availble rgb values which in the official control application | + | are not present in some modes causing them to not function. | + | There is no mechanism in the control software for manipulating | + | these values, as such this functionality is also omitted here. | + \*----------------------------------------------------------------*/ + const unsigned char bytes[] = { + 0xFF, 0x00, 0x00, 0xFF, 0xA5, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0xFF, + 0x8B, 0x00, 0xFF + }; + memcpy(&buf[17], bytes, sizeof(bytes)); + break; + }; + + int ret = hid_send_feature_report(device, buf, sizeof(buf)); + if(ret < 0) + { + LOG_ERROR("[%s] Failure to send report (%ls)!", name.c_str(), hid_error(device)); + } +} \ No newline at end of file diff --git a/Controllers/LaviewTechnologyController/LaviewTechnologyController/LaviewTechnologyController.h b/Controllers/LaviewTechnologyController/LaviewTechnologyController/LaviewTechnologyController.h new file mode 100644 index 00000000..98a75290 --- /dev/null +++ b/Controllers/LaviewTechnologyController/LaviewTechnologyController/LaviewTechnologyController.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------*\ +| LaviewTechnologyController.h | +| | +| Driver for Laview Tech. mice, including Glorious | +| | +| Kosta A (kostaarvanitis) 27 Oct 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-or-later | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define LAVIEW_TECHNOLOGY_REPORT_SIZE 64 + +enum +{ + LAVIEW_TECHNOLOGY_MODE_OFF = 0x00, // Off + LAVIEW_TECHNOLOGY_MODE_STATIC = 0x01, // Normally on + LAVIEW_TECHNOLOGY_MODE_FLASHING = 0x02, // Wave + LAVIEW_TECHNOLOGY_MODE_BREATHING = 0x04, // Breathing single color + LAVIEW_TECHNOLOGY_MODE_SPECTRUM_CYCLE = 0x06, // Breating does not work with factory Core software + LAVIEW_TECHNOLOGY_MODE_RAINBOW_WAVE = 0x10, // Glorious Mode + LAVIEW_TECHNOLOGY_MODE_CHASE = 0x11, // Tail + LAVIEW_TECHNOLOGY_MODE_WAVE = 0x14, // Rave (Same issue as breathing) + LAVIEW_TECHNOLOGY_MODE_SPECTRUM_BREATHING = 0x15, // Seamless Breathing +}; + +enum +{ + LAVIEW_TECHNOLOGY_SPEED_SLOW = 1, + LAVIEW_TECHNOLOGY_SPEED_NORMAL = 50, + LAVIEW_TECHNOLOGY_SPEED_FAST = 100, +}; + +enum +{ + LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW = 0, + LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL = 50, + LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST = 100, +}; + +class LaviewTechnologyController +{ +public: + LaviewTechnologyController(hid_device* dev_handle, hid_device_info* dev_info, std::string name); + ~LaviewTechnologyController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetVendor(); + std::string GetSerialNumber(); + std::string GetFirmwareVersion(); + + void SetMode(unsigned int mode, unsigned int brightness, unsigned int speed, RGBColor* color); + +private: + hid_device* device; + std::string location; + std::string name; + std::string vendor; + std::string serial; + unsigned int version; +}; diff --git a/Controllers/LaviewTechnologyController/LaviewTechnologyController/RGBController_LaviewTechnology.cpp b/Controllers/LaviewTechnologyController/LaviewTechnologyController/RGBController_LaviewTechnology.cpp new file mode 100644 index 00000000..bb19bc36 --- /dev/null +++ b/Controllers/LaviewTechnologyController/LaviewTechnologyController/RGBController_LaviewTechnology.cpp @@ -0,0 +1,213 @@ +/*---------------------------------------------------------*\ +| RGBController_LaviewTechnology.cpp | +| | +| RGBController for Laview Tech. mice, including Glorious | +| | +| Kosta A (kostaarvanitis) 27 Oct 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-or-later | +\*---------------------------------------------------------*/ + +#include "RGBController_LaviewTechnology.h" + +/**------------------------------------------------------------------*\ + @name Laview Technology Mice + @category Mouse + @type USB + @save :robot: + @direct :x: + @effects :white_check_mark: + @detectors DetectLaviewTechnologyMouse + @comment +\*-------------------------------------------------------------------*/ + +RGBController_LaviewTechnology::RGBController_LaviewTechnology(LaviewTechnologyController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + type = DEVICE_TYPE_MOUSE; + description = "Glorious Device"; + vendor = controller->GetVendor(); + location = controller->GetLocation(); + serial = controller->GetSerialNumber(); + version = controller->GetFirmwareVersion(); + + mode Custom; + Custom.name = "Custom"; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Custom.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW; + Custom.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL; + Custom.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.value = LAVIEW_TECHNOLOGY_MODE_STATIC; + modes.push_back(Custom); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Flashing.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW; + Flashing.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL; + Flashing.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST; + Flashing.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW; + Flashing.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL; + Flashing.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST; + Flashing.color_mode = MODE_COLORS_NONE; + Flashing.value = LAVIEW_TECHNOLOGY_MODE_FLASHING; + modes.push_back(Flashing); + + mode Chase; + Chase.name = "Chase"; + Chase.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Chase.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW; + Chase.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL; + Chase.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST; + Chase.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW; + Chase.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL; + Chase.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST; + Chase.color_mode = MODE_COLORS_NONE; + Chase.value = LAVIEW_TECHNOLOGY_MODE_CHASE; + modes.push_back(Chase); + + mode Wave; + Wave.name = "Wave"; + Wave.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Wave.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW; + Wave.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL; + Wave.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST; + Wave.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW; + Wave.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL; + Wave.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST; + Wave.color_mode = MODE_COLORS_NONE; + Wave.value = LAVIEW_TECHNOLOGY_MODE_WAVE; + modes.push_back(Wave); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + SpectrumCycle.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW; + SpectrumCycle.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL; + SpectrumCycle.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST; + SpectrumCycle.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW; + SpectrumCycle.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL; + SpectrumCycle.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.value = LAVIEW_TECHNOLOGY_MODE_SPECTRUM_CYCLE; + modes.push_back(SpectrumCycle); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Breathing.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW; + Breathing.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL; + Breathing.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST; + Breathing.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW; + Breathing.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL; + Breathing.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(1, ToRGBColor(255, 0, 0)); + Breathing.value = LAVIEW_TECHNOLOGY_MODE_BREATHING; + modes.push_back(Breathing); + + mode SpectrumBreathing; + SpectrumBreathing.name = "Spectrum Breathing"; + SpectrumBreathing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + SpectrumBreathing.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW; + SpectrumBreathing.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL; + SpectrumBreathing.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST; + SpectrumBreathing.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW; + SpectrumBreathing.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL; + SpectrumBreathing.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST; + SpectrumBreathing.color_mode = MODE_COLORS_NONE; + SpectrumBreathing.value = LAVIEW_TECHNOLOGY_MODE_SPECTRUM_BREATHING; + modes.push_back(SpectrumBreathing); + + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + RainbowWave.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW; + RainbowWave.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL; + RainbowWave.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST; + RainbowWave.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW; + RainbowWave.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL; + RainbowWave.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST; + RainbowWave.color_mode = MODE_COLORS_NONE; + RainbowWave.value = LAVIEW_TECHNOLOGY_MODE_RAINBOW_WAVE; + modes.push_back(RainbowWave); + + mode Off; + Off.name = "Off"; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + Off.value = LAVIEW_TECHNOLOGY_MODE_OFF; + modes.push_back(Off); + + SetupZones(); +} + +void RGBController_LaviewTechnology::SetupZones() +{ + /*---------------------------------------------------------*\ + | Create a single zone | + \*---------------------------------------------------------*/ + zone new_zone; + new_zone.name = "Mouse"; + new_zone.type = ZONE_TYPE_SINGLE; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + /*---------------------------------------------------------*\ + | Set up LEDs | + \*---------------------------------------------------------*/ + led new_led; + new_led.name = "LED"; + leds.push_back(new_led); + + SetupColors(); +} + +RGBController_LaviewTechnology::~RGBController_LaviewTechnology() +{ + delete controller; +} + +void RGBController_LaviewTechnology::ResizeZone(int /*zone*/, int /*new_size*/) +{ +} + +void RGBController_LaviewTechnology::DeviceUpdateLEDs() +{ + DeviceUpdateMode(); +} + +void RGBController_LaviewTechnology::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateMode(); +} + +void RGBController_LaviewTechnology::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateMode(); +} + +void RGBController_LaviewTechnology::DeviceUpdateMode() +{ + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + controller->SetMode(modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed, &colors[0]); + } + else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + controller->SetMode(modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed, &modes[active_mode].colors[0]); + } + else // MODE_COLORS_NONE + { + controller->SetMode(modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed, 0); + } +} diff --git a/Controllers/LaviewTechnologyController/LaviewTechnologyController/RGBController_LaviewTechnology.h b/Controllers/LaviewTechnologyController/LaviewTechnologyController/RGBController_LaviewTechnology.h new file mode 100644 index 00000000..8a7421c5 --- /dev/null +++ b/Controllers/LaviewTechnologyController/LaviewTechnologyController/RGBController_LaviewTechnology.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_LaviewTechnology.h | +| | +| RGBController for Laview Tech. mice, including Glorious | +| | +| Kosta A (kostaarvanitis) 27 Oct 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-or-later | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LaviewTechnologyController.h" + +class RGBController_LaviewTechnology : public RGBController +{ +public: + RGBController_LaviewTechnology(LaviewTechnologyController* controller_ptr); + ~RGBController_LaviewTechnology(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LaviewTechnologyController* controller; +}; diff --git a/Controllers/LaviewTechnologyController/LaviewTechnologyDetector.cpp b/Controllers/LaviewTechnologyController/LaviewTechnologyDetector.cpp new file mode 100644 index 00000000..37fe5bd7 --- /dev/null +++ b/Controllers/LaviewTechnologyController/LaviewTechnologyDetector.cpp @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| LaviewTechnologyDetect.cpp | +| | +| Detector for Laview Technology brand Mice (Glorious) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-or-later | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include "Detector.h" +#include "LaviewTechnologyController.h" +#include "RGBController.h" +#include "RGBController_LaviewTechnology.h" +#include "LogManager.h" + +#define LAVIEW_TECHNOLOGY_VID 0x22D4 + +#define GLORIOUS_MODEL_I_PID 0x1503 // Wired + +/******************************************************************************************\ +* * +* DetectLaviewTechnologyMouse * +* * +* Tests the USB address to see if a Laview Technology controller exists there. * +* * +\******************************************************************************************/ + +static void DetectLaviewTechnologyMouse(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LaviewTechnologyController* controller = new LaviewTechnologyController(dev, info, name); + RGBController_LaviewTechnology* rgb_controller = new RGBController_LaviewTechnology(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("Glorious Model I", DetectLaviewTechnologyMouse, LAVIEW_TECHNOLOGY_VID, GLORIOUS_MODEL_I_PID, 1, 0xFF01, 0x02);