support for Roccat Sense Aimo Mousepad (Mid and XXL) to resolve #2770

This commit is contained in:
Mola19 2023-08-10 02:42:58 +02:00
parent 9df7023b73
commit 0969b5d24e
No known key found for this signature in database
GPG key ID: 6446B87E73001409
6 changed files with 458 additions and 0 deletions

View file

@ -0,0 +1,194 @@
/*-----------------------------------------*\
| RGBController_RoccatSenseAimo.cpp |
| |
| Generic RGB Interface for OpenRGB |
| |
| Mola19 08/09/2023 |
\*-----------------------------------------*/
#include "RGBController_RoccatSenseAimo.h"
/**------------------------------------------------------------------*\
@name Roccat Sense Aimo Mousepad
@category Mousemat
@type USB
@save :robot:
@direct :white_check_mark:
@effects :white_check_mark:
@detectors DetectRoccatSenseAimoControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_RoccatSenseAimo::RGBController_RoccatSenseAimo(RoccatSenseAimoController* controller_ptr)
{
controller = controller_ptr;
name = "Roccat Sense Aimo";
vendor = "Roccat";
type = DEVICE_TYPE_MOUSEMAT;
description = "Roccat Sense Aimo Mousepad";
version = controller->GetVersion();
location = controller->GetLocation();
serial = controller->GetSerial();
mode Direct;
Direct.name = "Direct";
Direct.value = ROCCAT_SENSE_AIMO_MODE_DIRECT;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
mode Static;
Static.name = "Static";
Static.value = ROCCAT_SENSE_AIMO_MODE_STATIC;
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS;
Static.color_mode = MODE_COLORS_PER_LED;
Static.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT;
Static.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN;
Static.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX;
modes.push_back(Static);
mode Rainbow;
Rainbow.name = "Rainbow";
Rainbow.value = ROCCAT_SENSE_AIMO_MODE_WAVE;
Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Rainbow.color_mode = MODE_COLORS_NONE;
Rainbow.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT;
Rainbow.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN;
Rainbow.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX;
Rainbow.speed = ROCCAT_SENSE_AIMO_SPEED_DEFAULT;
Rainbow.speed_min = ROCCAT_SENSE_AIMO_SPEED_MIN;
Rainbow.speed_max = ROCCAT_SENSE_AIMO_SPEED_MAX;
modes.push_back(Rainbow);
mode Breathing;
Breathing.name = "Breathing";
Breathing.value = ROCCAT_SENSE_AIMO_MODE_BREATHING;
Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Breathing.color_mode = MODE_COLORS_PER_LED;
Breathing.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT;
Breathing.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN;
Breathing.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX;
Breathing.speed = ROCCAT_SENSE_AIMO_SPEED_DEFAULT;
Breathing.speed_min = ROCCAT_SENSE_AIMO_SPEED_MIN;
Breathing.speed_max = ROCCAT_SENSE_AIMO_SPEED_MAX;
modes.push_back(Breathing);
mode Heartbeat;
Heartbeat.name = "Heartbeat";
Heartbeat.value = ROCCAT_SENSE_AIMO_MODE_HEARTBEAT;
Heartbeat.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
Heartbeat.color_mode = MODE_COLORS_PER_LED;
Heartbeat.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT;
Heartbeat.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN;
Heartbeat.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX;
Heartbeat.speed = ROCCAT_SENSE_AIMO_SPEED_DEFAULT;
Heartbeat.speed_min = ROCCAT_SENSE_AIMO_SPEED_MIN;
Heartbeat.speed_max = ROCCAT_SENSE_AIMO_SPEED_MAX;
modes.push_back(Heartbeat);
/*---------------------------------------------------------------------*\
| This is the default mode for software modes, while swarm isn't active |
\*---------------------------------------------------------------------*/
mode Default;
Default.name = "Default";
Default.value = ROCCAT_SENSE_AIMO_MODE_DEFAULT;
Default.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS;
Default.color_mode = MODE_COLORS_NONE;
Default.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT;
Default.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN;
Default.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX;
modes.push_back(Default);
SetupZones();
mode_struct active = controller->GetMode();
for(uint32_t i = 0; i < modes.size(); i++)
{
if(modes[i].value == active.mode)
{
active_mode = i;
break;
}
/*----------------------------------------------*\
| If no mode was found, select 0th mode (direct) |
\*----------------------------------------------*/
if(i == modes.size() - 1)
{
active_mode = 0;
}
}
modes[active_mode].speed = active.speed;
modes[active_mode].brightness = active.brightness;
colors[0] = active.left;
colors[1] = active.right;
}
RGBController_RoccatSenseAimo::~RGBController_RoccatSenseAimo()
{
delete controller;
}
void RGBController_RoccatSenseAimo::SetupZones()
{
zone pad;
pad.name = "Mousepad";
pad.type = ZONE_TYPE_LINEAR;
pad.leds_min = 2;
pad.leds_max = 2;
pad.leds_count = 2;
pad.matrix_map = NULL;
zones.push_back(pad);
led left_led;
left_led.name = "Mousepad left led";
leds.push_back(left_led);
led right_led;
right_led.name = "Mousepad right led";
leds.push_back(right_led);
SetupColors();
}
void RGBController_RoccatSenseAimo::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_RoccatSenseAimo::DeviceUpdateLEDs()
{
if(modes[active_mode].value == ROCCAT_SENSE_AIMO_MODE_DIRECT)
{
controller->SendDirect(colors);
}
else
{
DeviceUpdateMode();
}
}
void RGBController_RoccatSenseAimo::UpdateZoneLEDs(int /*zone_idx*/)
{
DeviceUpdateLEDs();
}
void RGBController_RoccatSenseAimo::UpdateSingleLED(int /*led_idx*/)
{
DeviceUpdateLEDs();
}
void RGBController_RoccatSenseAimo::DeviceUpdateMode()
{
mode selected = modes[active_mode];
mode_struct active = controller->GetMode();
controller->SetMode(active.profile, selected.value, selected.speed, selected.brightness, colors);
}

