Publish LumaOps source
This commit is contained in:
@@ -0,0 +1,473 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| QMKVialRGBController.cpp |
|
||||
| |
|
||||
| Driver for VialRGB QMK Keyboard Protocol |
|
||||
| |
|
||||
| Adam Honse <calcprogrammer1@gmail.com) 29 Sep 2025 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hsv.h"
|
||||
#include "QMKVialRGBController.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Portions of this controller adapted from Raspberry Pi |
|
||||
| RPiKeyboardConfig utility: |
|
||||
| https://github.com/raspberrypi/rpi-keyboard-config |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
QMKVialRGBController::QMKVialRGBController(hid_device *dev_handle, const char *path)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Initialize controller fields |
|
||||
\*-----------------------------------------------------*/
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
supported = false;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Read product string |
|
||||
\*-----------------------------------------------------*/
|
||||
wchar_t product_string[256];
|
||||
|
||||
int ret = hid_get_product_string(dev, product_string, 256);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
name = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
name = StringUtils::wstring_to_string(product_string);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Read vendor string |
|
||||
\*-----------------------------------------------------*/
|
||||
wchar_t vendor_string[256];
|
||||
|
||||
ret = hid_get_manufacturer_string(dev, vendor_string, 256);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
vendor = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
vendor = StringUtils::wstring_to_string(vendor_string);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Read serial string |
|
||||
\*-----------------------------------------------------*/
|
||||
wchar_t serial_string[256];
|
||||
|
||||
ret = hid_get_serial_number_string(dev, serial_string, 256);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
serial = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
serial = StringUtils::wstring_to_string(serial_string);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Get VIA, Vial, and VialRGB information |
|
||||
\*-----------------------------------------------------*/
|
||||
CmdGetViaProtocolVersion(&via_protocol_version);
|
||||
|
||||
if(via_protocol_version < 9)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CmdGetVialInfo(&vial_protocol_version, &keyboard_uid, &vialrgb_flag);
|
||||
|
||||
if((vial_protocol_version < 4) || ((vialrgb_flag & 1) == 0))
|
||||
{
|
||||
supported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
CmdGetVialRGBInfo(&vialrgb_protocol_version, &maximum_brightness);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Get list of supported effects |
|
||||
\*-----------------------------------------------------*/
|
||||
CmdGetSupportedEffects();
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Get count of LEDs |
|
||||
\*-----------------------------------------------------*/
|
||||
CmdGetNumberLEDs(&number_leds);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Get info and keycode for all LEDs |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned short led_index = 0; led_index < number_leds; led_index++)
|
||||
{
|
||||
led_info.push_back(CmdGetLEDInfo(led_index));
|
||||
keycodes.push_back(CmdGetKeycode(0, led_info[led_index].row, led_info[led_index].col));
|
||||
}
|
||||
|
||||
supported = true;
|
||||
}
|
||||
|
||||
QMKVialRGBController::~QMKVialRGBController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string QMKVialRGBController::GetLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
std::string QMKVialRGBController::GetName()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
std::string QMKVialRGBController::GetSerial()
|
||||
{
|
||||
return(serial);
|
||||
}
|
||||
|
||||
std::string QMKVialRGBController::GetVendor()
|
||||
{
|
||||
return(vendor);
|
||||
}
|
||||
|
||||
std::string QMKVialRGBController::GetVersion()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Format UID string |
|
||||
\*-----------------------------------------------------*/
|
||||
char uid_buf[17];
|
||||
snprintf(uid_buf, sizeof(uid_buf), "%016llX", keyboard_uid);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Format multi-line version text |
|
||||
\*-----------------------------------------------------*/
|
||||
return("VIA: " + std::to_string(via_protocol_version) + "\r\n"
|
||||
+ "Vial: " + std::to_string(vial_protocol_version) + "\r\n"
|
||||
+ "VialRGB: " + std::to_string(vialrgb_protocol_version) + "\r\n"
|
||||
+ "UID: " + uid_buf);
|
||||
}
|
||||
|
||||
bool QMKVialRGBController::GetSupported()
|
||||
{
|
||||
return(supported);
|
||||
}
|
||||
|
||||
unsigned short QMKVialRGBController::GetEffect(std::size_t effect_idx)
|
||||
{
|
||||
return(supported_effects[effect_idx]);
|
||||
}
|
||||
|
||||
std::size_t QMKVialRGBController::GetEffectCount()
|
||||
{
|
||||
return(supported_effects.size());
|
||||
}
|
||||
|
||||
unsigned short QMKVialRGBController::GetKeycode(unsigned short led_index)
|
||||
{
|
||||
return(keycodes[led_index]);
|
||||
}
|
||||
|
||||
unsigned short QMKVialRGBController::GetLEDCount()
|
||||
{
|
||||
return(number_leds);
|
||||
}
|
||||
|
||||
qmk_rgb_matrix_led_info QMKVialRGBController::GetLEDInfo(unsigned short led_index)
|
||||
{
|
||||
return(led_info[led_index]);
|
||||
}
|
||||
|
||||
void QMKVialRGBController::GetMode
|
||||
(
|
||||
unsigned short* mode,
|
||||
unsigned char* speed,
|
||||
unsigned char* hue,
|
||||
unsigned char* sat,
|
||||
unsigned char* val
|
||||
)
|
||||
{
|
||||
CmdGetMode(mode, speed, hue, sat, val);
|
||||
}
|
||||
|
||||
void QMKVialRGBController::SendLEDs
|
||||
(
|
||||
unsigned short number_leds,
|
||||
RGBColor* color_data
|
||||
)
|
||||
{
|
||||
unsigned short led_start_index = 0;
|
||||
unsigned char number_packet_leds = 9;
|
||||
|
||||
while(led_start_index < number_leds)
|
||||
{
|
||||
if((number_leds - led_start_index) < 9)
|
||||
{
|
||||
number_packet_leds = (number_leds - led_start_index);
|
||||
}
|
||||
|
||||
CmdSendLEDs(led_start_index, number_packet_leds, &color_data[led_start_index]);
|
||||
|
||||
led_start_index += number_packet_leds;
|
||||
}
|
||||
}
|
||||
|
||||
void QMKVialRGBController::SetMode
|
||||
(
|
||||
unsigned short mode,
|
||||
unsigned char speed,
|
||||
unsigned char hue,
|
||||
unsigned char sat,
|
||||
unsigned char val
|
||||
)
|
||||
{
|
||||
CmdSetMode(mode, speed, hue, sat, val);
|
||||
}
|
||||
|
||||
unsigned short QMKVialRGBController::CmdGetKeycode
|
||||
(
|
||||
unsigned char layer,
|
||||
unsigned char row,
|
||||
unsigned char col
|
||||
)
|
||||
{
|
||||
unsigned char data[5];
|
||||
unsigned short keycode;
|
||||
|
||||
data[0] = row;
|
||||
data[1] = col;
|
||||
|
||||
SendCheckCommand(CMD_VIA_DYNAMIC_KEYMAP_GET_KEYCODE, layer, data, 2, data, 5);
|
||||
|
||||
memcpy(&keycode, &data[3], sizeof(unsigned short));
|
||||
|
||||
return(keycode);
|
||||
}
|
||||
|
||||
qmk_rgb_matrix_led_info QMKVialRGBController::CmdGetLEDInfo
|
||||
(
|
||||
unsigned short led_index
|
||||
)
|
||||
{
|
||||
qmk_rgb_matrix_led_info data;
|
||||
|
||||
SendCheckCommand(CMD_LIGHTING_GET_VALUE, VIALRGB_GET_LED_INFO, (unsigned char*)&led_index, sizeof(led_index), (unsigned char*)&data, sizeof(data));
|
||||
|
||||
return(data);
|
||||
}
|
||||
|
||||
void QMKVialRGBController::CmdGetMode
|
||||
(
|
||||
unsigned short* mode,
|
||||
unsigned char* speed,
|
||||
unsigned char* hue,
|
||||
unsigned char* sat,
|
||||
unsigned char* val
|
||||
)
|
||||
{
|
||||
unsigned char data[6];
|
||||
|
||||
SendCheckCommand(CMD_LIGHTING_GET_VALUE, VIALRGB_GET_MODE, NULL, 0, data, 6);
|
||||
|
||||
memcpy(mode, &data[0], sizeof(unsigned short));
|
||||
*speed = data[2];
|
||||
*hue = data[3];
|
||||
*sat = data[4];
|
||||
*val = data[5];
|
||||
}
|
||||
|
||||
void QMKVialRGBController::CmdGetNumberLEDs
|
||||
(
|
||||
unsigned short* number_leds
|
||||
)
|
||||
{
|
||||
SendCheckCommand(CMD_LIGHTING_GET_VALUE, VIALRGB_GET_NUMBER_LEDS, NULL, 0, (unsigned char*)number_leds, sizeof(unsigned short));
|
||||
}
|
||||
|
||||
void QMKVialRGBController::CmdGetSupportedEffects()
|
||||
{
|
||||
unsigned short packet_effects[15];
|
||||
unsigned short max_effect = 0;
|
||||
|
||||
supported_effects.clear();
|
||||
|
||||
supported_effects.push_back(0);
|
||||
|
||||
while(max_effect < VIALRGB_EFFECT_SKIP)
|
||||
{
|
||||
SendCheckCommand(CMD_LIGHTING_GET_VALUE, VIALRGB_GET_SUPPORTED, (unsigned char*)&max_effect, sizeof(max_effect), (unsigned char*)packet_effects, sizeof(packet_effects));
|
||||
|
||||
for(unsigned int effect_idx = 0; effect_idx < 15; effect_idx++)
|
||||
{
|
||||
if(packet_effects[effect_idx] == VIALRGB_EFFECT_SKIP)
|
||||
{
|
||||
return;
|
||||
}
|
||||
supported_effects.push_back(packet_effects[effect_idx]);
|
||||
max_effect = packet_effects[effect_idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QMKVialRGBController::CmdGetVialInfo
|
||||
(
|
||||
unsigned int* vial_protocol,
|
||||
unsigned long long* keyboard_uid,
|
||||
unsigned char* vialrgb_flag
|
||||
)
|
||||
{
|
||||
unsigned char data[sizeof(int) + sizeof(unsigned long long) + sizeof(unsigned char)];
|
||||
|
||||
SendCommand(CMD_VIAL_COMMAND, VIAL_GET_KEYBOARD_ID, NULL, 0, data, sizeof(data));
|
||||
|
||||
memcpy(vial_protocol, &data[0], sizeof(int));
|
||||
memcpy(keyboard_uid, &data[sizeof(int)], sizeof(unsigned long long));
|
||||
memcpy(vialrgb_flag, &data[sizeof(int) + sizeof(unsigned long long)], sizeof(unsigned char));
|
||||
}
|
||||
|
||||
void QMKVialRGBController::CmdGetVialRGBInfo
|
||||
(
|
||||
unsigned short* vialrgb_protocol_version,
|
||||
unsigned char* maximum_brightness
|
||||
)
|
||||
{
|
||||
unsigned char data[sizeof(unsigned short) + sizeof(unsigned char)];
|
||||
|
||||
SendCommand(CMD_VIAL_COMMAND, VIAL_GET_KEYBOARD_ID, NULL, 0, data, sizeof(data));
|
||||
|
||||
memcpy(vialrgb_protocol_version, &data[0], sizeof(unsigned short));
|
||||
memcpy(maximum_brightness, &data[sizeof(unsigned char)], sizeof(unsigned short));
|
||||
}
|
||||
|
||||
void QMKVialRGBController::CmdGetViaProtocolVersion
|
||||
(
|
||||
unsigned short* via_protocol_version
|
||||
)
|
||||
{
|
||||
SendCheckCommand(CMD_GET_PROTOCOL_VERSION, 0, NULL, 0, (unsigned char*)via_protocol_version, sizeof(unsigned int));
|
||||
}
|
||||
|
||||
void QMKVialRGBController::CmdSendLEDs
|
||||
(
|
||||
unsigned short start_index,
|
||||
unsigned char number_leds,
|
||||
RGBColor* color_data
|
||||
)
|
||||
{
|
||||
unsigned char data[30];
|
||||
|
||||
memcpy(&data[0], &start_index, sizeof(start_index));
|
||||
memcpy(&data[2], &number_leds, sizeof(number_leds));
|
||||
|
||||
if(number_leds > 9)
|
||||
{
|
||||
number_leds = 9;
|
||||
}
|
||||
|
||||
for(unsigned char led_index = 0; led_index < number_leds; led_index++)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| VialRGB sends direct packets in HSV for some |
|
||||
| inexplicable reason, so do the RGB to HSV |
|
||||
| conversion before sending |
|
||||
\*-------------------------------------------------*/
|
||||
hsv_t hsv_color;
|
||||
rgb2hsv(color_data[led_index], &hsv_color);
|
||||
|
||||
data[3 + (led_index * 3)] = (unsigned char)((float)hsv_color.hue * (256.0f / 360.0f));
|
||||
data[4 + (led_index * 3)] = hsv_color.saturation;
|
||||
data[5 + (led_index * 3)] = hsv_color.value;
|
||||
}
|
||||
|
||||
SendCheckCommand(CMD_LIGHTING_SET_VALUE, VIALRGB_DIRECT_FASTSET, data, sizeof(data), NULL, 0);
|
||||
}
|
||||
|
||||
void QMKVialRGBController::CmdSetMode
|
||||
(
|
||||
unsigned short mode,
|
||||
unsigned char speed,
|
||||
unsigned char hue,
|
||||
unsigned char sat,
|
||||
unsigned char val
|
||||
)
|
||||
{
|
||||
unsigned char data[6];
|
||||
|
||||
memcpy(&data[0], &mode, sizeof(unsigned short));
|
||||
|
||||
data[2] = speed;
|
||||
data[3] = hue;
|
||||
data[4] = sat;
|
||||
data[5] = val;
|
||||
|
||||
SendCommand(CMD_LIGHTING_SET_VALUE, VIALRGB_SET_MODE, data, sizeof(data), NULL, 0);
|
||||
}
|
||||
|
||||
int QMKVialRGBController::SendCommand
|
||||
(
|
||||
unsigned char cmd,
|
||||
unsigned char subcmd,
|
||||
unsigned char* data_in,
|
||||
unsigned char data_in_size,
|
||||
unsigned char* data_out,
|
||||
unsigned char data_out_size
|
||||
)
|
||||
{
|
||||
unsigned char usb_buf[MSG_LEN + 1];
|
||||
|
||||
memset(usb_buf, 0, sizeof(usb_buf));
|
||||
|
||||
usb_buf[0] = 0x00;
|
||||
usb_buf[1] = cmd;
|
||||
usb_buf[2] = subcmd;
|
||||
|
||||
memcpy(&usb_buf[3], data_in, data_in_size);
|
||||
|
||||
hid_write(dev, usb_buf, sizeof(usb_buf));
|
||||
int bytes_received = hid_read_timeout(dev, usb_buf, sizeof(usb_buf)-1, 1000);
|
||||
|
||||
memcpy(data_out, &usb_buf[0], data_out_size);
|
||||
|
||||
return(bytes_received);
|
||||
}
|
||||
|
||||
int QMKVialRGBController::SendCheckCommand
|
||||
(
|
||||
unsigned char cmd,
|
||||
unsigned char subcmd,
|
||||
unsigned char* data_in,
|
||||
unsigned char data_in_size,
|
||||
unsigned char* data_out,
|
||||
unsigned char data_out_size
|
||||
)
|
||||
{
|
||||
unsigned char usb_buf[MSG_LEN + 1];
|
||||
|
||||
memset(usb_buf, 0, sizeof(usb_buf));
|
||||
|
||||
usb_buf[0] = 0x00;
|
||||
usb_buf[1] = cmd;
|
||||
usb_buf[2] = subcmd;
|
||||
|
||||
memcpy(&usb_buf[3], data_in, data_in_size);
|
||||
|
||||
hid_write(dev, usb_buf, sizeof(usb_buf));
|
||||
int bytes_received = hid_read_timeout(dev, usb_buf, sizeof(usb_buf)-1, 1000);
|
||||
|
||||
memcpy(data_out, &usb_buf[2], data_out_size);
|
||||
|
||||
return(bytes_received);
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| QMKVialRGBController.h |
|
||||
| |
|
||||
| Driver for VialRGB QMK Keyboard Protocol |
|
||||
| |
|
||||
| Adam Honse <calcprogrammer1@gmail.com) 29 Sep 2025 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hidapi.h>
|
||||
#include "ResourceManager.h"
|
||||
#include "QMKCommon.h"
|
||||
#include "RGBController.h"
|
||||
|
||||
#define MSG_LEN 32
|
||||
|
||||
enum
|
||||
{
|
||||
CMD_GET_PROTOCOL_VERSION = 0x01,
|
||||
CMD_GET_KEYBOARD_VALUE = 0x02,
|
||||
CMD_SET_KEYBOARD_VALUE = 0x03,
|
||||
CMD_VIA_DYNAMIC_KEYMAP_GET_KEYCODE = 0x04,
|
||||
CMD_VIA_DYNAMIC_KEYMAP_SET_KEYCODE = 0x05,
|
||||
CMD_VIA_DYNAMIC_KEYMAP_RESET = 0x06,
|
||||
CMD_LIGHTING_SET_VALUE = 0x07,
|
||||
CMD_LIGHTING_GET_VALUE = 0x08,
|
||||
CMD_VIAL_COMMAND = 0xFE,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VIAL_GET_KEYBOARD_ID = 0x00,
|
||||
VIAL_GET_SIZE = 0x01,
|
||||
VIAL_GET_DEFINITION = 0x02,
|
||||
VIAL_GET_UNLOCK_STATUS = 0x05,
|
||||
VIAL_UNLOCK_START = 0x06,
|
||||
VIAL_UNLOCK_POLL = 0x07,
|
||||
VIAL_LOCK = 0x08,
|
||||
VIALRGB_GET_INFO = 0x40,
|
||||
VIALRGB_GET_MODE = 0x41,
|
||||
VIALRGB_GET_SUPPORTED = 0x42,
|
||||
VIALRGB_GET_NUMBER_LEDS = 0x43,
|
||||
VIALRGB_GET_LED_INFO = 0x44,
|
||||
VIALRGB_SET_MODE = 0x41,
|
||||
VIALRGB_DIRECT_FASTSET = 0x42,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VIALRGB_EFFECT_OFF,
|
||||
VIALRGB_EFFECT_DIRECT,
|
||||
VIALRGB_EFFECT_SOLID_COLOR,
|
||||
VIALRGB_EFFECT_ALPHAS_MODS,
|
||||
VIALRGB_EFFECT_GRADIENT_UP_DOWN,
|
||||
VIALRGB_EFFECT_GRADIENT_LEFT_RIGHT,
|
||||
VIALRGB_EFFECT_BREATHING,
|
||||
VIALRGB_EFFECT_BAND_SAT,
|
||||
VIALRGB_EFFECT_BAND_VAL,
|
||||
VIALRGB_EFFECT_BAND_PINWHEEL_SAT,
|
||||
VIALRGB_EFFECT_BAND_PINWHEEL_VAL,
|
||||
VIALRGB_EFFECT_BAND_SPIRAL_SAT,
|
||||
VIALRGB_EFFECT_BAND_SPIRAL_VAL,
|
||||
VIALRGB_EFFECT_CYCLE_ALL,
|
||||
VIALRGB_EFFECT_CYCLE_LEFT_RIGHT,
|
||||
VIALRGB_EFFECT_CYCLE_UP_DOWN,
|
||||
VIALRGB_EFFECT_RAINBOW_MOVING_CHEVRON,
|
||||
VIALRGB_EFFECT_CYCLE_OUT_IN,
|
||||
VIALRGB_EFFECT_CYCLE_OUT_IN_DUAL,
|
||||
VIALRGB_EFFECT_CYCLE_PINWHEEL,
|
||||
VIALRGB_EFFECT_CYCLE_SPIRAL,
|
||||
VIALRGB_EFFECT_DUAL_BEACON,
|
||||
VIALRGB_EFFECT_RAINBOW_BEACON,
|
||||
VIALRGB_EFFECT_RAINBOW_PINWHEELS,
|
||||
VIALRGB_EFFECT_RAINDROPS,
|
||||
VIALRGB_EFFECT_JELLYBEAN_RAINDROPS,
|
||||
VIALRGB_EFFECT_HUE_BREATHING,
|
||||
VIALRGB_EFFECT_HUE_PENDULUM,
|
||||
VIALRGB_EFFECT_HUE_WAVE,
|
||||
VIALRGB_EFFECT_TYPING_HEATMAP,
|
||||
VIALRGB_EFFECT_DIGITAL_RAIN,
|
||||
VIALRGB_EFFECT_SOLID_REACTIVE_SIMPLE,
|
||||
VIALRGB_EFFECT_SOLID_REACTIVE,
|
||||
VIALRGB_EFFECT_SOLID_REACTIVE_WIDE,
|
||||
VIALRGB_EFFECT_SOLID_REACTIVE_MULTIWIDE,
|
||||
VIALRGB_EFFECT_SOLID_REACTIVE_CROSS,
|
||||
VIALRGB_EFFECT_SOLID_REACTIVE_MULTICROSS,
|
||||
VIALRGB_EFFECT_SOLID_REACTIVE_NEXUS,
|
||||
VIALRGB_EFFECT_SOLID_REACTIVE_MULTINEXUS,
|
||||
VIALRGB_EFFECT_SPLASH,
|
||||
VIALRGB_EFFECT_MULTISPLASH,
|
||||
VIALRGB_EFFECT_SOLID_SPLASH,
|
||||
VIALRGB_EFFECT_SOLID_MULTISPLASH,
|
||||
VIALRGB_EFFECT_PIXEL_RAIN,
|
||||
VIALRGB_EFFECT_PIXEL_FRACTAL,
|
||||
VIALRGB_EFFECT_SKIP = 0xFFFF
|
||||
};
|
||||
|
||||
class QMKVialRGBController
|
||||
{
|
||||
public:
|
||||
QMKVialRGBController(hid_device *dev_handle, const char *path);
|
||||
~QMKVialRGBController();
|
||||
|
||||
std::string GetLocation();
|
||||
std::string GetName();
|
||||
std::string GetSerial();
|
||||
std::string GetVendor();
|
||||
std::string GetVersion();
|
||||
|
||||
bool GetSupported();
|
||||
|
||||
unsigned short GetEffect(std::size_t effect_idx);
|
||||
std::size_t GetEffectCount();
|
||||
unsigned short GetKeycode(unsigned short led_index);
|
||||
unsigned short GetLEDCount();
|
||||
qmk_rgb_matrix_led_info GetLEDInfo(unsigned short led_index);
|
||||
|
||||
void GetMode
|
||||
(
|
||||
unsigned short* mode,
|
||||
unsigned char* speed,
|
||||
unsigned char* hue,
|
||||
unsigned char* sat,
|
||||
unsigned char* val
|
||||
);
|
||||
|
||||
void SendLEDs
|
||||
(
|
||||
unsigned short number_leds,
|
||||
RGBColor* color_data
|
||||
);
|
||||
|
||||
void SetMode
|
||||
(
|
||||
unsigned short mode,
|
||||
unsigned char speed,
|
||||
unsigned char hue,
|
||||
unsigned char sat,
|
||||
unsigned char val
|
||||
);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
unsigned long long keyboard_uid;
|
||||
std::vector<unsigned short> keycodes;
|
||||
std::vector<qmk_rgb_matrix_led_info> led_info;
|
||||
std::string location;
|
||||
unsigned char maximum_brightness;
|
||||
std::string name;
|
||||
unsigned short number_leds;
|
||||
std::string serial;
|
||||
bool supported;
|
||||
std::vector<unsigned short> supported_effects;
|
||||
std::string vendor;
|
||||
unsigned short via_protocol_version;
|
||||
unsigned int vial_protocol_version;
|
||||
unsigned short vialrgb_protocol_version;
|
||||
unsigned char vialrgb_flag;
|
||||
|
||||
unsigned short CmdGetKeycode
|
||||
(
|
||||
unsigned char layer,
|
||||
unsigned char row,
|
||||
unsigned char col
|
||||
);
|
||||
|
||||
qmk_rgb_matrix_led_info CmdGetLEDInfo
|
||||
(
|
||||
unsigned short led_index
|
||||
);
|
||||
|
||||
void CmdGetMode
|
||||
(
|
||||
unsigned short* mode,
|
||||
unsigned char* speed,
|
||||
unsigned char* hue,
|
||||
unsigned char* sat,
|
||||
unsigned char* val
|
||||
);
|
||||
|
||||
void CmdGetNumberLEDs
|
||||
(
|
||||
unsigned short* number_leds
|
||||
);
|
||||
|
||||
void CmdGetSupportedEffects();
|
||||
|
||||
void CmdGetVialInfo
|
||||
(
|
||||
unsigned int* vial_protocol_version,
|
||||
unsigned long long* keyboard_uid,
|
||||
unsigned char* vialrgb_flag
|
||||
);
|
||||
|
||||
void CmdGetVialRGBInfo
|
||||
(
|
||||
unsigned short* vialrgb_protocol_version,
|
||||
unsigned char* maximum_brightness
|
||||
);
|
||||
|
||||
void CmdGetViaProtocolVersion
|
||||
(
|
||||
unsigned short* via_protocol_version
|
||||
);
|
||||
|
||||
void CmdSendLEDs
|
||||
(
|
||||
unsigned short start_index,
|
||||
unsigned char number_leds,
|
||||
RGBColor* color_data
|
||||
);
|
||||
|
||||
void CmdSetMode
|
||||
(
|
||||
unsigned short mode,
|
||||
unsigned char speed,
|
||||
unsigned char hue,
|
||||
unsigned char sat,
|
||||
unsigned char val
|
||||
);
|
||||
|
||||
int SendCommand
|
||||
(
|
||||
unsigned char cmd,
|
||||
unsigned char subcmd,
|
||||
unsigned char* data_in,
|
||||
unsigned char data_in_size,
|
||||
unsigned char* data_out,
|
||||
unsigned char data_out_size
|
||||
);
|
||||
|
||||
int SendCheckCommand
|
||||
(
|
||||
unsigned char cmd,
|
||||
unsigned char subcmd,
|
||||
unsigned char* data_in,
|
||||
unsigned char data_in_size,
|
||||
unsigned char* data_out,
|
||||
unsigned char data_out_size
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| QMKVialRGBControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for VialRGB QMK Keyboard Protocol |
|
||||
| |
|
||||
| Adam Honse <calcprogrammer1@gmail.com> 29 Sep 2025 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <string>
|
||||
#include <hidapi.h>
|
||||
#include "Detector.h"
|
||||
#include "QMKVialRGBController.h"
|
||||
#include "RGBController_QMKVialRGB.h"
|
||||
#include "SettingsManager.h"
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| USB IDs |
|
||||
\*-----------------------------------------------------*/
|
||||
#define RASPBERRY_PI_VID 0x2E8A
|
||||
#define RASPBERRY_PI_500_PLUS_PID 0x0011
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Usage and Usage Page |
|
||||
\*-----------------------------------------------------*/
|
||||
#define QMK_USAGE_PAGE 0xFF60
|
||||
#define QMK_USAGE 0x61
|
||||
|
||||
void DetectQMKVialRGBControllers(hid_device_info *info, const std::string&)
|
||||
{
|
||||
hid_device *dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
QMKVialRGBController* controller = new QMKVialRGBController(dev, info->path);
|
||||
|
||||
if(controller->GetSupported())
|
||||
{
|
||||
RGBController_QMKVialRGB* rgb_controller = new RGBController_QMKVialRGB(controller);
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterQMKVialRGBDetectors()
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Get QMKVialRGB settings |
|
||||
\*-------------------------------------------------*/
|
||||
json vial_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("QMKVialRGBDevices");
|
||||
|
||||
if(vial_settings.contains("devices"))
|
||||
{
|
||||
for(unsigned int device_idx = 0; device_idx < vial_settings["devices"].size(); device_idx++)
|
||||
{
|
||||
if( vial_settings["devices"][device_idx].contains("usb_pid")
|
||||
&& vial_settings["devices"][device_idx].contains("usb_vid")
|
||||
&& vial_settings["devices"][device_idx].contains("name"))
|
||||
{
|
||||
std::string usb_pid_str = vial_settings["devices"][device_idx]["usb_pid"];
|
||||
std::string usb_vid_str = vial_settings["devices"][device_idx]["usb_vid"];
|
||||
std::string name = vial_settings["devices"][device_idx]["name"];
|
||||
|
||||
/*-------------------------------------*\
|
||||
| Parse hex string to integer |
|
||||
\*-------------------------------------*/
|
||||
unsigned short usb_pid = std::stoi(usb_pid_str, 0, 16);
|
||||
unsigned short usb_vid = std::stoi(usb_vid_str, 0, 16);
|
||||
|
||||
REGISTER_DYNAMIC_HID_DETECTOR_PU(name, DetectQMKVialRGBControllers, usb_vid, usb_pid, QMK_USAGE_PAGE, QMK_USAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_DYNAMIC_DETECTOR("QMK VialRGB Devices", RegisterQMKVialRGBDetectors);
|
||||
|
||||
REGISTER_HID_DETECTOR_PU( "Raspberry Pi 500+", DetectQMKVialRGBControllers, RASPBERRY_PI_VID, RASPBERRY_PI_500_PLUS_PID, QMK_USAGE_PAGE, QMK_USAGE );
|
||||
@@ -0,0 +1,268 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_QMKVialRGB.cpp |
|
||||
| |
|
||||
| RGBController for VialRGB QMK Keyboard Protocol |
|
||||
| |
|
||||
| Adam Honse <calcprogrammer1@gmail.com) 29 Sep 2025 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "hsv.h"
|
||||
#include "QMKKeycodes.h"
|
||||
#include "RGBController_QMKVialRGB.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short value;
|
||||
std::string name;
|
||||
bool has_speed;
|
||||
} vialrgb_mode;
|
||||
|
||||
#define VIALRGB_NUM_MODES (sizeof(vialrgb_modes) / sizeof(vialrgb_mode))
|
||||
|
||||
static const vialrgb_mode vialrgb_modes[] =
|
||||
{
|
||||
{ VIALRGB_EFFECT_OFF, "Off", false },
|
||||
{ VIALRGB_EFFECT_DIRECT, "Direct", false },
|
||||
{ VIALRGB_EFFECT_SOLID_COLOR, "Static", false },
|
||||
{ VIALRGB_EFFECT_ALPHAS_MODS, "Alphas Mods", true },
|
||||
{ VIALRGB_EFFECT_GRADIENT_UP_DOWN, "Gradient Up Down", true },
|
||||
{ VIALRGB_EFFECT_GRADIENT_LEFT_RIGHT, "Gradient Left Right", true },
|
||||
{ VIALRGB_EFFECT_BREATHING, "Breathing", true },
|
||||
{ VIALRGB_EFFECT_BAND_SAT, "Band Sat", true },
|
||||
{ VIALRGB_EFFECT_BAND_VAL, "Band Val", true },
|
||||
{ VIALRGB_EFFECT_BAND_PINWHEEL_SAT, "Band Pinwheel Sat", true },
|
||||
{ VIALRGB_EFFECT_BAND_PINWHEEL_VAL, "Band Pinwheel Val", true },
|
||||
{ VIALRGB_EFFECT_BAND_SPIRAL_SAT, "Band Spiral Sat", true },
|
||||
{ VIALRGB_EFFECT_BAND_SPIRAL_VAL, "Band Spiral Val", true },
|
||||
{ VIALRGB_EFFECT_CYCLE_ALL, "Cycle All", true },
|
||||
{ VIALRGB_EFFECT_CYCLE_LEFT_RIGHT, "Cycle Left Right", true },
|
||||
{ VIALRGB_EFFECT_CYCLE_UP_DOWN, "Cycle Up Down", true },
|
||||
{ VIALRGB_EFFECT_RAINBOW_MOVING_CHEVRON, "Rainbow Moving Chevron", true },
|
||||
{ VIALRGB_EFFECT_CYCLE_OUT_IN, "Cycle Out In", true },
|
||||
{ VIALRGB_EFFECT_CYCLE_OUT_IN_DUAL, "Cycle Out In Dual", true },
|
||||
{ VIALRGB_EFFECT_CYCLE_PINWHEEL, "Cycle Pinwheel", true },
|
||||
{ VIALRGB_EFFECT_CYCLE_SPIRAL, "Cycle Spiral", true },
|
||||
{ VIALRGB_EFFECT_DUAL_BEACON, "Dual Beacon", true },
|
||||
{ VIALRGB_EFFECT_RAINBOW_BEACON, "Rainbow Beacon", true },
|
||||
{ VIALRGB_EFFECT_RAINBOW_PINWHEELS, "Rainbow Pinwheels", true },
|
||||
{ VIALRGB_EFFECT_RAINDROPS, "Raindrops", true },
|
||||
{ VIALRGB_EFFECT_JELLYBEAN_RAINDROPS, "Jellybean Raindrops", true },
|
||||
{ VIALRGB_EFFECT_HUE_BREATHING, "Hue Breathing", true },
|
||||
{ VIALRGB_EFFECT_HUE_PENDULUM, "Hue Pendulum", true },
|
||||
{ VIALRGB_EFFECT_HUE_WAVE, "Hue Wave", true },
|
||||
{ VIALRGB_EFFECT_TYPING_HEATMAP, "Typing Heatmap", true },
|
||||
{ VIALRGB_EFFECT_DIGITAL_RAIN, "Digital Rain", true },
|
||||
{ VIALRGB_EFFECT_SOLID_REACTIVE_SIMPLE, "Solid Reactive Simple", true },
|
||||
{ VIALRGB_EFFECT_SOLID_REACTIVE, "Solid Reactive", true },
|
||||
{ VIALRGB_EFFECT_SOLID_REACTIVE_WIDE, "Solid Reactive Wide", true },
|
||||
{ VIALRGB_EFFECT_SOLID_REACTIVE_MULTIWIDE, "Solid Reactive Multiwide", true },
|
||||
{ VIALRGB_EFFECT_SOLID_REACTIVE_CROSS, "Solid Reactive Cross", true },
|
||||
{ VIALRGB_EFFECT_SOLID_REACTIVE_MULTICROSS, "Solid Reactive Multicross", true },
|
||||
{ VIALRGB_EFFECT_SOLID_REACTIVE_NEXUS, "Solid Reactive Nexus", true },
|
||||
{ VIALRGB_EFFECT_SOLID_REACTIVE_MULTINEXUS, "Solid Reactive Multinexus", true },
|
||||
{ VIALRGB_EFFECT_SPLASH, "Splash", true },
|
||||
{ VIALRGB_EFFECT_MULTISPLASH, "Multisplash", true },
|
||||
{ VIALRGB_EFFECT_SOLID_SPLASH, "Solid Splash", true },
|
||||
{ VIALRGB_EFFECT_SOLID_MULTISPLASH, "Solid Multisplash", true },
|
||||
{ VIALRGB_EFFECT_PIXEL_RAIN, "Pixel Rain", true },
|
||||
{ VIALRGB_EFFECT_PIXEL_FRACTAL, "Pixel Fractal", true },
|
||||
};
|
||||
|
||||
RGBController_QMKVialRGB::RGBController_QMKVialRGB(QMKVialRGBController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
name = controller->GetName();
|
||||
description = "QMK VialRGB Device";
|
||||
vendor = controller->GetVendor();
|
||||
location = controller->GetLocation();
|
||||
serial = controller->GetSerial();
|
||||
version = controller->GetVersion();
|
||||
type = DEVICE_TYPE_KEYBOARD;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Read mode list |
|
||||
\*-----------------------------------------------------*/
|
||||
for(std::size_t effect_idx = 0; effect_idx < controller->GetEffectCount(); effect_idx++)
|
||||
{
|
||||
unsigned short mode_index = controller->GetEffect(effect_idx);
|
||||
mode new_mode;
|
||||
|
||||
if(mode_index > VIALRGB_NUM_MODES)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
new_mode.name = vialrgb_modes[mode_index].name;
|
||||
new_mode.value = vialrgb_modes[mode_index].value;
|
||||
|
||||
if(new_mode.value == VIALRGB_EFFECT_DIRECT)
|
||||
{
|
||||
new_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
new_mode.color_mode = MODE_COLORS_PER_LED;
|
||||
}
|
||||
|
||||
if(new_mode.value >= VIALRGB_EFFECT_SOLID_COLOR)
|
||||
{
|
||||
new_mode.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
|
||||
new_mode.color_mode = MODE_COLORS_MODE_SPECIFIC;
|
||||
new_mode.colors_min = 1;
|
||||
new_mode.colors_max = 1;
|
||||
new_mode.colors.resize(1);
|
||||
}
|
||||
|
||||
if(vialrgb_modes[mode_index].has_speed)
|
||||
{
|
||||
new_mode.flags |= MODE_FLAG_HAS_SPEED;
|
||||
new_mode.speed_min = 0;
|
||||
new_mode.speed_max = 255;
|
||||
new_mode.speed = 128;
|
||||
}
|
||||
|
||||
modes.push_back(new_mode);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Read current mode |
|
||||
\*-----------------------------------------------------*/
|
||||
unsigned short cur_mode;
|
||||
unsigned char cur_speed;
|
||||
unsigned char cur_hue;
|
||||
unsigned char cur_sat;
|
||||
unsigned char cur_val;
|
||||
|
||||
controller->GetMode(&cur_mode, &cur_speed, &cur_hue, &cur_sat, &cur_val);
|
||||
|
||||
active_mode = cur_mode;
|
||||
|
||||
if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED)
|
||||
{
|
||||
modes[active_mode].speed = cur_speed;
|
||||
}
|
||||
|
||||
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
hsv_t hsv_color;
|
||||
hsv_color.hue = (unsigned int)((float)cur_hue * (360.0f / 256.0f));
|
||||
hsv_color.saturation = cur_sat;
|
||||
hsv_color.value = cur_val;
|
||||
|
||||
RGBColor rgb_color = hsv2rgb(&hsv_color);
|
||||
modes[active_mode].colors[0] = rgb_color;
|
||||
}
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_QMKVialRGB::~RGBController_QMKVialRGB()
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_QMKVialRGB::SetupZones()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Build matrix map |
|
||||
\*-----------------------------------------------------*/
|
||||
unsigned char max_col = 0;
|
||||
unsigned char max_row = 0;
|
||||
|
||||
for(unsigned short led_index = 0; led_index < controller->GetLEDCount(); led_index++)
|
||||
{
|
||||
qmk_rgb_matrix_led_info info = controller->GetLEDInfo(led_index);
|
||||
|
||||
if(info.col > max_col)
|
||||
{
|
||||
max_col = info.col;
|
||||
}
|
||||
|
||||
if(info.row > max_row)
|
||||
{
|
||||
max_row = info.row;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char height = max_row + 1;
|
||||
unsigned char width = max_col + 1;
|
||||
|
||||
unsigned int* matrix_map = new unsigned int[width * height];
|
||||
|
||||
memset(matrix_map, 0xFF, (sizeof(unsigned int) * (width * height)));
|
||||
|
||||
for(unsigned short led_index = 0; led_index < controller->GetLEDCount(); led_index++)
|
||||
{
|
||||
qmk_rgb_matrix_led_info info = controller->GetLEDInfo(led_index);
|
||||
|
||||
matrix_map[(width * info.row) + info.col] = (unsigned int)led_index;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Create keyboard zone |
|
||||
\*-----------------------------------------------------*/
|
||||
zone keyboard;
|
||||
|
||||
keyboard.name = "Keyboard";
|
||||
keyboard.type = ZONE_TYPE_MATRIX;
|
||||
keyboard.leds_min = controller->GetLEDCount();
|
||||
keyboard.leds_max = controller->GetLEDCount();
|
||||
keyboard.leds_count = controller->GetLEDCount();
|
||||
keyboard.matrix_map = new matrix_map_type;
|
||||
keyboard.matrix_map->height = height;
|
||||
keyboard.matrix_map->width = width;
|
||||
keyboard.matrix_map->map = matrix_map;
|
||||
|
||||
zones.push_back(keyboard);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Create keyboard LEDs |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned short led_idx = 0; led_idx < controller->GetLEDCount(); led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = qmk_keynames[controller->GetKeycode(led_idx)];
|
||||
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_QMKVialRGB::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RGBController_QMKVialRGB::DeviceUpdateLEDs()
|
||||
{
|
||||
controller->SendLEDs((unsigned short)colors.size(), colors.data());
|
||||
}
|
||||
|
||||
void RGBController_QMKVialRGB::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_QMKVialRGB::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_QMKVialRGB::DeviceUpdateMode()
|
||||
{
|
||||
unsigned char hue = 0;
|
||||
unsigned char sat = 0;
|
||||
unsigned char val = 0;
|
||||
|
||||
if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
hsv_t hsv_color;
|
||||
rgb2hsv(modes[active_mode].colors[0], &hsv_color);
|
||||
|
||||
hue = (unsigned char)((float)hsv_color.hue * (256.0f / 360.0f));
|
||||
sat = hsv_color.saturation;
|
||||
val = hsv_color.value;
|
||||
}
|
||||
controller->SetMode(modes[active_mode].value, modes[active_mode].speed, hue, sat, val);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_QMKVialRGB.h |
|
||||
| |
|
||||
| RGBController for VialRGB QMK Keyboard Protocol |
|
||||
| |
|
||||
| Adam Honse <calcprogrammer1@gmail.com) 29 Sep 2025 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "QMKVialRGBController.h"
|
||||
#include "RGBController.h"
|
||||
|
||||
class RGBController_QMKVialRGB : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_QMKVialRGB(QMKVialRGBController* controller_ptr);
|
||||
~RGBController_QMKVialRGB();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
QMKVialRGBController* controller;
|
||||
};
|
||||
Reference in New Issue
Block a user