From 04ba47403043d636f04d2efc22a2c1fe4d1d0669 Mon Sep 17 00:00:00 2001 From: Lanzaa Date: Thu, 5 May 2022 22:56:30 +0000 Subject: [PATCH] Logitech G915 TKL mode support --- .../LogitechG915Controller.cpp | 171 +++++++++++++++--- .../LogitechG915Controller.h | 30 ++- .../RGBController_LogitechG915.cpp | 60 ++++-- 3 files changed, 218 insertions(+), 43 deletions(-) diff --git a/Controllers/LogitechController/LogitechG915Controller.cpp b/Controllers/LogitechController/LogitechG915Controller.cpp index c788cf6e..cf48a605 100644 --- a/Controllers/LogitechController/LogitechG915Controller.cpp +++ b/Controllers/LogitechController/LogitechG915Controller.cpp @@ -16,6 +16,7 @@ LogitechG915Controller::LogitechG915Controller(hid_device* dev_handle, bool wire if(wired) { + device_index = 0xFF; feature_4522_idx = 0x0E; feature_8040_idx = 0x13; feature_8071_idx = 0x09; @@ -23,6 +24,7 @@ LogitechG915Controller::LogitechG915Controller(hid_device* dev_handle, bool wire } else { + device_index = 0x01; feature_4522_idx = 0x0F; feature_8040_idx = 0x14; feature_8071_idx = 0x0A; @@ -69,14 +71,42 @@ void LogitechG915Controller::SetMode ( unsigned char mode, unsigned short speed, + unsigned short brightness, unsigned char red, unsigned char green, unsigned char blue ) { - SendMode(LOGITECH_G915_ZONE_MODE_KEYBOARD, mode, speed, red, green, blue); - SendMode(LOGITECH_G915_ZONE_MODE_LOGO, mode, speed, red, green, blue); - SendCommit(); + BeginModeSet(); + uint8_t logo_mode = mode; + switch(mode) + { + case LOGITECH_G915_MODE_OFF: + case LOGITECH_G915_MODE_STATIC: + { + logo_mode = mode; // static and off match + break; + } + case LOGITECH_G915_MODE_BREATHING: + { + logo_mode = LOGITECH_G915_LOGO_MODE_BREATHING; //0x03 + break; + } + case LOGITECH_G915_MODE_CYCLE: + case LOGITECH_G915_MODE_WAVE: + { + logo_mode = LOGITECH_G915_LOGO_MODE_CYCLE; //0x02 + break; + } + case LOGITECH_G915_MODE_RIPPLE: + { + logo_mode = LOGITECH_G915_LOGO_MODE_STATIC; + break; + } + } + + SendMode(LOGITECH_G915_ZONE_MODE_KEYBOARD, mode, speed, brightness, red, green, blue); + SendMode(LOGITECH_G915_ZONE_MODE_LOGO, logo_mode, speed, brightness, red, green, blue); } /*-------------------------------------------------------------------------------------------------*\ @@ -96,7 +126,7 @@ void LogitechG915Controller::SendCommit() | Set up Commit packet | \*-----------------------------------------------------*/ usb_buf[0x00] = 0x11; - usb_buf[0x01] = 0x01; + usb_buf[0x01] = device_index; usb_buf[0x02] = feature_8081_idx; usb_buf[0x03] = LOGITECH_G915_COMMIT_BYTE; @@ -107,7 +137,7 @@ void LogitechG915Controller::SendCommit() hid_read_timeout(dev_handle, (unsigned char *)usb_buf, 20, LOGITECH_READ_TIMEOUT); } -void LogitechG915Controller::InitializeDirect() +void LogitechG915Controller::BeginModeSet() { char usb_buf[20]; @@ -120,7 +150,7 @@ void LogitechG915Controller::InitializeDirect() | Set up Commit packet | \*-----------------------------------------------------*/ usb_buf[0x00] = 0x11; - usb_buf[0x01] = 0x01; + usb_buf[0x01] = device_index; usb_buf[0x02] = feature_4522_idx; usb_buf[0x03] = 0x3E; @@ -139,7 +169,77 @@ void LogitechG915Controller::InitializeDirect() | Set up Commit packet | \*-----------------------------------------------------*/ usb_buf[0x00] = 0x11; - usb_buf[0x01] = 0x01; + usb_buf[0x01] = device_index; + usb_buf[0x02] = feature_4522_idx; + usb_buf[0x03] = 0x1E; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev_handle, (unsigned char *)usb_buf, 20); + hid_read(dev_handle, (unsigned char *)usb_buf, 20); +} + +void LogitechG915Controller::InitializeModeSet() +{ + char usb_buf[20]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Commit packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x11; + usb_buf[0x01] = device_index; + usb_buf[0x02] = feature_8071_idx; + usb_buf[0x03] = 0x5E; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = 0x03; + usb_buf[0x06] = 0x07; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev_handle, (unsigned char *)usb_buf, 20); + hid_read(dev_handle, (unsigned char *)usb_buf, 20); +} + +void LogitechG915Controller::InitializeDirect() +{ + char usb_buf[20]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Commit packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x11; + usb_buf[0x01] = device_index; + usb_buf[0x02] = feature_4522_idx; + usb_buf[0x03] = 0x3E; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev_handle, (unsigned char *)usb_buf, 20); + hid_read(dev_handle, (unsigned char *)usb_buf, 20); + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Commit packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x11; + usb_buf[0x01] = device_index; usb_buf[0x02] = feature_4522_idx; usb_buf[0x03] = 0x1E; @@ -158,7 +258,7 @@ void LogitechG915Controller::InitializeDirect() | Set up Commit packet | \*-----------------------------------------------------*/ usb_buf[0x00] = 0x11; - usb_buf[0x01] = 0x01; + usb_buf[0x01] = device_index; usb_buf[0x02] = feature_8071_idx; usb_buf[0x03] = 0x1E; usb_buf[0x10] = 0x01; @@ -178,7 +278,7 @@ void LogitechG915Controller::InitializeDirect() | Set up Commit packet | \*-----------------------------------------------------*/ usb_buf[0x00] = 0x11; - usb_buf[0x01] = 0x01; + usb_buf[0x01] = device_index; usb_buf[0x02] = feature_8071_idx; usb_buf[0x03] = 0x1E; usb_buf[0x04] = 0x01; @@ -210,7 +310,7 @@ void LogitechG915Controller::SendSingleLed | Set up a 6F packet with a single color | \*-----------------------------------------------------*/ usb_buf[0x00] = 0x11; - usb_buf[0x01] = 0x01; + usb_buf[0x01] = device_index; usb_buf[0x02] = feature_8081_idx; usb_buf[0x03] = LOGITECH_G915_ZONE_FRAME_TYPE_LITTLE; @@ -244,7 +344,7 @@ void LogitechG915Controller::SendDirectFrame | Set up Lighting Control packet | \*-----------------------------------------------------*/ usb_buf[0x00] = 0x11; - usb_buf[0x01] = 0x01; + usb_buf[0x01] = device_index; usb_buf[0x02] = feature_8081_idx; usb_buf[0x03] = frame_type; @@ -265,6 +365,7 @@ void LogitechG915Controller::SendMode unsigned char zone, unsigned char mode, unsigned short speed, + unsigned short brightness, unsigned char red, unsigned char green, unsigned char blue @@ -282,35 +383,53 @@ void LogitechG915Controller::SendMode \*-----------------------------------------------------*/ usb_buf[0x00] = 0x11; - usb_buf[0x01] = 0x01; - usb_buf[0x02] = feature_8040_idx; - usb_buf[0x03] = 0x3D; //TODO: Check if it is the correct value for G915 - usb_buf[0x04] = zone; + usb_buf[0x01] = device_index; + usb_buf[0x02] = feature_8071_idx; + usb_buf[0x03] = 0x1E; + usb_buf[0x04] = zone; usb_buf[0x05] = mode; usb_buf[0x06] = red; usb_buf[0x07] = green; usb_buf[0x08] = blue; - speed = 100 * speed; + if(mode != LOGITECH_G915_MODE_RIPPLE) + { + speed = 100 * speed; + } - if(mode == LOGITECH_G915_MODE_CYCLE) + // mode == LOGITECH_G915_MODE_OFF; No data to set + if(mode == LOGITECH_G915_MODE_STATIC) { - usb_buf[0x0B] = speed >> 8; - usb_buf[0x0C] = speed & 0xFF; - usb_buf[0x0D] = 0x64; + usb_buf[0x09] = 0x02; } - else if(mode == LOGITECH_G915_MODE_BREATHING) + else if((mode == LOGITECH_G915_MODE_BREATHING && zone == LOGITECH_G915_ZONE_MODE_KEYBOARD) \ + || (mode == LOGITECH_G915_LOGO_MODE_BREATHING && zone == LOGITECH_G915_ZONE_MODE_LOGO)) { - usb_buf[0x09] = speed >> 8; - usb_buf[0x0A] = speed & 0xFF; - usb_buf[0x0C] = 0x64; + usb_buf[0x09] = speed >> 8; + usb_buf[0x0A] = speed & 0xFF; + usb_buf[0x0C] = brightness & 0xFF; } - else + else if((mode == LOGITECH_G915_MODE_CYCLE && zone == LOGITECH_G915_ZONE_MODE_KEYBOARD) \ + || (mode == LOGITECH_G915_LOGO_MODE_CYCLE && zone == LOGITECH_G915_ZONE_MODE_LOGO)) { - return; + usb_buf[0x0B] = speed >> 8; + usb_buf[0x0C] = speed & 0xFF; + usb_buf[0x0D] = brightness & 0xFF; } + else if(mode == LOGITECH_G915_MODE_WAVE) + { + usb_buf[0x0C] = speed & 0xFF; + usb_buf[0x0D] = 0x01; // Direction control 0x01 is horizontal + usb_buf[0x0E] = brightness & 0xFF; + usb_buf[0x0F] = speed >> 8; + } + else if(mode == LOGITECH_G915_MODE_RIPPLE) + { + usb_buf[0x0B] = speed & 0xFF; + } + usb_buf[0x10] = 0x01; /*-----------------------------------------------------*\ | Send packet | diff --git a/Controllers/LogitechController/LogitechG915Controller.h b/Controllers/LogitechController/LogitechG915Controller.h index be84bed3..9bbad50f 100644 --- a/Controllers/LogitechController/LogitechG915Controller.h +++ b/Controllers/LogitechController/LogitechG915Controller.h @@ -19,9 +19,9 @@ enum { - LOGITECH_G915_ZONE_MODE_KEYBOARD = 0x00, - LOGITECH_G915_ZONE_MODE_LOGO = 0x01, - LOGITECH_G915_ZONE_MODE_MULTIMEDIA = 0X02, + LOGITECH_G915_ZONE_MODE_KEYBOARD = 0x01, + LOGITECH_G915_ZONE_MODE_LOGO = 0x00, + LOGITECH_G915_ZONE_MODE_MULTIMEDIA = 0x02, LOGITECH_G915_ZONE_MODE_GKEYS = 0x03, LOGITECH_G915_ZONE_MODE_MODIFIERS = 0x04 }; @@ -47,7 +47,16 @@ enum LOGITECH_G915_MODE_BREATHING = 0x02, LOGITECH_G915_MODE_CYCLE = 0x03, LOGITECH_G915_MODE_WAVE = 0x04, - LOGITECH_G915_MODE_DIRECT = 0x05, + LOGITECH_G915_MODE_RIPPLE = 0x05, + LOGITECH_G915_MODE_DIRECT = 0xFF, +}; + +enum +{ + LOGITECH_G915_LOGO_MODE_OFF = 0x00, + LOGITECH_G915_LOGO_MODE_STATIC = 0x01, + LOGITECH_G915_LOGO_MODE_CYCLE = 0x02, + LOGITECH_G915_LOGO_MODE_BREATHING = 0x03, }; /*---------------------------------------------------------------------------------------------*\ @@ -61,6 +70,14 @@ enum LOGITECH_G915_SPEED_FASTEST = 0x0A, /* Fastest speed */ }; +/* Ripple speeds are in ms directly. */ +enum +{ + LOGITECH_G915_SPEED_RIPPLE_SLOW = 200, + LOGITECH_G915_SPEED_RIPPLE_NORMAL = 20, + LOGITECH_G915_SPEED_RIPPLE_FAST = 2, +}; + class LogitechG915Controller { public: @@ -70,6 +87,8 @@ public: std::string GetSerialString(); void Commit(); void InitializeDirect(); + void InitializeModeSet(); + void BeginModeSet(); void SetDirect ( unsigned char frame_type, @@ -86,6 +105,7 @@ public: ( unsigned char mode, unsigned short speed, + unsigned short brightness, unsigned char red, unsigned char green, unsigned char blue @@ -94,6 +114,7 @@ public: private: hid_device* dev_handle; char feature_4522_idx; + char device_index; char feature_8040_idx; char feature_8071_idx; char feature_8081_idx; @@ -109,6 +130,7 @@ private: unsigned char zone, unsigned char mode, unsigned short speed, + unsigned short brightness, unsigned char red, unsigned char green, unsigned char blue diff --git a/Controllers/LogitechController/RGBController_LogitechG915.cpp b/Controllers/LogitechController/RGBController_LogitechG915.cpp index 8c2a0e0c..69bf0f41 100644 --- a/Controllers/LogitechController/RGBController_LogitechG915.cpp +++ b/Controllers/LogitechController/RGBController_LogitechG915.cpp @@ -235,29 +235,63 @@ RGBController_LogitechG915::RGBController_LogitechG915(LogitechG915Controller* c Off.color_mode = MODE_COLORS_NONE; modes.push_back(Off); - mode Cycle; - Cycle.name = "Cycle"; - Cycle.value = LOGITECH_G915_MODE_CYCLE; - Cycle.flags = MODE_FLAG_HAS_SPEED; - Cycle.color_mode = MODE_COLORS_NONE; - Cycle.speed_min = LOGITECH_G915_SPEED_SLOWEST; - Cycle.speed_max = LOGITECH_G915_SPEED_FASTEST; - Cycle.speed = LOGITECH_G915_SPEED_NORMAL; - modes.push_back(Cycle); - mode Breathing; Breathing.name = "Breathing"; Breathing.value = LOGITECH_G915_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; Breathing.colors_min = 1; Breathing.colors_max = 1; Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; Breathing.colors.resize(1); + Breathing.brightness_min = 1; + Breathing.brightness_max = 100; + Breathing.brightness = 100; Breathing.speed_min = LOGITECH_G915_SPEED_SLOWEST; Breathing.speed_max = LOGITECH_G915_SPEED_FASTEST; Breathing.speed = LOGITECH_G915_SPEED_NORMAL; modes.push_back(Breathing); + mode Cycle; + Cycle.name = "Spectrum Cycle"; + Cycle.value = LOGITECH_G915_MODE_CYCLE; + Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Cycle.color_mode = MODE_COLORS_NONE; + Cycle.speed_min = LOGITECH_G915_SPEED_SLOWEST; + Cycle.speed_max = LOGITECH_G915_SPEED_FASTEST; + Cycle.speed = LOGITECH_G915_SPEED_NORMAL; + Cycle.brightness_min = 1; + Cycle.brightness_max = 100; + Cycle.brightness = 100; + modes.push_back(Cycle); + + mode Wave; + Wave.name = "Rainbow Wave"; + Wave.value = LOGITECH_G915_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + //Wave.flags |= MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_DIRECTION_HV; + Wave.brightness_min = 1; + Wave.brightness_max = 100; + Wave.brightness = 100; + Wave.color_mode = MODE_COLORS_NONE; + Wave.direction = MODE_DIRECTION_HORIZONTAL | MODE_DIRECTION_RIGHT; + Wave.speed_min = LOGITECH_G915_SPEED_SLOWEST; + Wave.speed_max = LOGITECH_G915_SPEED_FASTEST; + Wave.speed = LOGITECH_G915_SPEED_NORMAL; + modes.push_back(Wave); + + mode Ripple; + Ripple.name = "Reactive (Ripple)"; + Ripple.value = LOGITECH_G915_MODE_RIPPLE; + Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Ripple.colors_min = 1; + Ripple.colors_max = 1; + Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; + Ripple.colors.resize(1); + Ripple.speed_min = LOGITECH_G915_SPEED_RIPPLE_SLOW; + Ripple.speed_max = LOGITECH_G915_SPEED_RIPPLE_FAST; + Ripple.speed = LOGITECH_G915_SPEED_RIPPLE_NORMAL; + modes.push_back(Ripple); + SetupZones(); std::copy(colors.begin(), colors.end(),std::back_inserter(current_colors)); } @@ -554,6 +588,7 @@ void RGBController_LogitechG915::DeviceUpdateMode() controller->Commit(); return; } + controller->InitializeModeSet(); unsigned char red = 0; unsigned char grn = 0; @@ -565,6 +600,5 @@ void RGBController_LogitechG915::DeviceUpdateMode() grn = RGBGetGValue(modes[active_mode].colors[0]); blu = RGBGetBValue(modes[active_mode].colors[0]); } - - controller->SetMode(modes[active_mode].value, modes[active_mode].speed, red, grn, blu); + controller->SetMode(modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, red, grn, blu); }