diff --git a/Controllers/MSIVigorController/MSIVigorControllerDetect.cpp b/Controllers/MSIVigorController/MSIVigorControllerDetect.cpp new file mode 100644 index 00000000..f7b0dd98 --- /dev/null +++ b/Controllers/MSIVigorController/MSIVigorControllerDetect.cpp @@ -0,0 +1,30 @@ +#include "Detector.h" +#include "MSIVigorGK30Controller.h" +#include "RGBController.h" +#include "RGBController_MSIVigorGK30.h" + +/*---------------------------------------------------------*\ +| MSI vendor ID | +\*---------------------------------------------------------*/ +#define MSI_VID 0x0DB0 + +/*---------------------------------------------------------*\ +| Product ID | +\*---------------------------------------------------------*/ +#define MSI_VIGOR_GK30_PID 0x0B30 + +void DetectMSIVigorGK30Controllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + MSIVigorGK30Controller* controller = new MSIVigorGK30Controller(dev, *info); + RGBController_MSIVigorGK30* rgb_controller = new RGBController_MSIVigorGK30(controller); + rgb_controller->name = name; + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("MSI Vigor GK30 controller", DetectMSIVigorGK30Controllers, MSI_VID, MSI_VIGOR_GK30_PID, 1, 0xFF01, 1); diff --git a/Controllers/MSIVigorController/MSIVigorGK30Controller.cpp b/Controllers/MSIVigorController/MSIVigorGK30Controller.cpp new file mode 100644 index 00000000..3847eb55 --- /dev/null +++ b/Controllers/MSIVigorController/MSIVigorGK30Controller.cpp @@ -0,0 +1,229 @@ +/*-----------------------------------------*\ +| MSIVigorGK30Controller.cpp | +| | +| Driver for MSI Vigor GK 30 keyboard | +| controller | +| | +| Guimard Morgan (morg) 6/01/2022 | +\*-----------------------------------------*/ +#include "MSIVigorGK30Controller.h" +#include +#include + +static unsigned char argb_colour_index_data[2][2][2] = +{ //B0 B1 + { { 0x00, 0x04 }, //G0 R0 + { 0x02, 0x03 }, }, //G1 R0 + { { 0x00, 0x05 }, //G0 R1 + { 0x01, 0x06 }, } //G1 R1 +}; + +MSIVigorGK30Controller::MSIVigorGK30Controller(hid_device* dev_handle, const hid_device_info& info) +{ + dev = dev_handle; + location = info.path; + version = ""; + + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + serial_number = ""; + } + else + { + std::wstring return_wstring = serial_string; + serial_number = std::string(return_wstring.begin(), return_wstring.end()); + } + +} + +MSIVigorGK30Controller::~MSIVigorGK30Controller() +{ + hid_close(dev); +} + +std::string MSIVigorGK30Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string MSIVigorGK30Controller::GetSerialString() +{ + return(serial_number); +} + +std::string MSIVigorGK30Controller::GetFirmwareVersion() +{ + return(version); +} + +unsigned int MSIVigorGK30Controller::GetLargestColour(unsigned int red, unsigned int green, unsigned int blue) +{ + unsigned int largest; + + if ( red > green ) + { + ( red > blue ) ? largest = red : largest = blue; + } + else + { + ( green > blue ) ? largest = green : largest = blue; + } + + return (largest == 0) ? 1 : largest; +} + +unsigned char MSIVigorGK30Controller::GetColourIndex(unsigned char red, unsigned char green, unsigned char blue) +{ + /*-----------------------------------------------------*\ + | This device uses a limited colour pallette referenced | + | by an index | + | 0x00 red | + | 0x01 yellow | + | 0x02 green | + | 0x03 cyan | + | 0x04 blue | + | 0x05 magen | + | 0x06 white | + \*-----------------------------------------------------*/ + unsigned int divisor = GetLargestColour( red, green, blue); + unsigned int r = round( red / divisor ); + unsigned int g = round( green / divisor ); + unsigned int b = round( blue / divisor ); + unsigned char idx = argb_colour_index_data[r][g][b]; + return idx; +} + +void MSIVigorGK30Controller::SetMode(std::vector colors, unsigned char brightness, unsigned char speed, unsigned char mode_value, unsigned int mode_flags, unsigned int color_mode, unsigned char direction) +{ + unsigned char usb_buf[MSI_VIGOR_GK30_REPORT_SIZE]; + + memset(usb_buf, 0x00, MSI_VIGOR_GK30_REPORT_SIZE); + + usb_buf[0x00] = MSI_VIGOR_GK30_REPORT_ID; + usb_buf[0x01] = 0xFF; + usb_buf[0x02] = mode_value; + + /*-----------------------------------------------------*\ + | Parse one color for specific color mode | + \*-----------------------------------------------------*/ + if(color_mode == MODE_COLORS_MODE_SPECIFIC) + { + /*-----------------------------------------------------*\ + | Use OFF mode if color is black, black isnt an indexed | + | color | + \*-----------------------------------------------------*/ + if(colors[0] == 0) + { + usb_buf[0x02] = MSI_VIGOR_GK30_OFF_MODE_VALUE; + + hid_send_feature_report(dev, usb_buf, MSI_VIGOR_GK30_REPORT_SIZE); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + return; + } + + unsigned char red = RGBGetRValue(colors[0]); + unsigned char grn = RGBGetGValue(colors[0]); + unsigned char blu = RGBGetBValue(colors[0]); + + usb_buf[0x03] = GetColourIndex(red, grn, blu); + } + else if(color_mode == MODE_COLORS_PER_LED) + { + /*-----------------------------------------------------*\ + | Use OFF mode if color is black, black isnt an indexed | + | color | + \*-----------------------------------------------------*/ + unsigned int black_count = 0; + + for(unsigned int i = 0; i < MSI_VIGOR_GK30_LEDS_COUNT; i ++) + { + if(colors[i] == 0) + { + black_count++; + } + } + + if( black_count == MSI_VIGOR_GK30_LEDS_COUNT ) + { + usb_buf[0x02] = MSI_VIGOR_GK30_OFF_MODE_VALUE; + + hid_send_feature_report(dev, usb_buf, MSI_VIGOR_GK30_REPORT_SIZE); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + return; + } + + /*-----------------------------------------------------*\ + | Parse and set the 6 colors in the buffer | + \*-----------------------------------------------------*/ + unsigned int offset = 0; + + for(unsigned int i = 0; i < MSI_VIGOR_GK30_LEDS_COUNT; i ++) + { + unsigned char red = RGBGetRValue(colors[i]); + unsigned char grn = RGBGetGValue(colors[i]); + unsigned char blu = RGBGetBValue(colors[i]); + + unsigned char index = GetColourIndex(red, grn, blu); + + if(offset % 2 == 0) + { + index <<= 4; + } + + usb_buf[0x03 + offset/2] += index; + + offset++; + } + } + + /*-----------------------------------------------------*\ + | color index is shifted in breathing mode | + | 0x00 becomes random | + \*-----------------------------------------------------*/ + if(mode_value == MSI_VIGOR_GK30_BREATHING_MODE_VALUE) + { + if(color_mode == MODE_COLORS_RANDOM) + { + usb_buf[0x03] = 0x00; + } + else + { + usb_buf[0x03]++; + } + } + + /*-----------------------------------------------------*\ + | Direction byte | + \*-----------------------------------------------------*/ + if(mode_flags & MODE_FLAG_HAS_DIRECTION_LR) + { + usb_buf[0x04] = direction; + } + + /*-----------------------------------------------------*\ + | Speed byte | + \*-----------------------------------------------------*/ + if(mode_flags & MODE_FLAG_HAS_SPEED) + { + usb_buf[0x05] = speed; + } + + /*-----------------------------------------------------*\ + | Brightness byte | + \*-----------------------------------------------------*/ + if(mode_flags & MODE_FLAG_HAS_BRIGHTNESS) + { + usb_buf[0x06] = brightness; + } + + hid_send_feature_report(dev, usb_buf, MSI_VIGOR_GK30_REPORT_SIZE); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); +} diff --git a/Controllers/MSIVigorController/MSIVigorGK30Controller.h b/Controllers/MSIVigorController/MSIVigorGK30Controller.h new file mode 100644 index 00000000..f5c288f5 --- /dev/null +++ b/Controllers/MSIVigorController/MSIVigorGK30Controller.h @@ -0,0 +1,75 @@ +/*-----------------------------------------*\ +| MSIVigorGK30Controller.h | +| | +| Driver for MSI Vigor GK 30 keyboard | +| controller - header file | +| | +| Guimard Morgan (morg) 6/01/2022 | +\*-----------------------------------------*/ +#pragma once + +#include "RGBController.h" +#include +#include + +#define MSI_VIGOR_GK30_REPORT_SIZE 8 +#define MSI_VIGOR_GK30_LEDS_COUNT 6 +#define MSI_VIGOR_GK30_REPORT_ID 0x07 + +enum +{ + MSI_VIGOR_GK30_OFF_MODE_VALUE = 0x00, + MSI_VIGOR_GK30_STATIC_MODE_VALUE = 0x10, + MSI_VIGOR_GK30_BREATHING_MODE_VALUE = 0x20, + MSI_VIGOR_GK30_RAINBOW_MODE_VALUE = 0x30, + MSI_VIGOR_GK30_METEOR_MODE_VALUE = 0x40, + MSI_VIGOR_GK30_RIPPLE_MODE_VALUE = 0x50, + MSI_VIGOR_GK30_DIMMING_MODE_VALUE = 0x60, + MSI_VIGOR_GK30_CUSTOM_MODE_VALUE = 0x70 +}; + +enum +{ + MSI_VIGOR_GK30_BRIGHTNESS_MIN = 0x01, + MSI_VIGOR_GK30_BRIGHTNESS_MAX = 0x03 +}; + +enum +{ + MSI_VIGOR_GK30_SPEED_MIN = 0x01, + MSI_VIGOR_GK30_SPEED_MAX = 0x03 +}; + +class MSIVigorGK30Controller +{ +public: + MSIVigorGK30Controller(hid_device* dev_handle, const hid_device_info& info); + ~MSIVigorGK30Controller(); + + std::string GetSerialString(); + std::string GetDeviceLocation(); + std::string GetFirmwareVersion(); + + void SetMode(std::vector colors, + unsigned char brightness, + unsigned char speed, + unsigned char mode_value, + unsigned int mode_flags, + unsigned int color_mode, + unsigned char direction + ); + +protected: + hid_device* dev; + +private: + + unsigned int GetLargestColour(unsigned int red, unsigned int green, unsigned int blue); + unsigned char GetColourIndex(unsigned char red, unsigned char green, unsigned char blue); + + std::string location; + std::string serial_number; + std::string version; + + unsigned char color_test = 0x00; +}; diff --git a/Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp b/Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp new file mode 100644 index 00000000..5d77a456 --- /dev/null +++ b/Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp @@ -0,0 +1,206 @@ +/*-----------------------------------------*\ +| RGBController_MSIVigorGK30.cpp | +| | +| Generic RGB Interface for OpenRGB | +| MSI Vigor GK30 USB Driver | +| | +| Guimard Morgan (morg) 6/01/2022 | +\*-----------------------------------------*/ + +#include "RGBController_MSIVigorGK30.h" + +#include +#include + +/**------------------------------------------------------------------*\ + @name MSI Vigor GK30 + @category Keyboard + @type USB + @save :warning: + @direct :x: + @effects :white_check_mark: + @detectors DetectMSIVigorGK30Controllers + @comment This device does only support 7 different colors +\*-------------------------------------------------------------------*/ + +RGBController_MSIVigorGK30::RGBController_MSIVigorGK30(MSIVigorGK30Controller* controller_ptr) +{ + controller = controller_ptr; + name = "MSI VigorGK30 USB Device"; + vendor = "MSI"; + type = DEVICE_TYPE_KEYBOARD; + description = name; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); + + mode Custom; + Custom.name = "Custom"; + Custom.value = MSI_VIGOR_GK30_CUSTOM_MODE_VALUE; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Custom.brightness = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Custom.brightness_min = MSI_VIGOR_GK30_BRIGHTNESS_MIN; + Custom.brightness_max = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Custom.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Custom); + + mode Static; + Static.name = "Static"; + Static.value = MSI_VIGOR_GK30_STATIC_MODE_VALUE; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.brightness = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Static.brightness_min = MSI_VIGOR_GK30_BRIGHTNESS_MIN; + Static.brightness_max = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors.resize(1); + modes.push_back(Static); + + mode Off; + Off.name = "Off"; + Off.value = MSI_VIGOR_GK30_OFF_MODE_VALUE; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = MSI_VIGOR_GK30_BREATHING_MODE_VALUE; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.brightness = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Breathing.brightness_min = MSI_VIGOR_GK30_BRIGHTNESS_MIN; + Breathing.brightness_max = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Breathing.speed = MSI_VIGOR_GK30_SPEED_MIN; + Breathing.speed_min = MSI_VIGOR_GK30_SPEED_MIN; + Breathing.speed_max = MSI_VIGOR_GK30_SPEED_MAX; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = MSI_VIGOR_GK30_RAINBOW_MODE_VALUE; + Rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_DIRECTION_LR; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.brightness = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Rainbow.brightness_min = MSI_VIGOR_GK30_BRIGHTNESS_MIN; + Rainbow.brightness_max = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Rainbow.speed = MSI_VIGOR_GK30_SPEED_MIN; + Rainbow.speed_min = MSI_VIGOR_GK30_SPEED_MIN; + Rainbow.speed_max = MSI_VIGOR_GK30_SPEED_MAX; + Rainbow.direction = MODE_DIRECTION_LEFT; + modes.push_back(Rainbow); + + mode Meteor; + Meteor.name = "Meteor"; + Meteor.value = MSI_VIGOR_GK30_METEOR_MODE_VALUE; + Meteor.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_DIRECTION_LR; + Meteor.color_mode = MODE_COLORS_NONE; + Meteor.brightness = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Meteor.brightness_min = MSI_VIGOR_GK30_BRIGHTNESS_MIN; + Meteor.brightness_max = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Meteor.speed = MSI_VIGOR_GK30_SPEED_MIN; + Meteor.speed_min = MSI_VIGOR_GK30_SPEED_MIN; + Meteor.speed_max = MSI_VIGOR_GK30_SPEED_MAX; + Rainbow.direction = MODE_DIRECTION_LEFT; + modes.push_back(Meteor); + + mode Ripple; + Ripple.name = "Ripple"; + Ripple.value = MSI_VIGOR_GK30_RIPPLE_MODE_VALUE; + Ripple.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Ripple.brightness = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Ripple.brightness_min = MSI_VIGOR_GK30_BRIGHTNESS_MIN; + Ripple.brightness_max = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Ripple.speed = MSI_VIGOR_GK30_SPEED_MIN; + Ripple.speed_min = MSI_VIGOR_GK30_SPEED_MIN; + Ripple.speed_max = MSI_VIGOR_GK30_SPEED_MAX; + Ripple.color_mode = MODE_COLORS_NONE; + modes.push_back(Ripple); + + + mode Dimming; + Dimming.name = "Dimming"; + Dimming.value = MSI_VIGOR_GK30_DIMMING_MODE_VALUE; + Dimming.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Dimming.brightness = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Dimming.brightness_min = MSI_VIGOR_GK30_BRIGHTNESS_MIN; + Dimming.brightness_max = MSI_VIGOR_GK30_BRIGHTNESS_MAX; + Dimming.speed = MSI_VIGOR_GK30_SPEED_MIN; + Dimming.speed_min = MSI_VIGOR_GK30_SPEED_MIN; + Dimming.speed_max = MSI_VIGOR_GK30_SPEED_MAX; + Dimming.color_mode = MODE_COLORS_MODE_SPECIFIC; + Dimming.colors.resize(1); + modes.push_back(Dimming); + + SetupZones(); +} + +RGBController_MSIVigorGK30::~RGBController_MSIVigorGK30() +{ + delete controller; +} + +void RGBController_MSIVigorGK30::SetupZones() +{ + zone new_zone; + + new_zone.name = "Keyboard"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = MSI_VIGOR_GK30_LEDS_COUNT; + new_zone.leds_max = MSI_VIGOR_GK30_LEDS_COUNT; + new_zone.leds_count = MSI_VIGOR_GK30_LEDS_COUNT; + new_zone.matrix_map = nullptr; + + zones.emplace_back(new_zone); + + leds.resize(new_zone.leds_count); + + for(unsigned int i = 0; i < MSI_VIGOR_GK30_LEDS_COUNT; i++) + { + leds[i].name = "LED " + std::to_string(i); + } + + SetupColors(); +} + +void RGBController_MSIVigorGK30::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_MSIVigorGK30::DeviceUpdateLEDs() +{ + UpdateSingleLED(0); +} + +void RGBController_MSIVigorGK30::UpdateZoneLEDs(int /*zone*/) +{ + UpdateSingleLED(0); +} + +void RGBController_MSIVigorGK30::UpdateSingleLED(int /*led*/) +{ + const mode& active = modes[active_mode]; + + controller->SetMode( + active.color_mode == MODE_COLORS_MODE_SPECIFIC ? active.colors : colors, + active.brightness, + active.speed, + active.value, + active.flags, + active.color_mode, + active.direction + ); +} + +void RGBController_MSIVigorGK30::SetCustomMode() +{ + active_mode = 0; +} + +void RGBController_MSIVigorGK30::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/MSIVigorController/RGBController_MSIVigorGK30.h b/Controllers/MSIVigorController/RGBController_MSIVigorGK30.h new file mode 100644 index 00000000..9ca3f647 --- /dev/null +++ b/Controllers/MSIVigorController/RGBController_MSIVigorGK30.h @@ -0,0 +1,31 @@ +/*-----------------------------------------*\ +| RGBController_MSIVigorGK30.h | +| | +| Generic RGB Interface for OpenRGB | +| MIS Vigor GK30 RGB USB Driver | +| | +| Guimard Morgan (morg) 6/01/2022 | +\*-----------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "MSIVigorGK30Controller.h" + +class RGBController_MSIVigorGK30 : public RGBController +{ +public: + RGBController_MSIVigorGK30(MSIVigorGK30Controller* controller_ptr); + ~RGBController_MSIVigorGK30(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + void DeviceUpdateMode(); + void SetCustomMode(); + +private: + MSIVigorGK30Controller* controller; +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index 1b0a00c4..b6e6b97e 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -134,6 +134,7 @@ INCLUDEPATH += Controllers/MSIMysticLightController/ \ Controllers/MSIOptixController/ \ Controllers/MSIRGBController/ \ + Controllers/MSIVigorController/ \ Controllers/NanoleafController/ \ Controllers/NZXTHue2Controller/ \ Controllers/NZXTHuePlusController/ \ @@ -450,6 +451,8 @@ HEADERS += Controllers/MSIOptixController/MSIOptixController.h \ Controllers/MSIOptixController/RGBController_MSIOptix.h \ Controllers/MSIRGBController/MSIRGBController.h \ + Controllers/MSIVigorController/RGBController_MSIVigorGK30.h \ + Controllers/MSIVigorController/MSIVigorGK30Controller.h \ Controllers/NanoleafController/NanoleafController.h \ Controllers/MSIRGBController/RGBController_MSIRGB.h \ Controllers/NvidiaESAController/NvidiaESAController.h \ @@ -942,6 +945,9 @@ SOURCES += Controllers/MSIRGBController/MSIRGBController.cpp \ Controllers/MSIRGBController/MSIRGBControllerDetect.cpp \ Controllers/MSIRGBController/RGBController_MSIRGB.cpp \ + Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp \ + Controllers/MSIVigorController/MSIVigorControllerDetect.cpp \ + Controllers/MSIVigorController/MSIVigorGK30Controller.cpp \ Controllers/NanoleafController/NanoleafController.cpp \ Controllers/NanoleafController/NanoleafControllerDetect.cpp \ Controllers/NanoleafController/RGBController_Nanoleaf.cpp \