From b13840574018794ee89c3cea987a1f8ac4722251 Mon Sep 17 00:00:00 2001 From: Tiago Gomes Date: Wed, 30 Oct 2024 16:09:49 +0000 Subject: [PATCH] Add support for Omen 45L front fans, off mode and Wave and Radial effects --- .../HPOmen30LController.cpp | 151 +++++++++++------- .../HPOmen30LController/HPOmen30LController.h | 33 +++- .../RGBController_HPOmen30L.cpp | 82 +++++++++- README.md | 7 +- 4 files changed, 205 insertions(+), 68 deletions(-) diff --git a/Controllers/HPOmen30LController/HPOmen30LController.cpp b/Controllers/HPOmen30LController/HPOmen30LController.cpp index 57436433..6b2dcf6c 100644 --- a/Controllers/HPOmen30LController/HPOmen30LController.cpp +++ b/Controllers/HPOmen30LController/HPOmen30LController.cpp @@ -12,6 +12,10 @@ #include #include "HPOmen30LController.h" +#define HP_OMEN_30L_BUFFER_SIZE 58 +#define HP_OMEN_30L_VERSION_ID 0x12 +#define HP_OMEN_30L_MAX_BRIGHTNESS 0x64 + HPOmen30LController::HPOmen30LController(hid_device* dev_handle, const char* path) { dev = dev_handle; @@ -23,30 +27,50 @@ HPOmen30LController::HPOmen30LController(hid_device* dev_handle, const char* pat logo.value = HP_OMEN_30L_LOGO_ZONE; logo.mode = HP_OMEN_30L_DIRECT; logo.speed = HP_OMEN_30L_SPEED_MED; - logo.brightness = 0x64; + logo.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; hp_zones.push_back(logo); hp_zone bar; bar.value = HP_OMEN_30L_BAR_ZONE; bar.mode = HP_OMEN_30L_DIRECT; bar.speed = HP_OMEN_30L_SPEED_MED; - bar.brightness = 0x64; + bar.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; hp_zones.push_back(bar); hp_zone fan; fan.value = HP_OMEN_30L_FAN_ZONE; fan.mode = HP_OMEN_30L_DIRECT; fan.speed = HP_OMEN_30L_SPEED_MED; - fan.brightness = 0x64; + fan.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; hp_zones.push_back(fan); hp_zone cpu; cpu.value = HP_OMEN_30L_CPU_ZONE; cpu.mode = HP_OMEN_30L_DIRECT; cpu.speed = HP_OMEN_30L_SPEED_MED; - cpu.brightness = 0x64; + cpu.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; hp_zones.push_back(cpu); + hp_zone botFan; + botFan.value = HP_OMEN_30L_BOT_FAN_ZONE; + botFan.mode = HP_OMEN_30L_DIRECT; + botFan.speed = HP_OMEN_30L_SPEED_MED; + botFan.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; + hp_zones.push_back(botFan); + + hp_zone midFan; + midFan.value = HP_OMEN_30L_MID_FAN_ZONE; + midFan.mode = HP_OMEN_30L_DIRECT; + midFan.speed = HP_OMEN_30L_SPEED_MED; + midFan.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; + hp_zones.push_back(midFan); + + hp_zone topFan; + topFan.value = HP_OMEN_30L_TOP_FAN_ZONE; + topFan.mode = HP_OMEN_30L_DIRECT; + topFan.speed = HP_OMEN_30L_SPEED_MED; + topFan.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; + hp_zones.push_back(topFan); } HPOmen30LController::~HPOmen30LController() @@ -97,77 +121,88 @@ void HPOmen30LController::SetZoneColor(int zone, std::vector colors) void HPOmen30LController::SendZoneUpdate(int zone, std::vector colors) { - unsigned char usb_buf[] = - { - 0x00, 0x00, // [0x00-0x01] - 0x12, 0x05, 0x00, 0x00, // [0x02-0x05] - 0x00, 0x00, 0x00, 0x00, // [0x06-0x09] - 0x00, 0x00, 0x00, 0x00, // [0x0A-0x0D] - 0x00, 0x00, 0x00, 0x00, // [0x0E-0x11] - 0x00, 0x00, 0x00, 0x00, // [0x12-0x15] - 0x00, 0x00, 0x00, 0x00, // [0x16-0x19] - 0x00, 0x00, 0x00, 0x00, // [0x1A-0x1D] - 0x00, 0x00, 0x00, 0x00, // [0x1E-0x21] - 0x00, 0x00, 0x00, 0x00, // [0x22-0x25] - 0x00, 0x00, 0x00, 0x00, // [0x26-0x29] - 0x00, 0x00, 0x00, 0x00, // [0x2A-0x2D] - 0x00, 0x00, 0x00, 0x00, // [0x2E-0x31] - 0x00, 0x00, 0x00, 0x00, // [0x32-0x35] Always 0x00*4 - 0x00, 0x00, 0x00, 0x00 // [0x36-0x39] zone / 0x01 / theme / speed - }; + unsigned char usb_buf[HP_OMEN_30L_BUFFER_SIZE] = {}; // zero-initialize array + // 0x00 - 0x01: Unknown + // 0x02: Version ID (HP_OMEN_30L_VERSION_ID) + // 0x03: Lighting mode (static, direct, off, breathing, cycle, blinking, ...) + // 0x04: Total color count (only different from 1 in modes with changing colors) + // 0x05: Current color number (see above, used to set the different colors, one at a time, starting at 1) + // 0x06 - 0x07: Unknown + // 0x08 - 0x23: Used to control the RGB (static) or RGBA (direct) of the first seven LED zones + // 0x24 - 0x2f: Unknown, probably also used for RGB/RGBA control if there's support up to 10 zones + // 0x30: Brightness + // 0x31: Type (static=0x02, direct=0x04, changing colors=0x0A) + // 0x32 - 0x35: Unknown + // 0x36: Zone to update (can only update one at a time) + // 0x37: Power mode to update (on, suspend) + // 0x38: Theme (either 0 to use the colors set in 0x04/0x05, or the ID of a predefined theme) + // 0x39: Color change speed (only relevant for modes with changing colors) + usb_buf[0x02] = HP_OMEN_30L_VERSION_ID; usb_buf[0x36] = hp_zones[zone].value; - if(hp_zones[zone].mode != HP_OMEN_30L_DIRECT) - { - hid_write(dev, usb_buf, 58); - } - - usb_buf[0x37] = 0x01; - usb_buf[0x39] = hp_zones[zone].speed; + // The Omen controller allows setting different modes for when the computer is powered on + // vs when the computer is suspended. + // Because the OpenRGB UI does not allow such a choice, we're only changing the powered on mode. + // If this ever changes, we need to take the user choice into consideration (HP_OMEN_30L_POWER_SUSPEND) + usb_buf[0x37] = HP_OMEN_30L_POWER_ON; usb_buf[0x03] = hp_zones[zone].mode; + + if (hp_zones[zone].mode == HP_OMEN_30L_OFF) + { + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); + return; + } + usb_buf[0x30] = hp_zones[zone].brightness; - + int index = hp_zones[zone].value - 1; if(hp_zones[zone].mode == HP_OMEN_30L_DIRECT) { - usb_buf[0x31] = HP_OMEN_30L_DIRECT; - usb_buf[0x04] = 0x01; - } - else - { - usb_buf[0x31] = 0x0A; - } + usb_buf[0x31] = HP_OMEN_30L_DIRECT; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = 0x01; + usb_buf[0x08 + index * 4] = HP_OMEN_30L_MAX_BRIGHTNESS; + usb_buf[0x09 + index * 4] = RGBGetRValue(colors[zone]); + usb_buf[0x0A + index * 4] = RGBGetGValue(colors[zone]); + usb_buf[0x0B + index * 4] = RGBGetBValue(colors[zone]); - if(hp_zones[zone].mode == HP_OMEN_30L_DIRECT) - { - usb_buf[0x08] = usb_buf[0x0C] = usb_buf[0x10] = usb_buf[0x14] = 0x64; - usb_buf[0x09] = usb_buf[0x0D] = usb_buf[0x11] = usb_buf[0x15] = RGBGetRValue(colors[zone]); - usb_buf[0x0A] = usb_buf[0x0E] = usb_buf[0x12] = usb_buf[0x16] = RGBGetGValue(colors[zone]); - usb_buf[0x0B] = usb_buf[0x0F] = usb_buf[0x13] = usb_buf[0x17] = RGBGetBValue(colors[zone]); - - hid_write(dev, usb_buf, 58); + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); } else if(hp_zones[zone].mode == HP_OMEN_30L_STATIC) { - usb_buf[0x08] = usb_buf[0x0B] = usb_buf[0x0E] = usb_buf[0x11] = RGBGetRValue(colors[zone]); - usb_buf[0x09] = usb_buf[0x0C] = usb_buf[0x0F] = usb_buf[0x12] = RGBGetGValue(colors[zone]); - usb_buf[0x0A] = usb_buf[0x0D] = usb_buf[0x10] = usb_buf[0x13] = RGBGetBValue(colors[zone]); + usb_buf[0x31] = 0x02; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = 0x01; + usb_buf[0x08 + index * 3] = RGBGetRValue(colors[zone]); + usb_buf[0x09 + index * 3] = RGBGetGValue(colors[zone]); + usb_buf[0x0A + index * 3] = RGBGetBValue(colors[zone]); - hid_write(dev, usb_buf, 58); + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); } else { - usb_buf[0x04] = (unsigned char)colors.size(); + usb_buf[0x31] = 0x0A; + usb_buf[0x39] = hp_zones[zone].speed; - for(unsigned int i = 0; i < (unsigned int)colors.size(); i++) + // Theme is custom by default, but if we could select a theme through the UI, + // we would set it in usb_buf[0x38] here and ignore the custom colors vector + unsigned char theme = HP_OMEN_30L_THEME_CUSTOM; + usb_buf[0x38] = theme; + if (theme == HP_OMEN_30L_THEME_CUSTOM) { - usb_buf[0x05] = i + 1; - - usb_buf[0x08] = usb_buf[0x0B] = usb_buf[0x0E] = usb_buf[0x11] = RGBGetRValue(colors[i]); - usb_buf[0x09] = usb_buf[0x0C] = usb_buf[0x0F] = usb_buf[0x12] = RGBGetGValue(colors[i]); - usb_buf[0x0A] = usb_buf[0x0D] = usb_buf[0x10] = usb_buf[0x13] = RGBGetBValue(colors[i]); - - hid_write(dev, usb_buf, 58); + usb_buf[0x04] = (unsigned char)colors.size(); + for(unsigned int i = 0; i < (unsigned int)colors.size(); i++) + { + usb_buf[0x05] = i + 1; + usb_buf[0x08 + index * 3] = RGBGetRValue(colors[i]); + usb_buf[0x09 + index * 3] = RGBGetGValue(colors[i]); + usb_buf[0x0A + index * 3] = RGBGetBValue(colors[i]); + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); + } + } + else + { + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); } } } diff --git a/Controllers/HPOmen30LController/HPOmen30LController.h b/Controllers/HPOmen30LController/HPOmen30LController.h index bb0cd7ba..5cddd6b2 100644 --- a/Controllers/HPOmen30LController/HPOmen30LController.h +++ b/Controllers/HPOmen30LController/HPOmen30LController.h @@ -26,9 +26,12 @@ enum { HP_OMEN_30L_STATIC = 0x01, /* Static effect channel */ HP_OMEN_30L_DIRECT = 0x04, /* Direct for effects plugin */ + HP_OMEN_30L_OFF = 0x05, /* Turns off the led */ HP_OMEN_30L_BREATHING = 0x06, /* Breathing effect channel */ HP_OMEN_30L_COLOR_CYCLE = 0x07, /* Color cycle effect channel */ - HP_OMEN_30L_BLINKING = 0x08, /* Led blink */ + HP_OMEN_30L_BLINKING = 0x08, /* Blinking effect channel */ + HP_OMEN_30L_WAVE = 0x09, /* Wave effect channel */ + HP_OMEN_30L_RADIAL = 0x0A, /* Radial effect channel */ }; enum @@ -40,10 +43,29 @@ enum enum { - HP_OMEN_30L_LOGO_ZONE = 0x01, - HP_OMEN_30L_BAR_ZONE = 0x02, - HP_OMEN_30L_FAN_ZONE = 0x03, - HP_OMEN_30L_CPU_ZONE = 0x04, + HP_OMEN_30L_LOGO_ZONE = 0x01, + HP_OMEN_30L_BAR_ZONE = 0x02, + HP_OMEN_30L_FAN_ZONE = 0x03, + HP_OMEN_30L_CPU_ZONE = 0x04, + HP_OMEN_30L_BOT_FAN_ZONE = 0x05, + HP_OMEN_30L_MID_FAN_ZONE = 0x06, + HP_OMEN_30L_TOP_FAN_ZONE = 0x07, +}; + +enum +{ + HP_OMEN_30L_POWER_ON = 0x01, /* Settings for powered on */ + HP_OMEN_30L_POWER_SUSPEND = 0x02, /* Settings for suspended */ +}; + +enum +{ + HP_OMEN_30L_THEME_CUSTOM = 0x00, + HP_OMEN_30L_THEME_GALAXY = 0x01, + HP_OMEN_30L_THEME_VOLCANO = 0x02, + HP_OMEN_30L_THEME_JUNGLE = 0x03, + HP_OMEN_30L_THEME_OCEAN = 0x04, + HP_OMEN_30L_THEME_UNICORN = 0x05, }; class HPOmen30LController @@ -59,7 +81,6 @@ public: std::string GetLocationString(); std::string GetSerialString(); - void SetRingEffectChannel(unsigned char channel); void SetZoneMode(int zone,unsigned char mode, unsigned char speed, unsigned char brightness); void SetZoneColor(int zone, std::vector colors); diff --git a/Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp b/Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp index e4bea997..b52510e6 100644 --- a/Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp +++ b/Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp @@ -50,6 +50,13 @@ RGBController_HPOmen30L::RGBController_HPOmen30L(HPOmen30LController* controller Static.brightness = 100; modes.push_back(Static); + mode Off; + Off.name = "Off"; + Off.value = HP_OMEN_30L_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + mode Breathing; Breathing.name = "Breathing"; Breathing.value = HP_OMEN_30L_BREATHING; @@ -98,6 +105,38 @@ RGBController_HPOmen30L::RGBController_HPOmen30L(HPOmen30LController* controller Blinking.brightness = 100; modes.push_back(Blinking); + mode Wave; + Wave.name = "Wave"; + Wave.value = HP_OMEN_30L_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Wave.speed_min = HP_OMEN_30L_SPEED_SLOW; + Wave.speed_max = HP_OMEN_30L_SPEED_FAST; + Wave.speed = HP_OMEN_30L_SPEED_MED; + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wave.colors_min = 6; + Wave.colors_max = 6; + Wave.colors.resize(6); + Wave.brightness_min = 0; + Wave.brightness_max = 100; + Wave.brightness = 100; + modes.push_back(Wave); + + mode Radial; + Radial.name = "Radial"; + Radial.value = HP_OMEN_30L_RADIAL; + Radial.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Radial.speed_min = HP_OMEN_30L_SPEED_SLOW; + Radial.speed_max = HP_OMEN_30L_SPEED_FAST; + Radial.speed = HP_OMEN_30L_SPEED_MED; + Radial.color_mode = MODE_COLORS_MODE_SPECIFIC; + Radial.colors_min = 1; + Radial.colors_max = 6; + Radial.colors.resize(4); + Radial.brightness_min = 0; + Radial.brightness_max = 100; + Radial.brightness = 100; + modes.push_back(Radial); + SetupZones(); } @@ -147,6 +186,33 @@ void RGBController_HPOmen30L::SetupZones() cpu_zone.matrix_map = NULL; zones.push_back(cpu_zone); + zone bot_fan; + bot_fan.name = "Front Bottom Fan"; + bot_fan.type = ZONE_TYPE_SINGLE; + bot_fan.leds_min = 1; + bot_fan.leds_max = 1; + bot_fan.leds_count = 1; + bot_fan.matrix_map = NULL; + zones.push_back(bot_fan); + + zone mid_fan; + mid_fan.name = "Front Middle Fan"; + mid_fan.type = ZONE_TYPE_SINGLE; + mid_fan.leds_min = 1; + mid_fan.leds_max = 1; + mid_fan.leds_count = 1; + mid_fan.matrix_map = NULL; + zones.push_back(mid_fan); + + zone top_fan; + top_fan.name = "Front Top Fan"; + top_fan.type = ZONE_TYPE_SINGLE; + top_fan.leds_min = 1; + top_fan.leds_max = 1; + top_fan.leds_count = 1; + top_fan.matrix_map = NULL; + zones.push_back(top_fan); + /*---------------------------------------------------------*\ | Set up LEDs | \*---------------------------------------------------------*/ @@ -166,6 +232,18 @@ void RGBController_HPOmen30L::SetupZones() cpu_led.name = "CPU LED"; leds.push_back(cpu_led); + led bot_fan_led; + bot_fan_led.name = "Bottom Fan LED"; + leds.push_back(bot_fan_led); + + led mid_fan_led; + bot_fan_led.name = "Middle Fan LED"; + leds.push_back(bot_fan_led); + + led top_fan_led; + bot_fan_led.name = "Top Fan LED"; + leds.push_back(bot_fan_led); + SetupColors(); } @@ -180,7 +258,9 @@ void RGBController_HPOmen30L::DeviceUpdateLEDs() { for(unsigned int i = 0; i < zones.size(); i++) { - if(modes[active_mode].value == HP_OMEN_30L_STATIC || modes[active_mode].value == HP_OMEN_30L_DIRECT) + if(modes[active_mode].value == HP_OMEN_30L_STATIC || + modes[active_mode].value == HP_OMEN_30L_DIRECT || + modes[active_mode].value == HP_OMEN_30L_OFF) { controller->SetZoneColor(i, colors); } diff --git a/README.md b/README.md index baa1aada..829974f4 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,8 @@ While no code from these projects directly made its way into OpenRGB, these proj * Annemone: https://github.com/manualmanul/Annemone * libcmmk: https://github.com/chmod222/libcmmk * Signal RGB Plugins: https://gitlab.com/signalrgb/signal-plugins/-/tree/master/Plugins - * k550-macos https://github.com/vookimedlo/ck550-macos/tree/master - * luxafor-python https://github.com/vmitchell85/luxafor-python - * dreamcheekyusb https://github.com/gbrayut/dreamcheekyusb + * k550-macos: https://github.com/vookimedlo/ck550-macos/tree/master + * luxafor-python: https://github.com/vmitchell85/luxafor-python + * dreamcheekyusb: https://github.com/gbrayut/dreamcheekyusb + * omen-light: https://github.com/chiahsing/omen-light