diff --git a/Controllers/RoccatController/RGBController_RoccatSenseAimo.cpp b/Controllers/RoccatController/RGBController_RoccatSenseAimo.cpp new file mode 100644 index 00000000..7c82ea14 --- /dev/null +++ b/Controllers/RoccatController/RGBController_RoccatSenseAimo.cpp @@ -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); +} diff --git a/Controllers/RoccatController/RGBController_RoccatSenseAimo.h b/Controllers/RoccatController/RGBController_RoccatSenseAimo.h new file mode 100644 index 00000000..a6a2247f --- /dev/null +++ b/Controllers/RoccatController/RGBController_RoccatSenseAimo.h @@ -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; +}; diff --git a/Controllers/RoccatController/RoccatControllerDetect.cpp b/Controllers/RoccatController/RoccatControllerDetect.cpp index 1667388b..c9ec433c 100644 --- a/Controllers/RoccatController/RoccatControllerDetect.cpp +++ b/Controllers/RoccatController/RoccatControllerDetect.cpp @@ -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 ); diff --git a/Controllers/RoccatController/RoccatSenseAimoController.cpp b/Controllers/RoccatController/RoccatSenseAimoController.cpp new file mode 100644 index 00000000..25070171 --- /dev/null +++ b/Controllers/RoccatController/RoccatSenseAimoController.cpp @@ -0,0 +1,148 @@ +/*-------------------------------------------------------------------*\ +| RoccatSenseAimoController.cpp | +| | +| Driver for Roccat Sense Aimo | +| | +| Mola19 08/09/2023 | +\*-------------------------------------------------------------------*/ + +#include "RoccatSenseAimoController.h" + +#include + +#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 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 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)); + } +} diff --git a/Controllers/RoccatController/RoccatSenseAimoController.h b/Controllers/RoccatController/RoccatSenseAimoController.h new file mode 100644 index 00000000..8a63a853 --- /dev/null +++ b/Controllers/RoccatController/RoccatSenseAimoController.h @@ -0,0 +1,62 @@ +/*-------------------------------------------------------------------*\ +| RoccatSenseAimoController.cpp | +| | +| Driver for Roccat Sense Aimo | +| | +| Mola19 08/09/2023 | +\*-------------------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include + +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 colors); + void SetMode(uint8_t profile, uint8_t mode, uint8_t speed, uint8_t brightness, std::vector colors); + +private: + hid_device* dev; + std::string location; +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index f870345d..847f07df 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -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 \