From 7d3c02c0c59e3058e994dbf152446e9e6243776b Mon Sep 17 00:00:00 2001 From: Mohammed Julfikar Ali Mahbub Date: Sat, 6 Apr 2024 19:19:47 +0000 Subject: [PATCH] Added support for A4Tech B820R Keyboard --- .../A4TechController/A4Tech_Detector.cpp | 26 ++ .../BloodyB820RController.cpp | 102 ++++++++ .../A4TechController/BloodyB820RController.h | 51 ++++ .../RGBController_BloodyB820R.cpp | 247 ++++++++++++++++++ .../RGBController_BloodyB820R.h | 32 +++ 5 files changed, 458 insertions(+) create mode 100644 Controllers/A4TechController/BloodyB820RController.cpp create mode 100644 Controllers/A4TechController/BloodyB820RController.h create mode 100644 Controllers/A4TechController/RGBController_BloodyB820R.cpp create mode 100644 Controllers/A4TechController/RGBController_BloodyB820R.h diff --git a/Controllers/A4TechController/A4Tech_Detector.cpp b/Controllers/A4TechController/A4Tech_Detector.cpp index 5e576ff7..8dfce919 100644 --- a/Controllers/A4TechController/A4Tech_Detector.cpp +++ b/Controllers/A4TechController/A4Tech_Detector.cpp @@ -1,3 +1,13 @@ +/*-------------------------------------------------------------------*\ +| A4TechDetector.cpp | +| | +| Driver for A4Tech Devices Detector | +| | +| Chris M (Dr_No) 30 Jun 2022 | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +\*-------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ | OpenRGB includes | \*-----------------------------------------------------*/ @@ -9,6 +19,7 @@ | A4 Tech specific includes | \*-----------------------------------------------------*/ #include "RGBController_BloodyMouse.h" +#include "RGBController_BloodyB820R.h" /*-----------------------------------------------------*\ | A4 Tech USB vendor ID | @@ -29,6 +40,21 @@ void DetectA4TechMouseControllers(hid_device_info* info, const std::string& name } } +void DetectBloodyB820R(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + BloodyB820RController* controller = new BloodyB820RController(dev, info->path); + RGBController_BloodyB820R* rgb_controller = new RGBController_BloodyB820R(controller); + rgb_controller->name = name; + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + REGISTER_HID_DETECTOR_IPU("Bloody W60 Pro", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W60_PRO_PID, 2, 0xFF33, 0x0529); REGISTER_HID_DETECTOR_IPU("Bloody W90 Max", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W90_MAX_PID, 2, 0xFF33, 0x053D); REGISTER_HID_DETECTOR_IPU("Bloody MP 50RS", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_MP_50RS_PID, 2, 0xFFF2, 0x6009); +REGISTER_HID_DETECTOR_IPU("A4Tech Bloody B820R", DetectBloodyB820R, A4_TECH_VID, BLOODY_B820R_PID, 2, 0xFF52, 0x0210); \ No newline at end of file diff --git a/Controllers/A4TechController/BloodyB820RController.cpp b/Controllers/A4TechController/BloodyB820RController.cpp new file mode 100644 index 00000000..871213a8 --- /dev/null +++ b/Controllers/A4TechController/BloodyB820RController.cpp @@ -0,0 +1,102 @@ +/*-------------------------------------------------------------------*\ +| BloodyB820RController.cpp | +| | +| Driver for A4Tech Bloody B820R Keyboard Controller | +| | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +\*-------------------------------------------------------------------*/ + +#include "BloodyB820RController.h" + +/*--------------------------------------------------------------------------------------*\ + * The controller for this device should pass a packet of 64 bytes where the subsequent * + * two packets are for RED, GREEN, and BLUE respectively. The first 6 bytes are control * + * or information bytes and colors bytes starts from index 6. Moreover, the first pack- * + * et of each RGB contains color for 58 keys and the rest (104 - 58 == 46) are send on * + * the second packet. * +\*--------------------------------------------------------------------------------------*/ + +BloodyB820RController::BloodyB820RController(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; + + SendControlPacket(BLOODY_B820R_GAIN_CONTROL); +} + +BloodyB820RController::~BloodyB820RController() +{ + SendControlPacket(BLOODY_B820R_RELEASE_CONTROL); + hid_close(dev); +} + +std::string BloodyB820RController::GetSerial() +{ + const int szTemp = HID_MAX_STR; + wchar_t tmpName[szTemp]; + + hid_get_serial_number_string(dev, tmpName, szTemp); + std::wstring wName = std::wstring(tmpName); + std::string serial = std::string(wName.begin(), wName.end()); + + return serial; +} + +std::string BloodyB820RController::GetLocation() +{ + return("HID: " + location); +} + +void BloodyB820RController::SendControlPacket(uint8_t data) +{ + uint8_t buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00 }; + + hid_send_feature_report(dev, buffer, BLOODY_B820R_PACKET_SIZE); + + buffer[BLOODY_B820R_MODE_BYTE] = 0; + buffer[BLOODY_B820R_DATA_BYTE] = data; + + hid_send_feature_report(dev, buffer, BLOODY_B820R_PACKET_SIZE); +} + +void BloodyB820RController::SetLEDDirect(std::vector colors) +{ + + uint8_t r1_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x07, 0x00, 0x00 }; + uint8_t r2_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x08, 0x00, 0x00 }; + uint8_t g1_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x09, 0x00, 0x00 }; + uint8_t g2_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x0A, 0x00, 0x00 }; + uint8_t b1_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x0B, 0x00, 0x00 }; + uint8_t b2_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x0C, 0x00, 0x00 }; + + /*-----------------------------------------------------------------*\ + | Set up Direct packet | + | packet_map is the index of the Key from full_matrix_map and | + | the value is the position in the direct packet buffer | + \*-----------------------------------------------------------------*/ + + + for(size_t i = 0; i < colors.size(); i++) + { + RGBColor color = colors[i]; + uint8_t offset = BLOODY_B820R_RGB_OFFSET; + uint8_t buffer_idx = offset + i % BLOODY_B820R_RGB_BUFFER_SIZE; + uint8_t* buffers[2][3] = + { + {r1_buffer, g1_buffer, b1_buffer}, + {r2_buffer, g2_buffer, b2_buffer} + }; + + buffers[i >= BLOODY_B820R_RGB_BUFFER_SIZE][0][buffer_idx] = RGBGetRValue(color); + buffers[i >= BLOODY_B820R_RGB_BUFFER_SIZE][1][buffer_idx] = RGBGetGValue(color); + buffers[i >= BLOODY_B820R_RGB_BUFFER_SIZE][2][buffer_idx] = RGBGetBValue(color); + } + + hid_send_feature_report(dev, r1_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, r2_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, g1_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, g2_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, b1_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, b2_buffer, BLOODY_B820R_PACKET_SIZE); +} \ No newline at end of file diff --git a/Controllers/A4TechController/BloodyB820RController.h b/Controllers/A4TechController/BloodyB820RController.h new file mode 100644 index 00000000..02159107 --- /dev/null +++ b/Controllers/A4TechController/BloodyB820RController.h @@ -0,0 +1,51 @@ +/*-------------------------------------------------------------------*\ +| BloodyB820RController.h | +| | +| Driver for A4Tech Bloody B820R Keyboard Controller | +| | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +\*-------------------------------------------------------------------*/ + +#include +#include +#include "RGBController.h" + +#pragma once +#define NA 0xFFFFFFFF +#define HID_MAX_STR 255 + +#define BLOODY_B820R_RGB_BUFFER_SIZE 58 +#define BLOODY_B820R_RGB_OFFSET 6 +#define BLOODY_B820R_PACKET_SIZE 64 +#define BLOODY_B820R_KEYCOUNT 104 +#define BLOODY_B820R_MODE_BYTE 3 +#define BLOODY_B820R_DATA_BYTE 8 +#define BLOODY_B820R_GAIN_CONTROL 0x01 +#define BLOODY_B820R_RELEASE_CONTROL 0x00 + +/*---------------------------------------------------------*\ +| Bloody B820R product ID | +\*---------------------------------------------------------*/ +#define BLOODY_B820R_PID 0xFA10 + +enum +{ + BLOODY_B820R_MODE_DIRECT = 0x01, // Direct LED control - Independently set LEDs in zone +}; + +class BloodyB820RController +{ +public: + BloodyB820RController(hid_device* dev_handle, const char* path); + ~BloodyB820RController(); + + std::string GetSerial(); + std::string GetLocation(); + + void SetLEDDirect(std::vector colors); + void SendControlPacket(uint8_t data); +private: + std::string location; + hid_device* dev; +}; diff --git a/Controllers/A4TechController/RGBController_BloodyB820R.cpp b/Controllers/A4TechController/RGBController_BloodyB820R.cpp new file mode 100644 index 00000000..23c53c93 --- /dev/null +++ b/Controllers/A4TechController/RGBController_BloodyB820R.cpp @@ -0,0 +1,247 @@ +/*-------------------------------------------------------------------*\ +| RGBController_BloodyB820R.cpp | +| | +| Driver for A4Tech Bloody B820R Keyboard Controller | +| | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +\*-------------------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_BloodyB820R.h" + +static unsigned int matrix_map[6][21] = + { + {0, NA, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, NA, NA, NA, NA, 13, 14, 15}, + {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}, + {37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57}, + {58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, NA, NA, NA, NA, 71, 72, 73, NA}, + {74, NA, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, NA, NA, 86, NA, 87, 88, 89, 90}, + {91, 92, 93, 94, NA, NA, NA, NA, NA, NA, 95, 96, 97, 98, 99, 100, 101, 102, NA, 103, NA}, + }; + +static const char *led_names[] = + { + KEY_EN_ESCAPE, //00 + 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, + 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, //10 + KEY_EN_1, + KEY_EN_2, + KEY_EN_3, + 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, + KEY_EN_INSERT, + KEY_EN_HOME, + KEY_EN_PAGE_UP, + KEY_EN_NUMPAD_LOCK, + KEY_EN_NUMPAD_DIVIDE, + KEY_EN_NUMPAD_TIMES, + KEY_EN_NUMPAD_MINUS, + + KEY_EN_TAB, //20 + KEY_EN_Q, + KEY_EN_W, + KEY_EN_E, + KEY_EN_R, + KEY_EN_T, + KEY_EN_Y, + 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, + KEY_EN_NUMPAD_7, + KEY_EN_NUMPAD_8, + KEY_EN_NUMPAD_9, + KEY_EN_NUMPAD_PLUS, + + KEY_EN_CAPS_LOCK, //30 + 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, + KEY_EN_SEMICOLON, + KEY_EN_QUOTE, + KEY_EN_ANSI_ENTER, + KEY_EN_NUMPAD_4, + KEY_EN_NUMPAD_5, + KEY_EN_NUMPAD_6, + + KEY_EN_LEFT_SHIFT, //40 + KEY_EN_Z, + KEY_EN_X, + KEY_EN_C, + KEY_EN_V, + KEY_EN_B, + KEY_EN_N, + KEY_EN_M, + KEY_EN_COMMA, + KEY_EN_PERIOD, + KEY_EN_FORWARD_SLASH, + KEY_EN_RIGHT_SHIFT, + KEY_EN_UP_ARROW, + KEY_EN_NUMPAD_1, + KEY_EN_NUMPAD_2, + KEY_EN_NUMPAD_3, + KEY_EN_NUMPAD_ENTER, + + KEY_EN_LEFT_CONTROL, //50 + KEY_EN_LEFT_WINDOWS, + KEY_EN_LEFT_ALT, + KEY_EN_SPACE, + 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, + KEY_EN_NUMPAD_0, + KEY_EN_NUMPAD_PERIOD + }; + +/**------------------------------------------------------------------*\ + @name A4Tech Bloody B820R + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors A4TechDetector + @comment The A4Tech Bloody B820R keyboard controller currently + supports the full size (ANSI layout). +\*-------------------------------------------------------------------*/ + +RGBController_BloodyB820R::RGBController_BloodyB820R(BloodyB820RController *controller_ptr) +{ + controller = controller_ptr; + + name = "Bloody B820R"; + vendor = "A4Tech"; + type = DEVICE_TYPE_KEYBOARD; + description = "A4Tech Bloody Keyboard"; + serial = controller->GetSerial(); + location = controller->GetLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = BLOODY_B820R_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_BloodyB820R::~RGBController_BloodyB820R() +{ + delete controller; +} + +void RGBController_BloodyB820R::SetupZones() +{ + /*-------------------------------------------------*\ + | Create the Keyboard zone and add the matrix map | + \*-------------------------------------------------*/ + zone KB_zone; + KB_zone.name = ZONE_EN_KEYBOARD; + KB_zone.type = ZONE_TYPE_MATRIX; + KB_zone.leds_min = BLOODY_B820R_KEYCOUNT; + KB_zone.leds_max = BLOODY_B820R_KEYCOUNT; + KB_zone.leds_count = BLOODY_B820R_KEYCOUNT; + + KB_zone.matrix_map = new matrix_map_type; + KB_zone.matrix_map->height = 6; + KB_zone.matrix_map->width = 21; + KB_zone.matrix_map->map = (unsigned int *)&matrix_map; + zones.push_back(KB_zone); + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + for(unsigned int led_index = 0; led_index < BLOODY_B820R_KEYCOUNT; led_index++) + { + led new_led; + new_led.name = led_names[led_index]; + new_led.value = led_index; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_BloodyB820R::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + + +void RGBController_BloodyB820R::DeviceUpdateLEDs() +{ + controller->SetLEDDirect(colors); +} + +void RGBController_BloodyB820R::UpdateZoneLEDs(int zone) +{ + std::vector colour; + for(size_t i = 0; i < zones[zone].leds_count; i++) + { + colour.push_back(zones[zone].colors[i]); + } + + controller->SetLEDDirect(colour); +} + +void RGBController_BloodyB820R::UpdateSingleLED(int led) +{ + std::vector colour; + colour.push_back(colors[led]); + + controller->SetLEDDirect(colour); +} + +void RGBController_BloodyB820R::DeviceUpdateMode() +{ + /* This device does not support modes yet */ +} \ No newline at end of file diff --git a/Controllers/A4TechController/RGBController_BloodyB820R.h b/Controllers/A4TechController/RGBController_BloodyB820R.h new file mode 100644 index 00000000..1c823443 --- /dev/null +++ b/Controllers/A4TechController/RGBController_BloodyB820R.h @@ -0,0 +1,32 @@ +/*-------------------------------------------------------------------*\ +| RGBController_BloodyB820R.h | +| | +| Driver for A4Tech Bloody B820R Keyboard Controller | +| | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +\*-------------------------------------------------------------------*/ + +#pragma once +#include "RGBController.h" +#include "BloodyB820RController.h" +#include + +class RGBController_BloodyB820R : public RGBController +{ +public: + RGBController_BloodyB820R(BloodyB820RController* controller_ptr); + ~RGBController_BloodyB820R(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + BloodyB820RController* controller; +}; \ No newline at end of file