Skip to content

Commit c58ae26

Browse files
solarkennedyCalcProgrammer1
authored andcommitted
Add support for TUXEDO laptop per-key RGB keyboard (ITE 8291)
1 parent 555fb7b commit c58ae26

5 files changed

Lines changed: 878 additions & 0 deletions

File tree

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*---------------------------------------------------------*\
2+
| ClevoKeyboardController.cpp |
3+
| |
4+
| Driver for Clevo laptop per-key RGB keyboard (ITE 8291) |
5+
| Protocol based on tuxedo-drivers ite_8291 module |
6+
| |
7+
| Kyle Cascade (kyle@cascade.family) 16 Jan 2026 |
8+
| |
9+
| This file is part of the OpenRGB project |
10+
| SPDX-License-Identifier: GPL-2.0-or-later |
11+
\*---------------------------------------------------------*/
12+
13+
#include "ClevoKeyboardController.h"
14+
#include <cstring>
15+
16+
ClevoKeyboardController::ClevoKeyboardController(hid_device* dev_handle, const hid_device_info& info)
17+
{
18+
dev = dev_handle;
19+
location = info.path;
20+
}
21+
22+
ClevoKeyboardController::~ClevoKeyboardController()
23+
{
24+
hid_close(dev);
25+
}
26+
27+
std::string ClevoKeyboardController::GetDeviceLocation()
28+
{
29+
return("HID: " + location);
30+
}
31+
32+
std::string ClevoKeyboardController::GetSerialString()
33+
{
34+
wchar_t serial_string[128];
35+
int ret = hid_get_serial_number_string(dev, serial_string, 128);
36+
37+
if(ret != 0)
38+
{
39+
return("");
40+
}
41+
42+
std::wstring return_wstring = serial_string;
43+
std::string return_string(return_wstring.begin(), return_wstring.end());
44+
45+
return(return_string);
46+
}
47+
48+
void ClevoKeyboardController::WriteControl(unsigned char* data)
49+
{
50+
hid_send_feature_report(dev, data, CLEVO_KEYBOARD_REPORT_SIZE);
51+
}
52+
53+
void ClevoKeyboardController::WriteRowData(unsigned char* data)
54+
{
55+
hid_write(dev, data, CLEVO_KEYBOARD_ROW_DATA_SIZE);
56+
}
57+
58+
void ClevoKeyboardController::TurnOff()
59+
{
60+
/*---------------------------------------------------------*\
61+
| Turn off: 08 01 00 00 00 00 00 00 |
62+
\*---------------------------------------------------------*/
63+
unsigned char buf[CLEVO_KEYBOARD_REPORT_SIZE];
64+
65+
memset(buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
66+
buf[0] = 0x08;
67+
buf[1] = 0x01;
68+
69+
WriteControl(buf);
70+
}
71+
72+
void ClevoKeyboardController::SetMode(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char behaviour)
73+
{
74+
/*---------------------------------------------------------*\
75+
| Set params: 08 [power] [mode] [speed] [brightness] 08 |
76+
| [behaviour] 00 |
77+
| power: 01=off, 02=on |
78+
\*---------------------------------------------------------*/
79+
unsigned char buf[CLEVO_KEYBOARD_REPORT_SIZE];
80+
81+
memset(buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
82+
buf[0] = 0x08;
83+
buf[1] = 0x02; // Power on
84+
buf[2] = mode;
85+
buf[3] = speed;
86+
buf[4] = brightness;
87+
buf[5] = 0x08;
88+
buf[6] = behaviour;
89+
90+
WriteControl(buf);
91+
}
92+
93+
void ClevoKeyboardController::SetModeColor(unsigned char color_idx, unsigned char red, unsigned char green, unsigned char blue)
94+
{
95+
/*---------------------------------------------------------*\
96+
| Set color define: 14 00 [index] R G B 00 00 |
97+
| index: 1-7 for built-in effects |
98+
\*---------------------------------------------------------*/
99+
unsigned char buf[CLEVO_KEYBOARD_REPORT_SIZE];
100+
101+
memset(buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
102+
buf[0] = 0x14;
103+
buf[1] = 0x00;
104+
buf[2] = color_idx;
105+
buf[3] = red;
106+
buf[4] = green;
107+
buf[5] = blue;
108+
109+
WriteControl(buf);
110+
}
111+
112+
void ClevoKeyboardController::SendColors(unsigned char* color_data, unsigned char brightness)
113+
{
114+
/*---------------------------------------------------------*\
115+
| Per-key RGB mode (mode 0x33) |
116+
| 1. Set params with mode 0x33 and brightness |
117+
| 2. For each row 0-5: |
118+
| - Announce row: 16 00 [row] 00 00 00 00 00 |
119+
| - Send 65 bytes row data via output report |
120+
| |
121+
| Row data format (65 bytes): |
122+
| [0x00 padding][0x00 padding] |
123+
| [B0..B20][G0..G20][R0..R20] |
124+
\*---------------------------------------------------------*/
125+
unsigned char ctrl_buf[CLEVO_KEYBOARD_REPORT_SIZE];
126+
unsigned char row_buf[CLEVO_KEYBOARD_ROW_DATA_SIZE];
127+
128+
/*---------------------------------------------------------*\
129+
| Clamp brightness |
130+
\*---------------------------------------------------------*/
131+
if(brightness > CLEVO_KEYBOARD_BRIGHTNESS_MAX)
132+
{
133+
brightness = CLEVO_KEYBOARD_BRIGHTNESS_MAX;
134+
}
135+
136+
/*---------------------------------------------------------*\
137+
| Set params for per-key mode |
138+
\*---------------------------------------------------------*/
139+
memset(ctrl_buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
140+
ctrl_buf[0] = 0x08;
141+
ctrl_buf[1] = 0x02; // Power on
142+
ctrl_buf[2] = CLEVO_KEYBOARD_MODE_DIRECT; // Per-key mode
143+
ctrl_buf[3] = 0x00; // Speed (unused)
144+
ctrl_buf[4] = brightness;
145+
ctrl_buf[5] = 0x00;
146+
ctrl_buf[6] = 0x00;
147+
148+
WriteControl(ctrl_buf);
149+
150+
/*---------------------------------------------------------*\
151+
| Send each row |
152+
\*---------------------------------------------------------*/
153+
for(int row = 0; row < CLEVO_KEYBOARD_NUM_ROWS; row++)
154+
{
155+
/*-----------------------------------------------------*\
156+
| Announce row data |
157+
\*-----------------------------------------------------*/
158+
memset(ctrl_buf, 0x00, CLEVO_KEYBOARD_REPORT_SIZE);
159+
ctrl_buf[0] = 0x16;
160+
ctrl_buf[1] = 0x00;
161+
ctrl_buf[2] = row;
162+
163+
WriteControl(ctrl_buf);
164+
165+
/*-----------------------------------------------------*\
166+
| Build row data buffer |
167+
| Format: [pad][pad][B0..B20][G0..G20][R0..R20] |
168+
\*-----------------------------------------------------*/
169+
memset(row_buf, 0x00, CLEVO_KEYBOARD_ROW_DATA_SIZE);
170+
171+
for(int col = 0; col < CLEVO_KEYBOARD_NUM_COLS; col++)
172+
{
173+
int led_idx = (row * CLEVO_KEYBOARD_NUM_COLS) + col;
174+
int color_offset = led_idx * 3;
175+
176+
unsigned char red = color_data[color_offset + 0];
177+
unsigned char green = color_data[color_offset + 1];
178+
unsigned char blue = color_data[color_offset + 2];
179+
180+
/*-------------------------------------------------*\
181+
| Row data layout (after 2-byte padding): |
182+
| Bytes 2-22: Blue values for columns 0-20 |
183+
| Bytes 23-43: Green values for columns 0-20 |
184+
| Bytes 44-64: Red values for columns 0-20 |
185+
\*-------------------------------------------------*/
186+
row_buf[2 + col] = blue;
187+
row_buf[2 + CLEVO_KEYBOARD_NUM_COLS + col] = green;
188+
row_buf[2 + CLEVO_KEYBOARD_NUM_COLS*2 + col] = red;
189+
}
190+
191+
WriteRowData(row_buf);
192+
}
193+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*---------------------------------------------------------*\
2+
| ClevoKeyboardController.h |
3+
| |
4+
| Driver for Clevo laptop per-key RGB keyboard (ITE 8291) |
5+
| |
6+
| Kyle Cascade (kyle@cascade.family) 16 Jan 2026 |
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 <string>
15+
#include <hidapi.h>
16+
17+
/*-----------------------------------------------------*\
18+
| ITE 8291 keyboard defines |
19+
\*-----------------------------------------------------*/
20+
#define CLEVO_KEYBOARD_REPORT_SIZE 8
21+
#define CLEVO_KEYBOARD_ROW_DATA_SIZE 65
22+
23+
#define CLEVO_KEYBOARD_NUM_ROWS 6
24+
#define CLEVO_KEYBOARD_NUM_COLS 21
25+
#define CLEVO_KEYBOARD_NUM_LEDS (CLEVO_KEYBOARD_NUM_ROWS * CLEVO_KEYBOARD_NUM_COLS)
26+
27+
#define CLEVO_KEYBOARD_BRIGHTNESS_MIN 0x00
28+
#define CLEVO_KEYBOARD_BRIGHTNESS_MAX 0x32
29+
30+
#define CLEVO_KEYBOARD_SPEED_MIN 0x01
31+
#define CLEVO_KEYBOARD_SPEED_MAX 0x0A
32+
33+
/*-----------------------------------------------------*\
34+
| ITE 8291 modes |
35+
\*-----------------------------------------------------*/
36+
enum
37+
{
38+
CLEVO_KEYBOARD_MODE_DIRECT = 0x33,
39+
CLEVO_KEYBOARD_MODE_BREATH = 0x02,
40+
CLEVO_KEYBOARD_MODE_WAVE = 0x03,
41+
CLEVO_KEYBOARD_MODE_REACTIVE = 0x04,
42+
CLEVO_KEYBOARD_MODE_RAINBOW = 0x05,
43+
CLEVO_KEYBOARD_MODE_RIPPLE = 0x06,
44+
CLEVO_KEYBOARD_MODE_MARQUEE = 0x09,
45+
CLEVO_KEYBOARD_MODE_RAINDROP = 0x0A,
46+
CLEVO_KEYBOARD_MODE_AURORA = 0x0E,
47+
CLEVO_KEYBOARD_MODE_SPARK = 0x11,
48+
};
49+
50+
/*-----------------------------------------------------*\
51+
| Wave/reactive behaviour |
52+
\*-----------------------------------------------------*/
53+
enum
54+
{
55+
CLEVO_KEYBOARD_DIRECTION_LEFT = 0x01,
56+
CLEVO_KEYBOARD_DIRECTION_RIGHT = 0x02,
57+
CLEVO_KEYBOARD_DIRECTION_UP = 0x03,
58+
CLEVO_KEYBOARD_DIRECTION_DOWN = 0x04,
59+
};
60+
61+
enum
62+
{
63+
CLEVO_KEYBOARD_REACTIVE_KEYPRESS = 0x00,
64+
CLEVO_KEYBOARD_REACTIVE_AUTO = 0x01,
65+
};
66+
67+
class ClevoKeyboardController
68+
{
69+
public:
70+
ClevoKeyboardController(hid_device* dev_handle, const hid_device_info& info);
71+
~ClevoKeyboardController();
72+
73+
std::string GetDeviceLocation();
74+
std::string GetSerialString();
75+
76+
void TurnOff();
77+
void SetMode(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char behaviour);
78+
void SetModeColor(unsigned char color_idx, unsigned char red, unsigned char green, unsigned char blue);
79+
void SendColors(unsigned char* color_data, unsigned char brightness);
80+
81+
private:
82+
hid_device* dev;
83+
std::string location;
84+
85+
void WriteControl(unsigned char* data);
86+
void WriteRowData(unsigned char* data);
87+
};
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*---------------------------------------------------------*\
2+
| ClevoKeyboardControllerDetect.cpp |
3+
| |
4+
| Detector for Clevo per-key RGB keyboard (ITE 8291) |
5+
| |
6+
| Kyle Cascade (kyle@cascade.family) 16 Jan 2026 |
7+
| |
8+
| This file is part of the OpenRGB project |
9+
| SPDX-License-Identifier: GPL-2.0-or-later |
10+
\*---------------------------------------------------------*/
11+
12+
#include "Detector.h"
13+
#include "ClevoKeyboardController.h"
14+
#include "RGBController_ClevoKeyboard.h"
15+
#include "RGBController.h"
16+
#include <hidapi.h>
17+
18+
/*-----------------------------------------------------*\
19+
| ITE Tech vendor ID |
20+
\*-----------------------------------------------------*/
21+
#define ITE_VID 0x048D
22+
23+
/*-----------------------------------------------------*\
24+
| Clevo Keyboard product IDs |
25+
| These are ITE 8291 per-key RGB keyboard controllers |
26+
\*-----------------------------------------------------*/
27+
#define CLEVO_KEYBOARD_PID_600B 0x600B
28+
29+
void DetectClevoKeyboardControllers(hid_device_info* info, const std::string& name)
30+
{
31+
hid_device* dev = hid_open_path(info->path);
32+
33+
if(dev)
34+
{
35+
ClevoKeyboardController* controller = new ClevoKeyboardController(dev, *info);
36+
RGBController_ClevoKeyboard* rgb_controller = new RGBController_ClevoKeyboard(controller);
37+
rgb_controller->name = name;
38+
39+
ResourceManager::get()->RegisterRGBController(rgb_controller);
40+
}
41+
}
42+
43+
REGISTER_HID_DETECTOR_PU("Clevo Keyboard", DetectClevoKeyboardControllers, 0x048D, 0x600B, 0xFF03, 0x01);

0 commit comments

Comments
 (0)