Add Champion's Bane and Ironclad suport
This commit is contained in:
parent
3d8c11ea88
commit
ccb20f3930
6 changed files with 1576 additions and 22 deletions
|
|
@ -0,0 +1,443 @@
|
|||
/*-------------------------------------------------------------------*\
|
||||
| EVisionV2KeyboardController.cpp |
|
||||
| |
|
||||
| Driver for recent EVision RGB keyboard lighting controller |
|
||||
| |
|
||||
| Le Philousophe 25 Dec 2022 |
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#include <cstring>
|
||||
#include "LogManager.h"
|
||||
#include "EVisionV2KeyboardController.h"
|
||||
|
||||
#define BLANK_SPACE 6
|
||||
#define query_check_buffer(c) \
|
||||
do \
|
||||
{ \
|
||||
if(!(c)) \
|
||||
{ \
|
||||
return -256; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static uint8_t keyvalue_map[EVISION_V2_MATRIX_WIDTH * EVISION_V2_MATRIX_HEIGHT] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 19 19 20 */
|
||||
0, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96,
|
||||
1, 7, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 85, 91, 97, 103, 109, 115, 121,
|
||||
2, 8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80, 86, 92, 98, 104, 110, 116, 122,
|
||||
3, 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 105, 111, 117,
|
||||
4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 82, 94, 106, 112, 118, 124,
|
||||
5, 11, 17, 41, 65, 71, 77, 83, 89, 95, 101, 113, 119,
|
||||
};
|
||||
|
||||
EVisionV2KeyboardController::EVisionV2KeyboardController(hid_device* dev_handle, const char* path)
|
||||
{
|
||||
const uint8_t sz = HID_MAX_STR;
|
||||
wchar_t tmp[sz];
|
||||
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
|
||||
hid_get_manufacturer_string(dev, tmp, sz);
|
||||
std::wstring wName = std::wstring(tmp);
|
||||
device_name = std::string(wName.begin(), wName.end());
|
||||
|
||||
hid_get_product_string(dev, tmp, sz);
|
||||
wName = std::wstring(tmp);
|
||||
device_name.append(" ").append(std::string(wName.begin(), wName.end()));
|
||||
|
||||
uint8_t buffer[7];
|
||||
if(Read(EVISION_V2_CMD_READ_CAPABILITIES, 0, sizeof(buffer), buffer) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(buffer[0] != 0xaa && buffer[1] != 0x55)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
map_size = buffer[5];
|
||||
macros_size = buffer[6] * 0x80;
|
||||
}
|
||||
|
||||
EVisionV2KeyboardController::~EVisionV2KeyboardController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string EVisionV2KeyboardController::GetDeviceName()
|
||||
{
|
||||
return device_name;
|
||||
}
|
||||
|
||||
std::string EVisionV2KeyboardController::GetSerial()
|
||||
{
|
||||
const uint8_t sz = HID_MAX_STR;
|
||||
wchar_t tmp[sz];
|
||||
|
||||
int ret = hid_get_serial_number_string(dev, tmp, sz);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring w_tmp = std::wstring(tmp);
|
||||
std::string serial = std::string(w_tmp.begin(), w_tmp.end());
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
std::string EVisionV2KeyboardController::GetLocation()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
int EVisionV2KeyboardController::Query(uint8_t cmd, uint16_t offset, const uint8_t* idata, uint8_t size, uint8_t* odata)
|
||||
{
|
||||
uint8_t buffer[EVISION_V2_PACKET_SIZE];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
buffer[0] = EVISION_V2_REPORT_ID;
|
||||
buffer[3] = cmd;
|
||||
buffer[4] = size;
|
||||
buffer[5] = offset & 0xff;
|
||||
buffer[6] = (offset >> 8) & 0xff;
|
||||
|
||||
if(idata)
|
||||
{
|
||||
memcpy(buffer + 8, idata, size);
|
||||
}
|
||||
|
||||
uint16_t chksum = 0;
|
||||
for(uint8_t* p = &buffer[3]; p != &buffer[EVISION_V2_PACKET_SIZE]; p++)
|
||||
{
|
||||
chksum += *p;
|
||||
}
|
||||
buffer[1] = chksum & 0xff;
|
||||
buffer[2] = (chksum >> 8) & 0xff;
|
||||
|
||||
int bytes_read;
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(query_mutex);
|
||||
|
||||
hid_write(dev, buffer, sizeof(buffer));
|
||||
|
||||
do
|
||||
{
|
||||
bytes_read = hid_read(dev, buffer, sizeof(buffer));
|
||||
} while(bytes_read != 0 && buffer[0] != EVISION_V2_REPORT_ID);
|
||||
}
|
||||
query_check_buffer(bytes_read == sizeof(buffer));
|
||||
|
||||
query_check_buffer(buffer[0] == EVISION_V2_REPORT_ID);
|
||||
query_check_buffer(buffer[1] == (chksum & 0xff));
|
||||
query_check_buffer(buffer[2] == ((chksum >> 8) & 0xff));
|
||||
query_check_buffer(buffer[3] == cmd);
|
||||
query_check_buffer(buffer[5] == (offset & 0xff));
|
||||
query_check_buffer(buffer[6] == ((offset >> 8) & 0xff));
|
||||
|
||||
if(buffer[7] != 0)
|
||||
{
|
||||
return -buffer[7];
|
||||
}
|
||||
|
||||
size = buffer[4];
|
||||
if(size > EVISION_V2_PACKET_SIZE - 8)
|
||||
{
|
||||
return -256;
|
||||
}
|
||||
|
||||
if(odata)
|
||||
{
|
||||
memcpy(odata, buffer + 8, size);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int EVisionV2KeyboardController::BeginConfigure()
|
||||
{
|
||||
return Query(EVISION_V2_CMD_BEGIN_CONFIGURE);
|
||||
}
|
||||
|
||||
int EVisionV2KeyboardController::EndConfigure()
|
||||
{
|
||||
return Query(EVISION_V2_CMD_END_CONFIGURE);
|
||||
}
|
||||
|
||||
int EVisionV2KeyboardController::Read(uint8_t cmd, uint16_t offset, uint16_t size, uint8_t* odata)
|
||||
{
|
||||
while(size > 0)
|
||||
{
|
||||
uint8_t pktsz = std::min<size_t>(size, EVISION_V2_PACKET_SIZE - 8);
|
||||
int result = Query(cmd, offset, nullptr, pktsz, odata);
|
||||
if(result <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if(result > size)
|
||||
{
|
||||
return -256;
|
||||
}
|
||||
offset += result;
|
||||
odata += result;
|
||||
size -= result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVisionV2KeyboardController::Write(uint8_t cmd, uint16_t offset, const uint8_t* idata, uint16_t size)
|
||||
{
|
||||
while(size > 0)
|
||||
{
|
||||
uint8_t pktsz = std::min<size_t>(size, EVISION_V2_PACKET_SIZE - 8);
|
||||
int result = Query(cmd, offset, idata, pktsz);
|
||||
if(result <= 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
offset += pktsz;
|
||||
idata += pktsz;
|
||||
size -= pktsz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVisionV2KeyboardController::GetMode(EVisionV2KeyboardPart part, EvisionV2ModeConfig& config)
|
||||
{
|
||||
uint8_t buffer[18];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
uint8_t current_profile;
|
||||
int ret = Read(EVISION_V2_CMD_READ_CONFIG, EVISION_V2_OFFSET_CURRENT_PROFILE, 1, ¤t_profile);
|
||||
if(ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if(current_profile > 2)
|
||||
{
|
||||
current_profile = 0;
|
||||
}
|
||||
|
||||
uint16_t offset;
|
||||
uint8_t size;
|
||||
|
||||
offset = current_profile * 0x40 + EVISION_V2_OFFSET_FIRST_PROFILE;
|
||||
|
||||
switch(part)
|
||||
{
|
||||
case EVISION_V2_KEYBOARD_PART_KEYBOARD:
|
||||
size = sizeof(buffer);
|
||||
break;
|
||||
case EVISION_V2_KEYBOARD_PART_LOGO:
|
||||
offset += EVISION_V2_PARAMETER_LOGO;
|
||||
size = EVISION_V2_PARAMETER_LOGO_ON_OFF - EVISION_V2_PARAMETER_LOGO + 1;
|
||||
break;
|
||||
case EVISION_V2_KEYBOARD_PART_EDGE:
|
||||
offset += EVISION_V2_PARAMETER_EDGE;
|
||||
size = EVISION_V2_PARAMETER_END - EVISION_V2_PARAMETER_EDGE;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = Read(EVISION_V2_CMD_READ_CONFIG, offset, size, buffer);
|
||||
if(ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
config.mode = buffer[EVISION_V2_PARAMETER_MODE];
|
||||
config.brightness = buffer[EVISION_V2_PARAMETER_BRIGHTNESS];
|
||||
config.speed = buffer[EVISION_V2_PARAMETER_SPEED];
|
||||
config.direction = buffer[EVISION_V2_PARAMETER_DIRECTION];
|
||||
config.random_colours = buffer[EVISION_V2_PARAMETER_RANDOM_COLOR_FLAG] != 0;
|
||||
config.colour = ToRGBColor(buffer[EVISION_V2_PARAMETER_MODE_COLOR + 0],
|
||||
buffer[EVISION_V2_PARAMETER_MODE_COLOR + 1], buffer[EVISION_V2_PARAMETER_MODE_COLOR + 2]);
|
||||
if(part == EVISION_V2_KEYBOARD_PART_KEYBOARD)
|
||||
{
|
||||
config.ledmode = buffer[EVISION_V2_PARAMETER_LED_MODE_COLOR];
|
||||
if(config.mode == EVISION_V2_MODE_CUSTOM)
|
||||
{
|
||||
ret = Read(EVISION_V2_CMD_READ_CONFIG, current_profile * 0x40 + EVISION_V2_OFFSET_FIRST_PROFILE + EVISION_V2_PARAMETER_CURRENT_CUSTOM_MODE, sizeof(config.ledmode), &config.ledmode);
|
||||
if(ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(part == EVISION_V2_KEYBOARD_PART_LOGO)
|
||||
{
|
||||
// Use ledmode for logo on/off
|
||||
config.ledmode = buffer[EVISION_V2_PARAMETER_LOGO_ON_OFF - EVISION_V2_PARAMETER_LOGO];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EVisionV2KeyboardController::SetMode(EVisionV2KeyboardPart part, const EvisionV2ModeConfig& config)
|
||||
{
|
||||
uint8_t buffer[18];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
buffer[EVISION_V2_PARAMETER_MODE] = config.mode;
|
||||
buffer[EVISION_V2_PARAMETER_BRIGHTNESS] = config.brightness;
|
||||
buffer[EVISION_V2_PARAMETER_SPEED] = config.speed;
|
||||
buffer[EVISION_V2_PARAMETER_DIRECTION] = config.direction;
|
||||
buffer[EVISION_V2_PARAMETER_RANDOM_COLOR_FLAG] = (config.random_colours) ? 255 : 0;
|
||||
buffer[EVISION_V2_PARAMETER_MODE_COLOR + 0] = RGBGetRValue(config.colour);
|
||||
buffer[EVISION_V2_PARAMETER_MODE_COLOR + 1] = RGBGetGValue(config.colour);
|
||||
buffer[EVISION_V2_PARAMETER_MODE_COLOR + 2] = RGBGetBValue(config.colour);
|
||||
if(part == EVISION_V2_KEYBOARD_PART_KEYBOARD)
|
||||
{
|
||||
buffer[EVISION_V2_PARAMETER_COLOR_OFFSET] = 0;
|
||||
if(config.mode != EVISION_V2_MODE_CUSTOM)
|
||||
{
|
||||
buffer[EVISION_V2_PARAMETER_LED_MODE_COLOR] = config.ledmode;
|
||||
}
|
||||
}
|
||||
else if(part == EVISION_V2_KEYBOARD_PART_LOGO)
|
||||
{
|
||||
// Use ledmode for logo on/off
|
||||
buffer[EVISION_V2_PARAMETER_LOGO_ON_OFF - EVISION_V2_PARAMETER_LOGO] = config.ledmode;
|
||||
}
|
||||
|
||||
BeginConfigure();
|
||||
uint8_t current_profile;
|
||||
|
||||
int ret = Read(EVISION_V2_CMD_READ_CONFIG, EVISION_V2_OFFSET_CURRENT_PROFILE, 1, ¤t_profile);
|
||||
if(ret < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(current_profile > 2)
|
||||
{
|
||||
current_profile = 0;
|
||||
Write(EVISION_V2_CMD_WRITE_CONFIG, EVISION_V2_OFFSET_CURRENT_PROFILE, ¤t_profile, 1);
|
||||
}
|
||||
|
||||
uint16_t offset;
|
||||
uint8_t size;
|
||||
|
||||
offset = current_profile * 0x40 + EVISION_V2_OFFSET_FIRST_PROFILE;
|
||||
|
||||
switch(part)
|
||||
{
|
||||
case EVISION_V2_KEYBOARD_PART_KEYBOARD:
|
||||
size = sizeof(buffer);
|
||||
break;
|
||||
case EVISION_V2_KEYBOARD_PART_LOGO:
|
||||
offset += EVISION_V2_PARAMETER_LOGO;
|
||||
size = EVISION_V2_PARAMETER_LOGO_ON_OFF - EVISION_V2_PARAMETER_LOGO + 1;
|
||||
break;
|
||||
case EVISION_V2_KEYBOARD_PART_EDGE:
|
||||
offset += EVISION_V2_PARAMETER_EDGE;
|
||||
size = EVISION_V2_PARAMETER_END - EVISION_V2_PARAMETER_EDGE;
|
||||
break;
|
||||
}
|
||||
|
||||
Write(EVISION_V2_CMD_WRITE_CONFIG, offset, buffer, size);
|
||||
if((part == EVISION_V2_KEYBOARD_PART_KEYBOARD) && (config.mode == EVISION_V2_MODE_CUSTOM))
|
||||
{
|
||||
Write(EVISION_V2_CMD_WRITE_CONFIG, current_profile * 0x40 + EVISION_V2_OFFSET_FIRST_PROFILE + EVISION_V2_PARAMETER_CURRENT_CUSTOM_MODE, &config.ledmode, sizeof(config.ledmode));
|
||||
}
|
||||
EndConfigure();
|
||||
}
|
||||
|
||||
void EVisionV2KeyboardController::SetLedsDirect(const std::vector<RGBColor>& colours)
|
||||
{
|
||||
const size_t colours_num = std::min(colours.size(), sizeof(keyvalue_map) / sizeof(keyvalue_map[0]));
|
||||
|
||||
uint8_t* buffer = new uint8_t[3 * map_size];
|
||||
memset(buffer, 0, 3 * map_size);
|
||||
|
||||
for(size_t i = 0; i < colours_num; i++)
|
||||
{
|
||||
size_t j = (size_t)keyvalue_map[i] * 3;
|
||||
buffer[j + 0] = RGBGetRValue(colours[i]);
|
||||
buffer[j + 1] = RGBGetGValue(colours[i]);
|
||||
buffer[j + 2] = RGBGetBValue(colours[i]);
|
||||
}
|
||||
|
||||
Write(EVISION_V2_CMD_SEND_DYNAMIC_COLORS, 0, buffer, 3 * map_size);
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void EVisionV2KeyboardController::SetLedDirect(int led, RGBColor colour)
|
||||
{
|
||||
uint8_t buffer[3];
|
||||
buffer[0] = RGBGetRValue(colour);
|
||||
buffer[1] = RGBGetGValue(colour);
|
||||
buffer[2] = RGBGetBValue(colour);
|
||||
|
||||
Write(EVISION_V2_CMD_SEND_DYNAMIC_COLORS, keyvalue_map[led] * 3, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
void EVisionV2KeyboardController::RefreshLedDirect()
|
||||
{
|
||||
// Write one zero byte in the first blank space
|
||||
Query(EVISION_V2_CMD_SEND_DYNAMIC_COLORS, BLANK_SPACE * 3, nullptr, 1, nullptr);
|
||||
}
|
||||
|
||||
void EVisionV2KeyboardController::EndLedsDirect()
|
||||
{
|
||||
Query(EVISION_V2_CMD_END_DYNAMIC_COLORS);
|
||||
}
|
||||
|
||||
int EVisionV2KeyboardController::GetLedsCustom(uint8_t colorset, std::vector<RGBColor>& colours)
|
||||
{
|
||||
if(colorset > 9)
|
||||
{
|
||||
return -256;
|
||||
}
|
||||
|
||||
const size_t colours_num = std::min(colours.size(), sizeof(keyvalue_map) / sizeof(keyvalue_map[0]));
|
||||
|
||||
uint8_t* buffer = new uint8_t[3 * map_size];
|
||||
memset(buffer, 0, 3 * map_size);
|
||||
|
||||
int ret = Read(EVISION_V2_CMD_READ_CUSTOM_COLORS, 512 * colorset, 3 * map_size, buffer);
|
||||
if(ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < colours_num; i++)
|
||||
{
|
||||
size_t j = (size_t)keyvalue_map[i] * 3;
|
||||
colours[i] = ToRGBColor(buffer[j + 0], buffer[j + 1], buffer[j + 2]);
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EVisionV2KeyboardController::SetLedsCustom(uint8_t colorset, const std::vector<RGBColor>& colours)
|
||||
{
|
||||
if(colorset > 9)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t colours_num = std::min(colours.size(), sizeof(keyvalue_map) / sizeof(keyvalue_map[0]));
|
||||
|
||||
uint8_t* buffer = new uint8_t[3 * map_size];
|
||||
memset(buffer, 0, 3 * map_size);
|
||||
|
||||
for(size_t i = 0; i < colours_num; i++)
|
||||
{
|
||||
size_t j = (size_t)keyvalue_map[i] * 3;
|
||||
buffer[j + 0] = RGBGetRValue(colours[i]);
|
||||
buffer[j + 1] = RGBGetGValue(colours[i]);
|
||||
buffer[j + 2] = RGBGetBValue(colours[i]);
|
||||
}
|
||||
|
||||
BeginConfigure();
|
||||
Write(EVISION_V2_CMD_WRITE_CUSTOM_COLORS, 512 * colorset, buffer, 3 * map_size);
|
||||
EndConfigure();
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue