/*-------------------------------------------------------*\ | RGBController_RedSquareKeyrox.cpp | | | | Driver for Red Square Keyrox USB Controller | | Based on Keychron Controller by Guimard Morgan (morg) | | | | cafeed28 3 Nov 2022 | \*-------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_RedSquareKeyrox.h" #define NA 0xFFFFFFFF /*-----------------------------------*\ | TODO: Other Keyrox boards support | | (but I have only TKL) | \*-----------------------------------*/ typedef struct { const unsigned int width; /* matrix width */ const unsigned int height; /* matrix height */ std::vector> matrix_map; /* matrix map */ std::vector led_names; /* led names */ std::vector led_sequence_positions; /* position in buffers */ } keyrox; /*------------*\ | Keyrox TKL | \*------------*/ static keyrox keyrox_tkl = { 18, 6, { { 0, NA, 1, 2, 3, 4, 5, 6, 7, 8, NA, 9, 10, 11, 12, 13, 14, 15 }, { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, NA, 30, 31, 32 }, { 33, NA, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49 }, { 50, NA, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NA, 62, NA, NA, NA }, { 63, NA, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, NA, 74, NA, NA, 75, NA }, { 76, 77, 78, NA, NA, NA, 79, NA, NA, NA, 80, 81, NA, 82, 83, 84, 85, 86 } }, { // 0 KEY_EN_ESCAPE, KEY_EN_F1, KEY_EN_F2, KEY_EN_F3, KEY_EN_F4, KEY_EN_F5, KEY_EN_F6, KEY_EN_F7, KEY_EN_F8, KEY_EN_F9, // 10 KEY_EN_F10, KEY_EN_F11, KEY_EN_F12, KEY_EN_PRINT_SCREEN, KEY_EN_SCROLL_LOCK, KEY_EN_PAUSE_BREAK, KEY_EN_BACK_TICK, KEY_EN_1, KEY_EN_2, KEY_EN_3, // 20 KEY_EN_4, KEY_EN_5, KEY_EN_6, KEY_EN_7, KEY_EN_8, KEY_EN_9, KEY_EN_0, KEY_EN_MINUS, KEY_EN_EQUALS, KEY_EN_BACKSPACE, // 30 KEY_EN_INSERT, KEY_EN_HOME, KEY_EN_PAGE_UP, KEY_EN_TAB, KEY_EN_Q, KEY_EN_W, KEY_EN_E, KEY_EN_R, KEY_EN_T, KEY_EN_Y, // 40 KEY_EN_U, KEY_EN_I, KEY_EN_O, KEY_EN_P, KEY_EN_LEFT_BRACKET, KEY_EN_RIGHT_BRACKET, KEY_EN_ANSI_BACK_SLASH, KEY_EN_DELETE, KEY_EN_END, KEY_EN_PAGE_DOWN, // 50 KEY_EN_CAPS_LOCK, KEY_EN_A, KEY_EN_S, KEY_EN_D, KEY_EN_F, KEY_EN_G, KEY_EN_H, KEY_EN_J, KEY_EN_K, KEY_EN_L, // 60 KEY_EN_SEMICOLON, KEY_EN_QUOTE, KEY_EN_ANSI_ENTER, KEY_EN_LEFT_SHIFT, KEY_EN_Z, KEY_EN_X, KEY_EN_C, KEY_EN_V, KEY_EN_B, KEY_EN_N, // 70 KEY_EN_M, KEY_EN_COMMA, KEY_EN_PERIOD, KEY_EN_FORWARD_SLASH, KEY_EN_RIGHT_SHIFT, KEY_EN_UP_ARROW, KEY_EN_LEFT_CONTROL, KEY_EN_LEFT_WINDOWS, KEY_EN_LEFT_ALT, KEY_EN_SPACE, // 80 KEY_EN_RIGHT_ALT, KEY_EN_RIGHT_FUNCTION, KEY_EN_MENU, KEY_EN_RIGHT_CONTROL, KEY_EN_LEFT_ARROW, KEY_EN_DOWN_ARROW, KEY_EN_RIGHT_ARROW, }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 70, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 50, 75, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 88, 89, 94, 95, 96, 98, 100, 101, 102, 103, 104, 105, 106 } }; typedef struct { std::string name; int value; int flags; } keyrox_effect; RGBController_RedSquareKeyrox::RGBController_RedSquareKeyrox(RedSquareKeyroxController* controller_ptr) { controller = controller_ptr; name = "Red Square Keyrox"; vendor = "Red Square"; type = DEVICE_TYPE_KEYBOARD; description = name; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); keyrox_effect keyrox_effects[13] = { { "Custom", CUSTOM_MODE_VALUE, MODE_FLAG_HAS_PER_LED_COLOR }, { "Wave", WAVE_MODE_VALUE, MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD }, { "Const", CONST_MODE_VALUE, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS }, { "Breathe", BREATHE_MODE_VALUE, MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED }, { "Heartrate", HEARTRATE_MODE_VALUE, MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED }, { "Point", POINT_MODE_VALUE, MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED }, { "Winnower", WINNOWER_MODE_VALUE, MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD }, { "Stars", STARS_MODE_VALUE, MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED }, { "Spectrum", SPECTRUM_MODE_VALUE, MODE_FLAG_HAS_SPEED }, { "Plumflower", PLUMFLOWER_MODE_VALUE, MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED }, { "Shoot", SHOOT_MODE_VALUE, MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED }, { "Ambilight Rotate", AMBILIGHT_ROTATE_MODE_VALUE, MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD }, { "Ripple", RIPPLE_MODE_VALUE, MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED }, }; for(const keyrox_effect& effect : keyrox_effects) { mode m; m.name = effect.name; m.value = effect.value; m.flags = effect.flags | MODE_FLAG_HAS_BRIGHTNESS; if(m.flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) { m.color_mode = MODE_COLORS_MODE_SPECIFIC; m.colors_min = 1; m.colors_max = 1; m.colors.resize(1); m.colors.at(0) = ToRGBColor(255, 255, 255); } else if(m.flags & MODE_FLAG_HAS_PER_LED_COLOR) { m.color_mode = MODE_COLORS_PER_LED; } else { m.color_mode = MODE_COLORS_NONE; m.colors_min = 0; m.colors_max = 0; m.colors.resize(0); } if(m.flags & MODE_FLAG_HAS_SPEED) { m.speed_min = KEYROX_SPEED_MIN; m.speed_max = KEYROX_SPEED_MAX; m.speed = m.speed_max; } if(m.flags & MODE_FLAG_HAS_BRIGHTNESS) { m.brightness_min = KEYROX_BRIGHTNESS_MIN; /*------------------------------------------*\ | In Custom mode, Keyrox stores brightness | | in A of RGBA and range is 0x00-0xFF | \*------------------------------------------*/ m.brightness_max = (m.flags & MODE_FLAG_HAS_PER_LED_COLOR) ? 0xFF : KEYROX_BRIGHTNESS_MAX; m.brightness = m.brightness_max; } modes.push_back(m); } SetupZones(); } RGBController_RedSquareKeyrox::~RGBController_RedSquareKeyrox() { delete controller; } void RGBController_RedSquareKeyrox::SetupZones() { keyrox* keyboard; switch(controller->GetVariant()) { case KEYROX_VARIANT_TKL: keyboard = &keyrox_tkl; break; } controller->SetLedSequencePositions(keyboard->led_sequence_positions); /*-----------------*\ | Create the zone | \*-----------------*/ unsigned int zone_size = 0; zone z; z.name = ZONE_EN_KEYBOARD; z.type = ZONE_TYPE_MATRIX; z.matrix_map = new matrix_map_type; z.matrix_map->height = keyboard->height; z.matrix_map->width = keyboard->width; z.matrix_map->map = new unsigned int[keyboard->height * keyboard->width]; for(unsigned int h = 0; h < keyboard->height; h++) { for(unsigned int w = 0; w < keyboard->width; w++) { unsigned int key = keyboard->matrix_map[h][w]; z.matrix_map->map[h * keyboard->width + w] = key; if(key != NA) { led l; l.name = keyboard->led_names[key]; leds.push_back(l); zone_size++; } } } z.leds_min = zone_size; z.leds_max = zone_size; z.leds_count = zone_size; zones.push_back(z); SetupColors(); } void RGBController_RedSquareKeyrox::ResizeZone(int /*zone*/, int /*new_size*/) { /*---------------------------------------------------------*\ | This device does not support resizing zones | \*---------------------------------------------------------*/ } void RGBController_RedSquareKeyrox::DeviceUpdateLEDs() { controller->SetLEDsData(modes, active_mode, colors); } void RGBController_RedSquareKeyrox::UpdateZoneLEDs(int /*zone*/) { DeviceUpdateLEDs(); } void RGBController_RedSquareKeyrox::UpdateSingleLED(int /*led*/) { DeviceUpdateLEDs(); } void RGBController_RedSquareKeyrox::DeviceUpdateMode() { controller->SetMode(modes, active_mode); controller->SetModeData(modes, active_mode); }