Skip to content

Commit 8b9a4d1

Browse files
karvanitisCalcProgrammer1
authored andcommitted
Add support for Glorious Model I
1 parent 05b4f00 commit 8b9a4d1

5 files changed

Lines changed: 462 additions & 0 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*---------------------------------------------------------*\
2+
| LaviewTechnologyController.cpp |
3+
| |
4+
| Driver for Laview Tech. mice, including Glorious |
5+
| |
6+
| Kosta A (kostaarvanitis) 27 Oct 2025 |
7+
| |
8+
| This file is part of the OpenRGB project |
9+
| SPDX-License-Identifier: GPL-2.0-or-later |
10+
\*---------------------------------------------------------*/
11+
12+
#include <cstring>
13+
#include <cmath>
14+
#include "LogManager.h"
15+
#include "LaviewTechnologyController.h"
16+
#include "StringUtils.h"
17+
18+
LaviewTechnologyController::LaviewTechnologyController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name)
19+
{
20+
device = dev_handle;
21+
location = dev_info->path;
22+
name = dev_name;
23+
version = dev_info->release_number;
24+
vendor = StringUtils::wstring_to_string(dev_info->manufacturer_string);
25+
serial = StringUtils::wstring_to_string(dev_info->serial_number);
26+
}
27+
28+
LaviewTechnologyController::~LaviewTechnologyController()
29+
{
30+
hid_close(device);
31+
}
32+
33+
std::string LaviewTechnologyController::GetLocation()
34+
{
35+
return("HID: " + location);
36+
}
37+
38+
std::string LaviewTechnologyController::GetName()
39+
{
40+
return(name);
41+
}
42+
43+
std::string LaviewTechnologyController::GetVendor()
44+
{
45+
return(vendor);
46+
}
47+
48+
std::string LaviewTechnologyController::GetSerialNumber()
49+
{
50+
return(serial);
51+
}
52+
53+
std::string LaviewTechnologyController::GetFirmwareVersion()
54+
{
55+
return std::to_string(version);
56+
}
57+
58+
void LaviewTechnologyController::SetMode(unsigned int mode, unsigned int brightness, unsigned int speed, RGBColor* color)
59+
{
60+
uint8_t buf[LAVIEW_TECHNOLOGY_REPORT_SIZE];
61+
memset(buf, 0x00, sizeof(buf));
62+
63+
buf[0] = 0xA1;
64+
buf[1] = 0x0C;
65+
buf[5] = 0x01; // Profile
66+
67+
buf[16] = mode;
68+
buf[56] = std::clamp(0u, brightness, 64u);
69+
buf[58] = std::clamp(0u, speed, 64u);
70+
buf[60] = 0; // Set for some modes???
71+
72+
switch (mode)
73+
{
74+
case LAVIEW_TECHNOLOGY_MODE_STATIC:
75+
case LAVIEW_TECHNOLOGY_MODE_BREATHING:
76+
buf[17] = RGBGetRValue(color[0]);
77+
buf[18] = RGBGetGValue(color[0]);
78+
buf[19] = RGBGetBValue(color[0]);
79+
break;
80+
default:
81+
/*----------------------------------------------------------------*\
82+
| For these reports we inject the default color scheme into the |
83+
| availble rgb values which in the official control application |
84+
| are not present in some modes causing them to not function. |
85+
| There is no mechanism in the control software for manipulating |
86+
| these values, as such this functionality is also omitted here. |
87+
\*----------------------------------------------------------------*/
88+
const unsigned char bytes[] = {
89+
0xFF, 0x00, 0x00, 0xFF, 0xA5, 0x00, 0xFF, 0xFF, 0x00,
90+
0x00, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0xFF,
91+
0x8B, 0x00, 0xFF
92+
};
93+
memcpy(&buf[17], bytes, sizeof(bytes));
94+
break;
95+
};
96+
97+
int ret = hid_send_feature_report(device, buf, sizeof(buf));
98+
if(ret < 0)
99+
{
100+
LOG_ERROR("[%s] Failure to send report (%ls)!", name.c_str(), hid_error(device));
101+
}
102+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*---------------------------------------------------------*\
2+
| LaviewTechnologyController.h |
3+
| |
4+
| Driver for Laview Tech. mice, including Glorious |
5+
| |
6+
| Kosta A (kostaarvanitis) 27 Oct 2025 |
7+
| |
8+
| This file is part of the OpenRGB project |
9+
| SPDX-License-Identifier: GPL-2.0-or-later |
10+
\*---------------------------------------------------------*/
11+
12+
#pragma once
13+
14+
#include <vector>
15+
#include <hidapi.h>
16+
#include "RGBController.h"
17+
18+
#define LAVIEW_TECHNOLOGY_REPORT_SIZE 64
19+
20+
enum
21+
{
22+
LAVIEW_TECHNOLOGY_MODE_OFF = 0x00, // Off
23+
LAVIEW_TECHNOLOGY_MODE_STATIC = 0x01, // Normally on
24+
LAVIEW_TECHNOLOGY_MODE_FLASHING = 0x02, // Wave
25+
LAVIEW_TECHNOLOGY_MODE_BREATHING = 0x04, // Breathing single color
26+
LAVIEW_TECHNOLOGY_MODE_SPECTRUM_CYCLE = 0x06, // Breating does not work with factory Core software
27+
LAVIEW_TECHNOLOGY_MODE_RAINBOW_WAVE = 0x10, // Glorious Mode
28+
LAVIEW_TECHNOLOGY_MODE_CHASE = 0x11, // Tail
29+
LAVIEW_TECHNOLOGY_MODE_WAVE = 0x14, // Rave (Same issue as breathing)
30+
LAVIEW_TECHNOLOGY_MODE_SPECTRUM_BREATHING = 0x15, // Seamless Breathing
31+
};
32+
33+
enum
34+
{
35+
LAVIEW_TECHNOLOGY_SPEED_SLOW = 1,
36+
LAVIEW_TECHNOLOGY_SPEED_NORMAL = 50,
37+
LAVIEW_TECHNOLOGY_SPEED_FAST = 100,
38+
};
39+
40+
enum
41+
{
42+
LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW = 0,
43+
LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL = 50,
44+
LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST = 100,
45+
};
46+
47+
class LaviewTechnologyController
48+
{
49+
public:
50+
LaviewTechnologyController(hid_device* dev_handle, hid_device_info* dev_info, std::string name);
51+
~LaviewTechnologyController();
52+
53+
std::string GetLocation();
54+
std::string GetName();
55+
std::string GetVendor();
56+
std::string GetSerialNumber();
57+
std::string GetFirmwareVersion();
58+
59+
void SetMode(unsigned int mode, unsigned int brightness, unsigned int speed, RGBColor* color);
60+
61+
private:
62+
hid_device* device;
63+
std::string location;
64+
std::string name;
65+
std::string vendor;
66+
std::string serial;
67+
unsigned int version;
68+
};
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/*---------------------------------------------------------*\
2+
| RGBController_LaviewTechnology.cpp |
3+
| |
4+
| RGBController for Laview Tech. mice, including Glorious |
5+
| |
6+
| Kosta A (kostaarvanitis) 27 Oct 2025 |
7+
| |
8+
| This file is part of the OpenRGB project |
9+
| SPDX-License-Identifier: GPL-2.0-or-later |
10+
\*---------------------------------------------------------*/
11+
12+
#include "RGBController_LaviewTechnology.h"
13+
14+
/**------------------------------------------------------------------*\
15+
@name Laview Technology Mice
16+
@category Mouse
17+
@type USB
18+
@save :robot:
19+
@direct :x:
20+
@effects :white_check_mark:
21+
@detectors DetectLaviewTechnologyMouse
22+
@comment
23+
\*-------------------------------------------------------------------*/
24+
25+
RGBController_LaviewTechnology::RGBController_LaviewTechnology(LaviewTechnologyController* controller_ptr)
26+
{
27+
controller = controller_ptr;
28+
29+
name = controller->GetName();
30+
type = DEVICE_TYPE_MOUSE;
31+
description = "Glorious Device";
32+
vendor = controller->GetVendor();
33+
location = controller->GetLocation();
34+
serial = controller->GetSerialNumber();
35+
version = controller->GetFirmwareVersion();
36+
37+
mode Custom;
38+
Custom.name = "Custom";
39+
Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
40+
Custom.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW;
41+
Custom.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL;
42+
Custom.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST;
43+
Custom.color_mode = MODE_COLORS_PER_LED;
44+
Custom.value = LAVIEW_TECHNOLOGY_MODE_STATIC;
45+
modes.push_back(Custom);
46+
47+
mode Flashing;
48+
Flashing.name = "Flashing";
49+
Flashing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
50+
Flashing.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW;
51+
Flashing.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL;
52+
Flashing.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST;
53+
Flashing.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW;
54+
Flashing.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL;
55+
Flashing.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST;
56+
Flashing.color_mode = MODE_COLORS_NONE;
57+
Flashing.value = LAVIEW_TECHNOLOGY_MODE_FLASHING;
58+
modes.push_back(Flashing);
59+
60+
mode Chase;
61+
Chase.name = "Chase";
62+
Chase.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
63+
Chase.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW;
64+
Chase.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL;
65+
Chase.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST;
66+
Chase.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW;
67+
Chase.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL;
68+
Chase.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST;
69+
Chase.color_mode = MODE_COLORS_NONE;
70+
Chase.value = LAVIEW_TECHNOLOGY_MODE_CHASE;
71+
modes.push_back(Chase);
72+
73+
mode Wave;
74+
Wave.name = "Wave";
75+
Wave.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
76+
Wave.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW;
77+
Wave.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL;
78+
Wave.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST;
79+
Wave.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW;
80+
Wave.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL;
81+
Wave.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST;
82+
Wave.color_mode = MODE_COLORS_NONE;
83+
Wave.value = LAVIEW_TECHNOLOGY_MODE_WAVE;
84+
modes.push_back(Wave);
85+
86+
mode SpectrumCycle;
87+
SpectrumCycle.name = "Spectrum Cycle";
88+
SpectrumCycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
89+
SpectrumCycle.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW;
90+
SpectrumCycle.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL;
91+
SpectrumCycle.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST;
92+
SpectrumCycle.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW;
93+
SpectrumCycle.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL;
94+
SpectrumCycle.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST;
95+
SpectrumCycle.color_mode = MODE_COLORS_NONE;
96+
SpectrumCycle.value = LAVIEW_TECHNOLOGY_MODE_SPECTRUM_CYCLE;
97+
modes.push_back(SpectrumCycle);
98+
99+
mode Breathing;
100+
Breathing.name = "Breathing";
101+
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
102+
Breathing.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW;
103+
Breathing.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL;
104+
Breathing.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST;
105+
Breathing.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW;
106+
Breathing.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL;
107+
Breathing.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST;
108+
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
109+
Breathing.colors_min = 1;
110+
Breathing.colors_max = 1;
111+
Breathing.colors.resize(1, ToRGBColor(255, 0, 0));
112+
Breathing.value = LAVIEW_TECHNOLOGY_MODE_BREATHING;
113+
modes.push_back(Breathing);
114+
115+
mode SpectrumBreathing;
116+
SpectrumBreathing.name = "Spectrum Breathing";
117+
SpectrumBreathing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
118+
SpectrumBreathing.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW;
119+
SpectrumBreathing.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL;
120+
SpectrumBreathing.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST;
121+
SpectrumBreathing.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW;
122+
SpectrumBreathing.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL;
123+
SpectrumBreathing.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST;
124+
SpectrumBreathing.color_mode = MODE_COLORS_NONE;
125+
SpectrumBreathing.value = LAVIEW_TECHNOLOGY_MODE_SPECTRUM_BREATHING;
126+
modes.push_back(SpectrumBreathing);
127+
128+
mode RainbowWave;
129+
RainbowWave.name = "Rainbow Wave";
130+
RainbowWave.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
131+
RainbowWave.brightness_min = LAVIEW_TECHNOLOGY_BRIGHTNESS_SLOW;
132+
RainbowWave.brightness = LAVIEW_TECHNOLOGY_BRIGHTNESS_NORMAL;
133+
RainbowWave.brightness_max = LAVIEW_TECHNOLOGY_BRIGHTNESS_FAST;
134+
RainbowWave.speed_min = LAVIEW_TECHNOLOGY_SPEED_SLOW;
135+
RainbowWave.speed = LAVIEW_TECHNOLOGY_SPEED_NORMAL;
136+
RainbowWave.speed_max = LAVIEW_TECHNOLOGY_SPEED_FAST;
137+
RainbowWave.color_mode = MODE_COLORS_NONE;
138+
RainbowWave.value = LAVIEW_TECHNOLOGY_MODE_RAINBOW_WAVE;
139+
modes.push_back(RainbowWave);
140+
141+
mode Off;
142+
Off.name = "Off";
143+
Off.flags = MODE_FLAG_AUTOMATIC_SAVE;
144+
Off.color_mode = MODE_COLORS_NONE;
145+
Off.value = LAVIEW_TECHNOLOGY_MODE_OFF;
146+
modes.push_back(Off);
147+
148+
SetupZones();
149+
}
150+
151+
void RGBController_LaviewTechnology::SetupZones()
152+
{
153+
/*---------------------------------------------------------*\
154+
| Create a single zone |
155+
\*---------------------------------------------------------*/
156+
zone new_zone;
157+
new_zone.name = "Mouse";
158+
new_zone.type = ZONE_TYPE_SINGLE;
159+
new_zone.leds_min = 1;
160+
new_zone.leds_max = 1;
161+
new_zone.leds_count = 1;
162+
new_zone.matrix_map = NULL;
163+
zones.push_back(new_zone);
164+
165+
/*---------------------------------------------------------*\
166+
| Set up LEDs |
167+
\*---------------------------------------------------------*/
168+
led new_led;
169+
new_led.name = "LED";
170+
leds.push_back(new_led);
171+
172+
SetupColors();
173+
}
174+
175+
RGBController_LaviewTechnology::~RGBController_LaviewTechnology()
176+
{
177+
delete controller;
178+
}
179+
180+
void RGBController_LaviewTechnology::ResizeZone(int /*zone*/, int /*new_size*/)
181+
{
182+
}
183+
184+
void RGBController_LaviewTechnology::DeviceUpdateLEDs()
185+
{
186+
DeviceUpdateMode();
187+
}
188+
189+
void RGBController_LaviewTechnology::UpdateZoneLEDs(int /*zone*/)
190+
{
191+
DeviceUpdateMode();
192+
}
193+
194+
void RGBController_LaviewTechnology::UpdateSingleLED(int /*led*/)
195+
{
196+
DeviceUpdateMode();
197+
}
198+
199+
void RGBController_LaviewTechnology::DeviceUpdateMode()
200+
{
201+
if(modes[active_mode].color_mode == MODE_COLORS_PER_LED)
202+
{
203+
controller->SetMode(modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed, &colors[0]);
204+
}
205+
else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
206+
{
207+
controller->SetMode(modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed, &modes[active_mode].colors[0]);
208+
}
209+
else // MODE_COLORS_NONE
210+
{
211+
controller->SetMode(modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed, 0);
212+
}
213+
}

0 commit comments

Comments
 (0)