From c1781bc4cb24408b16be182b49a218d41da0b39c Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Fri, 3 Oct 2025 15:00:04 -0500 Subject: [PATCH] Add support for led_classdev_mc via sysfs Update the LinuxLEDController to support multicolor LEDs defined by the Linux kernel. For multicolor LEDs Linux exposes a single brightness which allows a range of 0 (off) to 255 (max) and a multi_intensity value that accepts multiple channels of colors. This current implementation assumes that there are 3 multi_intensity channels between 0 and 255. https://docs.kernel.org/leds/leds-class-multicolor.html Note that for now in Linux the brightness value doesn't so much affect the brightness of the LED as it does apply a coefficient to the individual channel intensities. For now hard code the brightness to 255 and simply adjust the intensities to alter the color. This change should keep the existing sysfs code path as-is and only attempt to use this new method when a led_rgb_path is present in the config file. For reference, my OpenRGB.json has the following lines: ` "LinuxLEDDevices" : { "devices": [ { "name": "Fan LED 1", "rgb_path": "/sys/class/leds/rgb:programming-0/" } ] }` Signed-off-by: Chris Morgan --- .../LinuxLEDControllerDetect_Linux.cpp | 7 +++ .../LinuxLEDController_Linux.cpp | 60 ++++++++++++++----- .../LinuxLEDController_Linux.h | 5 ++ .../RGBController_LinuxLED_Linux.cpp | 4 +- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/Controllers/LinuxLEDController/LinuxLEDControllerDetect_Linux.cpp b/Controllers/LinuxLEDController/LinuxLEDControllerDetect_Linux.cpp index 8f6117ab0..268c3618d 100644 --- a/Controllers/LinuxLEDController/LinuxLEDControllerDetect_Linux.cpp +++ b/Controllers/LinuxLEDController/LinuxLEDControllerDetect_Linux.cpp @@ -42,6 +42,7 @@ void DetectLinuxLEDControllers() std::string red_path; std::string green_path; std::string blue_path; + std::string rgb_path; if(linux_led_settings["devices"][device_idx].contains("name")) { @@ -63,10 +64,16 @@ void DetectLinuxLEDControllers() blue_path = linux_led_settings["devices"][device_idx]["blue_path"]; } + if(linux_led_settings["devices"][device_idx].contains("rgb_path")) + { + rgb_path = linux_led_settings["devices"][device_idx]["rgb_path"]; + } + LinuxLEDController* controller = new LinuxLEDController(name); controller->OpenRedPath(red_path); controller->OpenGreenPath(green_path); controller->OpenBluePath(blue_path); + controller->OpenRgbPath(rgb_path); RGBController_LinuxLED* rgb_controller = new RGBController_LinuxLED(controller); diff --git a/Controllers/LinuxLEDController/LinuxLEDController_Linux.cpp b/Controllers/LinuxLEDController/LinuxLEDController_Linux.cpp index 8efc5287e..b4b2ff15b 100644 --- a/Controllers/LinuxLEDController/LinuxLEDController_Linux.cpp +++ b/Controllers/LinuxLEDController/LinuxLEDController_Linux.cpp @@ -41,6 +41,11 @@ std::string LinuxLEDController::GetBluePath() return(led_b_path); } +std::string LinuxLEDController::GetRgbPath() +{ + return(led_rgb_path); +} + void LinuxLEDController::OpenRedPath(std::string red_path) { led_r_path = red_path; @@ -59,29 +64,54 @@ void LinuxLEDController::OpenBluePath(std::string blue_path) led_b_brightness.open(led_b_path + "brightness"); } +void LinuxLEDController::OpenRgbPath(std::string rgb_path) +{ + led_rgb_path = rgb_path; + led_rgb_brightness.open(led_rgb_path + "brightness"); + led_rgb_color.open(led_rgb_path + "multi_intensity"); +} + void LinuxLEDController::SetRGB(unsigned char red, unsigned char grn, unsigned char blu) { std::string brightness_str; - /*-------------------------------------------------------------*\ - | My phone LED that I tested this on shuts down if you set zero | - \*-------------------------------------------------------------*/ - if(red == 0) red = 1; - if(grn == 0) grn = 1; - if(blu == 0) blu = 1; + if (led_rgb_path.empty()) { + /*-------------------------------------------------------------*\ + | My phone LED that I tested this on shuts down if you set zero | + \*-------------------------------------------------------------*/ + if(red == 0) red = 1; + if(grn == 0) grn = 1; + if(blu == 0) blu = 1; - brightness_str = std::to_string((unsigned int)red); + brightness_str = std::to_string((unsigned int)red); - led_r_brightness.write(brightness_str.c_str(), brightness_str.length()); - led_r_brightness.flush(); + led_r_brightness.write(brightness_str.c_str(), brightness_str.length()); + led_r_brightness.flush(); - brightness_str = std::to_string((unsigned int)grn); + brightness_str = std::to_string((unsigned int)grn); - led_g_brightness.write(brightness_str.c_str(), brightness_str.length()); - led_g_brightness.flush(); + led_g_brightness.write(brightness_str.c_str(), brightness_str.length()); + led_g_brightness.flush(); - brightness_str = std::to_string((unsigned int)blu); + brightness_str = std::to_string((unsigned int)blu); - led_b_brightness.write(brightness_str.c_str(), brightness_str.length()); - led_b_brightness.flush(); + led_b_brightness.write(brightness_str.c_str(), brightness_str.length()); + led_b_brightness.flush(); + } + + else { + /* + * For the led_classdev_mc brightness just aplies a coefficient to the + * multi_intensity. Set brightness to maximum and use the RGB values + * directly instead. + */ + brightness_str = std::to_string((unsigned int)255); + led_rgb_brightness.write(brightness_str.c_str(), brightness_str.length()); + led_rgb_brightness.flush(); + brightness_str = std::to_string((unsigned int)red) + " " \ + + std::to_string((unsigned int)grn) + " " \ + + std::to_string((unsigned int)blu); + led_rgb_color.write(brightness_str.c_str(), brightness_str.length()); + led_rgb_color.flush(); + } } diff --git a/Controllers/LinuxLEDController/LinuxLEDController_Linux.h b/Controllers/LinuxLEDController/LinuxLEDController_Linux.h index 4aa8f996e..ca764ae3e 100644 --- a/Controllers/LinuxLEDController/LinuxLEDController_Linux.h +++ b/Controllers/LinuxLEDController/LinuxLEDController_Linux.h @@ -24,10 +24,12 @@ public: std::string GetRedPath(); std::string GetBluePath(); std::string GetGreenPath(); + std::string GetRgbPath(); void OpenRedPath(std::string red_path); void OpenGreenPath(std::string green_path); void OpenBluePath(std::string blue_path); + void OpenRgbPath(std::string rgb_path); void SetRGB(unsigned char red, unsigned char grn, unsigned char blu); @@ -35,8 +37,11 @@ private: std::string led_r_path; std::string led_g_path; std::string led_b_path; + std::string led_rgb_path; std::ofstream led_r_brightness; std::ofstream led_g_brightness; std::ofstream led_b_brightness; + std::ofstream led_rgb_brightness; + std::ofstream led_rgb_color; std::string name; }; diff --git a/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.cpp b/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.cpp index ccd4a1c5e..2816d86f5 100644 --- a/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.cpp +++ b/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.cpp @@ -32,8 +32,8 @@ RGBController_LinuxLED::RGBController_LinuxLED(LinuxLEDController* controller_pt location = "R: " + controller->GetRedPath() + "\r\n" + "G: " + controller->GetGreenPath() + "\r\n" + - "B: " + controller->GetBluePath(); - + "B: " + controller->GetBluePath() + "\r\n" + + "M: " + controller->GetRgbPath(); mode Direct; Direct.name = "Direct"; Direct.value = 0;