View file

@ -0,0 +1,31 @@
/*-----------------------------------------*\
| RGBController_RoccatSenseAimo.h |
| |
| Generic RGB Interface for Roccat Sense |
| Aimo controller |
| |
| Mola19 08/09/2023 |
\*-----------------------------------------*/
#pragma once
#include "RGBController.h"
#include "RoccatSenseAimoController.h"
class RGBController_RoccatSenseAimo : public RGBController
{
public:
RGBController_RoccatSenseAimo(RoccatSenseAimoController* controller_ptr);
~RGBController_RoccatSenseAimo();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
RoccatSenseAimoController* controller;
};

View file

@ -9,6 +9,7 @@
#include "Detector.h"
#include "RoccatBurstController.h"
#include "RoccatKoneAimoController.h"
#include "RoccatSenseAimoController.h"
#include "RoccatVulcanAimoController.h"
#include "RoccatKovaController.h"
#include "RoccatEloController.h"
@ -16,6 +17,7 @@
#include "RGBController_RoccatBurst.h"
#include "RGBController_RoccatHordeAimo.h"
#include "RGBController_RoccatKoneAimo.h"
#include "RGBController_RoccatSenseAimo.h"
#include "RGBController_RoccatVulcanAimo.h"
#include "RGBController_RoccatKova.h"
#include "RGBController_RoccatElo.h"
@ -32,6 +34,8 @@
#define ROCCAT_BURST_PRO_PID 0x2DE1
#define ROCCAT_KOVA_PID 0x2CEE
#define ROCCAT_ELO_PID 0x3A34
#define ROCCAT_SENSE_AIMO_MID_PID 0x343A
#define ROCCAT_SENSE_AIMO_XXL_PID 0x343B
void DetectRoccatMouseControllers(hid_device_info* info, const std::string& name)
{
@ -189,6 +193,19 @@ void DetectRoccatEloControllers(hid_device_info* info, const std::string& name)
}
}
void DetectRoccatSenseAimoControllers(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);
if(dev)
{
RoccatSenseAimoController * controller = new RoccatSenseAimoController(dev, info->path);
RGBController_RoccatSenseAimo * rgb_controller = new RGBController_RoccatSenseAimo(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_PRE_DETECTION_HOOK(ResetRoccatVulcanAimoControllersPaths);
REGISTER_HID_DETECTOR_IPU("Roccat Kone Aimo", DetectRoccatMouseControllers, ROCCAT_VID, ROCCAT_KONE_AIMO_PID, 0, 0x0B, 0 );
@ -199,3 +216,5 @@ REGISTER_HID_DETECTOR_IPU("Roccat Burst Core", DetectRoccatBurstCor
REGISTER_HID_DETECTOR_IPU("Roccat Burst Pro", DetectRoccatBurstProControllers, ROCCAT_VID, ROCCAT_BURST_PRO_PID, 3, 0xFF01, 1 );
REGISTER_HID_DETECTOR_IPU("Roccat Kova", DetectRoccatKovaControllers, ROCCAT_VID, ROCCAT_KOVA_PID, 0, 0x0B, 0 );
REGISTER_HID_DETECTOR_IPU("Roccat Elo 7.1", DetectRoccatEloControllers, ROCCAT_VID, ROCCAT_ELO_PID, 3, 0x0C, 1 );
REGISTER_HID_DETECTOR_IPU("Roccat Sense Aimo Mid", DetectRoccatSenseAimoControllers, ROCCAT_VID, ROCCAT_SENSE_AIMO_MID_PID, 0, 0xFF01, 1 );
REGISTER_HID_DETECTOR_IPU("Roccat Sense Aimo XXL", DetectRoccatSenseAimoControllers, ROCCAT_VID, ROCCAT_SENSE_AIMO_XXL_PID, 0, 0xFF01, 1 );

View file

@ -0,0 +1,148 @@
/*-------------------------------------------------------------------*\
| RoccatSenseAimoController.cpp |
| |
| Driver for Roccat Sense Aimo |
| |
| Mola19 08/09/2023 |
\*-------------------------------------------------------------------*/
#include "RoccatSenseAimoController.h"
#include <cstring>
#include "LogManager.h"
RoccatSenseAimoController::RoccatSenseAimoController(hid_device* dev_handle, char *path)
{
dev = dev_handle;
location = path;
}
RoccatSenseAimoController::~RoccatSenseAimoController()
{
hid_close(dev);
}
std::string RoccatSenseAimoController::GetVersion()
{
uint8_t buf[8] = { 0x01 };
int return_length = hid_get_feature_report(dev, buf, 5);
if(return_length == -1)
{
LOG_DEBUG("[Roccat Sense Aimo]: Could not fetch mode. HIDAPI Error: %ls", hid_error(dev));
return std::string("Unknown");
}
char version[6];
snprintf(version, 6, "%2X.%02X", buf[1], buf[2]);
return std::string(version);
}
std::string RoccatSenseAimoController::GetSerial()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
std::wstring return_wstring = serial_string;
std::string return_string(return_wstring.begin(), return_wstring.end());
return(return_string);
}
std::string RoccatSenseAimoController::GetLocation()
{
return("HID: " + location);
}
mode_struct RoccatSenseAimoController::GetMode()
{
uint8_t buf[19] = { 0x02 };
int return_length = hid_get_feature_report(dev, buf, 19);
if(return_length == -1)
{
LOG_DEBUG("[Roccat Sense Aimo]: Could not fetch mode. HIDAPI Error: %ls", hid_error(dev));
mode_struct default_mode;
default_mode.profile = 0;
default_mode.mode = ROCCAT_SENSE_AIMO_MODE_STATIC;
default_mode.speed = 0;
default_mode.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT;
default_mode.left = ToRGBColor(0, 0, 0);
default_mode.right = ToRGBColor(0, 0, 0);
return default_mode;
}
mode_struct active_mode;
active_mode.profile = buf[1];
active_mode.mode = buf[2];
active_mode.speed = buf[3];
active_mode.brightness = buf[4];
active_mode.left = ToRGBColor(buf[6], buf[7], buf[8]);
active_mode.right = ToRGBColor(buf[14], buf[15], buf[16]);
return active_mode;
}
void RoccatSenseAimoController::SetMode(uint8_t profile, uint8_t mode, uint8_t speed, uint8_t brightness, std::vector<RGBColor> colors)
{
uint8_t buf[19];
memset(buf, 0x00, 19);
buf[0x00] = 0x02;
buf[0x01] = profile;
for(uint8_t i = 0; i < 2; i++)
{
buf[0x02 + i * 8] = mode; // this device has per led modes
buf[0x03 + i * 8] = speed;
buf[0x04 + i * 8] = brightness;
buf[0x05 + i * 8] = 0x00;
buf[0x06 + i * 8] = RGBGetRValue(colors[i]);
buf[0x07 + i * 8] = RGBGetGValue(colors[i]);
buf[0x08 + i * 8] = RGBGetBValue(colors[i]);
buf[0x09 + i * 8] = 0xFF; // this device uses RGBA, but OpenRGB doesn't allow it, so it is always max
}
buf[0x12] = 0x00; // this stores the swarm theme and first bit is a flag if custom is active in swarm. No usage outside Swarm
int return_length = hid_send_feature_report(dev, buf, 19);
if(return_length == -1)
{
LOG_DEBUG("[Roccat Sense Aimo]: Could not send mode. HIDAPI Error: %ls", hid_error(dev));
}
}
void RoccatSenseAimoController::SendDirect(std::vector<RGBColor> colors)
{
uint8_t buf[9];
memset(buf, 0x00, 9);
buf[0x00] = 0x03;
for(uint8_t i = 0; i < 2; i++)
{
buf[0x01 + i * 4] = RGBGetRValue(colors[i]);
buf[0x02 + i * 4] = RGBGetGValue(colors[i]);
buf[0x03 + i * 4] = RGBGetBValue(colors[i]);
buf[0x04 + i * 4] = 0xFF; // this device uses RGBA, but OpenRGB doesn't allow it, so it is always max
}
int return_length = hid_send_feature_report(dev, buf, 9);
if(return_length == -1)
{
LOG_DEBUG("[Roccat Sense Aimo]: Could not send direct. HIDAPI Error: %ls", hid_error(dev));
}
}

View file

@ -0,0 +1,62 @@
/*-------------------------------------------------------------------*\
| RoccatSenseAimoController.cpp |
| |
| Driver for Roccat Sense Aimo |
| |
| Mola19 08/09/2023 |
\*-------------------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include <hidapi/hidapi.h>
enum
{
ROCCAT_SENSE_AIMO_MODE_DIRECT = 0x0B,
ROCCAT_SENSE_AIMO_MODE_STATIC = 0x01,
ROCCAT_SENSE_AIMO_MODE_BREATHING = 0x03,
ROCCAT_SENSE_AIMO_MODE_HEARTBEAT = 0x04,
ROCCAT_SENSE_AIMO_MODE_DEFAULT = 0x09,
ROCCAT_SENSE_AIMO_MODE_WAVE = 0x0A
};
enum
{
ROCCAT_SENSE_AIMO_SPEED_MIN = 0xFF,
ROCCAT_SENSE_AIMO_SPEED_MAX = 0x00,
ROCCAT_SENSE_AIMO_SPEED_DEFAULT = 0x07,
ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN = 0x00,
ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX = 0xFF,
ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT = 0xFF
};
struct mode_struct
{
uint8_t profile;
uint8_t mode;
uint8_t speed;
uint8_t brightness;
RGBColor left;
RGBColor right;
};
class RoccatSenseAimoController
{
public:
RoccatSenseAimoController(hid_device* dev_handle, char *path);
~RoccatSenseAimoController();
std::string GetSerial();
std::string GetLocation();
std::string GetVersion();
mode_struct GetMode();
void SendDirect(std::vector<RGBColor> colors);
void SetMode(uint8_t profile, uint8_t mode, uint8_t speed, uint8_t brightness, std::vector<RGBColor> colors);
private:
hid_device* dev;
std::string location;
};

View file

@ -683,12 +683,14 @@ HEADERS +=
Controllers/RoccatController/RGBController_RoccatHordeAimo.h \
Controllers/RoccatController/RGBController_RoccatKoneAimo.h \
Controllers/RoccatController/RGBController_RoccatKova.h \
Controllers/RoccatController/RGBController_RoccatSenseAimo.h \
Controllers/RoccatController/RGBController_RoccatVulcanAimo.h \
Controllers/RoccatController/RoccatBurstController.h \
Controllers/RoccatController/RoccatEloController.h \
Controllers/RoccatController/RoccatHordeAimoController.h \
Controllers/RoccatController/RoccatKoneAimoController.h \
Controllers/RoccatController/RoccatKovaController.h \
Controllers/RoccatController/RoccatSenseAimoController.h \
Controllers/RoccatController/RoccatVulcanAimoController.h \
Controllers/RoccatController/RoccatVulcanAimoLayouts.h \
Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.h \
@ -1377,12 +1379,14 @@ SOURCES +=
Controllers/RoccatController/RGBController_RoccatHordeAimo.cpp \
Controllers/RoccatController/RGBController_RoccatKoneAimo.cpp \
Controllers/RoccatController/RGBController_RoccatKova.cpp \
Controllers/RoccatController/RGBController_RoccatSenseAimo.cpp \
Controllers/RoccatController/RGBController_RoccatVulcanAimo.cpp \
Controllers/RoccatController/RoccatBurstController.cpp \
Controllers/RoccatController/RoccatEloController.cpp \
Controllers/RoccatController/RoccatHordeAimoController.cpp \
Controllers/RoccatController/RoccatKoneAimoController.cpp \
Controllers/RoccatController/RoccatKovaController.cpp \
Controllers/RoccatController/RoccatSenseAimoController.cpp \
Controllers/RoccatController/RoccatVulcanAimoController.cpp \
Controllers/RoccatController/RoccatControllerDetect.cpp \
Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.cpp \