mirror of
https://github.com/CalcProgrammer1/OpenRGB.git
synced 2026-07-29 14:36:06 -04:00
164 lines
8.5 KiB
C++
164 lines
8.5 KiB
C++
/*---------------------------------------------------------*\
|
|
| MSIMonitorControllerDetect.cpp |
|
|
| |
|
|
| Detector for MSI monitor (MSI Gaming Controller) |
|
|
| |
|
|
| This file is part of the OpenRGB project |
|
|
| SPDX-License-Identifier: GPL-2.0-or-later |
|
|
\*---------------------------------------------------------*/
|
|
|
|
#include "DetectionManager.h"
|
|
#include "MSIMonitorController.h"
|
|
#include "RGBController_MSIMonitor.h"
|
|
#include "RGBController_MSIMonitor72.h"
|
|
|
|
#define MSI_USB_VID 0x1462
|
|
#define MSI_USB_PID 0x3FA4
|
|
|
|
/*---------------------------------------------------------*\
|
|
| Vendor layout table (from the version -> layout map). |
|
|
| The firmware reports its version to the 0xB0 query but |
|
|
| not a LED count, so count/direction/block-count come |
|
|
| from here. Fields: version, LED count, fill direction |
|
|
| (MSI_MONITOR_72_DIR_*), dual_block. |
|
|
| |
|
|
| Every entry here is a single linear run driven through |
|
|
| the 168 byte 0x72 buffer. Direction mirrors the fill so |
|
|
| OpenRGB LED 0 is the left/start on every model. Circle |
|
|
| and Ctype have no simple line mapping - they are driven |
|
|
| as a plain line here and should get a custom per model |
|
|
| layout once an owner maps the physical shape. |
|
|
| |
|
|
| Only version 34 is hardware verified (MPG 322URX). The |
|
|
| rest are derived from the vendor table: same buffer, LED |
|
|
| count and direction are the only differences, so effect |
|
|
| and single colour modes are correct by construction. |
|
|
| |
|
|
| Left out on purpose: |
|
|
| - dual_block versions 11/13/15 are stubbed but disabled |
|
|
| (see the commented block); their two control blocks |
|
|
| drive two runs and the per LED split is unconfirmed. |
|
|
| - Advanced/0x82 versions 31/47 need the 0x30 bulk report |
|
|
| this controller does not implement. |
|
|
| A version not matched here falls through to the legacy |
|
|
| 0x71 controller, home of the MAG272 class. |
|
|
\*---------------------------------------------------------*/
|
|
struct MSIMonitor72Layout
|
|
{
|
|
uint8_t version;
|
|
unsigned int leds;
|
|
unsigned int direction;
|
|
bool dual_block;
|
|
};
|
|
|
|
static const MSIMonitor72Layout msi_monitor_72_layouts[] =
|
|
{
|
|
{ 34, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG271QRXQD_OLED (MPG 322URX reports this) - verified */
|
|
{ 5, 12, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MAG272R */
|
|
{ 8, 24, MSI_MONITOR_72_DIR_CIRCLE, false }, /* MAG301CR - Circle, wants custom layout */
|
|
{ 10, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG273R */
|
|
{ 12, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG271VCR */
|
|
{ 14, 14, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* NXG253R */
|
|
{ 17, 8, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MAG2x5R */
|
|
{ 20, 12, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG301RF */
|
|
{ 21, 18, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG341QR */
|
|
{ 22, 24, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG321QRF */
|
|
{ 24, 12, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG321QR */
|
|
{ 25, 24, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG321UR */
|
|
{ 28, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG273CQR */
|
|
{ 29, 24, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MAG401QR */
|
|
{ 30, 21, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MAG325CQRF */
|
|
{ 32, 7, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG274QRF */
|
|
{ 33, 7, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG274URFQD */
|
|
{ 36, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG275CQRXF */
|
|
{ 37, 22, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG345CQRD */
|
|
{ 38, 20, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG325CQRFQDE2 */
|
|
{ 39, 8, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MPG321CURX_QD_OLED */
|
|
{ 40, 12, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MAG322URDFE16 */
|
|
{ 41, 14, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, false }, /* MPG242RX60N */
|
|
{ 42, 22, MSI_MONITOR_72_DIR_CTYPE, false }, /* MPG274URDFWE16 - Ctype, wants custom layout */
|
|
{ 43, 21, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG346CQRFX24 */
|
|
{ 44, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG271QRQD_OLEDX50 */
|
|
{ 46, 9, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, false }, /* MPG341CQRQD_OLEDX36 */
|
|
|
|
/*-----------------------------------------------------------------*\
|
|
| Dual block - stubbed but DISABLED. The dual_block path fills |
|
|
| both colour arrays so uniform colour modes are correct, but each |
|
|
| block drives its own run and the per LED split is unconfirmed, so |
|
|
| Direct is a guess. These versions also map colour index above 15 |
|
|
| to a separate DragonShield emblem region (unhandled). An owner |
|
|
| should enable, test, and ideally give it a custom layout: |
|
|
| { 11, 16, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, true }, MPG273CQR |
|
|
| { 13, 21, MSI_MONITOR_72_DIR_LEFT_TO_RIGHT, true }, MPG343CQR |
|
|
| { 15, 18, MSI_MONITOR_72_DIR_RIGHT_TO_LEFT, true }, MPG323CQR |
|
|
| |
|
|
| Advanced/0x82 - not addable here, need the 0x30 bulk report: |
|
|
| version 31, 40 LEDs, MEG342CQD_OLED |
|
|
| version 47, 83 LEDs, 4 areas, MEG_X |
|
|
\*-----------------------------------------------------------------*/
|
|
};
|
|
|
|
static const MSIMonitor72Layout* MSIMonitorLayout(uint8_t version)
|
|
{
|
|
for(unsigned int i = 0; i < (sizeof(msi_monitor_72_layouts) / sizeof(msi_monitor_72_layouts[0])); i++)
|
|
{
|
|
if(msi_monitor_72_layouts[i].version == version)
|
|
{
|
|
return(&msi_monitor_72_layouts[i]);
|
|
}
|
|
}
|
|
|
|
return(nullptr);
|
|
}
|
|
|
|
DetectedControllers DetectMSIMonitorController(hid_device_info* info, const std::string& name)
|
|
{
|
|
DetectedControllers detected_controllers;
|
|
hid_device* dev;
|
|
|
|
dev = hid_open_path(info->path);
|
|
|
|
if(dev)
|
|
{
|
|
/*-------------------------------------------------*\
|
|
| One VID/PID covers several buffer layouts, so ask |
|
|
| the MCU which one it speaks. A version in the |
|
|
| 0x72 table selects the 168 byte layout and its |
|
|
| LED count; anything else keeps the legacy 0x71 |
|
|
| path, which is what the older monitors answer to. |
|
|
\*-------------------------------------------------*/
|
|
MSIMonitorController* controller = new MSIMonitorController(dev, *info, name);
|
|
|
|
uint8_t version = controller->GetLayoutVersion();
|
|
const MSIMonitor72Layout* layout = MSIMonitorLayout(version);
|
|
|
|
if(layout != nullptr)
|
|
{
|
|
detected_controllers.push_back(new RGBController_MSIMonitor72(controller, layout->leds, layout->direction, layout->dual_block));
|
|
}
|
|
else
|
|
{
|
|
/*-------------------------------------------------*\
|
|
| 0x71 family (78 byte buffer), handled by the |
|
|
| legacy controller as a plain line. For an owner |
|
|
| who wants to bring one onto this controller: same |
|
|
| operative block 12, but the second colour array |
|
|
| is at index 50 (not 95) and store-flash at 77. |
|
|
| RightToLeft mirroring applies. version, LEDs, |
|
|
| direction: |
|
|
| 1, 9, RightToLeft (early/generic) |
|
|
| 2, 7, LeftToRight (malformed stub, skip) |
|
|
| 3, 9, RightToLeft (early/generic) |
|
|
| 4, 9, LeftToRight (early/generic) |
|
|
| 6, 9, UpToDown MAG270CR |
|
|
| 7, 7, LeftToRight MAG251RX |
|
|
\*-------------------------------------------------*/
|
|
detected_controllers.push_back(new RGBController_MSIMonitor(controller));
|
|
}
|
|
}
|
|
|
|
return(detected_controllers);
|
|
}
|
|
|
|
REGISTER_HID_DETECTOR_IPU("MSI Monitor (Gaming Controller)", DetectMSIMonitorController, MSI_USB_VID, MSI_USB_PID, 0, 0x01, 0);
|