Feat/ms 1565

This commit is contained in:
lulu731 2025-07-07 16:55:29 +00:00 committed by Adam Honse
parent f76dbb08cc
commit bdaebe1218
5 changed files with 531 additions and 0 deletions

View file

@ -0,0 +1,39 @@
/*---------------------------------------------------------*\
| MSIKeyboardControllerDetect.cpp |
| |
| Detector for MSI Mystic Light MS-1565 Keyboard |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "Detector.h"
#include "MSIMysticLightKBController.h"
#include "RGBController_MSIMysticLightKB.h"
#define MSI_USB_VID 0x1462
/*----------------------------------------------------------*\
| |
| DetectMSIKeyboardController |
| |
| Detect MSI Mystic Light MS-1565 keyboard |
| |
\*----------------------------------------------------------*/
void DetectMSIKeyboardController
(
hid_device_info* info,
const std::string& /*name*/
)
{
hid_device* dev = hid_open_path(info->path);
if(dev != nullptr)
{
MSIKeyboardController* controller = new MSIKeyboardController(dev, info->path);
RGBController_MSIKeyboard* rgb_controller = new RGBController_MSIKeyboard(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_HID_DETECTOR_PU("MSI Keyboard MS_1565", DetectMSIKeyboardController, MSI_USB_VID, 0x1601, 0x00FF, 0x01);

View file

@ -0,0 +1,128 @@
/*---------------------------------------------------------*\
| MSIMysticLightKBController.cpp |
| |
| Driver for MSI Mystic Light MS-1565 keyboard leds |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "MSIMysticLightKBController.h"
#include "StringUtils.h"
#include "hidapi.h"
#include <map>
std::map<MS_1565_ZONE, unsigned char> zone_map =
{
{ MS_1565_ZONE_1, 1 },
{ MS_1565_ZONE_2, 2 },
{ MS_1565_ZONE_3, 4 },
{ MS_1565_ZONE_4, 8 },
{ MS_1565_ZONE_DEVICE, 15}
};
MSIKeyboardController::MSIKeyboardController
(
hid_device *handle,
const char *path
)
{
dev = handle;
if(dev)
{
location = path;
}
}
MSIKeyboardController::~MSIKeyboardController()
{
hid_close(dev);
}
void MSIKeyboardController::SetMode
(
MS_1565_MODE mode,
MS_1565_SPEED speed1,
MS_1565_SPEED speed2,
MS_1565_WAVE_DIRECTION wave_dir,
MS_1565_ZONE zone,
ColorKeyFrame color_keyframes[]
)
{
unsigned char buf[64] = {};
buf[0] = 0x02;
buf[1] = 0x01;
buf[2] = zone_map[zone];
hid_send_feature_report(dev, buf, sizeof(buf));
FeaturePacket_MS1565 data;
data.mode = (unsigned char)(mode);
for(int i = 0; i < MAX_MS_1565_KEYFRAMES; i++)
{
data.color_keyframes[i] = color_keyframes[i];
}
data.speed2 = speed2;
data.speed1 = speed1;
data.wave_dir = (unsigned char)(wave_dir);
/*-----------------------------------------------------*\
| Send packet to hardware, return true if successful |
\*-----------------------------------------------------*/
hid_send_feature_report(dev, (unsigned char *)&data, sizeof(data));
return;
}
std::string MSIKeyboardController::GetDeviceName()
{
wchar_t tname[256];
/*-----------------------------------------------------*\
| Get the manufacturer string from HID |
\*-----------------------------------------------------*/
hid_get_manufacturer_string(dev, tname, 256);
/*-----------------------------------------------------*\
| Convert to std::string |
\*-----------------------------------------------------*/
std::string name = StringUtils::wstring_to_string(tname);
/*-----------------------------------------------------*\
| Get the product string from HID |
\*-----------------------------------------------------*/
hid_get_product_string(dev, tname, 256);
/*-----------------------------------------------------*\
| Append the product string to the manufacturer string |
\*-----------------------------------------------------*/
name.append(" ").append(StringUtils::wstring_to_string(tname));
return(name);
}
std::string MSIKeyboardController::GetFWVersion()
{
/*-----------------------------------------------------*\
| This device doesn't support firmware version |
\*-----------------------------------------------------*/
std::string firmware_version = "";
return firmware_version;
}
std::string MSIKeyboardController::GetDeviceLocation()
{
return ("HID: " + location);
}
std::string MSIKeyboardController::GetSerial()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}

View file

@ -0,0 +1,111 @@
/*---------------------------------------------------------*\
| MSIMysticLight1565Controller.h |
| |
| Driver for MSI Mystic Light MS-1565 keyboard leds |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#ifndef MSIMYSTICLIGHTKBCONTROLLER_H
#define MSIMYSTICLIGHTKBCONTROLLER_H
#include <cstring>
#include <string>
#include <hidapi.h>
#include <vector>
struct Color
{
unsigned char R;
unsigned char G;
unsigned char B;
};
struct ColorKeyFrame
{
unsigned char time_frame = 0x00;
Color color;
};
#define MAX_MS_1565_KEYFRAMES 10
typedef unsigned char MS_1565_SPEED;
// 64 bytes long feature
struct FeaturePacket_MS1565
{
unsigned char report_id = 0x02; // Report ID
unsigned char packet_id = 0x02;
unsigned char mode = 0x00;
unsigned char speed2 = 0x00; // Seconds X 100 = duration of animation cycle
unsigned char speed1 = 0x00; // In little endian
// 1 second => 100 = 0x0064, speed2 = 0x64, speed1 = 0x00
const unsigned char unused = 0x00;
const unsigned char unused2 = 0x00;
const unsigned char unused3 = 0x0F;
const unsigned char unused4 = 0x01;
unsigned char wave_dir = 0x00;
ColorKeyFrame color_keyframes[MAX_MS_1565_KEYFRAMES] = {};
const unsigned char padding[14] = {}; //pad to make the packet size 64 bytes
};
enum MS_1565_MODE
{
MS_1565_OFF = 0,
MS_1565_STEADY = 1,
MS_1565_BREATHING = 2,
MS_1565_CYCLE = 3,
MS_1565_WAVE = 4,
};
enum MS_1565_WAVE_DIRECTION
{
MS_1565_WAVE_DIRECTION_RIGHT_TO_LEFT = 0,
MS_1565_WAVE_DIRECTION_LEFT_TO_RIGHT = 1
};
enum MS_1565_ZONE
{
MS_1565_ZONE_1 = 1,
MS_1565_ZONE_2,
MS_1565_ZONE_3,
MS_1565_ZONE_4,
MS_1565_ZONE_DEVICE
};
class MSIKeyboardController
{
public:
MSIKeyboardController
(
hid_device* handle,
const char* path
);
~MSIKeyboardController();
void SetMode
(
MS_1565_MODE mode,
MS_1565_SPEED speed1,
MS_1565_SPEED speed2,
MS_1565_WAVE_DIRECTION wave_dir,
MS_1565_ZONE zone,
ColorKeyFrame color_keyframes[]
);
std::string GetDeviceName();
std::string GetDeviceLocation();
std::string GetFWVersion();
std::string GetSerial();
std::vector<MS_1565_ZONE> mode_zones;
private:
hid_device* dev;
std::string location;
};
#endif // MSIMYSTICLIGHTKBCONTROLLER_H

View file

@ -0,0 +1,203 @@
/*---------------------------------------------------------*\
| RGBController_MSIMysticLightKB.cpp |
| |
| Driver for MSI Mystic Light MS-1565 keyboard leds |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "RGBController_MSIMysticLightKB.h"
#include "MSIMysticLightKBController.h"
#include "RGBController.h"
#include <cstddef>
/**------------------------------------------------------------------*\
@name MSI MS-1565 Mystic Light Keyboard (64 Byte)
@category Keyboard
@type USB
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectMSIMysticLight1565Controller
@comment
\*-------------------------------------------------------------------*/
RGBController_MSIKeyboard::RGBController_MSIKeyboard
(
MSIKeyboardController *controller_ptr
)
{
controller = controller_ptr;
name = controller->GetDeviceName();
vendor = "MSI";
type = DEVICE_TYPE_KEYBOARD;
description = "MSI Mystic Light MS-1565";
version = controller->GetFWVersion();
location = controller->GetDeviceLocation();
serial = controller->GetSerial();
SetupModes();
SetupColors();
}
RGBController_MSIKeyboard::~RGBController_MSIKeyboard()
{
delete controller;
}
void RGBController_MSIKeyboard::ResizeZone
(
int /*zone*/,
int /*new_size*/
)
{
}
void RGBController_MSIKeyboard::SetupZones()
{
}
void RGBController_MSIKeyboard::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
void RGBController_MSIKeyboard::DeviceUpdateLEDs()
{
mode &Mode = modes[active_mode];
MS_1565_MODE msi_mode = (MS_1565_MODE)Mode.value;
MS_1565_ZONE zone = controller->mode_zones[active_mode];
/*----------------------------------*\
| speed is cycle duration in 1/100s |
| Mode.speed = 0 % => speed = 12.00s |
| Mode.speed = 50 % => speed = 7.50s |
| Mode.speed = 100 % => speed = 3.00 |
\*--------------------------------- */
unsigned int speed = 1200 - 9 * Mode.speed;
unsigned char speed2 = (unsigned char)(speed & 0xFF);
unsigned char speed1 = (unsigned char)((speed & 0xFF00) >> 8);
MS_1565_WAVE_DIRECTION wave_direction = (MS_1565_WAVE_DIRECTION)(Mode.direction);
const size_t colors_size = Mode.colors.size();
ColorKeyFrame ck[MAX_MS_1565_KEYFRAMES] = {};
for(size_t idx = 0; idx < colors_size; idx++)
{
ck[idx].time_frame = idx * 100 / colors_size;
ck[idx].color.R = RGBGetRValue(Mode.colors[idx]) * Mode.brightness / 100;
ck[idx].color.G = RGBGetGValue(Mode.colors[idx]) * Mode.brightness / 100;
ck[idx].color.B = RGBGetBValue(Mode.colors[idx]) * Mode.brightness / 100;
}
ck[colors_size].time_frame = 100;
ck[colors_size].color.R = RGBGetRValue(Mode.colors[0]) * Mode.brightness / 100;
ck[colors_size].color.G = RGBGetGValue(Mode.colors[0]) * Mode.brightness / 100;
ck[colors_size].color.B = RGBGetBValue(Mode.colors[0]) * Mode.brightness / 100;
controller->SetMode(msi_mode, speed1, speed2, wave_direction, zone, ck);
}
void RGBController_MSIKeyboard::UpdateZoneLEDs(int /*zone*/)
{
}
void RGBController_MSIKeyboard::UpdateSingleLED(int /*led*/)
{
}
void RGBController_MSIKeyboard::SetupModes()
{
SetupZonesMode("Off", MS_1565_MODE::MS_1565_OFF, 0);
SetupZonesMode("Static", MS_1565_MODE::MS_1565_STEADY, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_BRIGHTNESS);
SetupZonesMode("Breathing", MS_1565_MODE::MS_1565_BREATHING, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_BRIGHTNESS);
SetupZonesMode("Color Cycle", MS_1565_MODE::MS_1565_CYCLE, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_BRIGHTNESS);
SetupZonesMode("Wave", MS_1565_MODE::MS_1565_WAVE, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |
MODE_FLAG_HAS_SPEED |
MODE_FLAG_HAS_BRIGHTNESS |
MODE_FLAG_HAS_DIRECTION_LR);
}
void RGBController_MSIKeyboard::SetupMode
(
const std::string name,
MS_1565_MODE mod,
unsigned int flags,
MS_1565_ZONE zone
)
{
mode Mode;
Mode.name = name;
Mode.value = mod;
Mode.flags = flags;
if(Mode.value == MS_1565_MODE::MS_1565_OFF)
{
Mode.color_mode= MODE_COLORS_NONE;
Mode.colors_min = 0;
Mode.colors_max = 0;
Mode.colors.resize(1);
modes.push_back(Mode);
controller->mode_zones.push_back(zone);
return;
}
if(flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR)
{
Mode.color_mode= MODE_COLORS_MODE_SPECIFIC;
Mode.colors_min = 1;
if(Mode.value == MS_1565_MODE::MS_1565_STEADY)
{
Mode.colors_max = 1;
}
else
{
Mode.colors_max = MAX_MS_1565_KEYFRAMES - 1;
}
Mode.colors.resize(Mode.colors_max);
}
if(flags & MODE_FLAG_HAS_SPEED)
{
Mode.speed_min = 0;
Mode.speed_max = 100;
Mode.speed = 50;
}
if(flags & MODE_FLAG_HAS_BRIGHTNESS)
{
Mode.brightness_min = 0;
Mode.brightness_max = 100;
}
Mode.brightness = 100;
if(flags & MODE_FLAG_HAS_DIRECTION_LR)
{
Mode.direction = 0;
}
modes.push_back(Mode);
controller->mode_zones.push_back(zone);
}
void RGBController_MSIKeyboard::SetupZonesMode
(
const std::string name,
MS_1565_MODE mod,
unsigned int flags
)
{
SetupMode(name, mod, flags, MS_1565_ZONE_DEVICE);
for(int idx = 0; idx < 4; idx++)
{
SetupMode(name + " zone " + std::to_string(idx + 1), mod, flags, MS_1565_ZONE(idx + 1));
}
}

View file

@ -0,0 +1,50 @@
/*---------------------------------------------------------*\
| RGBController_MSIMysticLight1565.h |
| |
| Driver for MSI Mystic Light MS-1565 keyboard leds |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#ifndef RGBCONTROLLER_MSIMYSTICLIGHTKB_H
#define RGBCONTROLLER_MSIMYSTICLIGHTKB_H
#include "RGBController.h"
#include "MSIMysticLightKBController.h"
class RGBController_MSIKeyboard : public RGBController
{
public:
RGBController_MSIKeyboard(MSIKeyboardController* controller_ptr);
~RGBController_MSIKeyboard();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
MSIKeyboardController* controller;
void SetupModes();
void SetupMode
(
const std::string name,
MS_1565_MODE mode,
unsigned int flags,
MS_1565_ZONE zone
);
void SetupZonesMode
(
const std::string name,
MS_1565_MODE mod,
unsigned int flags
);
};
#endif // RGBCONTROLLER_MSIMYSTICLIGHTKB_H