Support for MSI boards 7B16 and 7E07 added

This commit is contained in:
thombo 2022-12-26 11:10:53 +01:00 committed by Adam Honse
parent 02ddd7378a
commit c1dc0fdfc5
8 changed files with 1051 additions and 0 deletions

View file

@ -0,0 +1,472 @@
/*-----------------------------------------*\
| MSIMysticLight112Controller.cpp |
| |
| Driver for MSI Mystic Light (112-byte) |
| USB lighting controller |
| |
| thombo 12/17/2022 |
\*-----------------------------------------*/
#include "MSIMysticLight112Controller.h"
#include <algorithm>
#include <array>
#include <bitset>
#define BITSET(val, bit, pos) ((unsigned char)std::bitset<8>(val).set((pos), (bit)).to_ulong())
struct Config
{
unsigned short pid; // PID of the board
size_t numof_onboard_leds; // number of onboard leds
const std::vector<MSI_ZONE>* supported_zones; // pointer to vector of supported zones
};
const std::vector<MSI_ZONE> zones_set =
{
MSI_ZONE_J_RGB_1,
MSI_ZONE_J_RAINBOW_1,
MSI_ZONE_J_CORSAIR,
MSI_ZONE_ON_BOARD_LED_0
};
MSIMysticLight112Controller::MSIMysticLight112Controller
(
hid_device* handle,
const char *path
)
{
dev = handle;
if(dev)
{
location = path;
ReadName();
ReadSerial();
ReadFwVersion();
ReadSettings();
}
/*-----------------------------------------*\
| Initialize save flag |
\*-----------------------------------------*/
data.save_data = 0;
data.on_board_led.colorFlags = 0x81; // force MS bit of color flags to 1 to have expected zone control
/*-----------------------------------------*\
| Initialize zone based per LED data |
\*-----------------------------------------*/
numof_onboard_leds = 7;
supported_zones = &zones_set;
zone_based_per_led_data.j_rgb_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_rgb_1.colorFlags = BITSET(zone_based_per_led_data.j_rgb_1.colorFlags, true, 7u);
zone_based_per_led_data.j_rainbow_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.j_rainbow_1.colorFlags = BITSET(zone_based_per_led_data.j_rainbow_1.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led.colorFlags = BITSET(zone_based_per_led_data.on_board_led.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_1.colorFlags = BITSET(zone_based_per_led_data.on_board_led_1.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_2.colorFlags = BITSET(zone_based_per_led_data.on_board_led_2.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_3.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_3.colorFlags = BITSET(zone_based_per_led_data.on_board_led_3.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_4.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_4.colorFlags = BITSET(zone_based_per_led_data.on_board_led_4.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_5.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2;
zone_based_per_led_data.on_board_led_5.colorFlags = BITSET(zone_based_per_led_data.on_board_led_5.colorFlags, true, 7u);
zone_based_per_led_data.on_board_led_6.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2 << 2;
zone_based_per_led_data.on_board_led_6.colorFlags = BITSET(zone_based_per_led_data.on_board_led_6.colorFlags, true, 7u);
zone_based_per_led_data.save_data = 0;
direct_mode = false;
}
MSIMysticLight112Controller::~MSIMysticLight112Controller()
{
hid_close(dev);
}
void MSIMysticLight112Controller::SetMode
(
MSI_ZONE zone,
MSI_MODE mode,
MSI_SPEED speed,
MSI_BRIGHTNESS brightness,
bool rainbow_color
)
{
ZoneData* zone_data = GetZoneData(data, zone);
if(zone_data == nullptr)
{
return;
}
if (zone <= MSI_ZONE_ON_BOARD_LED_0)
{
zone_data->effect = mode;
zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03);
zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u);
zone_data->padding = 0x00;
if(mode > MSI_MODE_DOUBLE_FLASHING)
{
zone_data->speedAndBrightnessFlags |= SYNC_SETTING_JRGB;
zone_data->colorFlags |= SYNC_SETTING_ONBOARD;
}
else
{
zone_data->speedAndBrightnessFlags &= ~SYNC_SETTING_JRGB;
zone_data->colorFlags &= ~SYNC_SETTING_ONBOARD;
}
}
if((zone >= MSI_ZONE_ON_BOARD_LED_0) && (mode <= MSI_MODE_DOUBLE_FLASHING))
{
zone_data = GetZoneData(data, (MSI_ZONE)((int)zone + 1));
if(zone_data != nullptr)
{
zone_data->effect = mode;
zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03);
zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u);
zone_data->padding = 0x00;
}
}
}
std::string MSIMysticLight112Controller::GetDeviceName()
{
return name;
}
std::string MSIMysticLight112Controller::GetFWVersion()
{
std::string firmware_version;
firmware_version = "APROM: " + version_APROM + ", LDROM: " + version_LDROM;
return firmware_version;
}
std::string MSIMysticLight112Controller::GetDeviceLocation()
{
return("HID: " + location);
}
std::string MSIMysticLight112Controller::GetSerial()
{
return chip_id;
}
bool MSIMysticLight112Controller::ReadSettings()
{
/*-----------------------------------------------------*\
| Read packet from hardware, return true if successful |
\*-----------------------------------------------------*/
return(hid_get_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof data);
}
bool MSIMysticLight112Controller::Update
(
bool save
)
{
/*-----------------------------------------------------*\
| Send packet to hardware, return true if successful |
\*-----------------------------------------------------*/
if(direct_mode)
{
return (hid_send_feature_report(dev, (unsigned char*)&zone_based_per_led_data, sizeof(zone_based_per_led_data)) == sizeof(zone_based_per_led_data));
}
else
{
data.save_data = save;
return (hid_send_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof(data));
}
}
void MSIMysticLight112Controller::SetZoneColor
(
MSI_ZONE zone,
unsigned char red1,
unsigned char grn1,
unsigned char blu1,
unsigned char red2,
unsigned char grn2,
unsigned char blu2
)
{
ZoneData* zone_data = GetZoneData(data, zone);
if(zone_data == nullptr)
{
return;
}
if (zone <= MSI_ZONE_ON_BOARD_LED_0)
{
zone_data->color.R = red1;
zone_data->color.G = grn1;
zone_data->color.B = blu1;
zone_data->color2.R = red2;
zone_data->color2.G = grn2;
zone_data->color2.B = blu2;
}
if(zone >= MSI_ZONE_ON_BOARD_LED_0)
{
zone_data = GetZoneData(data, (MSI_ZONE)((int)zone + 1));
if(zone_data != nullptr)
{
zone_data->color.R = red1;
zone_data->color.G = grn1;
zone_data->color.B = blu1;
zone_data->color2.R = red2;
zone_data->color2.G = grn2;
zone_data->color2.B = blu2;
}
}
}
void MSIMysticLight112Controller::SetLedColor
(
MSI_ZONE zone,
unsigned char red,
unsigned char grn,
unsigned char blu
)
{
if(zone >= MSI_ZONE_ON_BOARD_LED_0)
{
zone = (MSI_ZONE)((int)zone + 1);
}
ZoneData *zone_data = GetZoneData(zone_based_per_led_data, zone);
if(zone_data == nullptr)
{
return;
}
zone_data->color.R = red;
zone_data->color.G = grn;
zone_data->color.B = blu;
zone_data->color2.R = red;
zone_data->color2.G = grn;
zone_data->color2.B = blu;
}
ZoneData *MSIMysticLight112Controller::GetZoneData
(
FeaturePacket_112& data_packet,
MSI_ZONE zone
)
{
switch(zone)
{
case MSI_ZONE_J_RGB_1:
return &data_packet.j_rgb_1;
case MSI_ZONE_J_RAINBOW_1:
return &data_packet.j_rainbow_1;
case MSI_ZONE_ON_BOARD_LED_0:
return &data_packet.on_board_led;
case MSI_ZONE_ON_BOARD_LED_1:
return &data_packet.on_board_led_1;
case MSI_ZONE_ON_BOARD_LED_2:
return &data_packet.on_board_led_2;
case MSI_ZONE_ON_BOARD_LED_3:
return &data_packet.on_board_led_3;
case MSI_ZONE_ON_BOARD_LED_4:
return &data_packet.on_board_led_4;
case MSI_ZONE_ON_BOARD_LED_5:
return &data_packet.on_board_led_5;
case MSI_ZONE_ON_BOARD_LED_6:
return &data_packet.on_board_led_6;
case MSI_ZONE_J_CORSAIR:
return &data_packet.j_corsair_1;
default:
break;
}
return nullptr;
}
bool MSIMysticLight112Controller::ReadFwVersion()
{
unsigned char request[64];
unsigned char response[64];
int ret_val = 64;
/*-----------------------------------------------------*\
| First read the APROM |
| Checksum also available at report ID 180, with MSB |
| stored at index 0x08 and LSB at 0x09 |
\*-----------------------------------------------------*/
/*-----------------------------------------------------*\
| Zero out buffers |
\*-----------------------------------------------------*/
memset(request, 0x00, sizeof(request));
memset(response, 0x00, sizeof(response));
/*-----------------------------------------------------*\
| Set up APROM Firmware Version Request packet |
\*-----------------------------------------------------*/
request[0x00] = 0x01;
request[0x01] = 0xB0;
/*-----------------------------------------------------*\
| Fill request from 0x02 to 0x61 with 0xCC |
\*-----------------------------------------------------*/
memset(&request[0x02], 0xCC, sizeof(request) - 2);
/*-----------------------------------------------------*\
| Send request and receive response packets |
\*-----------------------------------------------------*/
ret_val &= hid_write(dev, request, 64);
ret_val &= hid_read(dev, response, 64);
/*-----------------------------------------------------*\
| Extract high and low values from response |
\*-----------------------------------------------------*/
unsigned char highValue = response[2] >> 4;
unsigned char lowValue = response[2] & 0x0F;
/*-----------------------------------------------------*\
| Build firmware string <high>.<low> |
\*-----------------------------------------------------*/
version_APROM = std::to_string((int)highValue).append(".").append(std::to_string((int)lowValue));
/*-----------------------------------------------------*\
| First read the LDROM |
| Checksum also available at report ID 184, with MSB |
| stored at index 0x08 and LSB at 0x09 |
\*-----------------------------------------------------*/
/*-----------------------------------------------------*\
| Set up LDROM Firmware Version Request packet |
\*-----------------------------------------------------*/
request[0x00] = 0x01;
request[0x01] = 0xB6;
/*-----------------------------------------------------*\
| Send request and receive response packets |
\*-----------------------------------------------------*/
ret_val &= hid_write(dev, request, 64);
ret_val &= hid_read(dev, response, 64);
/*-----------------------------------------------------*\
| Extract high and low values from response |
\*-----------------------------------------------------*/
highValue = response[2] >> 4;
lowValue = response[2] & 0x0F;
/*-----------------------------------------------------*\
| Build firmware string <high>.<low> |
\*-----------------------------------------------------*/
version_LDROM = std::to_string((int)highValue).append(".").append(std::to_string((int)lowValue));
/*-----------------------------------------------------*\
| If return value is zero it means an HID transfer |
| failed |
\*-----------------------------------------------------*/
return(ret_val > 0);
}
void MSIMysticLight112Controller::ReadSerial()
{
wchar_t serial[256];
/*-----------------------------------------------------*\
| Get the serial number string from HID |
\*-----------------------------------------------------*/
hid_get_serial_number_string(dev, serial, 256);
/*-----------------------------------------------------*\
| Convert wchar_t into std::wstring into std::string |
\*-----------------------------------------------------*/
std::wstring wserial = std::wstring(serial);
chip_id = std::string(wserial.begin(), wserial.end());
}
void MSIMysticLight112Controller::ReadName()
{
wchar_t tname[256];
/*-----------------------------------------------------*\
| Get the manufacturer string from HID |
\*-----------------------------------------------------*/
hid_get_manufacturer_string(dev, tname, 256);
/*-----------------------------------------------------*\
| Convert wchar_t into std::wstring into std::string |
\*-----------------------------------------------------*/
std::wstring wname = std::wstring(tname);
name = std::string(wname.begin(), wname.end());
/*-----------------------------------------------------*\
| Get the product string from HID |
\*-----------------------------------------------------*/
hid_get_product_string(dev, tname, 256);
/*-----------------------------------------------------*\
| Append the product string to the manufacturer string |
\*-----------------------------------------------------*/
wname = std::wstring(tname);
name.append(" ").append(std::string(wname.begin(), wname.end()));
}
MSI_MODE MSIMysticLight112Controller::GetMode()
{
return (MSI_MODE)data.on_board_led.effect;
}
void MSIMysticLight112Controller::GetMode
(
MSI_ZONE zone,
MSI_MODE &mode,
MSI_SPEED &speed,
MSI_BRIGHTNESS &brightness,
bool &rainbow_color,
unsigned int &color
)
{
/*-----------------------------------------------------*\
| Get data for given zone |
\*-----------------------------------------------------*/
ZoneData *zone_data = GetZoneData(data, zone);
/*-----------------------------------------------------*\
| Return if zone is invalid |
\*-----------------------------------------------------*/
if(zone_data == nullptr)
{
return;
}
/*-----------------------------------------------------*\
| Update pointers with data |
\*-----------------------------------------------------*/
mode = (MSI_MODE)zone_data->effect;
speed = (MSI_SPEED)(zone_data->speedAndBrightnessFlags & 0x03);
brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> 2) & 0x1F);
rainbow_color = (zone_data->colorFlags & 0x80) == 0 ? true : false;
color = ToRGBColor(zone_data->color.R, zone_data->color.G, zone_data->color.B);
}
void MSIMysticLight112Controller::SetDirectMode
(
bool mode
)
{
direct_mode = mode;
}
size_t MSIMysticLight112Controller::GetMaxOnboardLeds()
{
return numof_onboard_leds;
}

