Files
OpenRGB/Controllers/ThrustmasterSolController/RGBController_ThrustmasterSol.cpp

354 lines
11 KiB
C++

/*---------------------------------------------------------*\
| RGBController_ThrustmasterSol.cpp |
| |
| RGBController for Thrustmaster Sol series joysticks |
| |
| Ken Sanislo 02 Apr 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_ThrustmasterSol.h"
/**------------------------------------------------------------------*\
@name Thrustmaster Sol
@category Gamepad
@type USB
@save :white_check_mark:
@direct :white_check_mark:
@effects :x:
@detectors DetectThrustmasterSolControllers
@comment Thrustmaster Sol series joystick RGB LED control. Supports
Sol-R, Sol F16, and Sol F18 variants. Only Sol-R has been tested.
Uses vendor-specific USB interface 1 (not HID).
\*-------------------------------------------------------------------*/
#define NA 0xFFFFFFFF
static unsigned int logo_matrix_map[2][2] =
{
{ 0, 3 },
{ 1, 2 },
};
static unsigned int ring_matrix_map[3][5] =
{
{ NA, 7, 0, 1, NA },
{ 6, NA, NA, NA, 2 },
{ NA, 5, 4, 3, NA },
};
static unsigned int right_buttons_matrix_map[2][2] =
{
{ 0, 1 },
{ 2, 3 },
};
static unsigned int left_buttons_matrix_map[2][2] =
{
{ 0, 1 },
{ 2, 3 },
};
RGBController_ThrustmasterSol::RGBController_ThrustmasterSol(ThrustmasterSolController* controller_ptr)
{
controller = controller_ptr;
vendor = "Thrustmaster";
type = DEVICE_TYPE_GAMEPAD;
description = "Thrustmaster Sol Series Joystick";
location = controller->GetDeviceLocation();
serial = controller->GetSerialString();
mode Direct;
Direct.name = "Direct";
Direct.value = 0;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
/*---------------------------------------------------------*\
| Read current EEPROM colors from device so the UI starts |
| with the actual hardware state rather than all-black |
\*---------------------------------------------------------*/
std::vector<unsigned int> hw_zones;
std::vector<RGBColor> hw_colors;
controller->ReadColors(hw_zones, hw_colors);
for(unsigned int i = 0; i < hw_zones.size(); i++)
{
for(unsigned int j = 0; j < leds.size(); j++)
{
if(leds[j].value == hw_zones[i])
{
colors[j] = hw_colors[i];
break;
}
}
}
}
RGBController_ThrustmasterSol::~RGBController_ThrustmasterSol()
{
delete controller;
}
void RGBController_ThrustmasterSol::SetupZones()
{
/*---------------------------------------------------------*\
| Thumbstick zone (grip, 1 LED) |
\*---------------------------------------------------------*/
zone thumbstick_zone;
thumbstick_zone.name = "Thumbstick";
thumbstick_zone.type = ZONE_TYPE_SINGLE;
thumbstick_zone.leds_min = 1;
thumbstick_zone.leds_max = 1;
thumbstick_zone.leds_count = 1;
thumbstick_zone.matrix_map = NULL;
zones.push_back(thumbstick_zone);
led thumbstick_led;
thumbstick_led.name = "Thumbstick";
thumbstick_led.value = THRUSTMASTER_SOL_GRIP_FLAG | 0x00;
leds.push_back(thumbstick_led);
/*---------------------------------------------------------*\
| TM Logo zone (3 LEDs) |
\*---------------------------------------------------------*/
zone logo_zone;
logo_zone.name = "TM Logo";
logo_zone.type = ZONE_TYPE_MATRIX;
logo_zone.leds_min = 4;
logo_zone.leds_max = 4;
logo_zone.leds_count = 4;
logo_zone.matrix_map = new matrix_map_type;
logo_zone.matrix_map->height = 2;
logo_zone.matrix_map->width = 2;
logo_zone.matrix_map->map = (unsigned int *)&logo_matrix_map;
zones.push_back(logo_zone);
led logo_top_left;
logo_top_left.name = "TM Logo Top Left";
logo_top_left.value = 0x01;
leds.push_back(logo_top_left);
led logo_bottom_left;
logo_bottom_left.name = "TM Logo Bottom Left";
logo_bottom_left.value = 0x02;
leds.push_back(logo_bottom_left);
led logo_bottom_right;
logo_bottom_right.name = "TM Logo Bottom Right";
logo_bottom_right.value = 0x03;
leds.push_back(logo_bottom_right);
led logo_top_right;
logo_top_right.name = "TM Logo Top Right";
logo_top_right.value = 0x00;
leds.push_back(logo_top_right);
/*---------------------------------------------------------*\
| Left Buttons zone (4 LEDs: buttons 5-8) |
\*---------------------------------------------------------*/
zone left_buttons_zone;
left_buttons_zone.name = "Left Buttons";
left_buttons_zone.type = ZONE_TYPE_MATRIX;
left_buttons_zone.leds_min = 4;
left_buttons_zone.leds_max = 4;
left_buttons_zone.leds_count = 4;
left_buttons_zone.matrix_map = new matrix_map_type;
left_buttons_zone.matrix_map->height = 2;
left_buttons_zone.matrix_map->width = 2;
left_buttons_zone.matrix_map->map = (unsigned int *)&left_buttons_matrix_map;
zones.push_back(left_buttons_zone);
led btn5;
btn5.name = "Button 5";
btn5.value = 0x11;
leds.push_back(btn5);
led btn6;
btn6.name = "Button 6";
btn6.value = 0x10;
leds.push_back(btn6);
led btn7;
btn7.name = "Button 7";
btn7.value = 0x12;
leds.push_back(btn7);
led btn8;
btn8.name = "Button 8";
btn8.value = 0x13;
leds.push_back(btn8);
/*---------------------------------------------------------*\
| Base Ring zone (8 LEDs, clockwise from top) |
\*---------------------------------------------------------*/
zone ring_zone;
ring_zone.name = "Base Ring";
ring_zone.type = ZONE_TYPE_MATRIX;
ring_zone.leds_min = 8;
ring_zone.leds_max = 8;
ring_zone.leds_count = 8;
ring_zone.matrix_map = new matrix_map_type;
ring_zone.matrix_map->height = 3;
ring_zone.matrix_map->width = 5;
ring_zone.matrix_map->map = (unsigned int *)&ring_matrix_map;
zones.push_back(ring_zone);
led ring_upper;
ring_upper.name = "Upper";
ring_upper.value = 0x04;
leds.push_back(ring_upper);
led ring_upper_right;
ring_upper_right.name = "Upper Right";
ring_upper_right.value = 0x05;
leds.push_back(ring_upper_right);
led ring_right;
ring_right.name = "Right";
ring_right.value = 0x06;
leds.push_back(ring_right);
led ring_bottom_right;
ring_bottom_right.name = "Bottom Right";
ring_bottom_right.value = 0x0B;
leds.push_back(ring_bottom_right);
led ring_bottom;
ring_bottom.name = "Bottom";
ring_bottom.value = 0x0C;
leds.push_back(ring_bottom);
led ring_bottom_left;
ring_bottom_left.name = "Bottom Left";
ring_bottom_left.value = 0x0D;
leds.push_back(ring_bottom_left);
led ring_left;
ring_left.name = "Left";
ring_left.value = 0x0E;
leds.push_back(ring_left);
led ring_upper_left;
ring_upper_left.name = "Upper Left";
ring_upper_left.value = 0x0F;
leds.push_back(ring_upper_left);
/*---------------------------------------------------------*\
| Right Buttons zone (4 LEDs: buttons 16-19) |
\*---------------------------------------------------------*/
zone right_buttons_zone;
right_buttons_zone.name = "Right Buttons";
right_buttons_zone.type = ZONE_TYPE_MATRIX;
right_buttons_zone.leds_min = 4;
right_buttons_zone.leds_max = 4;
right_buttons_zone.leds_count = 4;
right_buttons_zone.matrix_map = new matrix_map_type;
right_buttons_zone.matrix_map->height = 2;
right_buttons_zone.matrix_map->width = 2;
right_buttons_zone.matrix_map->map = (unsigned int *)&right_buttons_matrix_map;
zones.push_back(right_buttons_zone);
led btn17;
btn17.name = "Button 17";
btn17.value = 0x07;
leds.push_back(btn17);
led btn16;
btn16.name = "Button 16";
btn16.value = 0x08;
leds.push_back(btn16);
led btn19;
btn19.name = "Button 19";
btn19.value = 0x0A;
leds.push_back(btn19);
led btn18;
btn18.name = "Button 18";
btn18.value = 0x09;
leds.push_back(btn18);
SetupColors();
}
void RGBController_ThrustmasterSol::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_ThrustmasterSol::DeviceUpdateLEDs()
{
unsigned int led_zones[THRUSTMASTER_SOL_R_ZONE_COUNT];
RGBColor led_colors[THRUSTMASTER_SOL_R_ZONE_COUNT];
for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++)
{
led_zones[led_idx] = leds[led_idx].value;
led_colors[led_idx] = colors[led_idx];
}
controller->SetLEDColors(led_zones, led_colors, static_cast<unsigned int>(leds.size()));
}
void RGBController_ThrustmasterSol::UpdateZoneLEDs(int zone)
{
unsigned int start_idx = 0;
unsigned int zone_size = 0;
for(unsigned int z_idx = 0; z_idx < zones.size(); z_idx++)
{
if(z_idx == (unsigned int)zone)
{
zone_size = zones[z_idx].leds_count;
break;
}
start_idx += zones[z_idx].leds_count;
}
unsigned int led_zones[THRUSTMASTER_SOL_R_ZONE_COUNT];
RGBColor led_colors[THRUSTMASTER_SOL_R_ZONE_COUNT];
for(unsigned int led_idx = 0; led_idx < zone_size; led_idx++)
{
unsigned int current_idx = start_idx + led_idx;
led_zones[led_idx] = leds[current_idx].value;
led_colors[led_idx] = colors[current_idx];
}
controller->SetLEDColors(led_zones, led_colors, zone_size);
}
void RGBController_ThrustmasterSol::UpdateSingleLED(int led)
{
controller->SetLEDColor(leds[led].value, colors[led]);
}
void RGBController_ThrustmasterSol::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
void RGBController_ThrustmasterSol::DeviceSaveMode()
{
unsigned int led_zones[THRUSTMASTER_SOL_R_ZONE_COUNT];
RGBColor led_colors[THRUSTMASTER_SOL_R_ZONE_COUNT];
for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++)
{
led_zones[led_idx] = leds[led_idx].value;
led_colors[led_idx] = colors[led_idx];
}
controller->SaveColors(led_zones, led_colors, static_cast<unsigned int>(leds.size()));
}