diff --git a/Controllers/MSIKeyboardController/MSIKeyboardControllerDetect.cpp b/Controllers/MSIKeyboardController/MSIKeyboardControllerDetect.cpp new file mode 100644 index 000000000..e4f508063 --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIKeyboardControllerDetect.cpp @@ -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); \ No newline at end of file diff --git a/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.cpp b/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.cpp new file mode 100644 index 000000000..c06f8f7c7 --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.cpp @@ -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 + +std::map 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)); +} diff --git a/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.h b/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.h new file mode 100644 index 000000000..ddee81c42 --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.h @@ -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 +#include +#include +#include + +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 mode_zones; + +private: + hid_device* dev; + std::string location; +}; + + +#endif // MSIMYSTICLIGHTKBCONTROLLER_H diff --git a/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.cpp b/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.cpp new file mode 100644 index 000000000..9536e6cdc --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.cpp @@ -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 + +/**------------------------------------------------------------------*\ + @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)); + } +} diff --git a/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.h b/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.h new file mode 100644 index 000000000..6636e893f --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.h @@ -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