View file

@ -0,0 +1,111 @@
/*-----------------------------------------*\
| MSIMysticLight112Controller.h |
| |
| Definitions and types for MSI Mystic |
| Light (112-byte) USB lighting controllers|
| |
| thombo 12/17/2022 |
\*-----------------------------------------*/
#include "MSIMysticLightCommon.h"
#include "RGBController.h"
#include <cstring>
#include <hidapi/hidapi.h>
#include <limits>
#pragma once
class MSIMysticLight112Controller
{
public:
MSIMysticLight112Controller
(
hid_device* handle,
const char *path
);
~MSIMysticLight112Controller();
void SetMode
(
MSI_ZONE zone,
MSI_MODE mode,
MSI_SPEED speed,
MSI_BRIGHTNESS brightness,
bool rainbow_color
);
MSI_MODE GetMode();
void GetMode
(
MSI_ZONE zone,
MSI_MODE &mode,
MSI_SPEED &speed,
MSI_BRIGHTNESS &brightness,
bool &rainbow_color,
unsigned int &color
);
void SetZoneColor
(
MSI_ZONE zone,
unsigned char red1,
unsigned char grn1,
unsigned char blu1,
unsigned char red2,
unsigned char grn2,
unsigned char blu2
);
void SetLedColor
(
MSI_ZONE zone,
unsigned char red,
unsigned char grn,
unsigned char blu
);
bool Update
(
bool save
);
std::string GetDeviceName();
std::string GetDeviceLocation();
std::string GetFWVersion();
std::string GetSerial();
void SetDirectMode
(
bool mode
);
bool IsDirectModeActive() { return direct_mode; }
size_t GetMaxOnboardLeds();
const std::vector<MSI_ZONE>*
GetSupportedZones() { return supported_zones; }
private:
bool ReadSettings();
bool ReadFwVersion();
void ReadSerial();
void ReadName();
ZoneData* GetZoneData
(
FeaturePacket_112& dataPacket,
MSI_ZONE zone
);
hid_device* dev;
std::string name;
std::string location;
std::string version_APROM;
std::string version_LDROM;
std::string chip_id;
FeaturePacket_112 data;
FeaturePacket_112 zone_based_per_led_data;
bool direct_mode;
size_t numof_onboard_leds;
const std::vector<MSI_ZONE>* supported_zones;
};

