Publish LumaOps source
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatBurst.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Burst |
|
||||
| |
|
||||
| Morgan Guimard (morg) 01 Jun 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RoccatBurst.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Burst Mouse
|
||||
@category Mouse
|
||||
@type USB
|
||||
@save :robot:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectRoccatBurstCoreControllers,DetectRoccatBurstProControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatBurst::RGBController_RoccatBurst(RoccatBurstController* controller_ptr, unsigned int leds_count):
|
||||
leds_count(leds_count)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_MOUSE;
|
||||
description = "Roccat Burst Mouse Device";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = ROCCAT_BURST_DIRECT_MODE_VALUE;
|
||||
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_BURST_STATIC_MODE_VALUE;
|
||||
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Static.brightness = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
Static.brightness_min = ROCCAT_BURST_BRIGHTNESS_MIN;
|
||||
Static.brightness_max = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
Static.colors.resize(leds_count);
|
||||
modes.push_back(Static);
|
||||
|
||||
mode Rainbow;
|
||||
Rainbow.name = "Rainbow";
|
||||
Rainbow.value = ROCCAT_BURST_WAVE_MODE_VALUE;
|
||||
Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Rainbow.color_mode = MODE_COLORS_NONE;
|
||||
Rainbow.brightness = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
Rainbow.brightness_min = ROCCAT_BURST_BRIGHTNESS_MIN;
|
||||
Rainbow.brightness_max = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
Rainbow.speed = ROCCAT_BURST_SPEED_MIN;
|
||||
Rainbow.speed_min = ROCCAT_BURST_SPEED_MIN;
|
||||
Rainbow.speed_max = ROCCAT_BURST_SPEED_MAX;
|
||||
modes.push_back(Rainbow);
|
||||
|
||||
mode HeartBeat;
|
||||
HeartBeat.name = "HeartBeat";
|
||||
HeartBeat.value = ROCCAT_BURST_HEARTBEAT_MODE_VALUE;
|
||||
HeartBeat.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
HeartBeat.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
HeartBeat.brightness = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
HeartBeat.brightness_min = ROCCAT_BURST_BRIGHTNESS_MIN;
|
||||
HeartBeat.brightness_max = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
HeartBeat.speed = ROCCAT_BURST_SPEED_MIN;
|
||||
HeartBeat.speed_min = ROCCAT_BURST_SPEED_MIN;
|
||||
HeartBeat.speed_max = ROCCAT_BURST_SPEED_MAX;
|
||||
HeartBeat.colors.resize(leds_count);
|
||||
modes.push_back(HeartBeat);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = ROCCAT_BURST_BREATHING_MODE_VALUE;
|
||||
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Breathing.brightness = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
Breathing.brightness_min = ROCCAT_BURST_BRIGHTNESS_MIN;
|
||||
Breathing.brightness_max = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
Breathing.speed = ROCCAT_BURST_SPEED_MIN;
|
||||
Breathing.speed_min = ROCCAT_BURST_SPEED_MIN;
|
||||
Breathing.speed_max = ROCCAT_BURST_SPEED_MAX;
|
||||
Breathing.colors.resize(leds_count);
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Blinking;
|
||||
Blinking.name = "Blinking";
|
||||
Blinking.value = ROCCAT_BURST_BLINKING_MODE_VALUE;
|
||||
Blinking.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Blinking.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Blinking.brightness = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
Blinking.brightness_min = ROCCAT_BURST_BRIGHTNESS_MIN;
|
||||
Blinking.brightness_max = ROCCAT_BURST_BRIGHTNESS_MAX;
|
||||
Blinking.speed = ROCCAT_BURST_SPEED_MIN;
|
||||
Blinking.speed_min = ROCCAT_BURST_SPEED_MIN;
|
||||
Blinking.speed_max = ROCCAT_BURST_SPEED_MAX;
|
||||
Blinking.colors.resize(leds_count);
|
||||
modes.push_back(Blinking);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatBurst::~RGBController_RoccatBurst()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurst::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
new_zone.name = "Mouse";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = leds_count;
|
||||
new_zone.leds_max = leds_count;
|
||||
new_zone.leds_count = leds_count;
|
||||
new_zone.matrix_map = NULL;
|
||||
zones.push_back(new_zone);
|
||||
|
||||
std::string led_names[2] =
|
||||
{
|
||||
"Scroll Wheel",
|
||||
"Logo"
|
||||
};
|
||||
|
||||
for(unsigned int i = 0; i < leds_count; i++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = led_names[i];
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurst::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurst::DeviceUpdateLEDs()
|
||||
{
|
||||
UpdateZoneLEDs(0);
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurst::UpdateZoneLEDs(int /*zone_idx*/)
|
||||
{
|
||||
const mode& active = modes[active_mode];
|
||||
|
||||
if(active.value == ROCCAT_BURST_DIRECT_MODE_VALUE)
|
||||
{
|
||||
controller->SendDirect(colors);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller->SetMode(active.colors, active.value, active.speed, active.brightness, active.color_mode, active.flags);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurst::UpdateSingleLED(int /*led_idx*/)
|
||||
{
|
||||
UpdateZoneLEDs(0);
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurst::DeviceUpdateMode()
|
||||
{
|
||||
if(modes[active_mode].value == ROCCAT_BURST_DIRECT_MODE_VALUE)
|
||||
{
|
||||
controller->SetupDirectMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatBurst.h |
|
||||
| |
|
||||
| RGBController for Roccat Burst |
|
||||
| |
|
||||
| Morgan Guimard (morg) 01 Jun 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatBurstController.h"
|
||||
|
||||
class RGBController_RoccatBurst : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatBurst(RoccatBurstController* controller_ptr, unsigned int leds_count);
|
||||
~RGBController_RoccatBurst();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatBurstController* controller;
|
||||
unsigned int leds_count;
|
||||
};
|
||||
@@ -0,0 +1,166 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatBurstController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Burst |
|
||||
| |
|
||||
| Morgan Guimard (morg) 24 Feb 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "RoccatBurstController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatBurstController::RoccatBurstController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
|
||||
SetupDirectMode();
|
||||
}
|
||||
|
||||
RoccatBurstController::~RoccatBurstController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatBurstController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatBurstController::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatBurstController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
void RoccatBurstController::SetupDirectMode()
|
||||
{
|
||||
SwitchControl(true);
|
||||
}
|
||||
|
||||
void RoccatBurstController::SwitchControl(bool direct)
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_BURST_CONTROL_MODE_PACKET_LENGTH];
|
||||
|
||||
usb_buf[0x00] = 0x0E;
|
||||
usb_buf[0x01] = 0x06;
|
||||
usb_buf[0x02] = 0x01;
|
||||
usb_buf[0x03] = direct ? 0x01 : 0x00;
|
||||
usb_buf[0x04] = 0x00;
|
||||
usb_buf[0x05] = 0xFF;
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, ROCCAT_BURST_CONTROL_MODE_PACKET_LENGTH);
|
||||
}
|
||||
|
||||
void RoccatBurstController::SendDirect(std::vector<RGBColor> colors)
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_BURST_DIRECT_MODE_PACKET_LENGTH];
|
||||
|
||||
memset(usb_buf, 0x00, ROCCAT_BURST_DIRECT_MODE_PACKET_LENGTH);
|
||||
|
||||
usb_buf[0x00] = ROCCAT_BURST_DIRECT_MODE_REPORT_ID;
|
||||
usb_buf[0x01] = ROCCAT_BURST_DIRECT_MODE_BYTE;
|
||||
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
usb_buf[0x02 + 3 * i] = RGBGetRValue(colors[i]);
|
||||
usb_buf[0x03 + 3 * i] = RGBGetGValue(colors[i]);
|
||||
usb_buf[0x04 + 3 * i] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, ROCCAT_BURST_DIRECT_MODE_PACKET_LENGTH);
|
||||
}
|
||||
|
||||
void RoccatBurstController::SetMode(std::vector<RGBColor> colors, unsigned char mode_value, unsigned char speed, unsigned char brightness, unsigned int color_mode, unsigned int mode_flags)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| 1. Read from flash |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char usb_buf[ROCCAT_BURST_FLASH_PACKET_LENGTH];
|
||||
memset(usb_buf, 0x00, ROCCAT_BURST_FLASH_PACKET_LENGTH);
|
||||
|
||||
usb_buf[0x00] = 0x06;
|
||||
|
||||
hid_get_feature_report(dev, usb_buf, ROCCAT_BURST_FLASH_PACKET_LENGTH);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 2. Update needed bytes |
|
||||
\*---------------------------------------------------------*/
|
||||
usb_buf[0x01] = 0x3F;
|
||||
usb_buf[0x03] = 0x06;
|
||||
usb_buf[0x04] = 0x06;
|
||||
usb_buf[0x05] = 0x1F;
|
||||
|
||||
usb_buf[30] = mode_value;
|
||||
usb_buf[31] = mode_flags & MODE_FLAG_HAS_SPEED ? speed : 0xFF;
|
||||
usb_buf[32] = brightness;
|
||||
|
||||
usb_buf[34] = 0xFF;
|
||||
|
||||
if(color_mode & MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
usb_buf[36] = 0x14;
|
||||
usb_buf[37] = 0xFF;
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
usb_buf[38 + 10 * i] = RGBGetRValue(colors[i]);
|
||||
usb_buf[39 + 10 * i] = RGBGetGValue(colors[i]);
|
||||
usb_buf[40 + 10 * i] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
}
|
||||
else if (color_mode & MODE_COLORS_NONE)
|
||||
{
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
usb_buf[38 + 10 * i] = 0xF4;
|
||||
usb_buf[39 + 10 * i] = 0x00;
|
||||
usb_buf[40 + 10 * i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int crc = CalculateCRC(&usb_buf[0]);
|
||||
|
||||
usb_buf[61] = (unsigned char) crc;
|
||||
usb_buf[62] = crc >> 8;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 3. Send to flash |
|
||||
\*---------------------------------------------------------*/
|
||||
hid_send_feature_report(dev, usb_buf, ROCCAT_BURST_FLASH_PACKET_LENGTH);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 4. Switch to built-in mode |
|
||||
\*---------------------------------------------------------*/
|
||||
SwitchControl(false);
|
||||
}
|
||||
|
||||
unsigned int RoccatBurstController::CalculateCRC(unsigned char* bytes)
|
||||
{
|
||||
unsigned int crc = 0;
|
||||
|
||||
for(unsigned int i = 0; i < ROCCAT_BURST_FLASH_PACKET_LENGTH - 2; i++)
|
||||
{
|
||||
crc += bytes[i];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatBurstController.h |
|
||||
| |
|
||||
| Driver for Roccat Burst |
|
||||
| |
|
||||
| Morgan Guimard (morg) 01 Jun 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include <hidapi.h>
|
||||
|
||||
#define ROCCAT_BURST_CONTROL_MODE_PACKET_LENGTH 6
|
||||
#define ROCCAT_BURST_DIRECT_MODE_PACKET_LENGTH 11
|
||||
#define ROCCAT_BURST_FLASH_PACKET_LENGTH 63
|
||||
#define ROCCAT_BURST_FLASH_REPORT_ID 0x06
|
||||
#define ROCCAT_BURST_DIRECT_MODE_REPORT_ID 0x0D
|
||||
#define ROCCAT_BURST_DIRECT_MODE_BYTE 0x0B
|
||||
#define ROCCAT_BURST_CORE_NUMBER_OF_LEDS 1
|
||||
#define ROCCAT_BURST_PRO_NUMBER_OF_LEDS 2
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_BURST_DIRECT_MODE_VALUE = 0x00,
|
||||
ROCCAT_BURST_STATIC_MODE_VALUE = 0x01,
|
||||
ROCCAT_BURST_WAVE_MODE_VALUE = 0x0A,
|
||||
ROCCAT_BURST_HEARTBEAT_MODE_VALUE = 0x04,
|
||||
ROCCAT_BURST_BREATHING_MODE_VALUE = 0x03,
|
||||
ROCCAT_BURST_BLINKING_MODE_VALUE = 0x02
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_BURST_SPEED_MIN = 0x01,
|
||||
ROCCAT_BURST_SPEED_MAX = 0x0B,
|
||||
ROCCAT_BURST_BRIGHTNESS_MIN = 0x00,
|
||||
ROCCAT_BURST_BRIGHTNESS_MAX = 0xFF
|
||||
};
|
||||
|
||||
class RoccatBurstController
|
||||
{
|
||||
public:
|
||||
RoccatBurstController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name);
|
||||
~RoccatBurstController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SetupDirectMode();
|
||||
void SendDirect(std::vector<RGBColor> colors);
|
||||
void SetMode(std::vector<RGBColor> colors,
|
||||
unsigned char mode_value,
|
||||
unsigned char speed,
|
||||
unsigned char brightness,
|
||||
unsigned int color_mode,
|
||||
unsigned int mode_flags
|
||||
);
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
unsigned int CalculateCRC(unsigned char* bytes);
|
||||
void SwitchControl(bool direct);
|
||||
};
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatBurstProAir.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Burst Pro Air |
|
||||
| |
|
||||
| Morgan Guimard (morg) 16 Jun 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RoccatBurstProAir.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Burst Pro Air
|
||||
@category Mouse
|
||||
@type USB
|
||||
@save :warning:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectRoccatBurstProAirCoreControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatBurstProAir::RGBController_RoccatBurstProAir(RoccatBurstProAirController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_MOUSE;
|
||||
description = "Roccat Burst Pro Air Mouse Device";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = ROCCAT_BURST_PRO_AIR_DIRECT_MODE_VALUE;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
Direct.brightness = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Direct.brightness_min = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN;
|
||||
Direct.brightness_max = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX;
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Blink;
|
||||
Blink.name = "Blink";
|
||||
Blink.value = ROCCAT_BURST_PRO_AIR_BLINK_MODE_VALUE;
|
||||
Blink.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Blink.color_mode = MODE_COLORS_PER_LED;
|
||||
Blink.brightness = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Blink.brightness_min = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN;
|
||||
Blink.brightness_max = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Blink.speed = ROCCAT_BURST_PRO_AIR_SPEED_MIN;
|
||||
Blink.speed_min = ROCCAT_BURST_PRO_AIR_SPEED_MIN;
|
||||
Blink.speed_max = ROCCAT_BURST_PRO_AIR_SPEED_MAX;
|
||||
modes.push_back(Blink);
|
||||
|
||||
mode Breath;
|
||||
Breath.name = "Breathing";
|
||||
Breath.value = ROCCAT_BURST_PRO_AIR_BREATH_MODE_VALUE;
|
||||
Breath.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Breath.color_mode = MODE_COLORS_PER_LED;
|
||||
Breath.brightness = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Breath.brightness_min = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN;
|
||||
Breath.brightness_max = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Breath.speed = ROCCAT_BURST_PRO_AIR_SPEED_MIN;
|
||||
Breath.speed_min = ROCCAT_BURST_PRO_AIR_SPEED_MIN;
|
||||
Breath.speed_max = ROCCAT_BURST_PRO_AIR_SPEED_MAX;
|
||||
modes.push_back(Breath);
|
||||
|
||||
mode Wave;
|
||||
Wave.name = "Wave";
|
||||
Wave.value = ROCCAT_BURST_PRO_AIR_WAVE_MODE_VALUE;
|
||||
Wave.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Wave.color_mode = MODE_COLORS_PER_LED;
|
||||
Wave.brightness = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Wave.brightness_min = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN;
|
||||
Wave.brightness_max = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Wave.speed = ROCCAT_BURST_PRO_AIR_SPEED_MIN;
|
||||
Wave.speed_min = ROCCAT_BURST_PRO_AIR_SPEED_MIN;
|
||||
Wave.speed_max = ROCCAT_BURST_PRO_AIR_SPEED_MAX;
|
||||
modes.push_back(Wave);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatBurstProAir::~RGBController_RoccatBurstProAir()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurstProAir::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
new_zone.name = "Mouse";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS;
|
||||
new_zone.leds_max = ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS;
|
||||
new_zone.leds_count = ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS;
|
||||
new_zone.matrix_map = NULL;
|
||||
zones.push_back(new_zone);
|
||||
|
||||
std::string led_names[ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS] =
|
||||
{
|
||||
"Scroll Wheel",
|
||||
"Logo",
|
||||
"Left button",
|
||||
"Right button"
|
||||
};
|
||||
|
||||
for(unsigned int i = 0; i < ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS; i++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = led_names[i];
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurstProAir::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurstProAir::DeviceUpdateLEDs()
|
||||
{
|
||||
UpdateZoneLEDs(0);
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurstProAir::UpdateZoneLEDs(int /*zone_idx*/)
|
||||
{
|
||||
controller->SetColors(colors);
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurstProAir::UpdateSingleLED(int /*led_idx*/)
|
||||
{
|
||||
UpdateZoneLEDs(0);
|
||||
}
|
||||
|
||||
void RGBController_RoccatBurstProAir::DeviceUpdateMode()
|
||||
{
|
||||
const mode& active = modes[active_mode];
|
||||
controller->SetModeValues(active.value, active.speed, active.brightness);
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatBurstProAir.h |
|
||||
| |
|
||||
| RGBController for Roccat Burst Pro Air |
|
||||
| |
|
||||
| Morgan Guimard (morg) 16 Jun 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatBurstProAirController.h"
|
||||
|
||||
class RGBController_RoccatBurstProAir : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatBurstProAir(RoccatBurstProAirController* controller_ptr);
|
||||
~RGBController_RoccatBurstProAir();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatBurstProAirController* controller;
|
||||
};
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatBurstProAirController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Burst Pro Air |
|
||||
| |
|
||||
| Morgan Guimard (morg) 16 Jun 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "RoccatBurstProAirController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatBurstProAirController::RoccatBurstProAirController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
RoccatBurstProAirController::~RoccatBurstProAirController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatBurstProAirController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatBurstProAirController::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatBurstProAirController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
void RoccatBurstProAirController::SetColors(std::vector<RGBColor> colors)
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_BURST_PRO_AIR_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ROCCAT_BURST_PRO_AIR_REPORT_SIZE);
|
||||
|
||||
usb_buf[0] = ROCCAT_BURST_PRO_AIR_REPORT_ID;
|
||||
|
||||
usb_buf[1] = 0x01;
|
||||
usb_buf[2] = 0x4C;
|
||||
usb_buf[3] = 0x06;
|
||||
usb_buf[4] = 0x14;
|
||||
|
||||
for(unsigned char i = 0; i < colors.size(); i++)
|
||||
{
|
||||
usb_buf[5 + 5 * i] = i + 1;
|
||||
usb_buf[6 + 5 * i] = 0xFF;
|
||||
usb_buf[7 + 5 * i] = RGBGetRValue(colors[i]);
|
||||
usb_buf[8 + 5 * i] = RGBGetGValue(colors[i]);
|
||||
usb_buf[9 + 5 * i] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, ROCCAT_BURST_PRO_AIR_REPORT_SIZE);
|
||||
}
|
||||
|
||||
void RoccatBurstProAirController::SetModeValues(unsigned char mode_value, unsigned char speed, unsigned char brightness)
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_BURST_PRO_AIR_REPORT_SIZE];
|
||||
memset(usb_buf, 0x00, ROCCAT_BURST_PRO_AIR_REPORT_SIZE);
|
||||
|
||||
usb_buf[0] = ROCCAT_BURST_PRO_AIR_REPORT_ID;
|
||||
|
||||
usb_buf[1] = 0x01;
|
||||
usb_buf[2] = 0x4C;
|
||||
usb_buf[3] = 0x06;
|
||||
usb_buf[4] = 0x06;
|
||||
|
||||
usb_buf[5] = mode_value;
|
||||
usb_buf[6] = speed;
|
||||
usb_buf[7] = brightness;
|
||||
|
||||
usb_buf[8] = 0x0F;
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, ROCCAT_BURST_PRO_AIR_REPORT_SIZE);
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatBurstProAirController.h |
|
||||
| |
|
||||
| Driver for Roccat Burst Pro Air |
|
||||
| |
|
||||
| Morgan Guimard (morg) 16 Jun 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define ROCCAT_BURST_PRO_AIR_REPORT_ID 0x06
|
||||
#define ROCCAT_BURST_PRO_AIR_REPORT_SIZE 30
|
||||
#define ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS 4
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_BURST_PRO_AIR_DIRECT_MODE_VALUE = 0x01,
|
||||
ROCCAT_BURST_PRO_AIR_BLINK_MODE_VALUE = 0x02,
|
||||
ROCCAT_BURST_PRO_AIR_BREATH_MODE_VALUE = 0x03,
|
||||
ROCCAT_BURST_PRO_AIR_WAVE_MODE_VALUE = 0x04
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN = 0x00,
|
||||
ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX = 0xFF,
|
||||
ROCCAT_BURST_PRO_AIR_SPEED_MIN = 0x00,
|
||||
ROCCAT_BURST_PRO_AIR_SPEED_MAX = 0x0B
|
||||
};
|
||||
|
||||
class RoccatBurstProAirController
|
||||
{
|
||||
public:
|
||||
RoccatBurstProAirController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name);
|
||||
~RoccatBurstProAirController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SetColors(std::vector<RGBColor> colors);
|
||||
void SetModeValues(unsigned char mode_value, unsigned char speed, unsigned char brightness);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
};
|
||||
@@ -0,0 +1,373 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for Roccat devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "Detector.h"
|
||||
#include "RoccatBurstController.h"
|
||||
#include "RoccatBurstProAirController.h"
|
||||
#include "RoccatKoneAimoController.h"
|
||||
#include "RoccatKoneProController.h"
|
||||
#include "RoccatKoneProAirController.h"
|
||||
#include "RoccatKoneXPController.h"
|
||||
#include "RoccatSenseAimoController.h"
|
||||
#include "RoccatVulcanKeyboardController.h"
|
||||
#include "RoccatKovaController.h"
|
||||
#include "RoccatEloController.h"
|
||||
#include "RGBController_RoccatBurst.h"
|
||||
#include "RGBController_RoccatBurstProAir.h"
|
||||
#include "RGBController_RoccatHordeAimo.h"
|
||||
#include "RGBController_RoccatKoneAimo.h"
|
||||
#include "RGBController_RoccatKonePro.h"
|
||||
#include "RGBController_RoccatKoneProAir.h"
|
||||
#include "RGBController_RoccatKoneXP.h"
|
||||
#include "RGBController_RoccatSenseAimo.h"
|
||||
#include "RGBController_RoccatVulcanKeyboard.h"
|
||||
#include "RGBController_RoccatKova.h"
|
||||
#include "RGBController_RoccatElo.h"
|
||||
#include <hidapi.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#define ROCCAT_VID 0x1E7D
|
||||
#define TURTLE_BEACH_VID 0x10F5
|
||||
|
||||
/*--------------------------------------------------------------------------------*\
|
||||
| KEYBOARDS |
|
||||
| RoccatVulcanKeyboardController PIDs defined in RoccatVulcanKeyboardController.h |
|
||||
\*--------------------------------------------------------------------------------*/
|
||||
#define ROCCAT_HORDE_AIMO_PID 0x303E
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| MICE |
|
||||
\*-----------------------------------------------------------------*/
|
||||
#define ROCCAT_BURST_CORE_PID 0x2DE6
|
||||
#define ROCCAT_BURST_PRO_PID 0x2DE1
|
||||
#define ROCCAT_BURST_PRO_AIR_PID 0x2CA6
|
||||
#define ROCCAT_KONE_AIMO_PID 0x2E27
|
||||
#define ROCCAT_KONE_AIMO_16K_PID 0x2E2C
|
||||
#define ROCCAT_KONE_PRO_PID 0x2C88
|
||||
#define ROCCAT_KONE_PRO_AIR_PID 0x2C8E
|
||||
#define ROCCAT_KONE_PRO_AIR_WIRED_PID 0x2C92
|
||||
#define ROCCAT_KONE_XP_PID 0x2C8B
|
||||
#define ROCCAT_KOVA_PID 0x2CEE
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| MOUSEMATS |
|
||||
\*-----------------------------------------------------------------*/
|
||||
#define ROCCAT_SENSE_AIMO_MID_PID 0x343A
|
||||
#define ROCCAT_SENSE_AIMO_XXL_PID 0x343B
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| HEADSETS |
|
||||
\*-----------------------------------------------------------------*/
|
||||
#define ROCCAT_ELO_PID 0x3A34
|
||||
|
||||
void DetectRoccatMouseControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatKoneAimoController * controller = new RoccatKoneAimoController(dev, info->path, name);
|
||||
RGBController_RoccatKoneAimo * rgb_controller = new RGBController_RoccatKoneAimo(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*\
|
||||
| Tracks the paths used in DetectRoccatVulcanKeyboardControllers so multiple Roccat |
|
||||
| devices can be detected without all controlling the same device. |
|
||||
\*---------------------------------------------------------------------------------*/
|
||||
static std::unordered_set<std::string> used_paths;
|
||||
|
||||
/*--------------------------------------------------------------------------------*\
|
||||
| Removes all entries in used_paths so device discovery does not skip any of them. |
|
||||
\*--------------------------------------------------------------------------------*/
|
||||
void ResetRoccatVulcanKeyboardControllersPaths()
|
||||
{
|
||||
used_paths.clear();
|
||||
}
|
||||
|
||||
void DetectRoccatVulcanKeyboardControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
/*-------------------------------------------------------------------------------------------------*\
|
||||
| Create a local copy of the HID enumerations for the Roccat Vulcan Keyboard VID/PID and iterate |
|
||||
| through it. This prevents detection from failing if interface 1 comes before interface 0 in the |
|
||||
| main info list. |
|
||||
\*-------------------------------------------------------------------------------------------------*/
|
||||
hid_device* dev_ctrl = nullptr;
|
||||
hid_device* dev_led = nullptr;
|
||||
hid_device_info* info_full = hid_enumerate(info->vendor_id, info->product_id);
|
||||
hid_device_info* info_temp = info_full;
|
||||
|
||||
/*--------------------------------------------------------------------------------------------*\
|
||||
| Keep track of paths so they can be added to used_paths only if both interfaces can be found. |
|
||||
\*--------------------------------------------------------------------------------------------*/
|
||||
std::string dev_ctrl_path;
|
||||
std::string dev_led_path;
|
||||
int dev_led_page;
|
||||
int dev_ctrl_page;
|
||||
int dev_led_iface = 3;
|
||||
int dev_ctrl_iface = 1;
|
||||
|
||||
switch(info->product_id)
|
||||
{
|
||||
case ROCCAT_VULCAN_PRO_PID:
|
||||
case ROCCAT_VULCAN_TKL_PRO_PID:
|
||||
case ROCCAT_PYRO_PID:
|
||||
case ROCCAT_MAGMA_PID:
|
||||
case ROCCAT_MAGMA_MINI_PID:
|
||||
case ROCCAT_VULCAN_II_PID:
|
||||
case ROCCAT_VULCAN_II_MAX_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_PID:
|
||||
dev_led_page = 0xFF00;
|
||||
dev_ctrl_page = 0xFF01;
|
||||
dev_led_iface = 3;
|
||||
dev_ctrl_iface = 1;
|
||||
break;
|
||||
case TURTLE_BEACH_VULCAN_II_TKL_PRO_PID:
|
||||
dev_led_page = 0xFF00;
|
||||
dev_ctrl_page = 0x0001;
|
||||
dev_led_iface = 4;
|
||||
dev_ctrl_iface = 1;
|
||||
break;
|
||||
default:
|
||||
dev_led_page = 0x0001;
|
||||
dev_ctrl_page = 0x000B;
|
||||
dev_led_iface = 3;
|
||||
dev_ctrl_iface = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
while(info_temp)
|
||||
{
|
||||
/*----------------------------------------------------------------------------------------*\
|
||||
| Check for paths used on an already registered Roccat Vulcan Keyboard controller to avoid |
|
||||
| registering multiple controllers that refer to the same physical hardware. |
|
||||
\*----------------------------------------------------------------------------------------*/
|
||||
if(info_temp->vendor_id == info->vendor_id
|
||||
&& info_temp->product_id == info->product_id
|
||||
&& used_paths.find(info_temp->path) == used_paths.end() )
|
||||
{
|
||||
if(info_temp->interface_number == dev_ctrl_iface && info_temp->usage_page == dev_ctrl_page)
|
||||
{
|
||||
dev_ctrl = hid_open_path(info_temp->path);
|
||||
dev_ctrl_path = info_temp->path;
|
||||
}
|
||||
else if(info_temp->interface_number == dev_led_iface && info_temp->usage_page == dev_led_page)
|
||||
{
|
||||
dev_led = hid_open_path(info_temp->path);
|
||||
dev_led_path = info_temp->path;
|
||||
}
|
||||
}
|
||||
if(dev_ctrl && dev_led)
|
||||
{
|
||||
break;
|
||||
}
|
||||
info_temp = info_temp->next;
|
||||
}
|
||||
|
||||
hid_free_enumeration(info_full);
|
||||
|
||||
if(dev_ctrl && dev_led)
|
||||
{
|
||||
RoccatVulcanKeyboardController * controller = new RoccatVulcanKeyboardController(dev_ctrl, dev_led, info->path, info->product_id, name);
|
||||
RGBController_RoccatVulcanKeyboard * rgb_controller = new RGBController_RoccatVulcanKeyboard(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
|
||||
used_paths.insert(dev_ctrl_path);
|
||||
used_paths.insert(dev_led_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not all of them could be opened, do some cleanup
|
||||
hid_close(dev_ctrl);
|
||||
hid_close(dev_led);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatHordeAimoKeyboardControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatHordeAimoController * controller = new RoccatHordeAimoController(dev, *info, name);
|
||||
RGBController_RoccatHordeAimo * rgb_controller = new RGBController_RoccatHordeAimo(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatBurstCoreControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatBurstController * controller = new RoccatBurstController(dev, *info, name);
|
||||
RGBController_RoccatBurst * rgb_controller = new RGBController_RoccatBurst(controller, ROCCAT_BURST_CORE_NUMBER_OF_LEDS);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatBurstProControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatBurstController * controller = new RoccatBurstController(dev, *info, name);
|
||||
RGBController_RoccatBurst * rgb_controller = new RGBController_RoccatBurst(controller, ROCCAT_BURST_PRO_NUMBER_OF_LEDS);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatBurstProAirControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatBurstProAirController * controller = new RoccatBurstProAirController(dev, *info, name);
|
||||
RGBController_RoccatBurstProAir * rgb_controller = new RGBController_RoccatBurstProAir(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatKoneProControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatKoneProController * controller = new RoccatKoneProController(dev, *info, name);
|
||||
RGBController_RoccatKonePro * rgb_controller = new RGBController_RoccatKonePro(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatKoneProAirControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatKoneProAirController * controller = new RoccatKoneProAirController(dev, *info, name);
|
||||
RGBController_RoccatKoneProAir * rgb_controller = new RGBController_RoccatKoneProAir(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatKoneXPControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatKoneXPController * controller = new RoccatKoneXPController(dev, info->path, name);
|
||||
RGBController_RoccatKoneXP * rgb_controller = new RGBController_RoccatKoneXP(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatKovaControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatKovaController * controller = new RoccatKovaController(dev, info->path, name);
|
||||
RGBController_RoccatKova * rgb_controller = new RGBController_RoccatKova(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectRoccatEloControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
RoccatEloController * controller = new RoccatEloController(dev, *info, name);
|
||||
RGBController_RoccatElo * rgb_controller = new RGBController_RoccatElo(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
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, name);
|
||||
RGBController_RoccatSenseAimo * rgb_controller = new RGBController_RoccatSenseAimo(controller);
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_PRE_DETECTION_HOOK(ResetRoccatVulcanKeyboardControllersPaths);
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| KEYBOARDS |
|
||||
\*-----------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Horde Aimo", DetectRoccatHordeAimoKeyboardControllers, ROCCAT_VID, ROCCAT_HORDE_AIMO_PID, 1, 0x0B, 0 );
|
||||
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Magma", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_MAGMA_PID, 1, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Magma Mini", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_MAGMA_MINI_PID, 1, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Pyro", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_PYRO_PID, 1, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Vulcan 100 Aimo", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_100_AIMO_PID, 1, 11);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Vulcan 120-Series Aimo", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_120_AIMO_PID, 1, 11);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Vulcan TKL", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_TKL_PID, 1, 11);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Vulcan Pro", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_PRO_PID, 1, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Vulcan TKL Pro", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_TKL_PRO_PID, 1, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Vulcan II", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_II_PID, 1, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP ("Roccat Vulcan II Max", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_II_MAX_PID, 1, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP ("Turtle Beach Vulcan II", DetectRoccatVulcanKeyboardControllers, TURTLE_BEACH_VID, TURTLE_BEACH_VULCAN_II_PID, 1, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP ("Turtle Beach Vulcan II TKL", DetectRoccatVulcanKeyboardControllers, TURTLE_BEACH_VID, TURTLE_BEACH_VULCAN_II_TKL_PID, 1, 11);
|
||||
REGISTER_HID_DETECTOR_IP ("Turtle Beach Vulcan II TKL Pro", DetectRoccatVulcanKeyboardControllers, TURTLE_BEACH_VID, TURTLE_BEACH_VULCAN_II_TKL_PRO_PID, 1, 0x0001);
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| MICE |
|
||||
\*-----------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Burst Core", DetectRoccatBurstCoreControllers, ROCCAT_VID, ROCCAT_BURST_CORE_PID, 3, 0xFF01, 1 );
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Burst Pro", DetectRoccatBurstProControllers, ROCCAT_VID, ROCCAT_BURST_PRO_PID, 3, 0xFF01, 1 );
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Burst Pro Air", DetectRoccatBurstProAirControllers, ROCCAT_VID, ROCCAT_BURST_PRO_AIR_PID, 0, 0x01, 2 );
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Kone Aimo", DetectRoccatMouseControllers, ROCCAT_VID, ROCCAT_KONE_AIMO_PID, 0, 0x0B, 0 );
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Kone Aimo 16K", DetectRoccatMouseControllers, ROCCAT_VID, ROCCAT_KONE_AIMO_16K_PID, 0, 0x0B, 0 );
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Kone Pro", DetectRoccatKoneProControllers, ROCCAT_VID, ROCCAT_KONE_PRO_PID, 3, 0xFF01, 1 );
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Kone Pro Air", DetectRoccatKoneProAirControllers, ROCCAT_VID, ROCCAT_KONE_PRO_AIR_PID, 2, 0xFF00, 1 );
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Kone Pro Air (Wired)", DetectRoccatKoneProAirControllers, ROCCAT_VID, ROCCAT_KONE_PRO_AIR_WIRED_PID, 1, 0xFF13, 1 );
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Kone XP", DetectRoccatKoneXPControllers, ROCCAT_VID, ROCCAT_KONE_XP_PID, 3, 0xFF01, 1 );
|
||||
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Kova", DetectRoccatKovaControllers, ROCCAT_VID, ROCCAT_KOVA_PID, 0, 0x0B, 0 );
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| MOUSEMATS |
|
||||
\*-----------------------------------------------------------------*/
|
||||
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 );
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| HEADSETS |
|
||||
\*-----------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IPU("Roccat Elo 7.1", DetectRoccatEloControllers, ROCCAT_VID, ROCCAT_ELO_PID, 3, 0x0C, 1 );
|
||||
@@ -0,0 +1,95 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatElo.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Elo |
|
||||
| |
|
||||
| Flora Aubry 02 Jan 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "RGBController_RoccatElo.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Elo 7.1
|
||||
@category Headset
|
||||
@type USB
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectRoccatEloControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatElo::RGBController_RoccatElo(RoccatEloController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_HEADSET;
|
||||
description = "Roccat Elo 7.1 Headset Device";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatElo::~RGBController_RoccatElo()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatElo::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
|
||||
new_zone.name = "Headset";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = ROCCAT_ELO_LEDS_COUNT;
|
||||
new_zone.leds_max = ROCCAT_ELO_LEDS_COUNT;
|
||||
new_zone.leds_count = ROCCAT_ELO_LEDS_COUNT;
|
||||
new_zone.matrix_map = nullptr;
|
||||
|
||||
zones.emplace_back(new_zone);
|
||||
|
||||
leds.resize(new_zone.leds_count);
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RoccatElo::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatElo::DeviceUpdateLEDs()
|
||||
{
|
||||
controller->SendDirect(colors[0]);
|
||||
}
|
||||
|
||||
void RGBController_RoccatElo::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatElo::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatElo::DeviceUpdateMode()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatElo.h |
|
||||
| |
|
||||
| RGBController for Roccat Elo |
|
||||
| |
|
||||
| Flora Aubry 02 Jan 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatEloController.h"
|
||||
|
||||
class RGBController_RoccatElo : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatElo(RoccatEloController* controller_ptr);
|
||||
~RGBController_RoccatElo();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatEloController* controller;
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatEloController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Elo |
|
||||
| |
|
||||
| Flora Aubry 02 Jan 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
#include "RoccatEloController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatEloController::RoccatEloController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
|
||||
SendInit();
|
||||
}
|
||||
|
||||
RoccatEloController::~RoccatEloController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatEloController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatEloController::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatEloController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
void RoccatEloController::SendInit()
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_ELO_REPORT_SIZE];
|
||||
|
||||
memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ROCCAT_ELO_REPORT_ID;
|
||||
usb_buf[0x01] = 0x01;
|
||||
|
||||
hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x01] = 0x02;
|
||||
|
||||
hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x01] = 0x03;
|
||||
usb_buf[0x03] = 0x01;
|
||||
|
||||
hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE);
|
||||
|
||||
SendDirect(0);
|
||||
|
||||
memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ROCCAT_ELO_REPORT_ID;
|
||||
usb_buf[0x01] = 0x01;
|
||||
|
||||
hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE);
|
||||
}
|
||||
|
||||
void RoccatEloController::SendDirect(RGBColor color)
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_ELO_REPORT_SIZE];
|
||||
|
||||
memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE);
|
||||
|
||||
usb_buf[0x00] = ROCCAT_ELO_REPORT_ID;
|
||||
usb_buf[0x01] = 0x04;
|
||||
usb_buf[0x04] = RGBGetRValue(color);
|
||||
usb_buf[0x05] = RGBGetGValue(color);
|
||||
usb_buf[0x06] = RGBGetBValue(color);
|
||||
|
||||
hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatEloController.h |
|
||||
| |
|
||||
| Driver for Roccat Elo |
|
||||
| |
|
||||
| Flora Aubry 02 Jan 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define ROCCAT_ELO_REPORT_SIZE 16
|
||||
#define ROCCAT_ELO_LEDS_COUNT 1
|
||||
#define ROCCAT_ELO_REPORT_ID 0xFF
|
||||
|
||||
class RoccatEloController
|
||||
{
|
||||
public:
|
||||
RoccatEloController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name);
|
||||
~RoccatEloController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SendDirect(RGBColor color);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
void SendInit();
|
||||
};
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatHordeAimo.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Horde Aimo |
|
||||
| |
|
||||
| Morgan Guimard (morg) 24 Feb 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RoccatHordeAimo.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Horde Aimo
|
||||
@category Keyboard
|
||||
@type USB
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectRoccatHordeAimoKeyboardControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatHordeAimo::RGBController_RoccatHordeAimo(RoccatHordeAimoController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_KEYBOARD;
|
||||
description = "Roccat Horde Aimo Keyboard Device";
|
||||
location = controller->GetDeviceLocation();
|
||||
serial = controller->GetSerialString();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatHordeAimo::~RGBController_RoccatHordeAimo()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatHordeAimo::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
new_zone.name = "Keyboard";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = NUMBER_OF_LEDS;
|
||||
new_zone.leds_max = NUMBER_OF_LEDS;
|
||||
new_zone.leds_count = NUMBER_OF_LEDS;
|
||||
new_zone.matrix_map = NULL;
|
||||
zones.push_back(new_zone);
|
||||
|
||||
for(unsigned int i = 0; i < NUMBER_OF_LEDS; i++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = "LED " + std::to_string(i + 1);
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RoccatHordeAimo::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatHordeAimo::DeviceUpdateLEDs()
|
||||
{
|
||||
UpdateZoneLEDs(0);
|
||||
}
|
||||
|
||||
void RGBController_RoccatHordeAimo::UpdateZoneLEDs(int /*zone_idx*/)
|
||||
{
|
||||
controller->SetColors(colors);
|
||||
}
|
||||
|
||||
void RGBController_RoccatHordeAimo::UpdateSingleLED(int /*led_idx*/)
|
||||
{
|
||||
UpdateZoneLEDs(0);
|
||||
}
|
||||
|
||||
void RGBController_RoccatHordeAimo::DeviceUpdateMode()
|
||||
{
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatHordeAimo.h |
|
||||
| |
|
||||
| RGBController for Roccat Horde Aimo |
|
||||
| |
|
||||
| Morgan Guimard (morg) 24 Feb 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatHordeAimoController.h"
|
||||
|
||||
class RGBController_RoccatHordeAimo : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatHordeAimo(RoccatHordeAimoController* controller_ptr);
|
||||
~RGBController_RoccatHordeAimo();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatHordeAimoController* controller;
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatHordeAimoController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Horde Aimo |
|
||||
| |
|
||||
| Morgan Guimard (morg) 24 Feb 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "RoccatHordeAimoController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatHordeAimoController::RoccatHordeAimoController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
|
||||
InitialPacket();
|
||||
}
|
||||
|
||||
RoccatHordeAimoController::~RoccatHordeAimoController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
void RoccatHordeAimoController::InitialPacket()
|
||||
{
|
||||
unsigned char usb_buf[8];
|
||||
|
||||
memset(usb_buf, 0x00,8);
|
||||
|
||||
usb_buf[0x00] = 0x13;
|
||||
usb_buf[0x01] = 0x08;
|
||||
usb_buf[0x02] = 0x01;
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, 8);
|
||||
}
|
||||
|
||||
std::string RoccatHordeAimoController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatHordeAimoController::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatHordeAimoController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
void RoccatHordeAimoController::SetColors(std::vector<RGBColor> colors)
|
||||
{
|
||||
unsigned char usb_buf[WRITE_PACKET_LENGTH];
|
||||
|
||||
usb_buf[0x00] = REPORT_ID;
|
||||
usb_buf[0x01] = WRITE_PACKET_LENGTH;
|
||||
usb_buf[0x02] = 0xFF;
|
||||
usb_buf[0x03] = 0xFF;
|
||||
|
||||
for(unsigned int i = 0; i < 6; i++)
|
||||
{
|
||||
usb_buf[0x04 + (i * 3)] = RGBGetRValue(colors[i]);
|
||||
usb_buf[0x05 + (i * 3)] = RGBGetGValue(colors[i]);
|
||||
usb_buf[0x06 + (i * 3)] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
|
||||
int crc = 0;
|
||||
|
||||
for(unsigned int i = 0; i < WRITE_PACKET_LENGTH - 2; i++)
|
||||
{
|
||||
crc += usb_buf[i];
|
||||
}
|
||||
|
||||
usb_buf[22] = crc;
|
||||
usb_buf[23] = crc >> 8;
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, WRITE_PACKET_LENGTH);
|
||||
|
||||
unsigned char usb_read_buf[READ_PACKET_LENGTH];
|
||||
hid_get_feature_report(dev, usb_read_buf, READ_PACKET_LENGTH);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatHordeAimoController.h |
|
||||
| |
|
||||
| Driver for Roccat Horde Aimo |
|
||||
| |
|
||||
| Morgan Guimard (morg) 24 Feb 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define WRITE_PACKET_LENGTH 24
|
||||
#define READ_PACKET_LENGTH 3
|
||||
#define REPORT_ID 0x18
|
||||
#define NUMBER_OF_LEDS 6
|
||||
|
||||
class RoccatHordeAimoController
|
||||
{
|
||||
public:
|
||||
RoccatHordeAimoController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name);
|
||||
~RoccatHordeAimoController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SetColors(std::vector<RGBColor> colors);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
void InitialPacket();
|
||||
};
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKoneAimo.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Kone Aimo |
|
||||
| |
|
||||
| Thibaud M (enlight3d) 17 Nov 2020 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RoccatKoneAimo.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Kone Aimo
|
||||
@category Mouse
|
||||
@type USB
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectRoccatMouseControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatKoneAimo::RGBController_RoccatKoneAimo(RoccatKoneAimoController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetName();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_MOUSE;
|
||||
description = "Roccat Kone Aimo Mouse Device";
|
||||
location = controller->GetLocation();
|
||||
serial = controller->GetSerial();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.speed_min = 0;
|
||||
Direct.speed_max = 0;
|
||||
Direct.speed = 0;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
active_mode = 0;
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatKoneAimo::~RGBController_RoccatKoneAimo()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneAimo::SetupZones()
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Set up zones and leds per zone |
|
||||
\*---------------------------------------------------------*/
|
||||
zone WHEEL_zone;
|
||||
WHEEL_zone.name = "Scroll Wheel";
|
||||
WHEEL_zone.type = ZONE_TYPE_SINGLE;
|
||||
WHEEL_zone.leds_min = 1;
|
||||
WHEEL_zone.leds_max = 1;
|
||||
WHEEL_zone.leds_count = 1;
|
||||
WHEEL_zone.matrix_map = NULL;
|
||||
zones.push_back(WHEEL_zone);
|
||||
zones_channel.push_back(SCROLL_WHEEL);
|
||||
|
||||
led WHEEL_led;
|
||||
WHEEL_led.name = "Wheel LED";
|
||||
WHEEL_led.value = (unsigned int)zones.size();
|
||||
leds.push_back(WHEEL_led);
|
||||
leds_channel.push_back(SCROLL_WHEEL);
|
||||
|
||||
zone STRIP_LEFT_zone;
|
||||
STRIP_LEFT_zone.name = "Strip left";
|
||||
STRIP_LEFT_zone.type = ZONE_TYPE_LINEAR;
|
||||
STRIP_LEFT_zone.leds_min = 4;
|
||||
STRIP_LEFT_zone.leds_max = 4;
|
||||
STRIP_LEFT_zone.leds_count = 4;
|
||||
STRIP_LEFT_zone.matrix_map = NULL;
|
||||
zones.push_back(STRIP_LEFT_zone);
|
||||
zones_channel.push_back(STRIP_LEFT);
|
||||
|
||||
for(std::size_t led_idx = 0; led_idx < STRIP_LEFT_zone.leds_max; led_idx++)
|
||||
{
|
||||
led STRIP_LEFT_led;
|
||||
STRIP_LEFT_led.name = "Strip left LED " + std::to_string(led_idx + 1);
|
||||
STRIP_LEFT_led.value = (unsigned int)zones.size();
|
||||
leds.push_back(STRIP_LEFT_led);
|
||||
leds_channel.push_back(STRIP_LEFT);
|
||||
}
|
||||
|
||||
zone STRIP_RIGHT_zone;
|
||||
STRIP_RIGHT_zone.name = "Strip right";
|
||||
STRIP_RIGHT_zone.type = ZONE_TYPE_LINEAR;
|
||||
STRIP_RIGHT_zone.leds_min = 4;
|
||||
STRIP_RIGHT_zone.leds_max = 4;
|
||||
STRIP_RIGHT_zone.leds_count = 4;
|
||||
STRIP_RIGHT_zone.matrix_map = NULL;
|
||||
zones.push_back(STRIP_RIGHT_zone);
|
||||
zones_channel.push_back(STRIP_RIGHT);
|
||||
|
||||
for(std::size_t led_idx = 0; led_idx < STRIP_RIGHT_zone.leds_max; led_idx++)
|
||||
{
|
||||
led STRIP_RIGHT_led;
|
||||
STRIP_RIGHT_led.name = "Strip right LED " + std::to_string(led_idx + 1);
|
||||
STRIP_RIGHT_led.value = (unsigned int)zones.size();
|
||||
leds.push_back(STRIP_RIGHT_led);
|
||||
leds_channel.push_back(STRIP_RIGHT);
|
||||
}
|
||||
|
||||
zone LOWER_LEFT_zone;
|
||||
LOWER_LEFT_zone.name = "Lower left";
|
||||
LOWER_LEFT_zone.type = ZONE_TYPE_SINGLE;
|
||||
LOWER_LEFT_zone.leds_min = 1;
|
||||
LOWER_LEFT_zone.leds_max = 1;
|
||||
LOWER_LEFT_zone.leds_count = 1;
|
||||
LOWER_LEFT_zone.matrix_map = NULL;
|
||||
zones.push_back(LOWER_LEFT_zone);
|
||||
zones_channel.push_back(LOWER_LEFT);
|
||||
|
||||
led LOWER_LEFT_led;
|
||||
LOWER_LEFT_led.name = "Lower left LED";
|
||||
LOWER_LEFT_led.value = (unsigned int)zones.size();
|
||||
leds.push_back(LOWER_LEFT_led);
|
||||
leds_channel.push_back(LOWER_LEFT);
|
||||
|
||||
zone LOWER_RIGHT_zone;
|
||||
LOWER_RIGHT_zone.name = "Lower right";
|
||||
LOWER_RIGHT_zone.type = ZONE_TYPE_SINGLE;
|
||||
LOWER_RIGHT_zone.leds_min = 1;
|
||||
LOWER_RIGHT_zone.leds_max = 1;
|
||||
LOWER_RIGHT_zone.leds_count = 1;
|
||||
LOWER_RIGHT_zone.matrix_map = NULL;
|
||||
zones.push_back(LOWER_RIGHT_zone);
|
||||
zones_channel.push_back(LOWER_RIGHT);
|
||||
|
||||
led LOWER_RIGHT_led;
|
||||
LOWER_RIGHT_led.name = "Lower right LED";
|
||||
LOWER_RIGHT_led.value = (unsigned int)zones.size();
|
||||
leds.push_back(LOWER_RIGHT_led);
|
||||
leds_channel.push_back(LOWER_RIGHT);
|
||||
|
||||
SetupColors();
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Initialize colors for each LED |
|
||||
\*---------------------------------------------------------*/
|
||||
for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++)
|
||||
{
|
||||
unsigned char red = 0x00;
|
||||
unsigned char grn = 0x00;
|
||||
unsigned char blu = 0x00;
|
||||
|
||||
colors[led_idx] = ToRGBColor(red, grn, blu);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneAimo::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneAimo::DeviceUpdateLEDs()
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Set colors for all channel/leds |
|
||||
\*---------------------------------------------------------*/
|
||||
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
controller->SetChannelColors(zones_channel[zone_idx], zones[zone_idx].colors, zones[zone_idx].leds_count);
|
||||
}
|
||||
/*---------------------------------------------------------*\
|
||||
| Apply new colors to the mouse |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SendUpdate();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneAimo::UpdateZoneLEDs(int zone_idx)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Set colors for one channel of leds |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SetChannelColors(zones_channel[zone_idx], zones[zone_idx].colors, zones[zone_idx].leds_count);
|
||||
/*---------------------------------------------------------*\
|
||||
| Apply new colors to the mouse |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SendUpdate();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneAimo::UpdateSingleLED(int led_idx)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Get channel corresponding to led |
|
||||
\*---------------------------------------------------------*/
|
||||
ROCCAT_KONE_AIMO_CHANNEL channel = leds_channel[led_idx];
|
||||
/*---------------------------------------------------------*\
|
||||
| Update channel corresponding to led |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SetChannelColors(channel, zones[leds[led_idx].value].colors, zones[leds[led_idx].value].leds_count);
|
||||
/*---------------------------------------------------------*\
|
||||
| Apply new colors to the mouse |
|
||||
\*---------------------------------------------------------*/
|
||||
controller->SendUpdate();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneAimo::DeviceUpdateMode()
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support changing mode |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKoneAimo.h |
|
||||
| |
|
||||
| RGBController for Roccat Kone Aimo |
|
||||
| |
|
||||
| Thibaud M (enlight3d) 17 Nov 2020 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatKoneAimoController.h"
|
||||
|
||||
class RGBController_RoccatKoneAimo : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatKoneAimo(RoccatKoneAimoController* controller_ptr);
|
||||
~RGBController_RoccatKoneAimo();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatKoneAimoController* controller;
|
||||
std::vector<ROCCAT_KONE_AIMO_CHANNEL> zones_channel;
|
||||
std::vector<ROCCAT_KONE_AIMO_CHANNEL> leds_channel;
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKoneAimoController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Kone Aimo |
|
||||
| |
|
||||
| Thibaud M (enlight3d) 17 Nov 2020 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "RoccatKoneAimoController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatKoneAimoController::RoccatKoneAimoController(hid_device* dev_handle, char *_path, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = _path;
|
||||
name = dev_name;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Init usb buffer to 0 and add first two bytes |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_colors_buf, 0x00, USB_COLOR_BUFF_LEN);
|
||||
usb_colors_buf[0x00] = 0x0D;
|
||||
usb_colors_buf[0x01] = 0x2E;
|
||||
|
||||
SendInit();
|
||||
}
|
||||
|
||||
RoccatKoneAimoController::~RoccatKoneAimoController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatKoneAimoController::GetName()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatKoneAimoController::GetSerial()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
std::string RoccatKoneAimoController::GetLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
void RoccatKoneAimoController::SendInit()
|
||||
{
|
||||
unsigned char usb_buf[6] = {00};
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Read first a packet from mouse (swarm does it) |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_get_feature_report(dev, usb_buf, 3);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up Init packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x0E;
|
||||
usb_buf[0x01] = 0x06;
|
||||
usb_buf[0x02] = 0x01;
|
||||
usb_buf[0x03] = 0x01;
|
||||
usb_buf[0x04] = 0x00;
|
||||
usb_buf[0x05] = 0xFF;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_send_feature_report(dev, usb_buf, 6);
|
||||
}
|
||||
|
||||
void RoccatKoneAimoController::SetChannelColors(ROCCAT_KONE_AIMO_CHANNEL channel, RGBColor * colors, unsigned int num_colors)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Receiving update request for only one channel |
|
||||
| and updating usb buffer to match colors |
|
||||
\*---------------------------------------------------------*/
|
||||
for(unsigned char i = 0; i < num_colors; i++)
|
||||
{
|
||||
std::size_t color = channel + i;
|
||||
int usb_idx = (int)(0x02 + (color * 4));
|
||||
|
||||
usb_colors_buf[usb_idx + R_OFFSET] = RGBGetRValue(colors[i]);
|
||||
usb_colors_buf[usb_idx + G_OFFSET] = RGBGetGValue(colors[i]);
|
||||
usb_colors_buf[usb_idx + B_OFFSET] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void RoccatKoneAimoController::SendUpdate()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet (whole buffer needs to be sent everytime) |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_send_feature_report(dev, usb_colors_buf, 46);
|
||||
/*-----------------------------------------------------*\
|
||||
| Read a packet from mouse (swarm does it) |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_get_feature_report(dev, usb_colors_buf, 3);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKoneAimoController.h |
|
||||
| |
|
||||
| Driver for Roccat Kone Aimo |
|
||||
| |
|
||||
| Thibaud M (enlight3d) 17 Nov 2020 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define HID_MAX_STR 255
|
||||
#define NUM_LEDS 11
|
||||
|
||||
#define R_OFFSET 0
|
||||
#define G_OFFSET 1
|
||||
#define B_OFFSET 2
|
||||
|
||||
#define USB_COLOR_BUFF_LEN 46
|
||||
|
||||
enum ROCCAT_KONE_AIMO_CHANNEL
|
||||
{
|
||||
SCROLL_WHEEL = 0,
|
||||
STRIP_LEFT = 1,
|
||||
STRIP_RIGHT = 5,
|
||||
LOWER_LEFT = 9,
|
||||
LOWER_RIGHT = 10
|
||||
};
|
||||
|
||||
class RoccatKoneAimoController
|
||||
{
|
||||
public:
|
||||
RoccatKoneAimoController(hid_device* dev_handle, char *_path, std::string dev_name);
|
||||
~RoccatKoneAimoController();
|
||||
|
||||
std::string GetLocation();
|
||||
std::string GetName();
|
||||
std::string GetSerial();
|
||||
|
||||
void SetChannelColors(ROCCAT_KONE_AIMO_CHANNEL channel, RGBColor * colors, unsigned int num_colors);
|
||||
void SendUpdate();
|
||||
|
||||
private:
|
||||
std::string location;
|
||||
std::string name;
|
||||
hid_device* dev;
|
||||
unsigned char usb_colors_buf[USB_COLOR_BUFF_LEN]; // USB buffer to be sent everytime we update mouse's LEDs
|
||||
|
||||
void SendInit();
|
||||
};
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKoneProAir.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Kone Pro Air |
|
||||
| |
|
||||
| Plunti 10 Jun 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RoccatKoneProAir.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Kone Pro Air Mouse
|
||||
@category Mouse
|
||||
@type USB
|
||||
@save :robot:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectRoccatKoneProAirControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatKoneProAir::RGBController_RoccatKoneProAir(RoccatKoneProAirController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_MOUSE;
|
||||
description = "Roccat Kone Pro Air Mouse Device";
|
||||
serial = controller->GetSerialString();
|
||||
location = controller->GetDeviceLocation();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = ROCCAT_KONE_PRO_AIR_DIRECT_MODE_VALUE;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.value = ROCCAT_KONE_PRO_AIR_OFF_MODE_VALUE;
|
||||
Off.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Off);
|
||||
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = ROCCAT_KONE_PRO_AIR_STATIC_MODE_VALUE;
|
||||
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_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Static.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN;
|
||||
Static.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
modes.push_back(Static);
|
||||
|
||||
mode RainbowWave;
|
||||
RainbowWave.name = "Rainbow Wave";
|
||||
RainbowWave.value = ROCCAT_KONE_PRO_AIR_RAINBOW_WAVE_MODE_VALUE;
|
||||
RainbowWave.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
RainbowWave.color_mode = MODE_COLORS_NONE;
|
||||
RainbowWave.brightness = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
RainbowWave.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN;
|
||||
RainbowWave.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
RainbowWave.speed = ROCCAT_KONE_PRO_AIR_SPEED_MID;
|
||||
RainbowWave.speed_min = ROCCAT_KONE_PRO_AIR_SPEED_MIN;
|
||||
RainbowWave.speed_max = ROCCAT_KONE_PRO_AIR_SPEED_MAX;
|
||||
modes.push_back(RainbowWave);
|
||||
|
||||
mode Heartbeat;
|
||||
Heartbeat.name = "Heartbeat";
|
||||
Heartbeat.value = ROCCAT_KONE_PRO_AIR_HEARTBEAT_MODE_VALUE;
|
||||
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_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Heartbeat.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN;
|
||||
Heartbeat.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Heartbeat.speed = ROCCAT_KONE_PRO_AIR_SPEED_MID;
|
||||
Heartbeat.speed_min = ROCCAT_KONE_PRO_AIR_SPEED_MIN;
|
||||
Heartbeat.speed_max = ROCCAT_KONE_PRO_AIR_SPEED_MAX;
|
||||
modes.push_back(Heartbeat);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = ROCCAT_KONE_PRO_AIR_BREATHING_MODE_VALUE;
|
||||
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_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Breathing.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN;
|
||||
Breathing.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Breathing.speed = ROCCAT_KONE_PRO_AIR_SPEED_MID;
|
||||
Breathing.speed_min = ROCCAT_KONE_PRO_AIR_SPEED_MIN;
|
||||
Breathing.speed_max = ROCCAT_KONE_PRO_AIR_SPEED_MAX;
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Flashing;
|
||||
Flashing.name = "Flashing";
|
||||
Flashing.value = ROCCAT_KONE_PRO_AIR_FLASHING_MODE_VALUE;
|
||||
Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Flashing.color_mode = MODE_COLORS_PER_LED;
|
||||
Flashing.brightness = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Flashing.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN;
|
||||
Flashing.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX;
|
||||
Flashing.speed = ROCCAT_KONE_PRO_AIR_SPEED_MID;
|
||||
Flashing.speed_min = ROCCAT_KONE_PRO_AIR_SPEED_MIN;
|
||||
Flashing.speed_max = ROCCAT_KONE_PRO_AIR_SPEED_MAX;
|
||||
modes.push_back(Flashing);
|
||||
|
||||
mode Battery;
|
||||
Battery.name = "Battery";
|
||||
Battery.value = ROCCAT_KONE_PRO_AIR_BATTERY_MODE_VALUE;
|
||||
Battery.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Battery.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Battery);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatKoneProAir::~RGBController_RoccatKoneProAir()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneProAir::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
new_zone.name = "Mouse";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = ROCCAT_KONE_PRO_AIR_LED_COUNT;
|
||||
new_zone.leds_max = ROCCAT_KONE_PRO_AIR_LED_COUNT;
|
||||
new_zone.leds_count = ROCCAT_KONE_PRO_AIR_LED_COUNT;
|
||||
new_zone.matrix_map = NULL;
|
||||
zones.push_back(new_zone);
|
||||
|
||||
std::string led_names[2] =
|
||||
{
|
||||
"Left Button",
|
||||
"Right Button"
|
||||
};
|
||||
|
||||
for(unsigned int i = 0; i < ROCCAT_KONE_PRO_AIR_LED_COUNT; i++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = led_names[i];
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneProAir::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneProAir::DeviceUpdateLEDs()
|
||||
{
|
||||
const mode& active = modes[active_mode];
|
||||
|
||||
if(active.value == ROCCAT_KONE_PRO_AIR_DIRECT_MODE_VALUE)
|
||||
{
|
||||
controller->SendDirect(colors);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller->SetMode(colors, active.value, active.speed, active.brightness, active.flags);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneProAir::UpdateZoneLEDs(int /*zone_idx*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneProAir::UpdateSingleLED(int /*led_idx*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneProAir::DeviceUpdateMode()
|
||||
{
|
||||
const mode& active = modes[active_mode];
|
||||
|
||||
if(!(active.flags & MODE_FLAG_HAS_PER_LED_COLOR))
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKoneProAir.h |
|
||||
| |
|
||||
| RGBController for Roccat Kone Pro Air |
|
||||
| |
|
||||
| Plunti 10 Jun 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatKoneProAirController.h"
|
||||
|
||||
class RGBController_RoccatKoneProAir : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatKoneProAir(RoccatKoneProAirController* controller_ptr);
|
||||
~RGBController_RoccatKoneProAir();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatKoneProAirController* controller;
|
||||
};
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKoneProAirController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Kone Pro Air |
|
||||
| |
|
||||
| Plunti 10 Jun 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "RoccatKoneProAirController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatKoneProAirController::RoccatKoneProAirController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
RoccatKoneProAirController::~RoccatKoneProAirController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatKoneProAirController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatKoneProAirController::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatKoneProAirController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
void RoccatKoneProAirController::SendDirect(std::vector<RGBColor> colors)
|
||||
{
|
||||
SendRGB(true, colors, ROCCAT_KONE_PRO_AIR_DIRECT_MODE_VALUE, ROCCAT_KONE_PRO_AIR_SPEED_MAX, ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX);
|
||||
}
|
||||
|
||||
void RoccatKoneProAirController::SetMode(std::vector<RGBColor> colors, unsigned char mode_value, unsigned char speed, unsigned char brightness, unsigned int mode_flags)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| 1. Read settings |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char active_settings[ROCCAT_KONE_PRO_AIR_SETTINGS_READ_PACKET_LENGTH];
|
||||
|
||||
unsigned char settings_request[] = {0x00, 0x90, 0x00, 0x04, 0x00, 0x18, 0x25, 0x51, 0x32};
|
||||
hid_write(dev, settings_request, sizeof(settings_request));
|
||||
|
||||
do
|
||||
{
|
||||
hid_read(dev, active_settings, ROCCAT_KONE_PRO_AIR_SETTINGS_READ_PACKET_LENGTH);
|
||||
} while( (active_settings[0] != 0x90) || (active_settings[2] != 0x26) );
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 2. Send settings and select profile |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char usb_buf[ROCCAT_KONE_PRO_AIR_SETTINGS_WRITE_PACKET_LENGTH];
|
||||
memset(usb_buf, 0x00, ROCCAT_KONE_PRO_AIR_SETTINGS_WRITE_PACKET_LENGTH);
|
||||
|
||||
usb_buf[1] = 0x10;
|
||||
usb_buf[2] = 0x50;
|
||||
usb_buf[3] = 0x14;
|
||||
memcpy(usb_buf + 5, active_settings + 10, 19);
|
||||
usb_buf[24] = active_settings[41];
|
||||
|
||||
hid_write(dev, usb_buf, ROCCAT_KONE_PRO_AIR_SETTINGS_WRITE_PACKET_LENGTH);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 3. Send RGB |
|
||||
\*---------------------------------------------------------*/
|
||||
SendRGB(false,
|
||||
colors,
|
||||
mode_value,
|
||||
(mode_flags & MODE_FLAG_HAS_SPEED ) ? speed : (unsigned char)ROCCAT_KONE_PRO_AIR_SPEED_MAX,
|
||||
(mode_flags & MODE_FLAG_HAS_BRIGHTNESS) ? brightness : (unsigned char)ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX
|
||||
);
|
||||
}
|
||||
|
||||
void RoccatKoneProAirController::SendRGB(bool direct, std::vector<RGBColor> colors, unsigned char mode_value, unsigned char speed, unsigned char brightness)
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_KONE_PRO_AIR_RGB_PACKET_LENGTH];
|
||||
memset(usb_buf, 0x00, ROCCAT_KONE_PRO_AIR_RGB_PACKET_LENGTH);
|
||||
|
||||
usb_buf[1] = 0x10;
|
||||
usb_buf[2] = direct ? 0x10 : 0x50;
|
||||
usb_buf[3] = 0x0B;
|
||||
usb_buf[4] = direct ? 0x00 : 0x01;
|
||||
usb_buf[5] = mode_value;
|
||||
usb_buf[6] = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; // Explicit brightness for first LED, not used by OpenRGB
|
||||
usb_buf[7] = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; // Explicit brightness for second LED, not used by OpenRGB
|
||||
usb_buf[8] = brightness;
|
||||
usb_buf[9] = speed;
|
||||
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
usb_buf[10 + 3 * i] = RGBGetRValue(colors[i]);
|
||||
usb_buf[11 + 3 * i] = RGBGetGValue(colors[i]);
|
||||
usb_buf[12 + 3 * i] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
|
||||
hid_write(dev, usb_buf, ROCCAT_KONE_PRO_AIR_RGB_PACKET_LENGTH);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKoneProAirController.h |
|
||||
| |
|
||||
| Driver for Roccat Kone Pro Air |
|
||||
| |
|
||||
| Plunti 10 Jun 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define ROCCAT_KONE_PRO_AIR_RGB_PACKET_LENGTH 16
|
||||
#define ROCCAT_KONE_PRO_AIR_SETTINGS_WRITE_PACKET_LENGTH 25
|
||||
#define ROCCAT_KONE_PRO_AIR_SETTINGS_READ_PACKET_LENGTH 42
|
||||
#define ROCCAT_KONE_PRO_AIR_LED_COUNT 2
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_KONE_PRO_AIR_DIRECT_MODE_VALUE = 0x09,
|
||||
ROCCAT_KONE_PRO_AIR_OFF_MODE_VALUE = 0x00,
|
||||
ROCCAT_KONE_PRO_AIR_STATIC_MODE_VALUE = 0x01,
|
||||
ROCCAT_KONE_PRO_AIR_RAINBOW_WAVE_MODE_VALUE = 0x06,
|
||||
ROCCAT_KONE_PRO_AIR_HEARTBEAT_MODE_VALUE = 0x05,
|
||||
ROCCAT_KONE_PRO_AIR_BREATHING_MODE_VALUE = 0x02,
|
||||
ROCCAT_KONE_PRO_AIR_FLASHING_MODE_VALUE = 0x08,
|
||||
ROCCAT_KONE_PRO_AIR_BATTERY_MODE_VALUE = 0x0A
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_KONE_PRO_AIR_SPEED_MIN = 0x01,
|
||||
ROCCAT_KONE_PRO_AIR_SPEED_MAX = 0x0B,
|
||||
ROCCAT_KONE_PRO_AIR_SPEED_MID = (ROCCAT_KONE_PRO_AIR_SPEED_MAX - ROCCAT_KONE_PRO_AIR_SPEED_MIN) / 2,
|
||||
ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN = 0x00,
|
||||
ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX = 0x64
|
||||
};
|
||||
|
||||
class RoccatKoneProAirController
|
||||
{
|
||||
public:
|
||||
RoccatKoneProAirController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name);
|
||||
~RoccatKoneProAirController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SendDirect(std::vector<RGBColor> colors);
|
||||
void SetMode(std::vector<RGBColor> colors, unsigned char mode_value, unsigned char speed, unsigned char brightness, unsigned int mode_flags);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
void SendRGB(bool direct, std::vector<RGBColor> colors, unsigned char mode_value, unsigned char speed, unsigned char brightness);
|
||||
};
|
||||
@@ -0,0 +1,188 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKonePro.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Kone Pro |
|
||||
| |
|
||||
| Garrett Denham (GardenOfWyers) 12 Jan 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RoccatKonePro.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Kone Pro Mouse
|
||||
@category Mouse
|
||||
@type USB
|
||||
@save :robot:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectRoccatKoneProControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatKonePro::RGBController_RoccatKonePro(RoccatKoneProController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetNameString();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_MOUSE;
|
||||
description = "Roccat Kone Pro Mouse Device";
|
||||
serial = controller->GetSerialString();
|
||||
location = controller->GetDeviceLocation();
|
||||
|
||||
// Also known as "Intelligent Lighting System" mode in Roccat Swarm
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = ROCCAT_KONE_PRO_DIRECT_MODE_VALUE;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
// Also known as "Fully Lit" mode in Roccat Swarm
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = ROCCAT_KONE_PRO_STATIC_MODE_VALUE;
|
||||
Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Static.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Static.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Static.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN;
|
||||
Static.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Static.colors.resize(ROCCAT_KONE_PRO_LED_COUNT);
|
||||
modes.push_back(Static);
|
||||
|
||||
// Also known as "Wave" mode in Roccat Swarm
|
||||
mode Rainbow;
|
||||
Rainbow.name = "Rainbow";
|
||||
Rainbow.value = ROCCAT_KONE_PRO_WAVE_MODE_VALUE;
|
||||
Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Rainbow.color_mode = MODE_COLORS_NONE;
|
||||
Rainbow.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Rainbow.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN;
|
||||
Rainbow.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Rainbow.speed = ROCCAT_KONE_PRO_SPEED_MID;
|
||||
Rainbow.speed_min = ROCCAT_KONE_PRO_SPEED_MIN;
|
||||
Rainbow.speed_max = ROCCAT_KONE_PRO_SPEED_MAX;
|
||||
modes.push_back(Rainbow);
|
||||
|
||||
mode Heartbeat;
|
||||
Heartbeat.name = "Heartbeat";
|
||||
Heartbeat.value = ROCCAT_KONE_PRO_HEARTBEAT_MODE_VALUE;
|
||||
Heartbeat.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Heartbeat.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Heartbeat.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Heartbeat.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN;
|
||||
Heartbeat.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Heartbeat.speed = ROCCAT_KONE_PRO_SPEED_MID;
|
||||
Heartbeat.speed_min = ROCCAT_KONE_PRO_SPEED_MIN;
|
||||
Heartbeat.speed_max = ROCCAT_KONE_PRO_SPEED_MAX;
|
||||
Heartbeat.colors.resize(ROCCAT_KONE_PRO_LED_COUNT);
|
||||
modes.push_back(Heartbeat);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = ROCCAT_KONE_PRO_BREATHING_MODE_VALUE;
|
||||
Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Breathing.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Breathing.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN;
|
||||
Breathing.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Breathing.speed = ROCCAT_KONE_PRO_SPEED_MID;
|
||||
Breathing.speed_min = ROCCAT_KONE_PRO_SPEED_MIN;
|
||||
Breathing.speed_max = ROCCAT_KONE_PRO_SPEED_MAX;
|
||||
Breathing.colors.resize(ROCCAT_KONE_PRO_LED_COUNT);
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Blinking;
|
||||
Blinking.name = "Blinking";
|
||||
Blinking.value = ROCCAT_KONE_PRO_BLINKING_MODE_VALUE;
|
||||
Blinking.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Blinking.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
Blinking.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Blinking.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN;
|
||||
Blinking.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX;
|
||||
Blinking.speed = ROCCAT_KONE_PRO_SPEED_MID;
|
||||
Blinking.speed_min = ROCCAT_KONE_PRO_SPEED_MIN;
|
||||
Blinking.speed_max = ROCCAT_KONE_PRO_SPEED_MAX;
|
||||
Blinking.colors.resize(ROCCAT_KONE_PRO_LED_COUNT);
|
||||
modes.push_back(Blinking);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatKonePro::~RGBController_RoccatKonePro()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatKonePro::SetupZones()
|
||||
{
|
||||
zone new_zone;
|
||||
new_zone.name = "Mouse";
|
||||
new_zone.type = ZONE_TYPE_LINEAR;
|
||||
new_zone.leds_min = ROCCAT_KONE_PRO_LED_COUNT;
|
||||
new_zone.leds_max = ROCCAT_KONE_PRO_LED_COUNT;
|
||||
new_zone.leds_count = ROCCAT_KONE_PRO_LED_COUNT;
|
||||
new_zone.matrix_map = NULL;
|
||||
zones.push_back(new_zone);
|
||||
|
||||
std::string led_names[2] =
|
||||
{
|
||||
"Left Button",
|
||||
"Right Button"
|
||||
};
|
||||
|
||||
for(unsigned int i = 0; i < ROCCAT_KONE_PRO_LED_COUNT; i++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = led_names[i];
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKonePro::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatKonePro::DeviceUpdateLEDs()
|
||||
{
|
||||
const mode& active = modes[active_mode];
|
||||
|
||||
if(active.value == ROCCAT_KONE_PRO_DIRECT_MODE_VALUE)
|
||||
{
|
||||
controller->SendDirect(colors);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller->SetMode(active.colors, active.value, active.speed, active.brightness, active.color_mode, active.flags);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RoccatKonePro::UpdateZoneLEDs(int /*zone_idx*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKonePro::UpdateSingleLED(int /*led_idx*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKonePro::DeviceUpdateMode()
|
||||
{
|
||||
if(modes[active_mode].value == ROCCAT_KONE_PRO_DIRECT_MODE_VALUE)
|
||||
{
|
||||
controller->SetupDirectMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKonePro.h |
|
||||
| |
|
||||
| RGBController for Roccat Kone Pro |
|
||||
| |
|
||||
| Garrett Denham (GardenOfWyers) 12 Jan 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatKoneProController.h"
|
||||
|
||||
class RGBController_RoccatKonePro : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatKonePro(RoccatKoneProController* controller_ptr);
|
||||
~RGBController_RoccatKonePro();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatKoneProController* controller;
|
||||
};
|
||||
@@ -0,0 +1,169 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKoneProController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Kone Pro |
|
||||
| |
|
||||
| Garrett Denham (GardenOfWyers) 12 Jan 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "RoccatKoneProController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatKoneProController::RoccatKoneProController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = info.path;
|
||||
name = dev_name;
|
||||
|
||||
SetupDirectMode();
|
||||
}
|
||||
|
||||
RoccatKoneProController::~RoccatKoneProController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatKoneProController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatKoneProController::GetNameString()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatKoneProController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
void RoccatKoneProController::SetupDirectMode()
|
||||
{
|
||||
SwitchControl(true);
|
||||
}
|
||||
|
||||
void RoccatKoneProController::SwitchControl(bool direct)
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_KONE_PRO_CONTROL_MODE_PACKET_LENGTH];
|
||||
|
||||
usb_buf[0x00] = 0x0E;
|
||||
usb_buf[0x01] = 0x06;
|
||||
usb_buf[0x02] = 0x01;
|
||||
usb_buf[0x03] = direct ? 0x01 : 0x00;
|
||||
usb_buf[0x04] = 0x00;
|
||||
usb_buf[0x05] = 0xFF;
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, ROCCAT_KONE_PRO_CONTROL_MODE_PACKET_LENGTH);
|
||||
}
|
||||
|
||||
void RoccatKoneProController::SendDirect(std::vector<RGBColor> colors)
|
||||
{
|
||||
unsigned char usb_buf[ROCCAT_KONE_PRO_DIRECT_MODE_PACKET_LENGTH];
|
||||
|
||||
memset(usb_buf, 0x00, ROCCAT_KONE_PRO_DIRECT_MODE_PACKET_LENGTH);
|
||||
|
||||
usb_buf[0x00] = ROCCAT_KONE_PRO_DIRECT_MODE_REPORT_ID;
|
||||
usb_buf[0x01] = ROCCAT_KONE_PRO_DIRECT_MODE_BYTE;
|
||||
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
usb_buf[0x02 + 3 * i] = RGBGetRValue(colors[i]);
|
||||
usb_buf[0x03 + 3 * i] = RGBGetGValue(colors[i]);
|
||||
usb_buf[0x04 + 3 * i] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
|
||||
hid_send_feature_report(dev, usb_buf, ROCCAT_KONE_PRO_DIRECT_MODE_PACKET_LENGTH);
|
||||
}
|
||||
|
||||
void RoccatKoneProController::SetMode(std::vector<RGBColor> colors, unsigned char mode_value, unsigned char speed, unsigned char brightness, unsigned int color_mode, unsigned int mode_flags)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| 1. Read from flash |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char usb_buf[ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH];
|
||||
memset(usb_buf, 0x00, ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH);
|
||||
|
||||
hid_get_feature_report(dev, usb_buf, ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 2. Update needed bytes |
|
||||
\*---------------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x06;
|
||||
usb_buf[0x01] = 0x45;
|
||||
|
||||
usb_buf[0x03] = 0x06;
|
||||
usb_buf[0x04] = 0x06;
|
||||
usb_buf[0x05] = 0x1F;
|
||||
|
||||
usb_buf[0x1E] = mode_value;
|
||||
usb_buf[0x1F] = mode_flags & MODE_FLAG_HAS_SPEED ? speed : 0xFF;
|
||||
usb_buf[0x20] = brightness;
|
||||
|
||||
if(color_mode & MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
usb_buf[0x24 + 5 * i] = 0x14;
|
||||
usb_buf[0x25 + 5 * i] = 0xFF;
|
||||
usb_buf[0x26 + 5 * i] = RGBGetRValue(colors[i]);
|
||||
usb_buf[0x27 + 5 * i] = RGBGetGValue(colors[i]);
|
||||
usb_buf[0x28 + 5 * i] = RGBGetBValue(colors[i]);
|
||||
}
|
||||
}
|
||||
else if(color_mode & MODE_COLORS_NONE)
|
||||
{
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
usb_buf[0x24 + 5 * i] = 0x14;
|
||||
usb_buf[0x25 + 5 * i] = 0x00;
|
||||
usb_buf[0x26 + 5 * i] = 0x00;
|
||||
usb_buf[0x27 + 5 * i] = 0x00;
|
||||
usb_buf[0x28 + 5 * i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
usb_buf[0x2E] = 0x14;
|
||||
usb_buf[0x2F] = 0xFF;
|
||||
|
||||
unsigned int crc = CalculateCRC(&usb_buf[0x00]);
|
||||
|
||||
usb_buf[0x43] = (unsigned char) crc;
|
||||
usb_buf[0x44] = crc >> 8;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 3. Send to flash |
|
||||
\*---------------------------------------------------------*/
|
||||
hid_send_feature_report(dev, usb_buf, ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| 4. Switch to built-in mode |
|
||||
\*---------------------------------------------------------*/
|
||||
SwitchControl(false);
|
||||
}
|
||||
|
||||
unsigned int RoccatKoneProController::CalculateCRC(unsigned char* bytes)
|
||||
{
|
||||
unsigned int crc = 0;
|
||||
|
||||
for(unsigned int i = 0; i < ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH - 2; i++)
|
||||
{
|
||||
crc += bytes[i];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKoneProController.h |
|
||||
| |
|
||||
| Driver for Roccat Kone Pro |
|
||||
| |
|
||||
| Garrett Denham (GardenOfWyers) 12 Jan 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define ROCCAT_KONE_PRO_CONTROL_MODE_PACKET_LENGTH 6
|
||||
#define ROCCAT_KONE_PRO_DIRECT_MODE_PACKET_LENGTH 11
|
||||
#define ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH 69
|
||||
#define ROCCAT_KONE_PRO_FLASH_REPORT_ID 0x06
|
||||
#define ROCCAT_KONE_PRO_DIRECT_MODE_REPORT_ID 0x0D
|
||||
#define ROCCAT_KONE_PRO_DIRECT_MODE_BYTE 0x0B
|
||||
#define ROCCAT_KONE_PRO_LED_COUNT 2
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_KONE_PRO_DIRECT_MODE_VALUE = 0x00,
|
||||
ROCCAT_KONE_PRO_STATIC_MODE_VALUE = 0x01,
|
||||
ROCCAT_KONE_PRO_WAVE_MODE_VALUE = 0x0A,
|
||||
ROCCAT_KONE_PRO_HEARTBEAT_MODE_VALUE = 0x04,
|
||||
ROCCAT_KONE_PRO_BREATHING_MODE_VALUE = 0x03,
|
||||
ROCCAT_KONE_PRO_BLINKING_MODE_VALUE = 0x02
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_KONE_PRO_SPEED_MIN = 0x01,
|
||||
ROCCAT_KONE_PRO_SPEED_MAX = 0x0B,
|
||||
ROCCAT_KONE_PRO_SPEED_MID = (ROCCAT_KONE_PRO_SPEED_MAX - ROCCAT_KONE_PRO_SPEED_MIN) / 2,
|
||||
ROCCAT_KONE_PRO_BRIGHTNESS_MIN = 0x00,
|
||||
ROCCAT_KONE_PRO_BRIGHTNESS_MAX = 0xFF
|
||||
};
|
||||
|
||||
class RoccatKoneProController
|
||||
{
|
||||
public:
|
||||
RoccatKoneProController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name);
|
||||
~RoccatKoneProController();
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetNameString();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SetupDirectMode();
|
||||
void SendDirect(std::vector<RGBColor> colors);
|
||||
void SetMode(std::vector<RGBColor> colors,
|
||||
unsigned char mode_value,
|
||||
unsigned char speed,
|
||||
unsigned char brightness,
|
||||
unsigned int color_mode,
|
||||
unsigned int mode_flags
|
||||
);
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
unsigned int CalculateCRC(unsigned char* bytes);
|
||||
void SwitchControl(bool direct);
|
||||
};
|
||||
@@ -0,0 +1,285 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKoneXP.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Kone XP |
|
||||
| |
|
||||
| Mola19 12 Jun 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RoccatKoneXP.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Kone XP Mouse
|
||||
@category Mouse
|
||||
@type USB
|
||||
@save :robot:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectRoccatKoneXPControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatKoneXP::RGBController_RoccatKoneXP(RoccatKoneXPController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetName();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_MOUSE;
|
||||
description = "Roccat Kone XP Mouse Device";
|
||||
version = controller->GetVersion();
|
||||
location = controller->GetLocation();
|
||||
serial = controller->GetSerial();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = ROCCAT_KONE_XP_MODE_DIRECT;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.value = ROCCAT_KONE_XP_MODE_OFF;
|
||||
Off.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Off);
|
||||
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = ROCCAT_KONE_XP_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_KONE_XP_BRIGHTNESS_DEFAULT;
|
||||
Static.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN;
|
||||
Static.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX;
|
||||
modes.push_back(Static);
|
||||
|
||||
mode Rainbow;
|
||||
Rainbow.name = "Rainbow";
|
||||
Rainbow.value = ROCCAT_KONE_XP_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_KONE_XP_BRIGHTNESS_DEFAULT;
|
||||
Rainbow.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN;
|
||||
Rainbow.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX;
|
||||
Rainbow.speed = ROCCAT_KONE_XP_SPEED_DEFAULT;
|
||||
Rainbow.speed_min = ROCCAT_KONE_XP_SPEED_MIN;
|
||||
Rainbow.speed_max = ROCCAT_KONE_XP_SPEED_MAX;
|
||||
modes.push_back(Rainbow);
|
||||
|
||||
mode Blinking;
|
||||
Blinking.name = "Blinking";
|
||||
Blinking.value = ROCCAT_KONE_XP_MODE_BLINKING;
|
||||
Blinking.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED;
|
||||
Blinking.color_mode = MODE_COLORS_PER_LED;
|
||||
Blinking.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT;
|
||||
Blinking.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN;
|
||||
Blinking.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX;
|
||||
Blinking.speed = ROCCAT_KONE_XP_SPEED_DEFAULT;
|
||||
Blinking.speed_min = ROCCAT_KONE_XP_SPEED_MIN;
|
||||
Blinking.speed_max = ROCCAT_KONE_XP_SPEED_MAX;
|
||||
modes.push_back(Blinking);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = ROCCAT_KONE_XP_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_KONE_XP_BRIGHTNESS_DEFAULT;
|
||||
Breathing.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN;
|
||||
Breathing.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX;
|
||||
Breathing.speed = ROCCAT_KONE_XP_SPEED_DEFAULT;
|
||||
Breathing.speed_min = ROCCAT_KONE_XP_SPEED_MIN;
|
||||
Breathing.speed_max = ROCCAT_KONE_XP_SPEED_MAX;
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Heartbeat;
|
||||
Heartbeat.name = "Heartbeat";
|
||||
Heartbeat.value = ROCCAT_KONE_XP_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_KONE_XP_BRIGHTNESS_DEFAULT;
|
||||
Heartbeat.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN;
|
||||
Heartbeat.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX;
|
||||
Heartbeat.speed = ROCCAT_KONE_XP_SPEED_DEFAULT;
|
||||
Heartbeat.speed_min = ROCCAT_KONE_XP_SPEED_MIN;
|
||||
Heartbeat.speed_max = ROCCAT_KONE_XP_SPEED_MAX;
|
||||
modes.push_back(Heartbeat);
|
||||
|
||||
mode Photon;
|
||||
Photon.name = "Photon FX";
|
||||
Photon.value = ROCCAT_KONE_XP_MODE_PHOTON_FX;
|
||||
Photon.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Photon.color_mode = MODE_COLORS_NONE;
|
||||
Photon.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT;
|
||||
Photon.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN;
|
||||
Photon.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX;
|
||||
modes.push_back(Photon);
|
||||
|
||||
/*---------------------------------------------------------------------*\
|
||||
| This is the default mode for software modes, while swarm isn't active |
|
||||
\*---------------------------------------------------------------------*/
|
||||
mode Default;
|
||||
Default.name = "Default";
|
||||
Default.value = ROCCAT_KONE_XP_MODE_DEFAULT;
|
||||
Default.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Default.color_mode = MODE_COLORS_NONE;
|
||||
Default.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT;
|
||||
Default.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN;
|
||||
Default.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX;
|
||||
modes.push_back(Default);
|
||||
|
||||
SetupZones();
|
||||
|
||||
uint8_t active_profile = controller->GetActiveProfile();
|
||||
controller->SetReadProfile(active_profile);
|
||||
controller->WaitUntilReady();
|
||||
|
||||
roccat_kone_xp_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;
|
||||
|
||||
for(uint8_t i = 0; i < 20; i++)
|
||||
{
|
||||
colors[i] = active.colors[i].color;
|
||||
}
|
||||
}
|
||||
|
||||
RGBController_RoccatKoneXP::~RGBController_RoccatKoneXP()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneXP::SetupZones()
|
||||
{
|
||||
zone left;
|
||||
left.name = "Left";
|
||||
left.type = ZONE_TYPE_LINEAR;
|
||||
left.leds_min = 9;
|
||||
left.leds_max = 9;
|
||||
left.leds_count = 9;
|
||||
left.matrix_map = NULL;
|
||||
zones.push_back(left);
|
||||
|
||||
for (uint8_t i = 1; i <= 9; i++) {
|
||||
led left_led;
|
||||
left_led.name = "Left LED " + std::to_string(i);
|
||||
leds.push_back(left_led);
|
||||
}
|
||||
|
||||
zone right;
|
||||
right.name = "Right";
|
||||
right.type = ZONE_TYPE_LINEAR;
|
||||
right.leds_min = 9;
|
||||
right.leds_max = 9;
|
||||
right.leds_count = 9;
|
||||
right.matrix_map = NULL;
|
||||
zones.push_back(right);
|
||||
|
||||
for (uint8_t i = 1; i <= 9; i++) {
|
||||
led left_led;
|
||||
left_led.name = "Right LED " + std::to_string(i);
|
||||
leds.push_back(left_led);
|
||||
}
|
||||
|
||||
zone wheel;
|
||||
wheel.name = "Scrollwheel";
|
||||
wheel.type = ZONE_TYPE_SINGLE;
|
||||
wheel.leds_min = 1;
|
||||
wheel.leds_max = 1;
|
||||
wheel.leds_count = 1;
|
||||
wheel.matrix_map = NULL;
|
||||
zones.push_back(wheel);
|
||||
|
||||
led wheel_led;
|
||||
wheel_led.name = "Scrollwheel LED";
|
||||
leds.push_back(wheel_led);
|
||||
|
||||
zone dpi;
|
||||
dpi.name = "DPI button";
|
||||
dpi.type = ZONE_TYPE_SINGLE;
|
||||
dpi.leds_min = 1;
|
||||
dpi.leds_max = 1;
|
||||
dpi.leds_count = 1;
|
||||
dpi.matrix_map = NULL;
|
||||
zones.push_back(dpi);
|
||||
|
||||
led dpi_led;
|
||||
dpi_led.name = "DPI button LED";
|
||||
leds.push_back(dpi_led);
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneXP::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneXP::DeviceUpdateLEDs()
|
||||
{
|
||||
if(modes[active_mode].value == ROCCAT_KONE_XP_MODE_DIRECT)
|
||||
{
|
||||
controller->SendDirect(colors);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceUpdateMode();
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneXP::UpdateZoneLEDs(int /*zone_idx*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneXP::UpdateSingleLED(int /*led_idx*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKoneXP::DeviceUpdateMode()
|
||||
{
|
||||
mode selected = modes[active_mode];
|
||||
|
||||
roccat_kone_xp_mode_struct active = controller->GetMode();
|
||||
|
||||
active.mode = selected.value;
|
||||
active.speed = selected.speed;
|
||||
active.brightness = (modes[active_mode].value == ROCCAT_KONE_XP_MODE_DIRECT) ? 0xFF : selected.brightness;
|
||||
|
||||
for(uint8_t i = 0; i < 20; i++)
|
||||
{
|
||||
active.colors[i].color = colors[i];
|
||||
}
|
||||
|
||||
controller->SetMode(active);
|
||||
controller->WaitUntilReady();
|
||||
|
||||
controller->EnableDirect(selected.value == ROCCAT_KONE_XP_MODE_DIRECT);
|
||||
controller->WaitUntilReady();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKoneXP.h |
|
||||
| |
|
||||
| RGBController for Roccat Kone XP |
|
||||
| |
|
||||
| Mola19 12 Jun 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatKoneXPController.h"
|
||||
|
||||
class RGBController_RoccatKoneXP : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatKoneXP(RoccatKoneXPController* controller_ptr);
|
||||
~RGBController_RoccatKoneXP();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatKoneXPController* controller;
|
||||
};
|
||||
@@ -0,0 +1,308 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKoneXPController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Kone XP |
|
||||
| |
|
||||
| Mola19 12 Jun 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include "LogManager.h"
|
||||
#include "RoccatKoneXPController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatKoneXPController::RoccatKoneXPController(hid_device* dev_handle, char *path, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
RoccatKoneXPController::~RoccatKoneXPController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatKoneXPController::GetLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatKoneXPController::GetName()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatKoneXPController::GetSerial()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
|
||||
}
|
||||
|
||||
std::string RoccatKoneXPController::GetVersion()
|
||||
{
|
||||
uint8_t buf[9] = { 0x09 };
|
||||
int return_length = hid_get_feature_report(dev, buf, 9);
|
||||
|
||||
if(return_length == -1)
|
||||
{
|
||||
LOG_DEBUG("[Roccat Kone XP]: Could not fetch version. HIDAPI Error: %ls", hid_error(dev));
|
||||
return std::string("Unknown");
|
||||
}
|
||||
|
||||
char version[5];
|
||||
snprintf(version, 5, "%d.%02d", buf[2] / 100, buf[2] % 100);
|
||||
|
||||
return std::string(version);
|
||||
}
|
||||
|
||||
uint8_t RoccatKoneXPController::GetActiveProfile()
|
||||
{
|
||||
uint8_t buf[4] = { 0x05 };
|
||||
int return_length = hid_get_feature_report(dev, buf, 4);
|
||||
|
||||
if(return_length == -1)
|
||||
{
|
||||
LOG_DEBUG("[Roccat Kone XP]: Could not fetch active profile. HIDAPI Error: %ls", hid_error(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return buf[2];
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
roccat_kone_xp_mode_struct RoccatKoneXPController::GetMode()
|
||||
{
|
||||
uint8_t buf[0xAE] = { 0x06 };
|
||||
int return_length = hid_get_feature_report(dev, buf, 0xAE);
|
||||
|
||||
if(return_length == -1)
|
||||
{
|
||||
LOG_DEBUG("[Roccat Kone XP]: Could not fetch mode. HIDAPI Error: %ls", hid_error(dev));
|
||||
roccat_kone_xp_mode_struct default_mode;
|
||||
return default_mode;
|
||||
}
|
||||
|
||||
roccat_kone_xp_mode_struct active_mode;
|
||||
|
||||
active_mode.profile = buf[2];
|
||||
active_mode.byte_3 = buf[3];
|
||||
active_mode.byte_4 = buf[4];
|
||||
active_mode.dpi_flag = buf[5];
|
||||
active_mode.byte_6 = buf[6];
|
||||
|
||||
for(uint8_t i = 0; i < 10; i++)
|
||||
{
|
||||
active_mode.dpi[i] = (buf[8 + i * 2] << 8) + buf[7 + i * 2];
|
||||
}
|
||||
|
||||
active_mode.angle_snapping = (bool) buf[27];
|
||||
active_mode.byte_28 = buf[28];
|
||||
active_mode.polling_rate = buf[29];
|
||||
active_mode.mode = buf[30];
|
||||
active_mode.speed = buf[31];
|
||||
active_mode.brightness = buf[32];
|
||||
active_mode.time_until_idle = buf[33];
|
||||
active_mode.idle_mode = buf[34];
|
||||
active_mode.byte_35 = buf[35];
|
||||
|
||||
for(uint8_t i = 0; i < 20; i++)
|
||||
{
|
||||
active_mode.colors[i].brightness = buf[37 + i * 6];
|
||||
active_mode.colors[i].color = ToRGBColor(
|
||||
buf[38 + i * 6],
|
||||
buf[39 + i * 6],
|
||||
buf[40 + i * 6]
|
||||
);
|
||||
}
|
||||
|
||||
active_mode.byte_156 = buf[156];
|
||||
active_mode.byte_157 = buf[157];
|
||||
active_mode.profile_color_brightness = buf[158];
|
||||
active_mode.profile_color_red = buf[159];
|
||||
active_mode.profile_color_green = buf[160];
|
||||
active_mode.profile_color_blue = buf[161];
|
||||
active_mode.byte_162 = buf[162];
|
||||
active_mode.theme = buf[163];
|
||||
active_mode.auto_dpi_flag = buf[164];
|
||||
|
||||
active_mode.end_bytes[0] = buf[165];
|
||||
active_mode.end_bytes[1] = buf[166];
|
||||
active_mode.end_bytes[2] = buf[167];
|
||||
active_mode.end_bytes[3] = buf[168];
|
||||
active_mode.end_bytes[4] = buf[169];
|
||||
active_mode.end_bytes[5] = buf[170];
|
||||
active_mode.end_bytes[6] = buf[171];
|
||||
|
||||
return active_mode;
|
||||
}
|
||||
|
||||
void RoccatKoneXPController::EnableDirect(bool on_off_switch)
|
||||
{
|
||||
unsigned char usb_buf[6];
|
||||
|
||||
usb_buf[0x00] = 0x0E;
|
||||
usb_buf[0x01] = 0x06;
|
||||
usb_buf[0x02] = 0x01;
|
||||
usb_buf[0x03] = on_off_switch;
|
||||
usb_buf[0x04] = 0x00;
|
||||
usb_buf[0x05] = 0xFF;
|
||||
|
||||
int return_length = hid_send_feature_report(dev, usb_buf, 6);
|
||||
|
||||
if(return_length == -1)
|
||||
{
|
||||
LOG_DEBUG("[Roccat Kone XP]: Could not send mode. HIDAPI Error: %ls", hid_error(dev));
|
||||
}
|
||||
}
|
||||
|
||||
void RoccatKoneXPController::SetReadProfile(uint8_t profile)
|
||||
{
|
||||
unsigned char usb_buf[4];
|
||||
|
||||
usb_buf[0x00] = 0x04;
|
||||
usb_buf[0x01] = profile;
|
||||
usb_buf[0x02] = 0x80;
|
||||
usb_buf[0x03] = 0xFF;
|
||||
|
||||
int return_length = hid_send_feature_report(dev, usb_buf, 4);
|
||||
|
||||
if(return_length == -1)
|
||||
{
|
||||
LOG_DEBUG("[Roccat Kone XP]: Could not set profile to read. HIDAPI Error: %ls", hid_error(dev));
|
||||
}
|
||||
}
|
||||
|
||||
void RoccatKoneXPController::SetMode(roccat_kone_xp_mode_struct mode)
|
||||
{
|
||||
uint8_t buf[0xAE];
|
||||
memset(buf, 0x00, 0xAE);
|
||||
|
||||
buf[0x00] = 0x06;
|
||||
buf[0x01] = 0xAE;
|
||||
|
||||
buf[0x02] = mode.profile;
|
||||
buf[0x03] = mode.byte_3;
|
||||
buf[0x04] = mode.byte_4;
|
||||
buf[0x05] = mode.dpi_flag;
|
||||
buf[0x06] = mode.byte_6;
|
||||
|
||||
for(uint8_t i = 0; i < 10; i++)
|
||||
{
|
||||
buf[0x07 + i * 2] = mode.dpi[i] & 0xFF;
|
||||
buf[0x08 + i * 2] = mode.dpi[i] >> 8;
|
||||
}
|
||||
|
||||
buf[0x1B] = mode.angle_snapping;
|
||||
buf[0x1C] = mode.byte_28;
|
||||
buf[0x1D] = mode.polling_rate;
|
||||
buf[0x1E] = mode.mode;
|
||||
buf[0x1F] = mode.speed;
|
||||
buf[0x20] = mode.brightness;
|
||||
buf[0x21] = mode.time_until_idle;
|
||||
buf[0x22] = mode.idle_mode;
|
||||
buf[0x23] = mode.byte_35;
|
||||
|
||||
for(uint8_t i = 0; i < 20; i++)
|
||||
{
|
||||
buf[0x24 + i * 6] = mode.colors[i].byte_0;
|
||||
buf[0x25 + i * 6] = 0xFF;
|
||||
buf[0x26 + i * 6] = RGBGetRValue(mode.colors[i].color);
|
||||
buf[0x27 + i * 6] = RGBGetGValue(mode.colors[i].color);
|
||||
buf[0x28 + i * 6] = RGBGetBValue(mode.colors[i].color);
|
||||
buf[0x29 + i * 6] = mode.colors[i].byte_5;
|
||||
}
|
||||
|
||||
buf[0x9C] = mode.byte_156;
|
||||
buf[0x9D] = mode.byte_157;
|
||||
buf[0x9E] = mode.profile_color_brightness;
|
||||
buf[0x9F] = mode.profile_color_red;
|
||||
buf[0xA0] = mode.profile_color_green;
|
||||
buf[0xA1] = mode.profile_color_blue;
|
||||
buf[0xA2] = mode.byte_162;
|
||||
buf[0xA3] = mode.theme & ~0x80; // this stores the swarm intern selected theme (biggest bit is a flag for custom theme)
|
||||
buf[0xA4] = mode.auto_dpi_flag;
|
||||
|
||||
for(uint8_t i = 0; i < 7; i++)
|
||||
{
|
||||
buf[0xA5 + i] = mode.end_bytes[i];
|
||||
}
|
||||
|
||||
unsigned short total = 0;
|
||||
for(int i = 0; i < 0xAE - 2; i++) total += buf[i];
|
||||
|
||||
buf[0xAE - 2] = total & 0xFF;
|
||||
buf[0xAE - 1] = total >> 8;
|
||||
|
||||
|
||||
int return_length = hid_send_feature_report(dev, buf, 0xAE);
|
||||
|
||||
if(return_length == -1)
|
||||
{
|
||||
LOG_DEBUG("[Roccat Kone XP]: Could not send mode. HIDAPI Error: %ls", hid_error(dev));
|
||||
}
|
||||
}
|
||||
|
||||
void RoccatKoneXPController::SendDirect(std::vector<RGBColor> colors)
|
||||
{
|
||||
uint8_t buf[0x7A];
|
||||
memset(buf, 0x00, 0x7A);
|
||||
|
||||
buf[0x00] = 0x0D;
|
||||
buf[0x01] = 0x7A;
|
||||
|
||||
for(uint8_t i = 0; i < colors.size() && i < 20; i++)
|
||||
{
|
||||
/*-----------------------------------------------------------*\
|
||||
| This device uses rgbrgb which means that e.g. the red value |
|
||||
| is calculated by multiplying both given red values. |
|
||||
| Maybe it is some sort of brightness? |
|
||||
| For OpenRGBs purpose these aren't usefull, |
|
||||
| so the second part is always 0xff. |
|
||||
\*-----------------------------------------------------------*/
|
||||
buf[0x02 + i * 6] = RGBGetRValue(colors[i]);
|
||||
buf[0x03 + i * 6] = RGBGetGValue(colors[i]);
|
||||
buf[0x04 + i * 6] = RGBGetBValue(colors[i]);
|
||||
buf[0x05 + i * 6] = 0xFF;
|
||||
buf[0x06 + i * 6] = 0xFF;
|
||||
buf[0x07 + i * 6] = 0xFF;
|
||||
}
|
||||
|
||||
int return_length = hid_send_feature_report(dev, buf, 0x7A);
|
||||
|
||||
if(return_length == -1)
|
||||
{
|
||||
LOG_DEBUG("[Roccat Kone XP]: Could not send direct. HIDAPI Error: %ls", hid_error(dev));
|
||||
}
|
||||
}
|
||||
|
||||
void RoccatKoneXPController::WaitUntilReady()
|
||||
{
|
||||
uint8_t buf[4];
|
||||
memset(buf, 0x00, 4);
|
||||
|
||||
buf[0] = 0x04;
|
||||
|
||||
for(unsigned char i = 0; buf[1] != 1 && i < 100; i++)
|
||||
{
|
||||
if(i != 0)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
|
||||
hid_get_feature_report(dev, buf, 4);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKoneXPController.h |
|
||||
| |
|
||||
| Driver for Roccat Kone XP |
|
||||
| |
|
||||
| Mola19 12 Jun 2024 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_KONE_XP_MODE_DIRECT = 0x0B,
|
||||
ROCCAT_KONE_XP_MODE_OFF = 0x00,
|
||||
ROCCAT_KONE_XP_MODE_STATIC = 0x01,
|
||||
ROCCAT_KONE_XP_MODE_BLINKING = 0x02,
|
||||
ROCCAT_KONE_XP_MODE_BREATHING = 0x03,
|
||||
ROCCAT_KONE_XP_MODE_HEARTBEAT = 0x04,
|
||||
ROCCAT_KONE_XP_MODE_PHOTON_FX = 0x05,
|
||||
ROCCAT_KONE_XP_MODE_DEFAULT = 0x09,
|
||||
ROCCAT_KONE_XP_MODE_WAVE = 0x0A
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_KONE_XP_SPEED_MIN = 0x0B,
|
||||
ROCCAT_KONE_XP_SPEED_MAX = 0x01,
|
||||
ROCCAT_KONE_XP_SPEED_DEFAULT = 0x06,
|
||||
ROCCAT_KONE_XP_BRIGHTNESS_MIN = 0x00,
|
||||
ROCCAT_KONE_XP_BRIGHTNESS_MAX = 0xFF,
|
||||
ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT = 0xFF
|
||||
};
|
||||
|
||||
struct roccat_kone_xp_color_struct
|
||||
{
|
||||
uint8_t byte_0 = 0x14;
|
||||
uint8_t brightness = 0xFF;
|
||||
RGBColor color = 0;
|
||||
uint8_t byte_5 = 0x64;
|
||||
};
|
||||
|
||||
struct roccat_kone_xp_mode_struct
|
||||
{
|
||||
uint8_t profile = 0;
|
||||
uint8_t byte_3 = 0x06;
|
||||
uint8_t byte_4 = 0x06;
|
||||
uint8_t dpi_flag = 0x1F;
|
||||
uint8_t byte_6 = 0x01;
|
||||
uint16_t dpi[10] = { 0x08, 0x10, 0x18, 0x20, 0x40, 0x08, 0x10, 0x18, 0x20, 0x40 };
|
||||
bool angle_snapping = false;
|
||||
uint8_t byte_28 = 0x00;
|
||||
uint8_t polling_rate = 0x03;
|
||||
uint8_t mode = ROCCAT_KONE_XP_MODE_STATIC;
|
||||
uint8_t speed = 0x00;
|
||||
uint8_t brightness = 0xFF;
|
||||
uint8_t time_until_idle = 0x0F;
|
||||
uint8_t idle_mode = 0x00;
|
||||
uint8_t byte_35 = 0x00;
|
||||
roccat_kone_xp_color_struct colors[20];
|
||||
uint8_t byte_156 = 0x01;
|
||||
uint8_t byte_157 = 0x64;
|
||||
uint8_t profile_color_brightness = 0xFF;
|
||||
uint8_t profile_color_red = 0xFF;
|
||||
uint8_t profile_color_green = 0x00;
|
||||
uint8_t profile_color_blue = 0x00;
|
||||
uint8_t byte_162 = 0x00;
|
||||
uint8_t theme = 0x80;
|
||||
uint8_t auto_dpi_flag = 0x00;
|
||||
uint8_t end_bytes[7] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
};
|
||||
|
||||
class RoccatKoneXPController
|
||||
{
|
||||
public:
|
||||
RoccatKoneXPController(hid_device* dev_handle, char *path, std::string dev_name);
|
||||
~RoccatKoneXPController();
|
||||
|
||||
std::string GetLocation();
|
||||
std::string GetName();
|
||||
std::string GetSerial();
|
||||
std::string GetVersion();
|
||||
|
||||
uint8_t GetActiveProfile();
|
||||
roccat_kone_xp_mode_struct GetMode();
|
||||
|
||||
void EnableDirect(bool on_off_switch);
|
||||
void SetReadProfile(uint8_t profile);
|
||||
void SendDirect(std::vector<RGBColor> colors);
|
||||
void SetMode(roccat_kone_xp_mode_struct mode);
|
||||
|
||||
void WaitUntilReady();
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
};
|
||||
@@ -0,0 +1,147 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKova.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Kova |
|
||||
| |
|
||||
| Gustash 01 Dec 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_RoccatKova.h"
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Kova
|
||||
@category Mouse
|
||||
@type USB
|
||||
@save :robot:
|
||||
@direct :x:
|
||||
@effects :white_check_mark:
|
||||
@detectors RoccatControllerDetect
|
||||
@comment Color Flow mode is only supported starting at the first
|
||||
preset color in the mouse's memory, and color offsets for each LED
|
||||
are not supported. You'd need to use Swarm if you intend to use that
|
||||
specific feature.
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatKova::RGBController_RoccatKova(RoccatKovaController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetName();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_MOUSE;
|
||||
description = "Roccat Kova Mouse Device";
|
||||
serial = controller->GetSerial();
|
||||
location = controller->GetLocation();
|
||||
version = controller->GetVersion();
|
||||
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = ROCCAT_KOVA_MODE_STATIC;
|
||||
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Static.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Static);
|
||||
|
||||
mode ColorFlow;
|
||||
ColorFlow.name = "Color Flow";
|
||||
ColorFlow.value = ROCCAT_KOVA_MODE_COLOR_FLOW;
|
||||
ColorFlow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE;
|
||||
ColorFlow.color_mode = MODE_COLORS_RANDOM;
|
||||
ColorFlow.speed_min = ROCCAT_KOVA_SPEED_MIN;
|
||||
ColorFlow.speed_max = ROCCAT_KOVA_SPEED_MAX;
|
||||
modes.push_back(ColorFlow);
|
||||
|
||||
mode Flashing;
|
||||
Flashing.name = "Flashing";
|
||||
Flashing.value = ROCCAT_KOVA_MODE_FLASHING;
|
||||
Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Flashing.color_mode = MODE_COLORS_PER_LED;
|
||||
Flashing.speed_min = ROCCAT_KOVA_SPEED_MIN;
|
||||
Flashing.speed_max = ROCCAT_KOVA_SPEED_MAX;
|
||||
modes.push_back(Flashing);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = ROCCAT_KOVA_MODE_BREATHING;
|
||||
Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Breathing.color_mode = MODE_COLORS_PER_LED;
|
||||
Breathing.speed_min = ROCCAT_KOVA_SPEED_MIN;
|
||||
Breathing.speed_max = ROCCAT_KOVA_SPEED_MAX;
|
||||
modes.push_back(Breathing);
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.value = 0x00;
|
||||
Off.flags = MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Off);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatKova::~RGBController_RoccatKova()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatKova::SetupZones()
|
||||
{
|
||||
zone Mouse;
|
||||
Mouse.name = "Mouse";
|
||||
Mouse.type = ZONE_TYPE_LINEAR;
|
||||
Mouse.leds_count = ROCCAT_KOVA_LED_COUNT;
|
||||
Mouse.leds_min = ROCCAT_KOVA_LED_COUNT;
|
||||
Mouse.leds_max = ROCCAT_KOVA_LED_COUNT;
|
||||
Mouse.matrix_map = NULL;
|
||||
zones.push_back(Mouse);
|
||||
|
||||
led WheelLED;
|
||||
WheelLED.name = "Wheel LED";
|
||||
WheelLED.value = ROCCAT_KOVA_WHEEL_IDX;
|
||||
leds.push_back(WheelLED);
|
||||
|
||||
led StripeLED;
|
||||
StripeLED.name = "Stripe LED";
|
||||
StripeLED.value = ROCCAT_KOVA_PIPE_IDX;
|
||||
leds.push_back(StripeLED);
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKova::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatKova::DeviceUpdateLEDs()
|
||||
{
|
||||
DeviceUpdateMode();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKova::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateMode();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKova::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateMode();
|
||||
}
|
||||
|
||||
void RGBController_RoccatKova::DeviceUpdateMode()
|
||||
{
|
||||
mode &active = modes[active_mode];
|
||||
int mode = active.value;
|
||||
bool is_color_flow = active.color_mode == MODE_COLORS_RANDOM;
|
||||
if(active.value == ROCCAT_KOVA_MODE_COLOR_FLOW)
|
||||
{
|
||||
mode = ROCCAT_KOVA_MODE_STATIC;
|
||||
is_color_flow = true;
|
||||
}
|
||||
|
||||
controller->SetColor(colors[0], colors[1], mode, active.speed, is_color_flow);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatKova.h |
|
||||
| |
|
||||
| RGBController for Roccat Kova |
|
||||
| |
|
||||
| Gustash 01 Dec 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatKovaController.h"
|
||||
|
||||
class RGBController_RoccatKova : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatKova(RoccatKovaController *controller_ptr);
|
||||
~RGBController_RoccatKova();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatKovaController *controller;
|
||||
};
|
||||
@@ -0,0 +1,147 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKovaController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Kova |
|
||||
| |
|
||||
| Gustash 01 Dec 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "LogManager.h"
|
||||
#include "RoccatKovaController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatKovaController::RoccatKovaController(hid_device* dev_handle, char *path, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
name = dev_name;
|
||||
|
||||
SendInitialPacket();
|
||||
FetchFirmwareVersion();
|
||||
}
|
||||
|
||||
RoccatKovaController::~RoccatKovaController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatKovaController::GetLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatKovaController::GetName()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatKovaController::GetSerial()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
std::string RoccatKovaController::GetVersion()
|
||||
{
|
||||
return(version);
|
||||
}
|
||||
|
||||
void RoccatKovaController::SetColor(RGBColor color_wheel,
|
||||
RGBColor color_stripe,
|
||||
uint8_t mode,
|
||||
uint8_t speed,
|
||||
bool color_flow)
|
||||
{
|
||||
bool is_off = mode == ROCCAT_KOVA_MODE_OFF;
|
||||
uint8_t report_buf[ROCCAT_KOVA_PROFILE_WRITE_PACKET_SIZE] {00};
|
||||
FetchProfileData(report_buf);
|
||||
|
||||
report_buf[0x0] = ROCCAT_KOVA_PROFILE_REPORT_ID;
|
||||
report_buf[0x1] = ROCCAT_KOVA_PROFILE_WRITE_PACKET_SIZE;
|
||||
|
||||
report_buf[ROCCAT_KOVA_FLAGS_IDX] |= ROCCAT_KOVA_USE_CUSTOM_COLORS_MASK;
|
||||
if(is_off)
|
||||
{
|
||||
report_buf[ROCCAT_KOVA_FLAGS_IDX] &= ~ROCCAT_KOVA_LIGHTS_ON_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
report_buf[ROCCAT_KOVA_FLAGS_IDX] |= ROCCAT_KOVA_LIGHTS_ON_MASK;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Set colors for each LED and reset the selected |
|
||||
| preset color to ensure consistency |
|
||||
\*-------------------------------------------------*/
|
||||
report_buf[ROCCAT_KOVA_WHEEL_IDX] = 0x0;
|
||||
report_buf[ROCCAT_KOVA_WHEEL_IDX + ROCCAT_KOVA_R_OFFSET] = RGBGetRValue(color_wheel);
|
||||
report_buf[ROCCAT_KOVA_WHEEL_IDX + ROCCAT_KOVA_G_OFFSET] = RGBGetGValue(color_wheel);
|
||||
report_buf[ROCCAT_KOVA_WHEEL_IDX + ROCCAT_KOVA_B_OFFSET] = RGBGetBValue(color_wheel);
|
||||
report_buf[ROCCAT_KOVA_PIPE_IDX] = 0x0;
|
||||
report_buf[ROCCAT_KOVA_PIPE_IDX + ROCCAT_KOVA_R_OFFSET] = RGBGetRValue(color_stripe);
|
||||
report_buf[ROCCAT_KOVA_PIPE_IDX + ROCCAT_KOVA_G_OFFSET] = RGBGetGValue(color_stripe);
|
||||
report_buf[ROCCAT_KOVA_PIPE_IDX + ROCCAT_KOVA_B_OFFSET] = RGBGetBValue(color_stripe);
|
||||
|
||||
report_buf[ROCCAT_KOVA_COLOR_FLOW_IDX] = color_flow;
|
||||
if(!is_off)
|
||||
{
|
||||
report_buf[ROCCAT_KOVA_MODE_IDX] = mode;
|
||||
}
|
||||
report_buf[ROCCAT_KOVA_EFFECT_SPEED_IDX] = speed;
|
||||
|
||||
uint16_t checksum = GenerateChecksum(report_buf, sizeof(report_buf) - 2);
|
||||
|
||||
report_buf[ROCCAT_KOVA_CHECKSUM_IDX] = checksum & 0xFF;
|
||||
report_buf[ROCCAT_KOVA_CHECKSUM_IDX + 1] = checksum >> 8;
|
||||
|
||||
hid_send_feature_report(dev, report_buf, ROCCAT_KOVA_PROFILE_WRITE_PACKET_SIZE);
|
||||
}
|
||||
|
||||
void RoccatKovaController::SendInitialPacket()
|
||||
{
|
||||
uint8_t buf[ROCCAT_KOVA_INIT_WRITE_PACKET_SIZE] {00};
|
||||
buf[0x00] = ROCCAT_KOVA_INIT_REPORT_ID;
|
||||
buf[0x01] = 0x00;
|
||||
buf[0x02] = 0x80;
|
||||
hid_send_feature_report(dev, buf, ROCCAT_KOVA_INIT_WRITE_PACKET_SIZE);
|
||||
}
|
||||
|
||||
void RoccatKovaController::FetchFirmwareVersion()
|
||||
{
|
||||
uint8_t buf[ROCCAT_KOVA_VERSION_READ_PACKET_SIZE] {00};
|
||||
buf[0x0] = ROCCAT_KOVA_VERSION_REPORT_ID;
|
||||
|
||||
hid_get_feature_report(dev, buf, ROCCAT_KOVA_VERSION_READ_PACKET_SIZE);
|
||||
|
||||
uint8_t fw_version = buf[ROCCAT_KOVA_FIRMWARE_VERSION_IDX];
|
||||
char version_str[5] {00};
|
||||
snprintf(version_str, 5, "%.2f", fw_version / 100.);
|
||||
version = version_str;
|
||||
}
|
||||
|
||||
void RoccatKovaController::FetchProfileData(uint8_t *buf)
|
||||
{
|
||||
buf[0x00] = ROCCAT_KOVA_PROFILE_REPORT_ID;
|
||||
hid_get_feature_report(dev, buf, ROCCAT_KOVA_PROFILE_WRITE_PACKET_SIZE);
|
||||
}
|
||||
|
||||
uint16_t RoccatKovaController::GenerateChecksum(uint8_t *buf, size_t length)
|
||||
{
|
||||
uint16_t checksum = 0x0;
|
||||
for (uint8_t idx = 0; idx < length; idx++)
|
||||
{
|
||||
checksum += buf[idx];
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatKovaController.h |
|
||||
| |
|
||||
| Driver for Roccat Kova |
|
||||
| |
|
||||
| Gustash 01 Dec 2022 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
#define ROCCAT_KOVA_HID_MAX_STR 255
|
||||
#define ROCCAT_KOVA_LED_COUNT 2
|
||||
#define ROCCAT_KOVA_SPEED_MIN 1
|
||||
#define ROCCAT_KOVA_SPEED_MAX 3
|
||||
#define ROCCAT_KOVA_INIT_REPORT_ID 4
|
||||
#define ROCCAT_KOVA_INIT_WRITE_PACKET_SIZE 3
|
||||
#define ROCCAT_KOVA_PROFILE_REPORT_ID 6
|
||||
#define ROCCAT_KOVA_PROFILE_WRITE_PACKET_SIZE 28
|
||||
#define ROCCAT_KOVA_VERSION_REPORT_ID 9
|
||||
#define ROCCAT_KOVA_VERSION_READ_PACKET_SIZE 8
|
||||
/*#define NUM_OF_DPI_SWITCHES 5*/
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_KOVA_FIRMWARE_VERSION_IDX = 2,
|
||||
/*ROCCAT_KOVA_SELECTED_PROFILE_IDX = 2,*/
|
||||
/*ROCCAT_KOVA_UNKNOWN_3_IDX = 3,*/
|
||||
/*ROCCAT_KOVA_UNKNOWN_4_IDX = 4,*/
|
||||
/*ROCCAT_KOVA_ORIENTATION_IDX = 5,*/
|
||||
/*ROCCAT_KOVA_DPI_SWITCHER_IDX = 6,*/
|
||||
/*ROCCAT_KOVA_DPI_SPEED_IDX = 7,*/
|
||||
/*ROCCAT_KOVA_SELECTED_DPI_IDX = 12,*/
|
||||
/*ROCCAT_KOVA_POLLING_RATE_IDX = 13,*/
|
||||
ROCCAT_KOVA_FLAGS_IDX = 14,
|
||||
ROCCAT_KOVA_COLOR_FLOW_IDX = 15,
|
||||
ROCCAT_KOVA_MODE_IDX = 16,
|
||||
ROCCAT_KOVA_EFFECT_SPEED_IDX = 17,
|
||||
ROCCAT_KOVA_PIPE_IDX = 18,
|
||||
ROCCAT_KOVA_WHEEL_IDX = 22,
|
||||
ROCCAT_KOVA_CHECKSUM_IDX = 26,
|
||||
};
|
||||
|
||||
#define ROCCAT_KOVA_R_OFFSET 1
|
||||
#define ROCCAT_KOVA_G_OFFSET 2
|
||||
#define ROCCAT_KOVA_B_OFFSET 3
|
||||
|
||||
#define ROCCAT_KOVA_USE_CUSTOM_COLORS_MASK 0b00110000
|
||||
#define ROCCAT_KOVA_LIGHTS_ON_MASK 0b00000011
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_KOVA_MODE_OFF = 0x00,
|
||||
ROCCAT_KOVA_MODE_STATIC = 0x01,
|
||||
ROCCAT_KOVA_MODE_FLASHING = 0x02,
|
||||
ROCCAT_KOVA_MODE_BREATHING = 0x03,
|
||||
ROCCAT_KOVA_MODE_COLOR_FLOW = 0xFF,
|
||||
};
|
||||
|
||||
class RoccatKovaController
|
||||
{
|
||||
public:
|
||||
RoccatKovaController(hid_device* dev_handle, char *path, std::string dev_name);
|
||||
~RoccatKovaController();
|
||||
|
||||
std::string GetLocation();
|
||||
std::string GetName();
|
||||
std::string GetSerial();
|
||||
std::string GetVersion();
|
||||
|
||||
void SetColor(RGBColor color_wheel,
|
||||
RGBColor color_stripe,
|
||||
uint8_t mode,
|
||||
uint8_t speed,
|
||||
bool color_flow);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
std::string name;
|
||||
std::string version;
|
||||
|
||||
void SendInitialPacket();
|
||||
void FetchProfileData(uint8_t *buf);
|
||||
void FetchFirmwareVersion();
|
||||
|
||||
uint16_t GenerateChecksum(uint8_t *buf, size_t length);
|
||||
};
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatSenseAimo.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Sense Aimo |
|
||||
| |
|
||||
| Mola19 09 Aug 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#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 = controller->GetName();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_MOUSEMAT;
|
||||
description = "Roccat Sense Aimo Mousepad Device";
|
||||
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);
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatSenseAimo.h |
|
||||
| |
|
||||
| RGBController for Roccat Sense Aimo |
|
||||
| |
|
||||
| Mola19 09 Aug 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#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;
|
||||
};
|
||||
@@ -0,0 +1,152 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatSenseAimoController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Sense Aimo |
|
||||
| |
|
||||
| Mola19 09 Aug 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "LogManager.h"
|
||||
#include "RoccatSenseAimoController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatSenseAimoController::RoccatSenseAimoController(hid_device* dev_handle, char *path, std::string dev_name)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
RoccatSenseAimoController::~RoccatSenseAimoController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string RoccatSenseAimoController::GetLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatSenseAimoController::GetName()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatSenseAimoController::GetSerial()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatSenseAimoController.h |
|
||||
| |
|
||||
| Driver for Roccat Sense Aimo |
|
||||
| |
|
||||
| Mola19 09 Aug 2023 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.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, std::string dev_name);
|
||||
~RoccatSenseAimoController();
|
||||
|
||||
std::string GetLocation();
|
||||
std::string GetName();
|
||||
std::string GetSerial();
|
||||
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;
|
||||
std::string name;
|
||||
};
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatVulcanKeyboard.cpp |
|
||||
| |
|
||||
| RGBController for Roccat Vulcan keyboard |
|
||||
| |
|
||||
| Mola19 17 Dec 2021 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <vector>
|
||||
#include "RGBControllerKeyNames.h"
|
||||
#include "RGBController_RoccatVulcanKeyboard.h"
|
||||
|
||||
#define NA 0xFFFFFFFF
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Roccat Vulcan Keyboard
|
||||
@category Keyboard
|
||||
@type USB
|
||||
@save :robot:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectRoccatVulcanKeyboardControllers
|
||||
@comment The mode "Default" differs from device to device and
|
||||
and sometimes also based on which profile you are on.
|
||||
Often it is very close to the rainbow mode.
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_RoccatVulcanKeyboard::RGBController_RoccatVulcanKeyboard(RoccatVulcanKeyboardController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
pid = controller->device_pid;
|
||||
|
||||
controller->InitDeviceInfo();
|
||||
|
||||
name = controller->GetName();
|
||||
vendor = "Roccat";
|
||||
type = DEVICE_TYPE_KEYBOARD;
|
||||
description = "Roccat Vulcan Keyboard Device";
|
||||
version = controller->GetDeviceInfo().version;
|
||||
location = controller->GetLocation();
|
||||
serial = controller->GetSerial();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = ROCCAT_VULCAN_MODE_DIRECT;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
|
||||
if(pid != ROCCAT_VULCAN_120_AIMO_PID && pid != ROCCAT_VULCAN_100_AIMO_PID)
|
||||
{
|
||||
Direct.flags |= MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Direct.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN;
|
||||
Direct.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX;
|
||||
Direct.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT;
|
||||
}
|
||||
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = ROCCAT_VULCAN_MODE_STATIC;
|
||||
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Static.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN;
|
||||
Static.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX;
|
||||
Static.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT;
|
||||
Static.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Static);
|
||||
|
||||
mode Wave;
|
||||
Wave.name = "Rainbow Wave";
|
||||
Wave.value = ROCCAT_VULCAN_MODE_WAVE;
|
||||
Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Wave.speed_min = ROCCAT_VULCAN_SPEED_MIN;
|
||||
Wave.speed_max = ROCCAT_VULCAN_SPEED_MAX;
|
||||
Wave.speed = ROCCAT_VULCAN_SPEED_DEFAULT;
|
||||
Wave.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN;
|
||||
Wave.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX;
|
||||
Wave.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT;
|
||||
Wave.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Wave);
|
||||
|
||||
mode Default;
|
||||
Default.name = "Default";
|
||||
Default.value = ROCCAT_VULCAN_MODE_DEFAULT;
|
||||
Default.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE;
|
||||
Default.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN;
|
||||
Default.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX;
|
||||
Default.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT;
|
||||
Default.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Default);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_RoccatVulcanKeyboard::~RGBController_RoccatVulcanKeyboard()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_RoccatVulcanKeyboard::SetupZones()
|
||||
{
|
||||
std::map<int,layout_info> * keyboard_ptr;
|
||||
|
||||
switch(pid)
|
||||
{
|
||||
case ROCCAT_VULCAN_100_AIMO_PID:
|
||||
case ROCCAT_VULCAN_120_AIMO_PID:
|
||||
keyboard_ptr = &RoccatVulcan120AimoLayouts;
|
||||
break;
|
||||
case ROCCAT_VULCAN_TKL_PID:
|
||||
case ROCCAT_VULCAN_TKL_PRO_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_TKL_PID:
|
||||
keyboard_ptr = &RoccatVulcanTKLLayouts;
|
||||
break;
|
||||
case TURTLE_BEACH_VULCAN_II_TKL_PRO_PID:
|
||||
keyboard_ptr = &TurtleBeachVulcanIITKLProLayouts;
|
||||
break;
|
||||
case ROCCAT_VULCAN_PRO_PID:
|
||||
case ROCCAT_PYRO_PID:
|
||||
keyboard_ptr = &RoccatPyroLayouts;
|
||||
break;
|
||||
case ROCCAT_VULCAN_II_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_PID:
|
||||
keyboard_ptr = &RoccatVulcanIILayouts;
|
||||
break;
|
||||
case ROCCAT_VULCAN_II_MAX_PID:
|
||||
keyboard_ptr = &RoccatVulcanIIMaxLayouts;
|
||||
break;
|
||||
case ROCCAT_MAGMA_PID:
|
||||
case ROCCAT_MAGMA_MINI_PID:
|
||||
keyboard_ptr = &RoccatMagmaLayouts;
|
||||
break;
|
||||
default:
|
||||
keyboard_ptr = &RoccatVulcan120AimoLayouts;
|
||||
}
|
||||
|
||||
std::map<int,layout_info> & keyboard = *keyboard_ptr;
|
||||
|
||||
unsigned char layout;
|
||||
|
||||
switch(controller->GetDeviceInfo().layout_type)
|
||||
{
|
||||
case ROCCAT_VULCAN_LAYOUT_DE:
|
||||
case ROCCAT_VULCAN_LAYOUT_UK:
|
||||
case ROCCAT_VULCAN_LAYOUT_FR:
|
||||
layout = ROCCAT_VULCAN_LAYOUT_UK;
|
||||
break;
|
||||
case ROCCAT_VULCAN_LAYOUT_US:
|
||||
default:
|
||||
layout = ROCCAT_VULCAN_LAYOUT_US;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Determine zone sizes |
|
||||
| Vulcan II MAX has 108 keyboard keys + 24 secondary LEDs |
|
||||
| (physically under parent keys) + 16 palm rest LEDs. |
|
||||
| Secondary LEDs are split into labeled linear zones. |
|
||||
\*---------------------------------------------------------*/
|
||||
int keyboard_size = keyboard[layout].size;
|
||||
|
||||
if(pid == ROCCAT_VULCAN_II_MAX_PID)
|
||||
{
|
||||
keyboard_size = 108;
|
||||
}
|
||||
|
||||
zone keyboard_zone;
|
||||
keyboard_zone.name = "Keyboard";
|
||||
keyboard_zone.type = ZONE_TYPE_MATRIX;
|
||||
keyboard_zone.leds_min = keyboard_size;
|
||||
keyboard_zone.leds_max = keyboard_size;
|
||||
keyboard_zone.leds_count = keyboard_size;
|
||||
keyboard_zone.matrix_map = new matrix_map_type;
|
||||
keyboard_zone.matrix_map->height = keyboard[layout].rows;
|
||||
keyboard_zone.matrix_map->width = keyboard[layout].cols;
|
||||
keyboard_zone.matrix_map->map = keyboard[layout].matrix_map;
|
||||
zones.push_back(keyboard_zone);
|
||||
|
||||
if(pid == ROCCAT_VULCAN_II_MAX_PID)
|
||||
{
|
||||
zone fkey_ind_zone;
|
||||
fkey_ind_zone.name = "F-Key Indicators";
|
||||
fkey_ind_zone.type = ZONE_TYPE_LINEAR;
|
||||
fkey_ind_zone.leds_min = 15;
|
||||
fkey_ind_zone.leds_max = 15;
|
||||
fkey_ind_zone.leds_count = 15;
|
||||
fkey_ind_zone.matrix_map = NULL;
|
||||
zones.push_back(fkey_ind_zone);
|
||||
|
||||
zone nav1_zone;
|
||||
nav1_zone.name = "Nav Cluster Indicators";
|
||||
nav1_zone.type = ZONE_TYPE_LINEAR;
|
||||
nav1_zone.leds_min = 3;
|
||||
nav1_zone.leds_max = 3;
|
||||
nav1_zone.leds_count = 3;
|
||||
nav1_zone.matrix_map = NULL;
|
||||
zones.push_back(nav1_zone);
|
||||
|
||||
zone numlock_zone;
|
||||
numlock_zone.name = "Num Lock Indicator";
|
||||
numlock_zone.type = ZONE_TYPE_LINEAR;
|
||||
numlock_zone.leds_min = 1;
|
||||
numlock_zone.leds_max = 1;
|
||||
numlock_zone.leds_count = 1;
|
||||
numlock_zone.matrix_map = NULL;
|
||||
zones.push_back(numlock_zone);
|
||||
|
||||
zone nav2_zone;
|
||||
nav2_zone.name = "Nav Cluster Indicators 2";
|
||||
nav2_zone.type = ZONE_TYPE_LINEAR;
|
||||
nav2_zone.leds_min = 3;
|
||||
nav2_zone.leds_max = 3;
|
||||
nav2_zone.leds_count = 3;
|
||||
nav2_zone.matrix_map = NULL;
|
||||
zones.push_back(nav2_zone);
|
||||
|
||||
zone caps_zone;
|
||||
caps_zone.name = "Caps Lock Indicator";
|
||||
caps_zone.type = ZONE_TYPE_LINEAR;
|
||||
caps_zone.leds_min = 1;
|
||||
caps_zone.leds_max = 1;
|
||||
caps_zone.leds_count = 1;
|
||||
caps_zone.matrix_map = NULL;
|
||||
zones.push_back(caps_zone);
|
||||
|
||||
zone win_zone;
|
||||
win_zone.name = "Win Key Indicator";
|
||||
win_zone.type = ZONE_TYPE_LINEAR;
|
||||
win_zone.leds_min = 1;
|
||||
win_zone.leds_max = 1;
|
||||
win_zone.leds_count = 1;
|
||||
win_zone.matrix_map = NULL;
|
||||
zones.push_back(win_zone);
|
||||
|
||||
zone palmrest_zone;
|
||||
palmrest_zone.name = "Palm Rest";
|
||||
palmrest_zone.type = ZONE_TYPE_LINEAR;
|
||||
palmrest_zone.leds_min = 16;
|
||||
palmrest_zone.leds_max = 16;
|
||||
palmrest_zone.leds_count = 16;
|
||||
palmrest_zone.matrix_map = NULL;
|
||||
zones.push_back(palmrest_zone);
|
||||
}
|
||||
|
||||
for(int led_id = 0; led_id < keyboard[layout].size; led_id++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = keyboard[layout].led_names[led_id].name;
|
||||
new_led.value = keyboard[layout].led_names[led_id].id;
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| sends the init packet for the default mode (direct) |
|
||||
\*---------------------------------------------------------*/
|
||||
DeviceUpdateMode();
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatVulcanKeyboard::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_RoccatVulcanKeyboard::DeviceUpdateLEDs()
|
||||
{
|
||||
if(modes[active_mode].value == ROCCAT_VULCAN_MODE_DIRECT)
|
||||
{
|
||||
std::vector<led_color> led_color_list = {};
|
||||
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
led_color_list.push_back({ leds[i].value, colors[i] });
|
||||
}
|
||||
|
||||
controller->SendColors(led_color_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceUpdateMode();
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_RoccatVulcanKeyboard::UpdateZoneLEDs(int /*zone_idx*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatVulcanKeyboard::UpdateSingleLED(int /*led_idx*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_RoccatVulcanKeyboard::DeviceUpdateMode()
|
||||
{
|
||||
std::vector<led_color> led_color_list = {};
|
||||
|
||||
if(modes[active_mode].value == ROCCAT_VULCAN_MODE_STATIC)
|
||||
{
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
led_color_list.push_back({ leds[i].value, colors[i] });
|
||||
}
|
||||
}
|
||||
|
||||
controller->SendMode(modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, led_color_list);
|
||||
controller->WaitUntilReady();
|
||||
|
||||
controller->EnableDirect(modes[active_mode].value == ROCCAT_VULCAN_MODE_DIRECT);
|
||||
controller->WaitUntilReady();
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_RoccatVulcanKeyboard.h |
|
||||
| |
|
||||
| RGBController for Roccat Vulcan keyboard |
|
||||
| |
|
||||
| Mola19 17 Dec 2021 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "RoccatVulcanKeyboardController.h"
|
||||
|
||||
class RGBController_RoccatVulcanKeyboard : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_RoccatVulcanKeyboard(RoccatVulcanKeyboardController* controller_ptr);
|
||||
~RGBController_RoccatVulcanKeyboard();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
RoccatVulcanKeyboardController* controller;
|
||||
uint16_t pid;
|
||||
};
|
||||
+540
@@ -0,0 +1,540 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatVulcanKeyboardController.cpp |
|
||||
| |
|
||||
| Driver for Roccat Vulcan keyboard |
|
||||
| |
|
||||
| Mola19 17 Dec 2021 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "LogManager.h"
|
||||
#include "RoccatVulcanKeyboardController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
RoccatVulcanKeyboardController::RoccatVulcanKeyboardController(hid_device* dev_ctrl_handle, hid_device* dev_led_handle, char *path, uint16_t pid, std::string dev_name)
|
||||
{
|
||||
dev_ctrl = dev_ctrl_handle;
|
||||
dev_led = dev_led_handle;
|
||||
location = path;
|
||||
name = dev_name;
|
||||
device_pid = pid;
|
||||
}
|
||||
|
||||
RoccatVulcanKeyboardController::~RoccatVulcanKeyboardController()
|
||||
{
|
||||
hid_close(dev_ctrl);
|
||||
hid_close(dev_led);
|
||||
}
|
||||
|
||||
std::string RoccatVulcanKeyboardController::GetLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string RoccatVulcanKeyboardController::GetName()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string RoccatVulcanKeyboardController::GetSerial()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
int ret = hid_get_serial_number_string(dev_ctrl, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
return(StringUtils::wstring_to_string(serial_string));
|
||||
}
|
||||
|
||||
device_info RoccatVulcanKeyboardController::InitDeviceInfo()
|
||||
{
|
||||
uint8_t packet_length;
|
||||
uint8_t report_id;
|
||||
|
||||
switch(device_pid)
|
||||
{
|
||||
case ROCCAT_PYRO_PID:
|
||||
case ROCCAT_MAGMA_PID:
|
||||
case ROCCAT_MAGMA_MINI_PID:
|
||||
case ROCCAT_VULCAN_PRO_PID:
|
||||
case ROCCAT_VULCAN_TKL_PRO_PID:
|
||||
case ROCCAT_VULCAN_II_PID:
|
||||
case ROCCAT_VULCAN_II_MAX_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_TKL_PRO_PID:
|
||||
packet_length = 9;
|
||||
report_id = 0x09;
|
||||
break;
|
||||
default:
|
||||
packet_length = 8;
|
||||
report_id = 0x0F;
|
||||
}
|
||||
|
||||
uint8_t* buf = new uint8_t[packet_length];
|
||||
memset(buf, 0x00, packet_length);
|
||||
|
||||
buf[0] = report_id;
|
||||
hid_get_feature_report(dev_ctrl, buf, packet_length);
|
||||
|
||||
/*-------------------------------------------------------------*\
|
||||
| buf[2] is version e.g. 103 means v1.03 |
|
||||
\*-------------------------------------------------------------*/
|
||||
dev_info.version_major = buf[2] / 100;
|
||||
dev_info.version_minor = buf[2] % 100;
|
||||
|
||||
char version[5];
|
||||
snprintf(version, 5, "%d.%02d", dev_info.version_major, dev_info.version_minor);
|
||||
dev_info.version = version;
|
||||
|
||||
if(device_pid == ROCCAT_MAGMA_PID || device_pid == ROCCAT_MAGMA_MINI_PID)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device doesn't need a layout, |
|
||||
| because it doesn't have per-led lighting. |
|
||||
| Taking us layout as placeholder instead |
|
||||
\*---------------------------------------------------------*/
|
||||
dev_info.layout_type = ROCCAT_VULCAN_LAYOUT_US;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_info.layout_type = buf[6];
|
||||
}
|
||||
|
||||
LOG_DEBUG("[Roccat Vulcan Keyboard]: Detected layout '0x%02X'", buf[6]);
|
||||
|
||||
delete[] buf;
|
||||
return dev_info;
|
||||
}
|
||||
|
||||
device_info RoccatVulcanKeyboardController::GetDeviceInfo()
|
||||
{
|
||||
return dev_info;
|
||||
}
|
||||
|
||||
bool RoccatVulcanKeyboardController::IsBigEndianDirectMode()
|
||||
{
|
||||
return (dev_info.version_major >= 1 && dev_info.version_minor >= 16);
|
||||
}
|
||||
|
||||
void RoccatVulcanKeyboardController::EnableDirect(bool on_off_switch)
|
||||
{
|
||||
uint8_t* buf;
|
||||
switch(device_pid)
|
||||
{
|
||||
case ROCCAT_PYRO_PID:
|
||||
case ROCCAT_MAGMA_PID:
|
||||
case ROCCAT_MAGMA_MINI_PID:
|
||||
case ROCCAT_VULCAN_PRO_PID:
|
||||
case ROCCAT_VULCAN_TKL_PRO_PID:
|
||||
case ROCCAT_VULCAN_II_PID:
|
||||
case ROCCAT_VULCAN_II_MAX_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_TKL_PRO_PID:
|
||||
buf = new uint8_t[5] { 0x0E, 0x05, on_off_switch, 0x00, 0x00 };
|
||||
hid_send_feature_report(dev_ctrl, buf, 5);
|
||||
break;
|
||||
default:
|
||||
buf = new uint8_t[3] { 0x15, 0x00, on_off_switch };
|
||||
hid_send_feature_report(dev_ctrl, buf, 3);
|
||||
}
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
void RoccatVulcanKeyboardController::SendColors(std::vector<led_color> colors)
|
||||
{
|
||||
unsigned short packet_length;
|
||||
unsigned char column_length;
|
||||
unsigned char protocol_version;
|
||||
|
||||
switch(device_pid)
|
||||
{
|
||||
case ROCCAT_MAGMA_PID:
|
||||
case ROCCAT_MAGMA_MINI_PID:
|
||||
packet_length = 64;
|
||||
column_length = 5;
|
||||
protocol_version = 2;
|
||||
break;
|
||||
case ROCCAT_PYRO_PID:
|
||||
packet_length = 378;
|
||||
column_length = 1;
|
||||
protocol_version = 2;
|
||||
break;
|
||||
case ROCCAT_VULCAN_PRO_PID:
|
||||
case ROCCAT_VULCAN_TKL_PRO_PID:
|
||||
packet_length = 384;
|
||||
column_length = 12;
|
||||
protocol_version = 2;
|
||||
break;
|
||||
case ROCCAT_VULCAN_II_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_PID:
|
||||
packet_length = 396;
|
||||
column_length = 1;
|
||||
protocol_version = 2;
|
||||
break;
|
||||
case ROCCAT_VULCAN_II_MAX_PID:
|
||||
packet_length = 567;
|
||||
column_length = 1;
|
||||
protocol_version = 2;
|
||||
break;
|
||||
case TURTLE_BEACH_VULCAN_II_TKL_PRO_PID:
|
||||
packet_length = 320;
|
||||
column_length = 1;
|
||||
protocol_version = 2;
|
||||
break;
|
||||
default:
|
||||
packet_length = 436;
|
||||
column_length = 12;
|
||||
protocol_version = 1;
|
||||
}
|
||||
|
||||
unsigned char packet_num = (unsigned char)(ceil((float)packet_length / 64));
|
||||
std::vector<std::vector<uint8_t>> bufs(packet_num);
|
||||
|
||||
for(int p = 0; p < packet_num; p++)
|
||||
{
|
||||
bufs[p].resize(65);
|
||||
memset(&bufs[p][0], 0x00, sizeof(bufs[p][0]) * bufs[p].size());
|
||||
}
|
||||
|
||||
if(protocol_version > 1)
|
||||
{
|
||||
for(unsigned int i = 0; i < packet_num; i++)
|
||||
{
|
||||
bufs[i][1] = 0xA1;
|
||||
bufs[i][2] = i + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bufs[0][1] = 0xA1;
|
||||
bufs[0][2] = 0x01;
|
||||
}
|
||||
|
||||
unsigned char header_length_first = (packet_length > 255) ? 4 : 3;
|
||||
|
||||
if(header_length_first == 3)
|
||||
{
|
||||
bufs[0][3] = (uint8_t)packet_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IsBigEndianDirectMode())
|
||||
{
|
||||
bufs[0][3] = (packet_length >> 8) & 0xFF;
|
||||
bufs[0][4] = packet_length & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufs[0][3] = packet_length & 0xFF;
|
||||
bufs[0][4] = (packet_length >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int data_length_packet = 64 - header_length_first;
|
||||
|
||||
unsigned int hw_leds = 0;
|
||||
if(device_pid == TURTLE_BEACH_VULCAN_II_TKL_PRO_PID)
|
||||
{
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
if(colors[i].value > hw_leds)
|
||||
{
|
||||
hw_leds = colors[i].value;
|
||||
}
|
||||
}
|
||||
hw_leds += 1;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
if(device_pid == TURTLE_BEACH_VULCAN_II_TKL_PRO_PID)
|
||||
{
|
||||
const unsigned int CHANNEL_OFFSET = hw_leds;
|
||||
|
||||
unsigned int led_index = colors[i].value;
|
||||
if(led_index >= hw_leds)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int logical_pos_r = led_index;
|
||||
unsigned int p_idx_r = logical_pos_r / data_length_packet;
|
||||
unsigned int b_idx_r = logical_pos_r % data_length_packet;
|
||||
|
||||
if(p_idx_r < bufs.size())
|
||||
{
|
||||
bufs[p_idx_r][b_idx_r + header_length_first + 1] = RGBGetRValue(colors[i].color);
|
||||
}
|
||||
|
||||
unsigned int logical_pos_g = led_index + CHANNEL_OFFSET;
|
||||
unsigned int p_idx_g = logical_pos_g / data_length_packet;
|
||||
unsigned int b_idx_g = logical_pos_g % data_length_packet;
|
||||
|
||||
if(p_idx_g < bufs.size())
|
||||
{
|
||||
bufs[p_idx_g][b_idx_g + header_length_first + 1] = RGBGetGValue(colors[i].color);
|
||||
}
|
||||
|
||||
unsigned int logical_pos_b = led_index + 2 * CHANNEL_OFFSET;
|
||||
unsigned int p_idx_b = logical_pos_b / data_length_packet;
|
||||
unsigned int b_idx_b = logical_pos_b % data_length_packet;
|
||||
|
||||
if(p_idx_b < bufs.size())
|
||||
{
|
||||
bufs[p_idx_b][b_idx_b + header_length_first + 1] = RGBGetBValue(colors[i].color);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
int column = (int)(floor(colors[i].value / column_length));
|
||||
int row = colors[i].value % column_length;
|
||||
|
||||
if(protocol_version == 1)
|
||||
{
|
||||
int offset = column * 3 * column_length + row + header_length_first;
|
||||
bufs[offset / 64][offset % 64 + 1] = RGBGetRValue(colors[i].color);
|
||||
offset += column_length;
|
||||
bufs[offset / 64][offset % 64 + 1] = RGBGetGValue(colors[i].color);
|
||||
offset += column_length;
|
||||
bufs[offset / 64][offset % 64 + 1] = RGBGetBValue(colors[i].color);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = column * 3 * column_length + row;
|
||||
|
||||
bufs[offset / data_length_packet][offset % data_length_packet + header_length_first + 1] = RGBGetRValue(colors[i].color);
|
||||
|
||||
offset += column_length;
|
||||
bufs[offset / data_length_packet][offset % data_length_packet + header_length_first + 1] = RGBGetGValue(colors[i].color);
|
||||
|
||||
offset += column_length;
|
||||
bufs[offset / data_length_packet][offset % data_length_packet + header_length_first + 1] = RGBGetBValue(colors[i].color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int p = 0; p < packet_num; p++)
|
||||
{
|
||||
hid_write(dev_led, &bufs[p][0], 65);
|
||||
}
|
||||
|
||||
ClearResponses();
|
||||
AwaitResponse(20);
|
||||
}
|
||||
|
||||
void RoccatVulcanKeyboardController::SendMode(unsigned int mode, unsigned int speed, unsigned int brightness, std::vector<led_color> colors)
|
||||
{
|
||||
if(speed == 0) speed = ROCCAT_VULCAN_SPEED_DEFAULT;
|
||||
if(brightness == 0) brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT;
|
||||
|
||||
unsigned short packet_length;
|
||||
unsigned char protocol_version;
|
||||
unsigned char column_length;
|
||||
|
||||
switch(device_pid)
|
||||
{
|
||||
case ROCCAT_PYRO_PID:
|
||||
protocol_version = 2;
|
||||
packet_length = 365;
|
||||
column_length = 1;
|
||||
break;
|
||||
case ROCCAT_MAGMA_PID:
|
||||
case ROCCAT_MAGMA_MINI_PID:
|
||||
protocol_version = 2;
|
||||
packet_length = 26;
|
||||
column_length = 5;
|
||||
break;
|
||||
case ROCCAT_VULCAN_PRO_PID:
|
||||
case ROCCAT_VULCAN_TKL_PRO_PID:
|
||||
protocol_version = 2;
|
||||
packet_length = 371;
|
||||
column_length = 12;
|
||||
break;
|
||||
case ROCCAT_VULCAN_II_PID:
|
||||
case TURTLE_BEACH_VULCAN_II_PID:
|
||||
protocol_version = 2;
|
||||
packet_length = 377;
|
||||
column_length = 1;
|
||||
break;
|
||||
case ROCCAT_VULCAN_II_MAX_PID:
|
||||
protocol_version = 2;
|
||||
packet_length = 542;
|
||||
column_length = 1;
|
||||
break;
|
||||
case TURTLE_BEACH_VULCAN_II_TKL_PRO_PID:
|
||||
packet_length = 284;
|
||||
column_length = 1;
|
||||
protocol_version = 2;
|
||||
break;
|
||||
default:
|
||||
protocol_version = 1;
|
||||
packet_length = 443;
|
||||
column_length = 12;
|
||||
}
|
||||
|
||||
|
||||
uint8_t* buf = new uint8_t[packet_length];
|
||||
memset(buf, 0x00, packet_length);
|
||||
|
||||
unsigned char header_length = (packet_length > 255) ? 2 : 1;
|
||||
|
||||
buf[0] = (protocol_version == 1) ? 0x0D : 0x11;
|
||||
|
||||
if(header_length == 1)
|
||||
{
|
||||
buf[1] = (uint8_t)packet_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[1] = packet_length % 256;
|
||||
buf[2] = packet_length / 256;
|
||||
}
|
||||
|
||||
unsigned char offset = header_length + 1;
|
||||
|
||||
buf[0 + offset] = 0x00;
|
||||
buf[1 + offset] = mode;
|
||||
buf[2 + offset] = speed;
|
||||
|
||||
if(protocol_version == 1)
|
||||
{
|
||||
buf[3 + offset] = 0x00;
|
||||
buf[4 + offset] = brightness;
|
||||
buf[5 + offset] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[3 + offset] = brightness;
|
||||
buf[4 + offset] = 0x00;
|
||||
buf[5 + offset] = 0x00;
|
||||
}
|
||||
|
||||
if(device_pid == TURTLE_BEACH_VULCAN_II_TKL_PRO_PID)
|
||||
{
|
||||
buf[0 + offset] = 0x03;
|
||||
buf[4 + offset] = 0x0B;
|
||||
buf[5 + offset] = 0x01;
|
||||
}
|
||||
|
||||
unsigned int hw_leds = 0;
|
||||
if(device_pid == TURTLE_BEACH_VULCAN_II_TKL_PRO_PID)
|
||||
{
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
if(colors[i].value > hw_leds)
|
||||
{
|
||||
hw_leds = colors[i].value;
|
||||
}
|
||||
}
|
||||
hw_leds += 1;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < colors.size(); i++)
|
||||
{
|
||||
if(device_pid == TURTLE_BEACH_VULCAN_II_TKL_PRO_PID)
|
||||
{
|
||||
const int HEADER_OFFSET = 9;
|
||||
const unsigned int CHANNEL_OFFSET = hw_leds;
|
||||
|
||||
unsigned int led_index = colors[i].value;
|
||||
if(led_index >= hw_leds) continue;
|
||||
|
||||
int pos_r = HEADER_OFFSET + led_index;
|
||||
int pos_g = HEADER_OFFSET + led_index + CHANNEL_OFFSET;
|
||||
int pos_b = HEADER_OFFSET + led_index + (2 * CHANNEL_OFFSET);
|
||||
|
||||
if (pos_b < packet_length - 2)
|
||||
{
|
||||
buf[pos_r] = RGBGetRValue(colors[i].color);
|
||||
buf[pos_g] = RGBGetGValue(colors[i].color);
|
||||
buf[pos_b] = RGBGetBValue(colors[i].color);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int column = (int)(floor(colors[i].value / column_length));
|
||||
int row = colors[i].value % column_length;
|
||||
int pos = column * 3 * column_length + row + 9;
|
||||
|
||||
if(pos + (2 * column_length) < packet_length - 2)
|
||||
{
|
||||
buf[pos] = RGBGetRValue(colors[i].color);
|
||||
pos += column_length;
|
||||
buf[pos] = RGBGetGValue(colors[i].color);
|
||||
pos += column_length;
|
||||
buf[pos] = RGBGetBValue(colors[i].color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short total = 0;
|
||||
for(int i = 0; i < packet_length - 2; i++) total += buf[i];
|
||||
|
||||
buf[packet_length - 2] = total & 0xFF;
|
||||
buf[packet_length - 1] = total >> 8;
|
||||
|
||||
hid_send_feature_report(dev_ctrl, buf, packet_length);
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
void RoccatVulcanKeyboardController::WaitUntilReady()
|
||||
{
|
||||
unsigned short packet_length;
|
||||
|
||||
switch(device_pid)
|
||||
{
|
||||
case ROCCAT_PYRO_PID:
|
||||
case ROCCAT_MAGMA_PID:
|
||||
case ROCCAT_MAGMA_MINI_PID:
|
||||
case ROCCAT_VULCAN_PRO_PID:
|
||||
case ROCCAT_VULCAN_TKL_PRO_PID:
|
||||
packet_length = 4;
|
||||
break;
|
||||
default:
|
||||
packet_length = 3;
|
||||
}
|
||||
|
||||
uint8_t* buf = new uint8_t[packet_length];
|
||||
|
||||
buf[0] = 0x04;
|
||||
|
||||
for(unsigned char i = 0; buf[1] != 1 && i < 100; i++)
|
||||
{
|
||||
if(i != 0)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
||||
}
|
||||
|
||||
hid_get_feature_report(dev_ctrl, buf, packet_length);
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
void RoccatVulcanKeyboardController::AwaitResponse(int ms)
|
||||
{
|
||||
unsigned char usb_buf_out[65];
|
||||
hid_read_timeout(dev_led, usb_buf_out, 65, ms);
|
||||
}
|
||||
|
||||
void RoccatVulcanKeyboardController::ClearResponses()
|
||||
{
|
||||
int result = 1;
|
||||
unsigned char usb_buf_flush[65];
|
||||
while(result > 0)
|
||||
{
|
||||
result = hid_read_timeout(dev_led, usb_buf_flush, 65, 0);
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RoccatVulcanKeyboardController.h |
|
||||
| |
|
||||
| Driver for Roccat Vulcan keyboard |
|
||||
| |
|
||||
| Mola19 17 Dec 2021 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "RGBController.h"
|
||||
#include "RoccatVulcanKeyboardLayouts.h"
|
||||
|
||||
/*--------------------------------------------------------------------------------*\
|
||||
| KEYBOARDS |
|
||||
| This section was used to be enum. |
|
||||
\*--------------------------------------------------------------------------------*/
|
||||
#define ROCCAT_VULCAN_100_AIMO_PID 0x307A
|
||||
#define ROCCAT_VULCAN_120_AIMO_PID 0x3098
|
||||
#define ROCCAT_VULCAN_TKL_PID 0x2FEE
|
||||
#define ROCCAT_VULCAN_PRO_PID 0x30F7
|
||||
#define ROCCAT_VULCAN_TKL_PRO_PID 0x311A
|
||||
#define ROCCAT_VULCAN_II_PID 0x2F4E
|
||||
#define ROCCAT_VULCAN_II_MAX_PID 0x2EE2
|
||||
#define ROCCAT_PYRO_PID 0x314C
|
||||
#define ROCCAT_MAGMA_PID 0x3124
|
||||
#define ROCCAT_MAGMA_MINI_PID 0x69A0
|
||||
#define TURTLE_BEACH_VULCAN_II_PID 0x501B
|
||||
#define TURTLE_BEACH_VULCAN_II_TKL_PID 0x5023
|
||||
#define TURTLE_BEACH_VULCAN_II_TKL_PRO_PID 0x5001
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_VULCAN_MODE_DIRECT = 0x0B,
|
||||
ROCCAT_VULCAN_MODE_STATIC = 0x01,
|
||||
ROCCAT_VULCAN_MODE_WAVE = 0x0A,
|
||||
/*-------------------------------------------------------------------*\
|
||||
| This mode is not a real mode, it's just the default mode when |
|
||||
| a mode is software generated, but Swarm is inactive, hence it has |
|
||||
| no id. Unfortunately 0 is refused by some keyboards, so 2 seems |
|
||||
| like a good choice as it is not used anywhere else |
|
||||
\*-------------------------------------------------------------------*/
|
||||
ROCCAT_VULCAN_MODE_DEFAULT = 0x02,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ROCCAT_VULCAN_SPEED_MIN = 0x01,
|
||||
ROCCAT_VULCAN_SPEED_MAX = 0x0B,
|
||||
ROCCAT_VULCAN_SPEED_DEFAULT = 0x06,
|
||||
ROCCAT_VULCAN_BRIGHTNESS_MIN = 0x01,
|
||||
ROCCAT_VULCAN_BRIGHTNESS_MAX = 0x45,
|
||||
ROCCAT_VULCAN_BRIGHTNESS_DEFAULT = 0x45,
|
||||
};
|
||||
|
||||
struct device_info
|
||||
{
|
||||
std::string version;
|
||||
int version_major;
|
||||
int version_minor;
|
||||
int layout_type;
|
||||
};
|
||||
|
||||
struct led_color
|
||||
{
|
||||
unsigned int value;
|
||||
RGBColor color;
|
||||
};
|
||||
|
||||
class RoccatVulcanKeyboardController
|
||||
{
|
||||
public:
|
||||
RoccatVulcanKeyboardController(hid_device* dev_ctrl_handle, hid_device* dev_led_handle, char *path, uint16_t pid, std::string dev_name);
|
||||
~RoccatVulcanKeyboardController();
|
||||
|
||||
std::string GetSerial();
|
||||
std::string GetLocation();
|
||||
std::string GetName();
|
||||
device_info InitDeviceInfo();
|
||||
device_info GetDeviceInfo();
|
||||
|
||||
void EnableDirect(bool on_off_switch);
|
||||
void SendColors(std::vector<led_color> colors);
|
||||
void SendMode(unsigned int mode, unsigned int speed, unsigned int brightness, std::vector<led_color> colors);
|
||||
void WaitUntilReady();
|
||||
void AwaitResponse(int ms);
|
||||
void ClearResponses();
|
||||
|
||||
|
||||
uint16_t device_pid;
|
||||
|
||||
private:
|
||||
hid_device* dev_ctrl;
|
||||
hid_device* dev_led;
|
||||
device_info dev_info;
|
||||
std::string location;
|
||||
std::string name;
|
||||
|
||||
bool IsBigEndianDirectMode();
|
||||
};
|
||||
+1387
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user