mirror of
https://github.com/CalcProgrammer1/OpenRGB.git
synced 2026-05-10 23:53:08 -04:00
Add support for Thrustmaster Sol series joystick RGB LEDs
This commit is contained in:
@@ -0,0 +1,353 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| 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()));
|
||||
}
|
||||
Reference in New Issue
Block a user