View file

@ -265,6 +265,7 @@ static const Config board_configs[] =
{ 0x7D77, 6, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650M-A WIFI
{ 0x7D91, 1, 0, 0, 1, &zones_set10, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG Z790 TOMAHAWK WIFI
{ 0x7E06, 0, 0, 0, 2, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO Z790-P WIFI DDR4
{ 0x7E07, 0, 0, 0, 2, &zones_set10, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO Z790-A WIFI DDR4
};

View file

@ -166,6 +166,23 @@ struct FeaturePacket_64
const unsigned char padding[37] = {}; //pad to make the packet size 64 bytes
};
struct FeaturePacket_112
{
const unsigned char report_id = 0x52; // Report ID
ZoneData j_rgb_1; // 1
ZoneData j_rainbow_1; // 11
ZoneData j_corsair_1; // 21
ZoneData j_corsair_outerll120; // 31
ZoneData on_board_led; // 41
ZoneData on_board_led_1; // 51
ZoneData on_board_led_2; // 61
ZoneData on_board_led_3; // 71
ZoneData on_board_led_4; // 81
ZoneData on_board_led_5; // 91
ZoneData on_board_led_6; // 101
unsigned char save_data = 0; // 111
};
struct FeaturePacket_162
{
const unsigned char report_id = 0x52; // Report ID

View file

@ -1,8 +1,10 @@
#include "Detector.h"
#include "MSIMysticLight64Controller.h"
#include "MSIMysticLight112Controller.h"
#include "MSIMysticLight162Controller.h"
#include "MSIMysticLight185Controller.h"
#include "RGBController_MSIMysticLight64.h"
#include "RGBController_MSIMysticLight112.h"
#include "RGBController_MSIMysticLight162.h"
#include "RGBController_MSIMysticLight185.h"
#include "dependencies/dmiinfo.h"
@ -55,6 +57,13 @@ void DetectMSIMysticLightControllers
rgb_controller->name = "MSI " + dmi.getMainboard();
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
else if((packet_length >= sizeof(FeaturePacket_112)) && (packet_length <= (sizeof(FeaturePacket_112) + 1)))
{
MSIMysticLight112Controller* controller = new MSIMysticLight112Controller(dev, info->path);
RGBController_MSIMysticLight112* rgb_controller = new RGBController_MSIMysticLight112(controller);
rgb_controller->name = "MSI " + dmi.getMainboard();
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
else // no supported length returned
{
std::string name = "MSI " + dmi.getMainboard();
@ -151,6 +160,7 @@ REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D69", DetectMSIMysticLightCont
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D77", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D77, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D91", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D91, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E06", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E06, 0x0001, 0x00);
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E07", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E07, 0x0001, 0x00);
#ifdef ENABLE_UNTESTED_MYSTIC_LIGHT
REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_3EA4", DetectMSIMysticLightControllers, MSI_USB_VID, 0x3EA4, 0x0001, 0x00);

View file

@ -0,0 +1,388 @@
/*-----------------------------------------*\
| RGBController_MSIMysticLight112.cpp |
| |
| Generic RGB Interface for OpenRGB |
| MSI Mystic Light (112-byte) USB Driver |
| |
| thombo 12/17/2022 |
\*-----------------------------------------*/
#include "RGBController_MSIMysticLight112.h"
struct ZoneDescription
{
std::string name;
MSI_ZONE zone_type;
};
#define NUMOF_ZONES (sizeof(led_zones) / sizeof(ZoneDescription))
const ZoneDescription led_zones[] =
{
ZoneDescription{ "JRGB1", MSI_ZONE_J_RGB_1 },
ZoneDescription{ "JRAINBOW1", MSI_ZONE_J_RAINBOW_1 },
ZoneDescription{ "JCORSAIR", MSI_ZONE_J_CORSAIR },
ZoneDescription{ "Onboard LEDs", MSI_ZONE_ON_BOARD_LED_0 }
};
static std::vector<const ZoneDescription*> zone_description;
/**------------------------------------------------------------------*\
@name MSI Mystic Light (112 Byte)
@category Motherboard
@type USB
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectMSIMysticLightControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_MSIMysticLight112::RGBController_MSIMysticLight112
(
MSIMysticLight112Controller* controller_ptr
)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "MSI";
type = DEVICE_TYPE_MOTHERBOARD;
description = "MSI Mystic Light Device (112-byte)";
version = controller->GetFWVersion();
location = controller->GetDeviceLocation();
serial = controller->GetSerial();
const std::vector<MSI_ZONE>* supported_zones = controller->GetSupportedZones();
for(std::size_t i = 0; i < supported_zones->size(); ++i)
{
for(std::size_t j = 0; j < NUMOF_ZONES; ++j)
{
if(led_zones[j].zone_type == (*supported_zones)[i])
{
zone_description.push_back(&led_zones[j]);
break;
}
}
}
SetupModes();
SetupZones();
SetupColors();
active_mode = GetDeviceMode();
GetDeviceConfig();
}
RGBController_MSIMysticLight112::~RGBController_MSIMysticLight112()
{
zone_description.clear();
delete controller;
}
int RGBController_MSIMysticLight112::GetDeviceMode()
{
MSI_MODE mode = controller->GetMode();
for(unsigned int i = 0; i < modes.size(); ++i)
{
if(mode == modes[i].value)
{
return i;
}
}
return 0;
}
void RGBController_MSIMysticLight112::SetupZones()
{
/*---------------------------------------------------------*\
| Set up zones |
\*---------------------------------------------------------*/
for(std::size_t zone_idx = 0; zone_idx < zone_description.size(); ++zone_idx)
{
const ZoneDescription* zd = zone_description[zone_idx];
zone new_zone;
new_zone.name = zd->name;
/*--------------------------------------------------\
| 112-byte MSI does not have resizable zones, but |
| onboard LED zones have multiple LEDs |
\*-------------------------------------------------*/
if(zd->zone_type == MSI_ZONE_ON_BOARD_LED_0)
{
new_zone.leds_max = (int)controller->GetMaxOnboardLeds();
}
else
{
new_zone.leds_max = 1;
}
new_zone.leds_min = new_zone.leds_max;
new_zone.leds_count = new_zone.leds_max;
/*-------------------------------------------------*\
| Determine zone type based on max number of LEDs |
\*-------------------------------------------------*/
if(new_zone.leds_max == 1)
{
new_zone.type = ZONE_TYPE_SINGLE;
}
else
{
new_zone.type = ZONE_TYPE_LINEAR;
}
new_zone.matrix_map = NULL;
zones.push_back(new_zone);
}
/*---------------------------------------------------------*\
| Set up LEDs |
\*---------------------------------------------------------*/
for(std::size_t zone_idx = 0; zone_idx < zone_description.size(); ++zone_idx)
{
for(std::size_t led_idx = 0; led_idx < zones[zone_idx].leds_count; ++led_idx)
{
led new_led;
new_led.name = zones[zone_idx].name + " LED ";
if(zones[zone_idx].leds_count > 1)
{
new_led.name.append(std::to_string(led_idx + 1));
}
new_led.value = (unsigned int)(zone_description[zone_idx]->zone_type + led_idx);
leds.push_back(new_led);
}
}
}
void RGBController_MSIMysticLight112::ResizeZone
(
int /*zone*/,
int /*new_size*/
)
{
}
void RGBController_MSIMysticLight112::DeviceUpdateLEDs()
{
for(std::size_t zone_idx = 0; zone_idx < zones.size(); ++zone_idx)
{
for(int led_idx = zones[zone_idx].leds_count - 1; led_idx >= 0; led_idx--)
{
UpdateLed((int)zone_idx, led_idx);
}
}
controller->Update((modes[active_mode].flags & MODE_FLAG_AUTOMATIC_SAVE) != 0);
}
void RGBController_MSIMysticLight112::UpdateZoneLEDs
(
int zone
)
{
for(int led_idx = zones[zone].leds_count - 1; led_idx >= 0; led_idx--)
{
UpdateLed(zone, led_idx);
}
controller->Update((modes[active_mode].flags & MODE_FLAG_AUTOMATIC_SAVE) != 0);
}
void RGBController_MSIMysticLight112::UpdateSingleLED
(
int led
)
{
UpdateLed(leds[led].value, led);
controller->Update((modes[active_mode].flags & MODE_FLAG_AUTOMATIC_SAVE) != 0);
}
void RGBController_MSIMysticLight112::DeviceUpdateMode()
{
if(modes[active_mode].value == MSI_MODE_DIRECT_DUMMY)
{
controller->SetDirectMode(true);
}
else
{
controller->SetDirectMode(false);
DeviceUpdateLEDs();
}
}
void RGBController_MSIMysticLight112::DeviceSaveMode()
{
controller->Update(true);
}
void RGBController_MSIMysticLight112::SetupModes()
{
constexpr unsigned int PER_LED_ONLY = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE;
constexpr unsigned int RANDOM_ONLY = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE;
constexpr unsigned int COMMON = RANDOM_ONLY | MODE_FLAG_HAS_PER_LED_COLOR;
SetupMode("Direct", MSI_MODE_DIRECT_DUMMY, MODE_FLAG_HAS_PER_LED_COLOR);
SetupMode("Static", MSI_MODE_STATIC, MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE);
SetupMode("Breathing", MSI_MODE_BREATHING, PER_LED_ONLY);
SetupMode("Flashing", MSI_MODE_FLASHING, COMMON);
SetupMode("Double flashing", MSI_MODE_DOUBLE_FLASHING, COMMON);
SetupMode("Lightning", MSI_MODE_LIGHTNING, PER_LED_ONLY);
SetupMode("Meteor", MSI_MODE_METEOR, COMMON);
SetupMode("Stack", MSI_MODE_WATER_DROP, COMMON);
SetupMode("Rainbow", MSI_MODE_COLOR_RING, COMMON);
SetupMode("Planetary", MSI_MODE_PLANETARY, RANDOM_ONLY);
SetupMode("Double meteor", MSI_MODE_DOUBLE_METEOR, RANDOM_ONLY);
SetupMode("Energy", MSI_MODE_ENERGY, RANDOM_ONLY);
SetupMode("Blink", MSI_MODE_BLINK, COMMON);
SetupMode("Clock", MSI_MODE_CLOCK, RANDOM_ONLY);
SetupMode("Color pulse", MSI_MODE_COLOR_PULSE, COMMON);
SetupMode("Color shift", MSI_MODE_COLOR_SHIFT, RANDOM_ONLY);
SetupMode("Color wave", MSI_MODE_COLOR_WAVE, COMMON);
SetupMode("Marquee", MSI_MODE_MARQUEE, PER_LED_ONLY);
SetupMode("Rainbow wave", MSI_MODE_RAINBOW_WAVE, RANDOM_ONLY);
SetupMode("Visor", MSI_MODE_VISOR, COMMON);
SetupMode("Rainbow flashing", MSI_MODE_RAINBOW_FLASHING, RANDOM_ONLY);
SetupMode("Rainbow double flashing", MSI_MODE_RAINBOW_DOUBLE_FLASHING, RANDOM_ONLY);
}
void RGBController_MSIMysticLight112::UpdateLed
(
int zone,
int led
)
{
unsigned char red = RGBGetRValue(zones[zone].colors[led]);
unsigned char grn = RGBGetGValue(zones[zone].colors[led]);
unsigned char blu = RGBGetBValue(zones[zone].colors[led]);
if(controller->IsDirectModeActive())
{
controller->SetLedColor((MSI_ZONE)zones[zone].leds[led].value, red, grn, blu);
}
else
{
bool random = modes[active_mode].color_mode == MODE_COLORS_RANDOM;
MSI_MODE mode = (MSI_MODE)modes[active_mode].value;
MSI_SPEED speed = (MSI_SPEED)modes[active_mode].speed;
MSI_BRIGHTNESS brightness = (MSI_BRIGHTNESS)modes[active_mode].brightness;
controller->SetMode((MSI_ZONE)zones[zone].leds[led].value, mode, speed, brightness, random);
controller->SetZoneColor((MSI_ZONE)zones[zone].leds[led].value, red, grn, blu, red, grn, blu);
}
}
void RGBController_MSIMysticLight112::SetupMode
(
const char *name,
MSI_MODE mod,
unsigned int flags
)
{
mode Mode;
Mode.name = name;
Mode.value = mod;
Mode.flags = flags;
if(flags & MODE_FLAG_HAS_PER_LED_COLOR)
{
Mode.color_mode = MODE_COLORS_PER_LED;
}
else
{
Mode.color_mode = MODE_COLORS_RANDOM;
}
if(flags & MODE_FLAG_HAS_SPEED)
{
Mode.speed = MSI_SPEED_MEDIUM;
Mode.speed_max = MSI_SPEED_HIGH;
Mode.speed_min = MSI_SPEED_LOW;
}
else
{
/*---------------------------------------------------------*\
| For modes without speed this needs to be set to avoid |
| bad values in the saved profile which in turn corrupts |
| the brightness calculation when loading the profile |
\*---------------------------------------------------------*/
Mode.speed = 0;
Mode.speed_max = 0;
Mode.speed_min = 0;
}
if(flags & MODE_FLAG_HAS_BRIGHTNESS)
{
Mode.brightness = MSI_BRIGHTNESS_LEVEL_100;
Mode.brightness_max = MSI_BRIGHTNESS_LEVEL_100;
Mode.brightness_min = MSI_BRIGHTNESS_OFF;
}
else
{
Mode.brightness = MSI_BRIGHTNESS_LEVEL_100;
Mode.brightness_max = MSI_BRIGHTNESS_LEVEL_100;
Mode.brightness_min = MSI_BRIGHTNESS_LEVEL_100;
}
modes.push_back(Mode);
}
void RGBController_MSIMysticLight112::GetDeviceConfig()
{
MSI_MODE mode;
MSI_SPEED speed;
MSI_BRIGHTNESS brightness;
bool rainbow;
unsigned int color;
for(size_t i = 0; i < zone_description.size(); ++i)
{
controller->GetMode(zone_description[i]->zone_type, mode, speed, brightness, rainbow, color);
for(size_t j = 0; j < zones[i].leds_count; ++j)
{
zones[i].colors[j] = color;
}
}
controller->GetMode(zone_description[0]->zone_type, mode, speed, brightness, rainbow, color);
for(size_t i = 0; i < modes.size(); ++i)
{
if(mode == modes[i].value)
{
if(modes[i].flags & MODE_FLAG_HAS_SPEED)
{
modes[i].speed = speed;
}
if(modes[i].flags & MODE_FLAG_HAS_BRIGHTNESS)
{
modes[i].brightness = brightness;
}
if(rainbow)
{
if(modes[i].flags & (MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR))
{
if(rainbow)
{
modes[i].color_mode = MODE_COLORS_RANDOM;
}
else
{
modes[i].color_mode = MODE_COLORS_PER_LED;
}
}
}
break;
}
}
}

View file

@ -0,0 +1,48 @@
/*-----------------------------------------*\
| RGBController_MSIMysticLight112.h |
| |
| Generic RGB Interface for OpenRGB |
| MSI Mystic Light (112-byte) USB Driver |
| |
| thombo 12/17/2022 |
\*-----------------------------------------*/
#pragma once
#include "RGBController.h"
#include "MSIMysticLight112Controller.h"
#include <vector>
class RGBController_MSIMysticLight112: public RGBController
{
public:
RGBController_MSIMysticLight112(MSIMysticLight112Controller* controller_ptr);
~RGBController_MSIMysticLight112();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
void DeviceSaveMode();
private:
void SetupModes();
void UpdateLed
(
int zone,
int led
);
void SetupMode
(
const char *name,
MSI_MODE mode,
unsigned int flags
);
int GetDeviceMode();
void GetDeviceConfig();
MSIMysticLight112Controller* controller;
};

View file

@ -501,9 +501,11 @@ HEADERS +=
Controllers/MSIGPUController/RGBController_MSIGPU.h \
Controllers/MSIMysticLightController/MSIMysticLightCommon.h \
Controllers/MSIMysticLightController/MSIMysticLight64Controller.h \
Controllers/MSIMysticLightController/MSIMysticLight112Controller.h \
Controllers/MSIMysticLightController/MSIMysticLight162Controller.h \
Controllers/MSIMysticLightController/MSIMysticLight185Controller.h \
Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.h \
Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.h \
Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.h \
Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.h \
Controllers/MSIOptixController/MSIOptixController.h \
@ -1075,9 +1077,11 @@ SOURCES +=
Controllers/MSIGPUController/RGBController_MSIGPU.cpp \
Controllers/MSIMysticLightController/MSIMysticLight64Controller.cpp \
Controllers/MSIMysticLightController/MSIMysticLight162Controller.cpp \
Controllers/MSIMysticLightController/MSIMysticLight112Controller.cpp \
Controllers/MSIMysticLightController/MSIMysticLight185Controller.cpp \
Controllers/MSIMysticLightController/MSIMysticLightControllerDetect.cpp \
Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.cpp \
Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.cpp \
Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.cpp \
Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.cpp \
Controllers/MSIOptixController/MSIOptixController.cpp \