From 4855628d7a36ceccc737a06212e24fd9ebde9920 Mon Sep 17 00:00:00 2001 From: Kyle Cascade Date: Wed, 21 Jan 2026 22:55:46 +0000 Subject: [PATCH] Added Effects for Clevo Lightbar --- .../ClevoKeyboardController.cpp | 8 ++ .../ClevoKeyboardController.h | 2 + .../RGBController_ClevoKeyboard.cpp | 1 + .../ClevoLightbarController.cpp | 33 +++++- .../ClevoLightbarController.h | 16 ++- .../RGBController_ClevoLightbar.cpp | 107 ++++++++++++++++-- 6 files changed, 150 insertions(+), 17 deletions(-) diff --git a/Controllers/ClevoKeyboardController/ClevoKeyboardController.cpp b/Controllers/ClevoKeyboardController/ClevoKeyboardController.cpp index 19a0217ee..f61c579b8 100644 --- a/Controllers/ClevoKeyboardController/ClevoKeyboardController.cpp +++ b/Controllers/ClevoKeyboardController/ClevoKeyboardController.cpp @@ -17,6 +17,7 @@ ClevoKeyboardController::ClevoKeyboardController(hid_device* dev_handle, const h { dev = dev_handle; location = info.path; + version = info.release_number; } ClevoKeyboardController::~ClevoKeyboardController() @@ -45,6 +46,13 @@ std::string ClevoKeyboardController::GetSerialString() return(return_string); } +std::string ClevoKeyboardController::GetFirmwareVersion() +{ + char version_string[16]; + snprintf(version_string, sizeof(version_string), "%d.%02d", version >> 8, version & 0xFF); + return(version_string); +} + void ClevoKeyboardController::WriteControl(unsigned char* data) { hid_send_feature_report(dev, data, CLEVO_KEYBOARD_REPORT_SIZE); diff --git a/Controllers/ClevoKeyboardController/ClevoKeyboardController.h b/Controllers/ClevoKeyboardController/ClevoKeyboardController.h index 8d3904efd..95526888e 100644 --- a/Controllers/ClevoKeyboardController/ClevoKeyboardController.h +++ b/Controllers/ClevoKeyboardController/ClevoKeyboardController.h @@ -72,6 +72,7 @@ public: std::string GetDeviceLocation(); std::string GetSerialString(); + std::string GetFirmwareVersion(); void TurnOff(); void SetMode(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char behaviour); @@ -81,6 +82,7 @@ public: private: hid_device* dev; std::string location; + unsigned short version; void WriteControl(unsigned char* data); void WriteRowData(unsigned char* data); diff --git a/Controllers/ClevoKeyboardController/RGBController_ClevoKeyboard.cpp b/Controllers/ClevoKeyboardController/RGBController_ClevoKeyboard.cpp index e4462d7af..8e10a16e7 100644 --- a/Controllers/ClevoKeyboardController/RGBController_ClevoKeyboard.cpp +++ b/Controllers/ClevoKeyboardController/RGBController_ClevoKeyboard.cpp @@ -201,6 +201,7 @@ RGBController_ClevoKeyboard::RGBController_ClevoKeyboard(ClevoKeyboardController description = "CLEVO Laptop Keyboard"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/ClevoLightbarController/ClevoLightbarController.cpp b/Controllers/ClevoLightbarController/ClevoLightbarController.cpp index d234ad24c..d3831c81c 100644 --- a/Controllers/ClevoLightbarController/ClevoLightbarController.cpp +++ b/Controllers/ClevoLightbarController/ClevoLightbarController.cpp @@ -17,6 +17,7 @@ ClevoLightbarController::ClevoLightbarController(hid_device* dev_handle, const h { dev = dev_handle; location = info.path; + version = info.release_number; } ClevoLightbarController::~ClevoLightbarController() @@ -45,6 +46,13 @@ std::string ClevoLightbarController::GetSerialString() return(return_string); } +std::string ClevoLightbarController::GetFirmwareVersion() +{ + char version_string[16]; + snprintf(version_string, sizeof(version_string), "%d.%02d", version >> 8, version & 0xFF); + return(version_string); +} + void ClevoLightbarController::WriteControl(unsigned char* data) { hid_send_feature_report(dev, data, CLEVO_LIGHTBAR_REPORT_SIZE); @@ -126,11 +134,26 @@ void ClevoLightbarController::SetBrightness(unsigned char brightness) void ClevoLightbarController::SetMode(unsigned char mode, unsigned char brightness, unsigned char speed) { /*---------------------------------------------------------*\ - | Currently only direct (mono) mode is implemented | - | Breathing mode would be: 0x08 0x22 0x02 speed brightness | + | Set mode for device 0x7001: | + | 0x08 0x22 MODE SPEED BRIGHTNESS 0x01 0x00 0x00 | + | | + | SPEED: 0x01 (fastest) to 0x0a (slowest) - we invert | \*---------------------------------------------------------*/ - (void)mode; - (void)speed; + unsigned char buf[CLEVO_LIGHTBAR_REPORT_SIZE]; - SetBrightness(brightness); + /*---------------------------------------------------------*\ + | Invert speed: UI uses 1=slow, 10=fast | + | Protocol uses 1=fast, 10=slow | + \*---------------------------------------------------------*/ + unsigned char inverted_speed = (CLEVO_LIGHTBAR_SPEED_MAX + CLEVO_LIGHTBAR_SPEED_MIN) - speed; + + memset(buf, 0x00, CLEVO_LIGHTBAR_REPORT_SIZE); + buf[0] = 0x08; + buf[1] = 0x22; + buf[2] = mode; + buf[3] = inverted_speed; + buf[4] = brightness; + buf[5] = 0x01; + + WriteControl(buf); } diff --git a/Controllers/ClevoLightbarController/ClevoLightbarController.h b/Controllers/ClevoLightbarController/ClevoLightbarController.h index c35540587..89b53c3db 100644 --- a/Controllers/ClevoLightbarController/ClevoLightbarController.h +++ b/Controllers/ClevoLightbarController/ClevoLightbarController.h @@ -24,9 +24,13 @@ enum { - CLEVO_LIGHTBAR_MODE_DIRECT = 0, - CLEVO_LIGHTBAR_MODE_BREATHING = 1, - CLEVO_LIGHTBAR_MODE_OFF = 2 + CLEVO_LIGHTBAR_MODE_DIRECT = 0x01, + CLEVO_LIGHTBAR_MODE_BREATHING = 0x02, + CLEVO_LIGHTBAR_MODE_WAVE = 0x03, + CLEVO_LIGHTBAR_MODE_BOUNCE = 0x04, + CLEVO_LIGHTBAR_MODE_MARQUEE = 0x05, + CLEVO_LIGHTBAR_MODE_SCAN = 0x06, + CLEVO_LIGHTBAR_MODE_OFF = 0x00 }; class ClevoLightbarController @@ -37,6 +41,7 @@ public: std::string GetDeviceLocation(); std::string GetSerialString(); + std::string GetFirmwareVersion(); void SetColor(unsigned char red, unsigned char green, unsigned char blue); void SetBrightness(unsigned char brightness); @@ -45,8 +50,9 @@ public: void TurnOff(); private: - hid_device* dev; - std::string location; + hid_device* dev; + std::string location; + unsigned short version; void WriteControl(unsigned char* data); }; diff --git a/Controllers/ClevoLightbarController/RGBController_ClevoLightbar.cpp b/Controllers/ClevoLightbarController/RGBController_ClevoLightbar.cpp index a87a0a2d8..74de0bf02 100644 --- a/Controllers/ClevoLightbarController/RGBController_ClevoLightbar.cpp +++ b/Controllers/ClevoLightbarController/RGBController_ClevoLightbar.cpp @@ -17,9 +17,9 @@ @type USB @save :x: @direct :white_check_mark: - @effects :x: + @effects :white_check_mark: @detectors DetectClevoLightbarControllers - @comment + @comment Experimental effects based on ITE 8291 protocol \*-------------------------------------------------------------------*/ RGBController_ClevoLightbar::RGBController_ClevoLightbar(ClevoLightbarController* controller_ptr) @@ -32,17 +32,83 @@ RGBController_ClevoLightbar::RGBController_ClevoLightbar(ClevoLightbarController description = "CLEVO Laptop Lightbar"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); mode Direct; - Direct.name = "Direct"; - Direct.value = CLEVO_LIGHTBAR_MODE_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = CLEVO_LIGHTBAR_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; Direct.brightness_min = CLEVO_LIGHTBAR_BRIGHTNESS_MIN; Direct.brightness_max = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; Direct.brightness = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; modes.push_back(Direct); + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = CLEVO_LIGHTBAR_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness_min = CLEVO_LIGHTBAR_BRIGHTNESS_MIN; + Breathing.brightness_max = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Breathing.brightness = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Breathing.speed_min = CLEVO_LIGHTBAR_SPEED_MIN; + Breathing.speed_max = CLEVO_LIGHTBAR_SPEED_MAX; + Breathing.speed = CLEVO_LIGHTBAR_SPEED_DEFAULT; + modes.push_back(Breathing); + + mode Wave; + Wave.name = "Wave"; + Wave.value = CLEVO_LIGHTBAR_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Wave.color_mode = MODE_COLORS_NONE; + Wave.brightness_min = CLEVO_LIGHTBAR_BRIGHTNESS_MIN; + Wave.brightness_max = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Wave.brightness = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Wave.speed_min = CLEVO_LIGHTBAR_SPEED_MIN; + Wave.speed_max = CLEVO_LIGHTBAR_SPEED_MAX; + Wave.speed = CLEVO_LIGHTBAR_SPEED_DEFAULT; + modes.push_back(Wave); + + mode Bounce; + Bounce.name = "Bounce"; + Bounce.value = CLEVO_LIGHTBAR_MODE_BOUNCE; + Bounce.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Bounce.color_mode = MODE_COLORS_PER_LED; + Bounce.brightness_min = CLEVO_LIGHTBAR_BRIGHTNESS_MIN; + Bounce.brightness_max = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Bounce.brightness = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Bounce.speed_min = CLEVO_LIGHTBAR_SPEED_MIN; + Bounce.speed_max = CLEVO_LIGHTBAR_SPEED_MAX; + Bounce.speed = CLEVO_LIGHTBAR_SPEED_DEFAULT; + modes.push_back(Bounce); + + mode Marquee; + Marquee.name = "Marquee"; + Marquee.value = CLEVO_LIGHTBAR_MODE_MARQUEE; + Marquee.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Marquee.color_mode = MODE_COLORS_NONE; + Marquee.brightness_min = CLEVO_LIGHTBAR_BRIGHTNESS_MIN; + Marquee.brightness_max = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Marquee.brightness = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Marquee.speed_min = CLEVO_LIGHTBAR_SPEED_MIN; + Marquee.speed_max = CLEVO_LIGHTBAR_SPEED_MAX; + Marquee.speed = CLEVO_LIGHTBAR_SPEED_DEFAULT; + modes.push_back(Marquee); + + mode Scan; + Scan.name = "Scan"; + Scan.value = CLEVO_LIGHTBAR_MODE_SCAN; + Scan.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Scan.color_mode = MODE_COLORS_PER_LED; + Scan.brightness_min = CLEVO_LIGHTBAR_BRIGHTNESS_MIN; + Scan.brightness_max = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Scan.brightness = CLEVO_LIGHTBAR_BRIGHTNESS_MAX; + Scan.speed_min = CLEVO_LIGHTBAR_SPEED_MIN; + Scan.speed_max = CLEVO_LIGHTBAR_SPEED_MAX; + Scan.speed = CLEVO_LIGHTBAR_SPEED_DEFAULT; + modes.push_back(Scan); + mode Off; Off.name = "Off"; Off.value = CLEVO_LIGHTBAR_MODE_OFF; @@ -90,7 +156,15 @@ void RGBController_ClevoLightbar::DeviceUpdateLEDs() unsigned char blue = RGBGetBValue(colors[0]); controller->SetColor(red, green, blue); - controller->SetBrightness(modes[active_mode].brightness); + + /*---------------------------------------------------------*\ + | Re-apply current mode to maintain effect state | + \*---------------------------------------------------------*/ + unsigned char brightness = modes[active_mode].brightness; + unsigned char speed = modes[active_mode].speed; + unsigned char mode_value = modes[active_mode].value; + + controller->SetMode(mode_value, brightness, speed); } void RGBController_ClevoLightbar::UpdateZoneLEDs(int /*zone*/) @@ -109,4 +183,23 @@ void RGBController_ClevoLightbar::DeviceUpdateMode() { controller->TurnOff(); } + else + { + unsigned char brightness = modes[active_mode].brightness; + unsigned char speed = modes[active_mode].speed; + unsigned char mode_value = modes[active_mode].value; + + /*---------------------------------------------------------*\ + | Set color first for modes that use it | + \*---------------------------------------------------------*/ + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + unsigned char red = RGBGetRValue(colors[0]); + unsigned char green = RGBGetGValue(colors[0]); + unsigned char blue = RGBGetBValue(colors[0]); + controller->SetColor(red, green, blue); + } + + controller->SetMode(mode_value, brightness, speed); + } }