set dpi destroys everything, media button only works on windows
This commit is contained in:
parent
01299aa9a8
commit
efbeeac8d5
12
README.md
12
README.md
|
|
@ -11,3 +11,15 @@ install udev rule that automatically runs driver when you plug in the device??
|
||||||
|
|
||||||
irgendwie hab ich ne zeit lang timout beim config writen bekommen nachdem des config restored wurde bzw wo ich immer mal wireless und wire geswitched habe
|
irgendwie hab ich ne zeit lang timout beim config writen bekommen nachdem des config restored wurde bzw wo ich immer mal wireless und wire geswitched habe
|
||||||
nach reboot und write von original software gehts aber wieder
|
nach reboot und write von original software gehts aber wieder
|
||||||
|
|
||||||
|
take a look at fire_key
|
||||||
|
|
||||||
|
validate macros
|
||||||
|
|
||||||
|
dpi things are weird
|
||||||
|
|
||||||
|
setButton could be accepting multiple keybardkeys max 2
|
||||||
|
|
||||||
|
test le _keyboardKeys
|
||||||
|
|
||||||
|
multimedia keys working on windows but not on linux for some reason
|
||||||
|
|
@ -46,10 +46,11 @@ First Part
|
||||||
0x04-0x07 ??
|
0x04-0x07 ??
|
||||||
0x08-0x09 0x64 0x17 Profil 1, 0x64 0x01 Profil 2 ?????
|
0x08-0x09 0x64 0x17 Profil 1, 0x64 0x01 Profil 2 ?????
|
||||||
0x0a USB Polling Rate [0x01-0x04]->[125,250,500,1000]
|
0x0a USB Polling Rate [0x01-0x04]->[125,250,500,1000]
|
||||||
0x0b 0x11-0x15 wert für häckchen bei dpi, erstes 0x11 zweites 0x12 usw..
|
0x0b 0x11-0x15 wert für häckchen bei dpi, erstes 0x11 zweites 0x12 usw.. (selected mode)(available modes)
|
||||||
0x0c ?
|
0x0c ?
|
||||||
0x0d-0x16 jeweils 2 byte most significant byte last, * 50 -> annäherung an dpi -50
|
0x0d-0x16 jeweils 2 byte most significant byte last, * 50 -> annäherung an dpi -50
|
||||||
0x17-0x44 ???
|
0x2d-0x3b Colorcode für welche DPI selected RGB * 5
|
||||||
|
0x3c-0x44 ???
|
||||||
0x45 Lighting Mode, 02 Steady, 01 Colorful Streaming, 03 Breathing
|
0x45 Lighting Mode, 02 Steady, 01 Colorful Streaming, 03 Breathing
|
||||||
0x46 0-4 Brightness und 0-4 Speed bei colorful 0x(br)(sp)
|
0x46 0-4 Brightness und 0-4 Speed bei colorful 0x(br)(sp)
|
||||||
0x47 ?
|
0x47 ?
|
||||||
|
|
@ -133,7 +134,7 @@ Tastenbelegung
|
||||||
ThreeClick -> 0x31 0x01 0x32 0x03, whatever this is?
|
ThreeClick -> 0x31 0x01 0x32 0x03, whatever this is?
|
||||||
RGB on/off -> 0x50 0x02 0x00 0x00 -> hat die letzten bytes mit 0 geschrieben
|
RGB on/off -> 0x50 0x02 0x00 0x00 -> hat die letzten bytes mit 0 geschrieben
|
||||||
Disable -> 0x50 0x01 0x00 0x00
|
Disable -> 0x50 0x01 0x00 0x00
|
||||||
Fire Key -> 0x31 0x01 0xff 0x03 -> 0xff ist the firespeed und iie kann man die klick anzahl (3) nicht ändern aber denke ist 0x03
|
Fire Key -> 0x31 0x01 0xff 0x03 -> 0xff ist the firespeed und iwie kann man die klick anzahl (3) nicht ändern aber denke ist 0x03
|
||||||
|
|
||||||
Multimedia->Starts with 0x22
|
Multimedia->Starts with 0x22
|
||||||
Media Player -> 0x22 0x00 0x01 0x00
|
Media Player -> 0x22 0x00 0x01 0x00
|
||||||
|
|
|
||||||
BIN
macrofileappend
BIN
macrofileappend
Binary file not shown.
|
|
@ -10,6 +10,8 @@ target_sources(kirigami-hello
|
||||||
main.cpp
|
main.cpp
|
||||||
conf.cpp conf.h
|
conf.cpp conf.h
|
||||||
usb_thingy.cpp usb_thingy.h
|
usb_thingy.cpp usb_thingy.h
|
||||||
|
a811.cpp a811.h
|
||||||
|
le_buttons.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
ecm_target_qml_sources(kirigami-hello
|
ecm_target_qml_sources(kirigami-hello
|
||||||
|
|
|
||||||
411
src/a811.cpp
Normal file
411
src/a811.cpp
Normal file
|
|
@ -0,0 +1,411 @@
|
||||||
|
#include <cstring>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "a811.h"
|
||||||
|
#include "usb_thingy.h"
|
||||||
|
|
||||||
|
#define CHK(X) \
|
||||||
|
if ((r = (X)) != 0) \
|
||||||
|
return r;
|
||||||
|
|
||||||
|
ssize_t logError(const std::string &errorMessage, const char *file, int line,
|
||||||
|
const char *function)
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR: " << file << ":" << line << " - " << function << ": "
|
||||||
|
<< errorMessage << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
A811::A811()
|
||||||
|
{
|
||||||
|
// Init usb lib
|
||||||
|
_connection = &(Connection::getInstance());
|
||||||
|
|
||||||
|
// init other vars
|
||||||
|
_conf12 = (conf_12 *)malloc(sizeof(conf_12));
|
||||||
|
memset(_conf12, 0, sizeof(conf_12));
|
||||||
|
|
||||||
|
readConfigFromDevice(CONF_TYPE::LIGHT);
|
||||||
|
|
||||||
|
_macros = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t A811::setLightMode(LIGHT_MODE mode, int p1, int p2)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case LIGHT_MODE::COLORFUL_STREAMING:
|
||||||
|
if (p1 <= 0 || p1 > 4 || p2 <= 0 || p2 > 4)
|
||||||
|
logError("ERROR: Invalid brightness or speed.", __FILE__, __LINE__,
|
||||||
|
__func__);
|
||||||
|
_conf12->c1.light_mode = (uint8_t)mode;
|
||||||
|
_conf12->c1.col_brightness_speed =
|
||||||
|
(uint8_t)((p1 & 0x0F) | ((p2 & 0x0F) << 4));
|
||||||
|
std::cout << std::hex << (int)_conf12->c1.light_mode << "-2\n";
|
||||||
|
break;
|
||||||
|
case LIGHT_MODE::STEADY:
|
||||||
|
if (p1 <= 0 || p1 > 4 || p2 <= 0 || p2 > 4)
|
||||||
|
logError("ERROR: Invalid brightness or speed.", __FILE__, __LINE__,
|
||||||
|
__func__);
|
||||||
|
_conf12->c1.col_brightness_speed =
|
||||||
|
(uint8_t)((p1 & 0x0F) | ((p2 & 0x0F) << 4));
|
||||||
|
_conf12->c1.light_mode = (uint8_t)mode;
|
||||||
|
break;
|
||||||
|
case LIGHT_MODE::BREATHING:
|
||||||
|
if (p1 <= 0 || p1 > 4 || p2 <= 0 || p2 > 6)
|
||||||
|
logError("ERROR: Invalid brightness or color number.", __FILE__, __LINE__,
|
||||||
|
__func__);
|
||||||
|
_conf12->c1.light_mode = (uint8_t)mode;
|
||||||
|
_conf12->c1.br_brightness_speed =
|
||||||
|
(uint8_t)((p1 & 0x0F) | ((p2 & 0x0F) << 4));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logError("ERROR: Invalid LIGHT_MODE.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LIGHT_MODE A811::getLightMode() { return LIGHT_MODE(_conf12->c1.light_mode); }
|
||||||
|
|
||||||
|
ssize_t A811::setLightModeColors(LIGHT_MODE mode, unsigned char colors[21])
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case LIGHT_MODE::STEADY:
|
||||||
|
std::memcpy(&_conf12->c1.col_steady, colors, sizeof(_conf12->c1.col_steady));
|
||||||
|
break;
|
||||||
|
case LIGHT_MODE::BREATHING:
|
||||||
|
std::memcpy(&_conf12->c1.col_breathing, colors,
|
||||||
|
sizeof(_conf12->c1.col_breathing));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logError("ERROR: Invalid LIGHT_MODE.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *A811::getLightModeColors(LIGHT_MODE mode)
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case LIGHT_MODE::STEADY:
|
||||||
|
return _conf12->c1.col_steady;
|
||||||
|
case LIGHT_MODE::BREATHING:
|
||||||
|
return _conf12->c1.col_breathing;
|
||||||
|
default:
|
||||||
|
logError("ERROR: Invalid LIGHT_MODE.", __FILE__, __LINE__, __func__);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t A811::setUSBPollingRate(POLLING_RATE pr)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ((uint8_t)pr <= 0 || (uint8_t)pr > 4)
|
||||||
|
logError("ERROR: Invalid POLLING_RATE.", __FILE__, __LINE__, __func__);
|
||||||
|
_conf12->c1.polling_rate = (uint8_t)pr;
|
||||||
|
return ssize_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
POLLING_RATE A811::getUSBPollingRate()
|
||||||
|
{
|
||||||
|
return POLLING_RATE(_conf12->c1.polling_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t A811::setDPI(DPI_MODE mode, unsigned char color[3], int dpi)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ((uint8_t)mode < (uint8_t)DPI_MODE::DPI_1 ||
|
||||||
|
(uint8_t)mode > (uint8_t)DPI_MODE::DPI_5)
|
||||||
|
{
|
||||||
|
logError("ERROR: Invalid DPI_MODE.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
if (dpi > 26000 || dpi < 50)
|
||||||
|
{
|
||||||
|
logError("ERROR: Invalid dpi.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(2);
|
||||||
|
}
|
||||||
|
// Calculate the DPI value according to the formula
|
||||||
|
int dpi_value = (dpi - 50) / 50;
|
||||||
|
|
||||||
|
// Split the value into two bytes (least significant byte first)
|
||||||
|
uint8_t lsb = dpi_value & 0xFF; // Extract the least significant byte
|
||||||
|
uint8_t msb = (dpi_value >> 8) & 0xFF; // Extract the most significant byte
|
||||||
|
|
||||||
|
_conf12->c1.dpi_modes =
|
||||||
|
(uint8_t)(((uint8_t)mode & 0x0F) | ((0x1 & 0x0F) << 4));
|
||||||
|
|
||||||
|
_conf12->c1.hdpi[(uint8_t)mode - 1 * 2] = lsb;
|
||||||
|
_conf12->c1.hdpi[(uint8_t)mode - 1 * 2 + 1] = msb;
|
||||||
|
_conf12->c1.col_dpi[0] = color[(uint8_t)mode - 1 * 3];
|
||||||
|
_conf12->c1.col_dpi[1] = color[(uint8_t)mode - 1 * 3 + 1];
|
||||||
|
_conf12->c1.col_dpi[2] = color[(uint8_t)mode - 1 * 3 + 2];
|
||||||
|
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int A811::getDPI(DPI_MODE mode)
|
||||||
|
{
|
||||||
|
if ((uint8_t)mode < (uint8_t)DPI_MODE::DPI_1 ||
|
||||||
|
(uint8_t)mode > (uint8_t)DPI_MODE::DPI_5)
|
||||||
|
{
|
||||||
|
logError("ERROR: Invalid DPI_MODE.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BATTERY_STAT A811::getBatteryStatus()
|
||||||
|
{
|
||||||
|
if (_batStat.wired == 0x10)
|
||||||
|
{
|
||||||
|
if (_batStat.capacity == 0x01)
|
||||||
|
return BATTERY_STAT::CHARGING;
|
||||||
|
else if (_batStat.capacity == 0x02)
|
||||||
|
return BATTERY_STAT::NOT_CHARGING;
|
||||||
|
}
|
||||||
|
return BATTERY_STAT::DISCHARGING;
|
||||||
|
}
|
||||||
|
|
||||||
|
int A811::getBatteryCapacity()
|
||||||
|
{
|
||||||
|
if (_batStat.wired == 0x11)
|
||||||
|
return (int)_batStat.capacity;
|
||||||
|
//@comment thats weird what to do i cant read the battery level if it is
|
||||||
|
// plugged???
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t A811::setMultimediaButton(int id, std::string keyname)
|
||||||
|
{
|
||||||
|
if (id >= 0 && id < 7)
|
||||||
|
{
|
||||||
|
// Assuming keyname is a valid key in the _keycodes map
|
||||||
|
if (_keycodes.find(keyname) == _keycodes.end())
|
||||||
|
{
|
||||||
|
logError("ERROR: Keyname not found in keycodes.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1); // or handle the error appropriately
|
||||||
|
}
|
||||||
|
auto arr = _keycodes[keyname];
|
||||||
|
unsigned char *mahbytes = (unsigned char *)&_conf12->c2.mouse_buttons[id];
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)sizeof(_conf12->c2.mouse_buttons[id]); ++i)
|
||||||
|
{
|
||||||
|
std::cout << std::hex << (int)mahbytes[i] << "|";
|
||||||
|
mahbytes[i] = ((unsigned char *)&arr)[i];
|
||||||
|
std::cout << std::hex << (int)mahbytes[i] << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (id >= 7 && id < 15)
|
||||||
|
{
|
||||||
|
// Assuming keyname is a valid key in the _keycodes map
|
||||||
|
auto it = _keycodes.find(keyname);
|
||||||
|
if (it != _keycodes.end())
|
||||||
|
{
|
||||||
|
const std::array<uint8_t, 4> &keycode_array = it->second; // Get the array from the map
|
||||||
|
// std::copy(keycode_array.begin(), keycode_array.end(), _conf12->c2.side[id - 7].keycode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError("ERROR: Keyname not found in keycodes.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1); // or handle the error appropriately
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError("ERROR: Invalid button id.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t A811::setMacroButton(int id, int macro_id, int cycle_type, int cycle_cnt)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned char keyConf[4] = {0x70, macro_id, cycle_type, cycle_cnt};
|
||||||
|
|
||||||
|
// maybe check if macro is on mouse
|
||||||
|
// check validity of data
|
||||||
|
// also i am not sure at all how the macro ids work like why is the 1st key alway macro nr 1 and so on
|
||||||
|
if (id >= 0 && id < 7)
|
||||||
|
{
|
||||||
|
memcpy(&_conf12->c2.mouse_buttons[id], keyConf, sizeof(_conf12->c2.mouse_buttons[id]));
|
||||||
|
}
|
||||||
|
else if (id >= 7 && id < 15)
|
||||||
|
{
|
||||||
|
memcpy(&_conf12->c2.side[id - 7], keyConf, sizeof(_conf12->c2.side[id]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError("ERROR: Invalid button id.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t A811::setButton(int id, std::string keyboardKey, int mod)
|
||||||
|
{
|
||||||
|
unsigned char key[4];
|
||||||
|
key[0] = 0x21;
|
||||||
|
key[1] = mod;
|
||||||
|
|
||||||
|
if (id >= 0 && id < 7)
|
||||||
|
{
|
||||||
|
// Assuming keyname is a valid key in the _keycodes map
|
||||||
|
auto it = _keyboardKeys.find(keyboardKey);
|
||||||
|
if (it != _keyboardKeys.end())
|
||||||
|
{
|
||||||
|
key[2] = it->second;
|
||||||
|
key[3] = 0x00; // optional button
|
||||||
|
memcpy(&_conf12->c2.mouse_buttons[id], key, sizeof(_conf12->c2.mouse_buttons[id]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError("ERROR: Keyname not found in _keyboardKeys.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1); // or handle the error appropriately
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (id >= 7 && id < 15)
|
||||||
|
{
|
||||||
|
// Assuming keyname is a valid key in the _keycodes map
|
||||||
|
auto it = _keyboardKeys.find(keyboardKey);
|
||||||
|
if (it != _keyboardKeys.end())
|
||||||
|
{
|
||||||
|
key[2] = it->second;
|
||||||
|
key[3] = 0x00; // optional button
|
||||||
|
memcpy(&_conf12->c2.side[id], key, sizeof(_conf12->c2.side[id]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError("ERROR: Keyname not found in _keyboardKeys.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1); // or handle the error appropriately
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError("ERROR: Invalid button id.", __FILE__, __LINE__, __func__);
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_r_button A811::getButton(int id)
|
||||||
|
{
|
||||||
|
|
||||||
|
_r_button b;
|
||||||
|
/*
|
||||||
|
if (id >= 0 && id < 7){
|
||||||
|
|
||||||
|
// Assuming keyname is a valid key in the _keycodes map
|
||||||
|
auto it = _buttonNames.find(id);
|
||||||
|
if (it != _buttonNames.end()) {
|
||||||
|
b.name = it->second;
|
||||||
|
} else {
|
||||||
|
logError("ERROR: Button name not found in _buttonNames.", __FILE__, __LINE__, __func__);
|
||||||
|
// Handle the error appropriately, e.g., returning an empty _r_button
|
||||||
|
return _r_button(); // Return empty or error _r_button
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (id >= 7 && id < 15)
|
||||||
|
{
|
||||||
|
// Assuming keyname is a valid key in the _keycodes map
|
||||||
|
auto it = _buttonNames.find(id-7);
|
||||||
|
if (it != _buttonNames.end()) {
|
||||||
|
b.name = it->second;
|
||||||
|
} else {
|
||||||
|
logError("ERROR: Button name not found in _buttonNames.", __FILE__, __LINE__, __func__);
|
||||||
|
// Handle the error appropriately, e.g., returning an empty _r_button
|
||||||
|
return _r_button(); // Return empty or error _r_button
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError("ERROR: Invalid button id.", __FILE__, __LINE__, __func__);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return _r_button();
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t A811::readConfigFromDevice(CONF_TYPE t_conf)
|
||||||
|
{
|
||||||
|
unsigned char _data[8] = {0x05, 0x21, 0, 0, 0, 0, 0, 0};
|
||||||
|
unsigned char _datas[520];
|
||||||
|
memset(_datas, 0, 520);
|
||||||
|
/*if(!connection->isWireless())
|
||||||
|
_data[1] = 0x11;*/
|
||||||
|
// not sure if this means anything
|
||||||
|
ssize_t r;
|
||||||
|
CHK(_connection->open());
|
||||||
|
|
||||||
|
switch (t_conf)
|
||||||
|
{
|
||||||
|
case CONF_TYPE::LIGHT:
|
||||||
|
_data[1] = 0x21;
|
||||||
|
CHK(_connection->setReport(0x0305, _data, 8));
|
||||||
|
CHK(_connection->getReport(0x0308, (unsigned char*)&_conf12->c1, 520));
|
||||||
|
break;
|
||||||
|
case CONF_TYPE::KEY:
|
||||||
|
_data[1] = 0x22;
|
||||||
|
CHK(_connection->setReport(0x0305, (unsigned char *)_data, 8));
|
||||||
|
CHK(_connection->getReport(0x0308, (unsigned char *)&_conf12->c2, 520));
|
||||||
|
break;
|
||||||
|
case CONF_TYPE::MACRO:
|
||||||
|
logError("ERROR: Macros not implemented.", __FILE__, __LINE__, __func__);
|
||||||
|
break;
|
||||||
|
case CONF_TYPE::BATTERY:
|
||||||
|
_data[1] = 0x90;
|
||||||
|
CHK(_connection->setReport(0x0305, (unsigned char *)_data, 8));
|
||||||
|
CHK(_connection->getReport(0x0305, (unsigned char *)&_batStat, 8));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logError("ERROR: Invalid CONF_TYPE.", __FILE__, __LINE__, __func__);
|
||||||
|
CHK(_connection->close());
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHK(_connection->close());
|
||||||
|
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t A811::writeConfigToDevice(CONF_TYPE t_conf)
|
||||||
|
{
|
||||||
|
ssize_t r;
|
||||||
|
CHK(_connection->open());
|
||||||
|
|
||||||
|
switch (t_conf)
|
||||||
|
{
|
||||||
|
case CONF_TYPE::LIGHT:
|
||||||
|
_conf12->c1.req_type = 0x92;
|
||||||
|
std::cout << std::hex << (int)_conf12->c1.light_mode << "-3\n";
|
||||||
|
CHK(_connection->setReport(0x0308, (unsigned char *)&_conf12->c1, 520));
|
||||||
|
break;
|
||||||
|
case CONF_TYPE::KEY:
|
||||||
|
_conf12->c2.req_type = 0x50;
|
||||||
|
CHK(_connection->setReport(0x0308, (unsigned char *)&_conf12->c2, 520));
|
||||||
|
break;
|
||||||
|
case CONF_TYPE::MACRO:
|
||||||
|
logError("ERROR: Macros not implemented.", __FILE__, __LINE__, __func__);
|
||||||
|
break;
|
||||||
|
case CONF_TYPE::BATTERY:
|
||||||
|
logError("ERROR: Invalid write to CONF_TYPE::BATTERY.", __FILE__, __LINE__,
|
||||||
|
__func__);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logError("ERROR: Invalid CONF_TYPE.", __FILE__, __LINE__, __func__);
|
||||||
|
CHK(_connection->close());
|
||||||
|
return ssize_t(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHK(_connection->close());
|
||||||
|
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
256
src/a811.h
Normal file
256
src/a811.h
Normal file
|
|
@ -0,0 +1,256 @@
|
||||||
|
#include <map>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "structs.h"
|
||||||
|
#include "usb_thingy.h"
|
||||||
|
|
||||||
|
#define MOD_CTRL 1
|
||||||
|
#define MOD_SHIFT 2
|
||||||
|
#define MOD_ALT 4
|
||||||
|
#define MOD_SUPER 8
|
||||||
|
|
||||||
|
struct _r_keyCode
|
||||||
|
{
|
||||||
|
std::string mods;
|
||||||
|
std::string keyCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _r_button
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
_r_keyCode key;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LIGHT_MODE : uint8_t
|
||||||
|
{
|
||||||
|
COLORFUL_STREAMING = 1,
|
||||||
|
STEADY,
|
||||||
|
BREATHING
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class POLLING_RATE : uint8_t
|
||||||
|
{
|
||||||
|
P_125 = 1,
|
||||||
|
P_250,
|
||||||
|
P_500,
|
||||||
|
P_1000
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DPI_MODE : uint8_t
|
||||||
|
{
|
||||||
|
DPI_1 = 1,
|
||||||
|
DPI_2,
|
||||||
|
DPI_3,
|
||||||
|
DPI_4,
|
||||||
|
DPI_5
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CONF_TYPE : uint8_t
|
||||||
|
{
|
||||||
|
LIGHT,
|
||||||
|
KEY,
|
||||||
|
MACRO,
|
||||||
|
BATTERY
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BATTERY_STAT : uint8_t
|
||||||
|
{
|
||||||
|
CHARGING,
|
||||||
|
DISCHARGING,
|
||||||
|
NOT_CHARGING
|
||||||
|
};
|
||||||
|
|
||||||
|
class A811
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
A811();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the light mode and its associated parameters.
|
||||||
|
*
|
||||||
|
* This function sets the light mode for a device. Depending on the `mode`
|
||||||
|
* parameter, the meanings of `param1` and `param2` will vary.
|
||||||
|
*
|
||||||
|
* @param mode The mode in which the light should operate.
|
||||||
|
*
|
||||||
|
* Possible values are:
|
||||||
|
*
|
||||||
|
* - `LIGHT_MODE::STEADY`: The light remains steady.
|
||||||
|
* - `param1`: Brightness (0-4).
|
||||||
|
* - `param2`: Index of Color (0-6).
|
||||||
|
* - `LIGHT_MODE::COLORFUL_STREAMING`: Rainbow effect.
|
||||||
|
* - `param1`: Brightness (0-4).
|
||||||
|
* - `param2`: Transition speed (0-4).
|
||||||
|
* - `LIGHT_MODE::BREATHING`: The light pulses gradually in intensity.
|
||||||
|
* - `param1`: Brightness (0-4).
|
||||||
|
* - `param2`: Transition speed (0-4).
|
||||||
|
*
|
||||||
|
* @param param1 The first parameter, whose meaning depends on the selected
|
||||||
|
* `mode`.
|
||||||
|
* @param param2 The second parameter, whose meaning depends on the selected
|
||||||
|
* `mode`.
|
||||||
|
*
|
||||||
|
* @return ssize_t Returns the status of the operation, where 0 indicates
|
||||||
|
* success and a negative value indicates failure.
|
||||||
|
*/
|
||||||
|
ssize_t setLightMode(LIGHT_MODE, int, int);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the current light mode.
|
||||||
|
*
|
||||||
|
* This function retrieves the current light mode of the device.
|
||||||
|
*
|
||||||
|
* @return LIGHT_MODE The current mode in which the light is operating.
|
||||||
|
*/
|
||||||
|
LIGHT_MODE getLightMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the colors for the light modes.
|
||||||
|
*
|
||||||
|
* This function allows you to set specific color values for different light
|
||||||
|
* modes.
|
||||||
|
*
|
||||||
|
* @param mode The mode for which to set the color values.
|
||||||
|
* @param colors An array of 21 unsigned char values representing 7 RGB
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* @return ssize_t Returns the status of the operation, where 0 indicates
|
||||||
|
* success and a negative value indicates failure.
|
||||||
|
*/
|
||||||
|
ssize_t setLightModeColors(LIGHT_MODE, unsigned char[21]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the colors for the light modes.
|
||||||
|
*
|
||||||
|
* This function allows you to set specific color values for different light
|
||||||
|
* modes.
|
||||||
|
*
|
||||||
|
* @param mode The mode for which to set the color values.
|
||||||
|
* @param colors An array of 21 unsigned char values representing 7 RGB
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* @return ssize_t Returns the status of the operation, where 0 indicates
|
||||||
|
* success and a negative value indicates failure.
|
||||||
|
*/
|
||||||
|
unsigned char *getLightModeColors(LIGHT_MODE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the polling rate.
|
||||||
|
*
|
||||||
|
* This function allows you to set a specific polling rate.
|
||||||
|
*
|
||||||
|
* @param p_rate The mode for which to set the color values.
|
||||||
|
*
|
||||||
|
* @return ssize_t Returns the status of the operation, where 0 indicates
|
||||||
|
* success and a negative value indicates failure.
|
||||||
|
*/
|
||||||
|
ssize_t setUSBPollingRate(POLLING_RATE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the current polling rate.
|
||||||
|
*
|
||||||
|
* This function retrieves the current light mode of the device.
|
||||||
|
*
|
||||||
|
* @return POLLING_RATE The current mode in which the light is operating.
|
||||||
|
*/
|
||||||
|
POLLING_RATE getUSBPollingRate();
|
||||||
|
|
||||||
|
// dpi loop loops consecutively throug dpi modes, e.g. if 1 is active but 2
|
||||||
|
// not it will loop to 2 before 3 how to solve this see witch modes are active
|
||||||
|
// and save them consecutively with according color and shit but then you need
|
||||||
|
// to put non active modes last and when you activate them again need to
|
||||||
|
// insert them in the right position int is DPI max is 26000 in is 50
|
||||||
|
/// itse not a this class probelm i think just set the values,
|
||||||
|
// itse more a dpi loop problem just need to set the values from frontend like
|
||||||
|
// explained before
|
||||||
|
ssize_t setDPI(DPI_MODE, unsigned char[3], int);
|
||||||
|
|
||||||
|
// returns all active dpi configurations
|
||||||
|
int getDPI(DPI_MODE);
|
||||||
|
|
||||||
|
BATTERY_STAT getBatteryStatus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the battery capacity.
|
||||||
|
*
|
||||||
|
* This function returns the battery capacity of the device.
|
||||||
|
*
|
||||||
|
* @note If the device is plugged in (wired mode), the battery level cannot be
|
||||||
|
* read and the function will return 0.
|
||||||
|
*
|
||||||
|
* @return int The current battery capacity if not plugged in; otherwise,
|
||||||
|
* returns 0.
|
||||||
|
*/
|
||||||
|
int getBatteryCapacity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assign a multimedia key to a button.
|
||||||
|
*
|
||||||
|
* Assign a multimedia key to a button.
|
||||||
|
*
|
||||||
|
* @param id id of the button to assign to 0-14.
|
||||||
|
* @param keyname name of the assigned key. @see _keycodes
|
||||||
|
*
|
||||||
|
* @return ssize_t Returns the status of the operation, where 0 indicates
|
||||||
|
* success and a negative value indicates failure.
|
||||||
|
*/
|
||||||
|
ssize_t setMultimediaButton(int, std::string);
|
||||||
|
/**
|
||||||
|
* @brief Assign a macro to a button.
|
||||||
|
*
|
||||||
|
* Assign a macro to a button.
|
||||||
|
*
|
||||||
|
* @param id id of the button to assign to 0-14.
|
||||||
|
* @param macro_id id of the macro to assign. @see _keycodes
|
||||||
|
* @param cycle_type if 0x02 cycle until any button pressed, if 0x04 cycle till the key is released
|
||||||
|
* @param cycle_cnt if cycle type 0x01 how often the macro should be cycled
|
||||||
|
*
|
||||||
|
* @return ssize_t Returns the status of the operation, where 0 indicates
|
||||||
|
* success and a negative value indicates failure.
|
||||||
|
*/
|
||||||
|
ssize_t setMacroButton(int, int, int, int);
|
||||||
|
/**
|
||||||
|
* @brief Assign a simple keyboard key w/o modifier to a button.
|
||||||
|
*
|
||||||
|
* Assign a simple keyboard key w/o modifier to a button.
|
||||||
|
*
|
||||||
|
* @param id id of the button to assign to 0-14.
|
||||||
|
* @param keyboardKey name of the assigned key. @see le_buttons.cpp
|
||||||
|
* @param mod which modifiers should be used.
|
||||||
|
*
|
||||||
|
* @return ssize_t Returns the status of the operation, where 0 indicates
|
||||||
|
* success and a negative value indicates failure.
|
||||||
|
*/
|
||||||
|
ssize_t setButton(int, std::string, int);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the button and its config.
|
||||||
|
*
|
||||||
|
* Get the configuration of a button.
|
||||||
|
*
|
||||||
|
* @param id id of the button to assign to 0-14.
|
||||||
|
*
|
||||||
|
* @return _r_button returns the button name, and the assigned keyCode
|
||||||
|
*/
|
||||||
|
_r_button getButton(int);
|
||||||
|
|
||||||
|
ssize_t readConfigFromDevice(CONF_TYPE);
|
||||||
|
ssize_t writeConfigToDevice(CONF_TYPE);
|
||||||
|
|
||||||
|
private:
|
||||||
|
conf_12 *_conf12;
|
||||||
|
|
||||||
|
battery_stat _batStat;
|
||||||
|
|
||||||
|
static std::map<std::string, std::array<uint8_t, 4>> _keycodes;
|
||||||
|
|
||||||
|
static std::map<int, std::string> _buttonNames;
|
||||||
|
|
||||||
|
static std::map<std::string, uint8_t> _keyboardKeys;
|
||||||
|
|
||||||
|
// still need to find out how many macros fit on device
|
||||||
|
// if i wanna do a full conf struct size of macros needs to be known?
|
||||||
|
macro **_macros;
|
||||||
|
|
||||||
|
Connection *_connection;
|
||||||
|
};
|
||||||
|
|
@ -31,7 +31,8 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
if (Connection::getInstance().findDevice())
|
if (Connection::getInstance().findDevice())
|
||||||
{
|
{
|
||||||
std::cerr << "ERROR: Device not found!";
|
std::cerr << "ERROR: Device not found!"
|
||||||
|
<< "\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
118
src/conf.cpp
118
src/conf.cpp
|
|
@ -1,8 +1,8 @@
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include <iostream>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <qfiledialog.h>
|
#include <iostream>
|
||||||
#include <klocalizedstring.h>
|
#include <klocalizedstring.h>
|
||||||
|
#include <qfiledialog.h>
|
||||||
|
|
||||||
#define CHK(X) \
|
#define CHK(X) \
|
||||||
if ((r = (X)) != 0) \
|
if ((r = (X)) != 0) \
|
||||||
|
|
@ -12,12 +12,17 @@ Conf::Conf(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
m_conf1 = (conf_1 *)malloc(sizeof(conf_1));
|
m_conf1 = (conf_1 *)malloc(sizeof(conf_1));
|
||||||
m_conf2 = (conf_2 *)malloc(sizeof(conf_2));
|
m_conf2 = (conf_2 *)malloc(sizeof(conf_2));
|
||||||
std::cout << std::dec << sizeof(conf_1) << "; " << sizeof(conf_2) << std::endl;
|
std::cout << std::dec << sizeof(conf_1) << "; " << sizeof(conf_2)
|
||||||
|
<< std::endl;
|
||||||
memset(m_conf1, 0, sizeof(conf_1));
|
memset(m_conf1, 0, sizeof(conf_1));
|
||||||
memset(m_conf2, 0, sizeof(conf_2));
|
memset(m_conf2, 0, sizeof(conf_2));
|
||||||
|
|
||||||
connection = &(Connection::getInstance());
|
connection = &(Connection::getInstance());
|
||||||
connection->findDevice();
|
if (connection->findDevice())
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR: device not found" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// read initial config from device
|
// read initial config from device
|
||||||
readConfigFromDevice(m_conf1);
|
readConfigFromDevice(m_conf1);
|
||||||
|
|
@ -76,7 +81,8 @@ ssize_t Conf::deleteMacroFromFile(macro *_macro, const char *filePath)
|
||||||
// Read each macro from the original file
|
// Read each macro from the original file
|
||||||
while (fread(&temp_macro, sizeof(macro), 1, infile) == 1)
|
while (fread(&temp_macro, sizeof(macro), 1, infile) == 1)
|
||||||
{
|
{
|
||||||
// If the macro ID does not match the one to delete, write it to the temp file
|
// If the macro ID does not match the one to delete, write it to the temp
|
||||||
|
// file
|
||||||
if (temp_macro.macro_nr != _macro->macro_nr)
|
if (temp_macro.macro_nr != _macro->macro_nr)
|
||||||
{
|
{
|
||||||
fwrite(&temp_macro, sizeof(macro), 1, tempfile);
|
fwrite(&temp_macro, sizeof(macro), 1, tempfile);
|
||||||
|
|
@ -93,7 +99,8 @@ ssize_t Conf::deleteMacroFromFile(macro *_macro, const char *filePath)
|
||||||
|
|
||||||
// Replace the original file with the temp file
|
// Replace the original file with the temp file
|
||||||
remove(filePath); // Delete the original file
|
remove(filePath); // Delete the original file
|
||||||
rename("tempfile.bin", filePath); // Rename the temp file to the original file name
|
rename("tempfile.bin",
|
||||||
|
filePath); // Rename the temp file to the original file name
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -102,18 +109,56 @@ ssize_t Conf::deleteMacroFromFile(macro *_macro, const char *filePath)
|
||||||
|
|
||||||
void Conf::testFunc()
|
void Conf::testFunc()
|
||||||
{
|
{
|
||||||
macro **macros;
|
/*macro **macros;
|
||||||
readMacrosFromDevice(macros, 4);
|
readMacrosFromDevice(macros, 4);
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
appendMacroToFile(macros[i], "macrofileappend");
|
appendMacroToFile(macros[i], "macrofileappend");
|
||||||
}
|
}*/
|
||||||
|
A811 *asd = new A811();
|
||||||
|
asd->readConfigFromDevice(CONF_TYPE::BATTERY);
|
||||||
|
asd->readConfigFromDevice(CONF_TYPE::LIGHT);
|
||||||
|
asd->readConfigFromDevice(CONF_TYPE::KEY);
|
||||||
|
|
||||||
|
asd->setLightMode(LIGHT_MODE::BREATHING, 1, 4);
|
||||||
|
asd->writeConfigToDevice(CONF_TYPE::LIGHT);
|
||||||
|
asd->setUSBPollingRate(POLLING_RATE::P_1000);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "UBS Polling rate: " << (int)asd->getUSBPollingRate() << std::endl;
|
||||||
|
std::cout << "BATTERYSTATUS: " << (int)asd->getBatteryStatus() << std::endl;
|
||||||
|
std::cout << "LIGHTMODE: " << (int)asd->getLightMode() << std::endl;
|
||||||
|
|
||||||
|
asd->setLightMode(LIGHT_MODE::COLORFUL_STREAMING, 1, 2);
|
||||||
|
asd->writeConfigToDevice(CONF_TYPE::LIGHT);
|
||||||
|
sleep(2);
|
||||||
|
|
||||||
|
asd->setMultimediaButton(2, "media_volume_up");
|
||||||
|
|
||||||
|
asd->writeConfigToDevice(CONF_TYPE::KEY);
|
||||||
|
std::cout << asd->getButton(3).name << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
asd->setLightMode(LIGHT_MODE::BREATHING, 4, 4);
|
||||||
|
|
||||||
|
unsigned char *cols;
|
||||||
|
cols = asd->getLightModeColors(LIGHT_MODE::BREATHING);
|
||||||
|
asd->getLightModeColors(LIGHT_MODE::COLORFUL_STREAMING);
|
||||||
|
unsigned char cols2[21] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00};
|
||||||
|
asd->setLightModeColors(LIGHT_MODE::BREATHING, cols2);
|
||||||
|
unsigned char cols3[3] = {0xff, 0xff, 0x00};
|
||||||
|
//asd->setDPI(DPI_MODE::DPI_1, cols3, 13000); --> setting this kills everything
|
||||||
|
|
||||||
|
//asd->writeConfigToDevice(CONF_TYPE::KEY);
|
||||||
|
|
||||||
|
std::cout << "Battery capacity:" << std::dec << asd->getBatteryCapacity() << std::endl;
|
||||||
|
asd->writeConfigToDevice(CONF_TYPE::LIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Conf::lightMode()
|
int Conf::lightMode() { return m_conf1->light_mode; }
|
||||||
{
|
|
||||||
return m_conf1->light_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Conf::setLightMode(int mode)
|
void Conf::setLightMode(int mode)
|
||||||
{
|
{
|
||||||
|
|
@ -214,6 +259,12 @@ ssize_t Conf::writeConfigToDevice(conf_1 *conf)
|
||||||
CHK(connection->setReport(0x0308, (unsigned char *)conf, 520));
|
CHK(connection->setReport(0x0308, (unsigned char *)conf, 520));
|
||||||
CHK(connection->close());
|
CHK(connection->close());
|
||||||
|
|
||||||
|
for (int i = 0; i < (0x44 - 0x16); i++)
|
||||||
|
{
|
||||||
|
std::cout << std::hex << (int)conf->__u5[i] << "\t";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,7 +386,8 @@ ssize_t Conf::readAssignedMacrosFromDevice()
|
||||||
int macroCnt = 0;
|
int macroCnt = 0;
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (m_conf2->side[i].pref == 0x70 || (m_conf2->mouse_buttons[i].pref == 0x70 && i < 6))
|
if (m_conf2->side[i].pref == 0x70 ||
|
||||||
|
(m_conf2->mouse_buttons[i].pref == 0x70 && i < 6))
|
||||||
macroCnt++;
|
macroCnt++;
|
||||||
}
|
}
|
||||||
std::cout << macroCnt << std::endl;
|
std::cout << macroCnt << std::endl;
|
||||||
|
|
@ -370,6 +422,12 @@ ssize_t Conf::readConfigFromDevice(conf_1 *conf)
|
||||||
CHK(connection->getReport(0x0308, (unsigned char *)conf, 520));
|
CHK(connection->getReport(0x0308, (unsigned char *)conf, 520));
|
||||||
CHK(connection->close());
|
CHK(connection->close());
|
||||||
|
|
||||||
|
for (int i = 0; i < (0x44 - 0x16); i++)
|
||||||
|
{
|
||||||
|
std::cout << std::hex << (int)conf->__u5[i] << "\t";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
return ssize_t(0);
|
return ssize_t(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -467,6 +525,40 @@ ssize_t Conf::readConfigFromFile(const char *filePath)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::getIdleStatus()
|
||||||
|
{
|
||||||
|
unsigned char conf[8] = {
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
unsigned char _data[8] = {0x05, 0x80, 0, 0, 0, 0, 0, 0};
|
||||||
|
/*if(!connection->isWireless())
|
||||||
|
_data[1] = 0x11;*/
|
||||||
|
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
CHK(connection->setReport(0x0305, _data, 8));
|
||||||
|
CHK(connection->getReport(0x0305, (unsigned char *)conf, 8));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
std::cout << "IDLE STATUS --------------------------" << std::endl;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
std::cout << std::hex << (int)conf[i] << "\t";
|
||||||
|
}
|
||||||
|
std::cout << "---------------" << std::endl;
|
||||||
|
|
||||||
|
return ssize_t(0);
|
||||||
|
|
||||||
|
return ssize_t();
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t Conf::readConfigFromFile()
|
ssize_t Conf::readConfigFromFile()
|
||||||
{
|
{
|
||||||
QFileDialog dialog(nullptr);
|
QFileDialog dialog(nullptr);
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
#include <libusb-1.0/libusb.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "usb_thingy.h"
|
#include "usb_thingy.h"
|
||||||
|
#include "a811.h"
|
||||||
|
|
||||||
#define CONF_FILE "conf.bin"
|
#define CONF_FILE "conf.bin"
|
||||||
|
|
||||||
|
|
@ -42,6 +42,8 @@ public:
|
||||||
Q_INVOKABLE ssize_t readConfigFromFile();
|
Q_INVOKABLE ssize_t readConfigFromFile();
|
||||||
ssize_t readConfigFromFile(const char *filePath);
|
ssize_t readConfigFromFile(const char *filePath);
|
||||||
|
|
||||||
|
ssize_t getIdleStatus();
|
||||||
|
|
||||||
// all the config should be in a single file
|
// all the config should be in a single file
|
||||||
ssize_t writeConfigToFile(conf_1 *conf, const char *filePath);
|
ssize_t writeConfigToFile(conf_1 *conf, const char *filePath);
|
||||||
ssize_t writeConfigToFile(conf_2 *conf, const char *filePath);
|
ssize_t writeConfigToFile(conf_2 *conf, const char *filePath);
|
||||||
|
|
@ -76,8 +78,6 @@ private:
|
||||||
int m_lightMode;
|
int m_lightMode;
|
||||||
conf_1 *m_conf1;
|
conf_1 *m_conf1;
|
||||||
conf_2 *m_conf2;
|
conf_2 *m_conf2;
|
||||||
libusb_device *m_device = NULL;
|
|
||||||
libusb_context *m_ctx = NULL;
|
|
||||||
QString m_fileName;
|
QString m_fileName;
|
||||||
Connection *connection;
|
Connection *connection;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
242
src/le_buttons.cpp
Normal file
242
src/le_buttons.cpp
Normal file
|
|
@ -0,0 +1,242 @@
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
|
#include "a811.h"
|
||||||
|
|
||||||
|
std::map< int, std::string > A811::_buttonNames = {
|
||||||
|
{ 0, "button_left" },
|
||||||
|
{ 1, "button_right" },
|
||||||
|
{ 2, "button_middle" },
|
||||||
|
{ 3, "button_backward" },
|
||||||
|
{ 4, "button_forward" },
|
||||||
|
{ 5, "button_dpi_down" },
|
||||||
|
{ 6, "button_dpi_up" },
|
||||||
|
{ 7, "button_1" },
|
||||||
|
{ 8, "button_2" },
|
||||||
|
{ 9, "button_3" },
|
||||||
|
{ 10, "button_4" },
|
||||||
|
{ 11, "button_5" },
|
||||||
|
{ 12, "button_6" },
|
||||||
|
{ 13, "button_7" },
|
||||||
|
{ 14, "button_8" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::map<std::string, std::array<uint8_t, 4>> A811::_keycodes = {
|
||||||
|
{"left", {0x11, 0x01, 0x00, 0x00}},
|
||||||
|
{"right", {0x11, 0x02, 0x00, 0x00}},
|
||||||
|
{"middle", {0x11, 0x04, 0x00, 0x00}},
|
||||||
|
{"backward", {0x11, 0x08, 0x00, 0x00}},
|
||||||
|
{"forward", {0x11, 0x10, 0x00, 0x00}},
|
||||||
|
{"dpi-cycle", {0x41, 0x00, 0x00, 0x00}},
|
||||||
|
{"dpi-", {0x41, 0x02, 0x00, 0x00}},
|
||||||
|
{"dpi+", {0x41, 0x01, 0x00, 0x00}},
|
||||||
|
{"media_player", {0x22, 0x00, 0x01, 0x00}},
|
||||||
|
{"media_play_pause", {0x22, 0x08, 0x00, 0x00}},
|
||||||
|
{"media_stop", {0x22, 0x04, 0x00, 0x00}},
|
||||||
|
{"media_previous", {0x22, 0x02, 0x00, 0x00}},
|
||||||
|
{"media_next", {0x22, 0x01, 0x00, 0x00}},
|
||||||
|
{"media_volume_up", {0x22, 0x40, 0x00, 0x00}},
|
||||||
|
{"media_volume_down", {0x22, 0x80, 0x00, 0x00}},
|
||||||
|
{"email", {0x22, 0x00, 0x10, 0x00}},
|
||||||
|
{"calculator", {0x22, 0x00, 0x20, 0x00}},
|
||||||
|
{"explorer", {0x22, 0x00, 0x02, 0x00}},
|
||||||
|
{"homepage", {0x22, 0x00, 0x00, 0x02}},
|
||||||
|
{"search", {0x22, 0x00, 0x00, 0x01}},
|
||||||
|
{"m_forward", {0x22, 0x00, 0x00, 0x08}},
|
||||||
|
{"m_backward", {0x22, 0x00, 0x00, 0x04}},
|
||||||
|
{"stopweb", {0x22, 0x00, 0x00, 0x10}},
|
||||||
|
{"refresh", {0x22, 0x00, 0x00, 0x20}},
|
||||||
|
{"favorites", {0x22, 0x00, 0x00, 0x40}},
|
||||||
|
{"disable_key", {0x50, 0x01, 0x00, 0x01}},
|
||||||
|
{"toggle_rgb", {0x50, 0x02, 0x00, 0x00}},
|
||||||
|
{"threeclick", {0x31, 0x01, 0x32, 0x03}},
|
||||||
|
{"firekey", {0x31, 0x01, 0xff, 0x03}},
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, uint8_t> A811::_keyboardKeys = {
|
||||||
|
// top row
|
||||||
|
{"Esc", 0x29},
|
||||||
|
{"F1", 0x3a},
|
||||||
|
{"F2", 0x3b},
|
||||||
|
{"F3", 0x3c},
|
||||||
|
{"F4", 0x3d},
|
||||||
|
{"F5", 0x3e},
|
||||||
|
{"F6", 0x3f},
|
||||||
|
{"F7", 0x40},
|
||||||
|
{"F8", 0x41},
|
||||||
|
{"F9", 0x42},
|
||||||
|
{"F10", 0x43},
|
||||||
|
{"F11", 0x44},
|
||||||
|
{"F12", 0x45},
|
||||||
|
{"PrtSc", 0x46},
|
||||||
|
{"ScrLk", 0x47},
|
||||||
|
{"Pause", 0x48},
|
||||||
|
// alphanumeric
|
||||||
|
{"a", 0x04},
|
||||||
|
{"b", 0x05},
|
||||||
|
{"c", 0x06},
|
||||||
|
{"d", 0x07},
|
||||||
|
{"e", 0x08},
|
||||||
|
{"f", 0x09},
|
||||||
|
{"g", 0x0a},
|
||||||
|
{"h", 0x0b},
|
||||||
|
{"i", 0x0c},
|
||||||
|
{"j", 0x0d},
|
||||||
|
{"k", 0x0e},
|
||||||
|
{"l", 0x0f},
|
||||||
|
{"m", 0x10},
|
||||||
|
{"n", 0x11},
|
||||||
|
{"o", 0x12},
|
||||||
|
{"p", 0x13},
|
||||||
|
{"q", 0x14},
|
||||||
|
{"r", 0x15},
|
||||||
|
{"s", 0x16},
|
||||||
|
{"t", 0x17},
|
||||||
|
{"u", 0x18},
|
||||||
|
{"v", 0x19},
|
||||||
|
{"w", 0x1a},
|
||||||
|
{"x", 0x1b},
|
||||||
|
{"y", 0x1c},
|
||||||
|
{"z", 0x1d},
|
||||||
|
{"1", 0x1e},
|
||||||
|
{"2", 0x1f},
|
||||||
|
{"3", 0x20},
|
||||||
|
{"4", 0x21},
|
||||||
|
{"5", 0x22},
|
||||||
|
{"6", 0x23},
|
||||||
|
{"7", 0x24},
|
||||||
|
{"8", 0x25},
|
||||||
|
{"9", 0x26},
|
||||||
|
{"0", 0x27},
|
||||||
|
// modifiers
|
||||||
|
{"Tab", 0x2b},
|
||||||
|
{"Caps_Lock", 0x39},
|
||||||
|
{"Shift_l", 0xe1},
|
||||||
|
{"Ctrl_l", 0xe0},
|
||||||
|
{"Alt_l", 0xe2},
|
||||||
|
{"Super_l", 0xe3},
|
||||||
|
{"Super_r", 0xe7},
|
||||||
|
{"Alt_r", 0xe6},
|
||||||
|
{"Menu", 0x65},
|
||||||
|
{"Ctrl_r", 0xe4},
|
||||||
|
{"Shift_r", 0xe5},
|
||||||
|
{"Return", 0x28},
|
||||||
|
{"Backspace", 0x2a},
|
||||||
|
// special characters
|
||||||
|
{"Space", 0x2c},
|
||||||
|
{"Tilde", 0x35},
|
||||||
|
{"Minus", 0x2d},
|
||||||
|
{"Equals", 0x2e},
|
||||||
|
{"Bracket_l", 0x2f},
|
||||||
|
{"Bracket_r", 0x30},
|
||||||
|
{"Backslash", 0x31},
|
||||||
|
{"Hash", 0x32},
|
||||||
|
{"Semicolon", 0x33},
|
||||||
|
{"Apostrophe", 0x34},
|
||||||
|
{"Comma", 0x36},
|
||||||
|
{"Period", 0x37},
|
||||||
|
{"Slash", 0x38},
|
||||||
|
{"Int_Key", 0x64},
|
||||||
|
// navigation
|
||||||
|
{"Right", 0x4f},
|
||||||
|
{"Left", 0x50},
|
||||||
|
{"Down", 0x51},
|
||||||
|
{"Up", 0x52},
|
||||||
|
{"Insert", 0x49},
|
||||||
|
{"Home", 0x4a},
|
||||||
|
{"PgUp", 0x4b},
|
||||||
|
{"Delete", 0x4c},
|
||||||
|
{"End", 0x4d},
|
||||||
|
{"PgDown", 0x4e},
|
||||||
|
// numpad
|
||||||
|
{"Num_Slash", 0x54},
|
||||||
|
{"Num_Asterisk", 0x55},
|
||||||
|
{"Num_Minus", 0x56},
|
||||||
|
{"Num_Plus", 0x57},
|
||||||
|
{"Num_Return", 0x58},
|
||||||
|
{"Num_1", 0x59},
|
||||||
|
{"Num_2", 0x5a},
|
||||||
|
{"Num_3", 0x5b},
|
||||||
|
{"Num_4", 0x5c},
|
||||||
|
{"Num_5", 0x5d},
|
||||||
|
{"Num_6", 0x5e},
|
||||||
|
{"Num_7", 0x5f},
|
||||||
|
{"Num_8", 0x60},
|
||||||
|
{"Num_9", 0x61},
|
||||||
|
{"Num_0", 0x62},
|
||||||
|
{"Num_Period", 0x63},
|
||||||
|
{"Num_Lock", 0x53},
|
||||||
|
{"Num_Equals", 0x67},
|
||||||
|
{"Num_Comma", 0x85},
|
||||||
|
{"Num_Paren_l", 0xb6},
|
||||||
|
{"Num_Paren_r", 0xb7},
|
||||||
|
// special keys
|
||||||
|
{"Power", 0x66},
|
||||||
|
{"Lang1", 0x90},
|
||||||
|
{"Lang2", 0x91},
|
||||||
|
{"Lang3", 0x92},
|
||||||
|
{"Lang4", 0x93},
|
||||||
|
{"Lang5", 0x94},
|
||||||
|
{"Lang6", 0x95},
|
||||||
|
{"Lang7", 0x96},
|
||||||
|
{"Lang8", 0x97},
|
||||||
|
{"Lang9", 0x98},
|
||||||
|
{"F13", 0x68},
|
||||||
|
{"F14", 0x69},
|
||||||
|
{"F15", 0x6a},
|
||||||
|
{"F16", 0x6b},
|
||||||
|
{"F17", 0x6c},
|
||||||
|
{"F18", 0x6d},
|
||||||
|
{"F19", 0x6e},
|
||||||
|
{"F20", 0x6f},
|
||||||
|
{"F21", 0x70},
|
||||||
|
{"F22", 0x71},
|
||||||
|
{"F23", 0x72},
|
||||||
|
{"F24", 0x73},
|
||||||
|
{"Execute", 0x74},
|
||||||
|
{"Help", 0x75},
|
||||||
|
{"Props", 0x76},
|
||||||
|
{"Select", 0x77},
|
||||||
|
{"Stop", 0x78},
|
||||||
|
{"Again", 0x79},
|
||||||
|
{"Undo", 0x7a},
|
||||||
|
{"Cut", 0x7b},
|
||||||
|
{"Copy", 0x7c},
|
||||||
|
{"Paste", 0x7d},
|
||||||
|
{"Find", 0x7e},
|
||||||
|
{"Mute", 0x7f},
|
||||||
|
{"Volume_Up", 0x80},
|
||||||
|
{"Volume_Down", 0x81},
|
||||||
|
{"International1", 0x87},
|
||||||
|
{"International2", 0x88},
|
||||||
|
{"International3", 0x89},
|
||||||
|
{"International4", 0x8a},
|
||||||
|
{"International5", 0x8b},
|
||||||
|
{"International6", 0x8c},
|
||||||
|
{"International7", 0x8d},
|
||||||
|
{"International8", 0x8e},
|
||||||
|
{"International9", 0x8f},
|
||||||
|
// media keys
|
||||||
|
{"Media_Play_Pause", 0xe8},
|
||||||
|
{"Media_Stop_CD", 0xe9},
|
||||||
|
{"Media_Previous", 0xea},
|
||||||
|
{"Media_Next", 0xeb},
|
||||||
|
{"Media_Eject_CD", 0xec},
|
||||||
|
{"Media_Volume_Up", 0xed},
|
||||||
|
{"Media_Volume_Down", 0xee},
|
||||||
|
{"Media_Mute", 0xef},
|
||||||
|
{"Media_WWW", 0xf0},
|
||||||
|
{"Media_Back", 0xf1},
|
||||||
|
{"Media_Forward", 0xf2},
|
||||||
|
{"Media_Stop", 0xf3},
|
||||||
|
{"Media_Find", 0xf4},
|
||||||
|
{"Media_Scroll_Up", 0xf5},
|
||||||
|
{"Media_Scroll_Down", 0xf6},
|
||||||
|
{"Media_Edit", 0xf7},
|
||||||
|
{"Media_Sleep", 0xf8},
|
||||||
|
{"Media_Screenlock", 0xf9},
|
||||||
|
{"Media_Refresh", 0xfa},
|
||||||
|
{"Media_Calc", 0xfb},
|
||||||
|
};
|
||||||
|
|
@ -16,7 +16,9 @@ struct conf_1
|
||||||
uint8_t dpi_modes; // 0x0b, 0x11-0x15 erste 4 welches ist aktiv? dann welhce für conf??
|
uint8_t dpi_modes; // 0x0b, 0x11-0x15 erste 4 welches ist aktiv? dann welhce für conf??
|
||||||
uint8_t __u4; // 0x0c zero
|
uint8_t __u4; // 0x0c zero
|
||||||
uint8_t hdpi[10]; // 0x0 0x0d-0x16 jeweils 2 byte most significant byte last, * 50 -> annäherung an dpi -50
|
uint8_t hdpi[10]; // 0x0 0x0d-0x16 jeweils 2 byte most significant byte last, * 50 -> annäherung an dpi -50
|
||||||
uint8_t __u5[0x44 - 0x16]; // 0x17 - 0x44 ????? zeros
|
uint8_t __uff[0x2c - 0x16]; // 22*something i fucking stayed up a night for
|
||||||
|
uint8_t col_dpi[15]; // 0x2d-0x3b Mouse wheel color for dpi modes 5 * RGB
|
||||||
|
uint8_t __u5[0x44 - 0x3b]; // 0x17 - 0x44 ????? zeros
|
||||||
uint8_t light_mode; // 0x45 Lighting Mode, 02 Steady, 01 Colorful Streaming, 03 Breathing
|
uint8_t light_mode; // 0x45 Lighting Mode, 02 Steady, 01 Colorful Streaming, 03 Breathing
|
||||||
uint8_t col_brightness_speed; // 0x46 0-4 Brightness und 0-4 Speed bei colorful 0x(br)(sp)
|
uint8_t col_brightness_speed; // 0x46 0-4 Brightness und 0-4 Speed bei colorful 0x(br)(sp)
|
||||||
uint8_t __u8; // 0x47 ???
|
uint8_t __u8; // 0x47 ???
|
||||||
|
|
@ -59,7 +61,8 @@ struct conf_2
|
||||||
uint8_t __u5[0x207 - 0x47]; // 0x48-0x58 ?? 0x58-end zeros
|
uint8_t __u5[0x207 - 0x47]; // 0x48-0x58 ?? 0x58-end zeros
|
||||||
};
|
};
|
||||||
|
|
||||||
struct macro_event{
|
struct macro_event
|
||||||
|
{
|
||||||
uint8_t updown_plus_delay_upper;
|
uint8_t updown_plus_delay_upper;
|
||||||
uint8_t delay_lower;
|
uint8_t delay_lower;
|
||||||
uint8_t keycode;
|
uint8_t keycode;
|
||||||
|
|
@ -67,7 +70,7 @@ struct macro_event{
|
||||||
|
|
||||||
struct macro
|
struct macro
|
||||||
{
|
{
|
||||||
uint8_t set_report_req[3]; //wirte macro Set_report 0x08 0x30 0x02
|
uint8_t set_report_req[3]; // wirte macro Set_report 0x08 0x30 0x02
|
||||||
uint8_t __u1[5];
|
uint8_t __u1[5];
|
||||||
uint8_t macro_nr;
|
uint8_t macro_nr;
|
||||||
uint8_t __u2;
|
uint8_t __u2;
|
||||||
|
|
@ -82,4 +85,12 @@ struct conf_12
|
||||||
conf_2 c2;
|
conf_2 c2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct battery_stat
|
||||||
|
{
|
||||||
|
uint8_t pref[2]; // 0x05, 0x90
|
||||||
|
uint8_t wired; // 0x10 -> wired, 0x11 -> wireless
|
||||||
|
uint8_t capacity; // if is 0x02 and wired is 0x10 then full and plugged, 0x01 plugged and loading
|
||||||
|
uint8_t __u1[4];
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -39,6 +39,8 @@ ssize_t Connection::findDevice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
libusb_free_device_list(list, 1);
|
libusb_free_device_list(list, 1);
|
||||||
|
|
||||||
if(!found_device)
|
if(!found_device)
|
||||||
|
|
@ -87,7 +89,7 @@ ssize_t Connection::setReport(uint16_t wValue, unsigned char *send_data, uint16_
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = libusb_control_transfer(handle, 0x21, 0x09, wValue, 1, send_data, 8, 2000)) < 0)
|
if ((r = libusb_control_transfer(handle, 0x21, 0x09, wValue, 1, send_data, wLength, 2000)) < 0)
|
||||||
return logError("ERROR: libusb_control_transfer: ", libusb_error_name(r), __FILE__, __LINE__, __func__);
|
return logError("ERROR: libusb_control_transfer: ", libusb_error_name(r), __FILE__, __LINE__, __func__);
|
||||||
|
|
||||||
return ssize_t(0);
|
return ssize_t(0);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue