Compare commits
No commits in common. "main" and "main" have entirely different histories.
16
README.md
16
README.md
|
|
@ -10,18 +10,4 @@ write a nixos module that also sets udev rules
|
||||||
install udev rule that automatically runs driver when you plug in the device??
|
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
|
|
||||||
|
|
||||||
if u bind media keys from _keyboardKeys in le_buttons.cpp its working dont know what the other keycodes are about maybe only specific for windows??
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
conf_12 check:
|
|
||||||
|
|
||||||
class datacheck:
|
|
||||||
type : (type?, [0,...,3], {2, 7, 19}, <x, >x)
|
|
||||||
length
|
|
||||||
funcptr
|
|
||||||
|
|
||||||
datachekc(type, typedef, length, ptr):
|
|
||||||
funcpotr = ptr
|
|
||||||
|
|
||||||
check(*data):
|
|
||||||
actdata = funcpotr(data)
|
|
||||||
switch(type):
|
|
||||||
case a: return actdata > typedef[0]
|
|
||||||
case b: return (actdata > typedef[0]) && (actdata < typedef[1])
|
|
||||||
|
|
||||||
|
|
||||||
map [pos] -> datacheck(0, [0,7], 16, (data) => return (data << 4) | (data >> 4))
|
|
||||||
map [pos+16] -> datacheck(0, [0,7], 16, (data) => return (data << 4) | (data >> 4))
|
|
||||||
|
|
||||||
map [pos] -> datacheck(1, [0], 8*16, (data) => uint8_t x = 0; for (int i = 0; i < 16; ++i) x | data[i]; return !x;)
|
|
||||||
|
|
||||||
|
|
||||||
func a(pos):
|
|
||||||
return map[pos]
|
|
||||||
|
|
||||||
pos not per byte but bit
|
|
||||||
|
|
||||||
|
|
||||||
a(pos).check
|
|
||||||
|
|
||||||
|
|
||||||
confch3ck():
|
|
||||||
isok = True
|
|
||||||
extralen = 0
|
|
||||||
chk;
|
|
||||||
for(int i = 0; i < (int)sizeof(conf_12) * 8;):
|
|
||||||
chk = map[i]
|
|
||||||
res = chk.check(&(((unsigned char *)conf_12)[i]))
|
|
||||||
i+=chk.length;
|
|
||||||
|
|
||||||
if not res:
|
|
||||||
isok = False
|
|
||||||
break;
|
|
||||||
if chk.type == set;
|
|
||||||
print("is fucked at byte x / bit y with length chk.length it is not part of set [chk.typedef]")
|
|
||||||
|
|
@ -46,11 +46,10 @@ 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.. (selected mode)(available modes)
|
0x0b 0x11-0x15 wert für häckchen bei dpi, erstes 0x11 zweites 0x12 usw..
|
||||||
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
|
||||||
0x2d-0x3b Colorcode für welche DPI selected RGB * 5
|
0x17-0x44 ???
|
||||||
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 ?
|
||||||
|
|
@ -134,7 +133,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 iwie kann man die klick anzahl (3) nicht ändern aber denke ist 0x03
|
Fire Key -> 0x31 0x01 0xff 0x03 -> 0xff ist the firespeed und iie 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,8 +10,6 @@ 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
|
||||||
|
|
|
||||||
535
src/a811.cpp
535
src/a811.cpp
|
|
@ -1,535 +0,0 @@
|
||||||
#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, int active)
|
|
||||||
{
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (active > 5 || active < 1)
|
|
||||||
{
|
|
||||||
logError("ERROR: Invalid active dpi modes.", __FILE__, __LINE__, __func__);
|
|
||||||
return ssize_t(2);
|
|
||||||
}
|
|
||||||
// Calculate the DPI value according to the formula
|
|
||||||
uint16_t 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 = // number of active modes
|
|
||||||
(1 & 0x0f) << 4 | ((active & 0x0F));
|
|
||||||
|
|
||||||
_conf12->c1.hdpi[((uint8_t)mode - 1) * 2] = lsb;
|
|
||||||
_conf12->c1.hdpi[((uint8_t)mode - 1) * 2 + 1] = msb;
|
|
||||||
_conf12->c1.col_dpi[((uint8_t)mode - 1) * 3] = color[0];
|
|
||||||
_conf12->c1.col_dpi[((uint8_t)mode - 1) * 3 + 1] = color[1];
|
|
||||||
_conf12->c1.col_dpi[((uint8_t)mode - 1) * 3 + 2] = color[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);
|
|
||||||
}
|
|
||||||
// Assume lsb and msb are given or extracted from your configuration structure
|
|
||||||
uint8_t lsb = _conf12->c1.hdpi[((uint8_t)mode - 1) * 2];
|
|
||||||
uint8_t msb = _conf12->c1.hdpi[((uint8_t)mode - 1) * 2 + 1];
|
|
||||||
|
|
||||||
// Reconstruct the dpi_value
|
|
||||||
uint16_t dpi_value = msb << 8 | (lsb & 0xFF);
|
|
||||||
|
|
||||||
std::cout << std::hex << dpi_value << " : " << (int)lsb << " : " << (int)msb << std::endl;
|
|
||||||
|
|
||||||
// Reverse the formula to get the original dpi
|
|
||||||
uint16_t dpi = (dpi_value * 50) + 50;
|
|
||||||
|
|
||||||
return dpi;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
mahbytes[i] = ((unsigned char *)&arr)[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (id >= 7 && id < 15)
|
|
||||||
{
|
|
||||||
// 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.side[id - 7];
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)sizeof(_conf12->c2.mouse_buttons[id]); ++i)
|
|
||||||
{
|
|
||||||
mahbytes[i] = ((unsigned char *)&arr)[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logError("ERROR: Invalid button id.", __FILE__, __LINE__, __func__);
|
|
||||||
return ssize_t(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ssize_t(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t A811::setMacroButton(int id, uint8_t macro_id, uint8_t cycle_type, uint8_t 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 - 7], 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);
|
|
||||||
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::readMacrosFromDevice(int cnt)
|
|
||||||
{
|
|
||||||
if (cnt > 255)
|
|
||||||
{
|
|
||||||
std::cout << "No more than 255 macros on device" << std::endl;
|
|
||||||
return ssize_t(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_macros = (macro **)malloc(cnt * sizeof(macro *));
|
|
||||||
|
|
||||||
_connection->open();
|
|
||||||
_connection->keepConnection(true);
|
|
||||||
|
|
||||||
for (int i = 1; i <= cnt; i++)
|
|
||||||
{
|
|
||||||
// get macro
|
|
||||||
// ist das bissl kacke weil immer neuer handle und detach und attach hmm
|
|
||||||
_macros[i - 1] = (macro *)malloc(sizeof(macro));
|
|
||||||
readMacroFromDevice(_macros[i - 1], i);
|
|
||||||
}
|
|
||||||
|
|
||||||
_connection->keepConnection(false);
|
|
||||||
_connection->close();
|
|
||||||
|
|
||||||
// check if any macros are read or if any empty macros are read
|
|
||||||
// maybe just read all possible macros
|
|
||||||
// or this function is actually completely useless just keep track of the macros in the gui code
|
|
||||||
return ssize_t(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t A811::readMacroFromDevice(macro *_macro, int id)
|
|
||||||
{
|
|
||||||
if (id > (uint8_t)255)
|
|
||||||
{
|
|
||||||
std::cout << "No more than 255 macros on device" << std::endl;
|
|
||||||
return ssize_t(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(_macro, 0, 520 * sizeof(unsigned char));
|
|
||||||
|
|
||||||
unsigned char _data[8] = {0x05, 0x31, (uint8_t)id, 0, 0, 0, 0, 0};
|
|
||||||
|
|
||||||
ssize_t r;
|
|
||||||
CHK(_connection->open());
|
|
||||||
CHK(_connection->setReport(0x0305, (unsigned char *)_data, 8));
|
|
||||||
CHK(_connection->getReport(0x0308, (unsigned char *)_macro, 520));
|
|
||||||
CHK(_connection->close());
|
|
||||||
|
|
||||||
// check if empty macro, if valid macro
|
|
||||||
return ssize_t(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t A811::writeMacroToDevice(macro *p_macro)
|
|
||||||
{
|
|
||||||
// conf_1
|
|
||||||
p_macro->set_report_req[0] = 0x80;
|
|
||||||
p_macro->set_report_req[1] = 0x30;
|
|
||||||
p_macro->set_report_req[2] = 0x02;
|
|
||||||
|
|
||||||
ssize_t r;
|
|
||||||
CHK(_connection->open());
|
|
||||||
CHK(_connection->setReport(0x0308, (unsigned char *)p_macro, 520));
|
|
||||||
CHK(_connection->close());
|
|
||||||
|
|
||||||
// check if macro is valid
|
|
||||||
return ssize_t(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool A811::isIdle()
|
|
||||||
{
|
|
||||||
unsigned char conf[8];
|
|
||||||
memset(conf, 0, 8);
|
|
||||||
unsigned char _data[8] = {0x05, 0x80, 0, 0, 0, 0, 0, 0};
|
|
||||||
|
|
||||||
ssize_t r;
|
|
||||||
CHK(_connection->open());
|
|
||||||
CHK(_connection->setReport(0x0305, _data, 8));
|
|
||||||
CHK(_connection->getReport(0x0305, (unsigned char *)conf, 8));
|
|
||||||
CHK(_connection->close());
|
|
||||||
|
|
||||||
if (conf[2] == 0x0 && conf[3] == 0x1)
|
|
||||||
return true;
|
|
||||||
else if (conf[2] == 0x1 && conf[3] == 0x1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
logError("ERROR: Reading idle status.", __FILE__, __LINE__, __func__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t A811::restoreConfig()
|
|
||||||
{
|
|
||||||
unsigned char _data[8] = {0x05, 0x40, 0x01, 0, 0, 0, 0, 0};
|
|
||||||
|
|
||||||
ssize_t r;
|
|
||||||
CHK(_connection->open());
|
|
||||||
CHK(_connection->setReport(0x0305, (unsigned char *)_data, 8));
|
|
||||||
CHK(_connection->close());
|
|
||||||
|
|
||||||
return ssize_t(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
337
src/a811.h
337
src/a811.h
|
|
@ -1,337 +0,0 @@
|
||||||
#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
|
|
||||||
//-- maybe active should be optional
|
|
||||||
/**
|
|
||||||
* @brief Set the DPI for a specific DPI MODE.
|
|
||||||
*
|
|
||||||
* This function allows you to set a specific DPI and an associated color
|
|
||||||
* for the mouse wheel for a Specific DPI mode.
|
|
||||||
*
|
|
||||||
* @param mode The mode for which to set the DPI and color values.
|
|
||||||
* @param color RGB
|
|
||||||
* @param dpi DPI value 50-26000
|
|
||||||
* @param active 1-5 how many DPI_MODE should be active.
|
|
||||||
*
|
|
||||||
* @return ssize_t Returns the status of the operation, where 0 indicates
|
|
||||||
* success and a negative value indicates failure.
|
|
||||||
*/
|
|
||||||
ssize_t setDPI(DPI_MODE, unsigned char[3], int, int);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the current DPI value for a DPI_MODE.
|
|
||||||
*
|
|
||||||
* This function retrieves the current light mode of the device.
|
|
||||||
*
|
|
||||||
* @return int The current DPI for DPI_MODE.
|
|
||||||
*/
|
|
||||||
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, uint8_t, uint8_t, uint8_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read macros from the mouse.
|
|
||||||
*
|
|
||||||
* Read a specific number of macros from the mouse.
|
|
||||||
*
|
|
||||||
* @param macros where the macros should be saved.
|
|
||||||
* @param cnt how many macros should be read.
|
|
||||||
*
|
|
||||||
* @return ssize_t Returns the status of the operation, where 0 indicates
|
|
||||||
* success and a negative value indicates failure.
|
|
||||||
*/
|
|
||||||
ssize_t readMacrosFromDevice(int);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a single macro from the mouse.
|
|
||||||
*
|
|
||||||
* Read a specific macro from the mouse.
|
|
||||||
*
|
|
||||||
* @param macro where the macro should be saved.
|
|
||||||
* @param id id of the macro.
|
|
||||||
*
|
|
||||||
* @return ssize_t Returns the status of the operation, where 0 indicates
|
|
||||||
* success and a negative value indicates failure.
|
|
||||||
*/
|
|
||||||
ssize_t readMacroFromDevice(macro *, int);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Write a single macro to the mouse.
|
|
||||||
*
|
|
||||||
* Read a specific macro from the mouse.
|
|
||||||
*
|
|
||||||
* @param macro the macro to be written.
|
|
||||||
*
|
|
||||||
* @return ssize_t Returns the status of the operation, where 0 indicates
|
|
||||||
* success and a negative value indicates failure.
|
|
||||||
*/
|
|
||||||
ssize_t writeMacroToDevice(macro *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the idle status of the mouse.
|
|
||||||
*
|
|
||||||
* Get the idle status of the mouse.
|
|
||||||
*
|
|
||||||
* @return bool returns true if idle, false else
|
|
||||||
*/
|
|
||||||
// the error logging here is kinda weird
|
|
||||||
bool isIdle();
|
|
||||||
|
|
||||||
// should be writing a custom thingy so i know what the restored config looks like
|
|
||||||
/**
|
|
||||||
* @brief Apply standard config.
|
|
||||||
*
|
|
||||||
* Write a standard configuration to the mouse if something went wrong.
|
|
||||||
*
|
|
||||||
* @return Returns the status of the operation, where 0 indicates
|
|
||||||
* success and a negative value indicates failure.
|
|
||||||
*/
|
|
||||||
ssize_t restoreConfig();
|
|
||||||
|
|
||||||
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,8 +31,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
345
src/conf.cpp
345
src/conf.cpp
|
|
@ -1,8 +1,8 @@
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include <QDebug>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <klocalizedstring.h>
|
#include <QDebug>
|
||||||
#include <qfiledialog.h>
|
#include <qfiledialog.h>
|
||||||
|
#include <klocalizedstring.h>
|
||||||
|
|
||||||
#define CHK(X) \
|
#define CHK(X) \
|
||||||
if ((r = (X)) != 0) \
|
if ((r = (X)) != 0) \
|
||||||
|
|
@ -12,20 +12,16 @@ 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::cout << std::dec << sizeof(conf_1) << "; " << sizeof(conf_2) << std::endl;
|
||||||
<< 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());
|
||||||
if (connection->findDevice())
|
connection->findDevice();
|
||||||
{
|
|
||||||
std::cerr << "ERROR: device not found" << std::endl;
|
// read initial config from device
|
||||||
exit(1);
|
readConfigFromDevice(m_conf1);
|
||||||
}
|
readConfigFromDevice(m_conf2);
|
||||||
m_mouse = new A811();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Conf::appendMacroToFile(macro *macro, const char *filePath)
|
ssize_t Conf::appendMacroToFile(macro *macro, const char *filePath)
|
||||||
|
|
@ -80,8 +76,7 @@ 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
|
// If the macro ID does not match the one to delete, write it to the temp file
|
||||||
// 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);
|
||||||
|
|
@ -97,9 +92,8 @@ ssize_t Conf::deleteMacroFromFile(macro *_macro, const char *filePath)
|
||||||
fclose(tempfile);
|
fclose(tempfile);
|
||||||
|
|
||||||
// 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",
|
rename("tempfile.bin", filePath); // Rename the temp file to the original file name
|
||||||
filePath); // Rename the temp file to the original file name
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -108,77 +102,59 @@ ssize_t Conf::deleteMacroFromFile(macro *_macro, const char *filePath)
|
||||||
|
|
||||||
void Conf::testFunc()
|
void Conf::testFunc()
|
||||||
{
|
{
|
||||||
|
macro **macros;
|
||||||
m_mouse->readConfigFromDevice(CONF_TYPE::BATTERY);
|
readMacrosFromDevice(macros, 4);
|
||||||
m_mouse->readConfigFromDevice(CONF_TYPE::LIGHT);
|
for (int i = 0; i < 4; i++)
|
||||||
m_mouse->readConfigFromDevice(CONF_TYPE::KEY);
|
|
||||||
|
|
||||||
m_mouse->setLightMode(LIGHT_MODE::BREATHING, 1, 4);
|
|
||||||
m_mouse->writeConfigToDevice(CONF_TYPE::LIGHT);
|
|
||||||
m_mouse->setUSBPollingRate(POLLING_RATE::P_1000);
|
|
||||||
|
|
||||||
std::cout << "UBS Polling rate: " << (int)m_mouse->getUSBPollingRate() << std::endl;
|
|
||||||
std::cout << "BATTERYSTATUS: " << (int)m_mouse->getBatteryStatus() << std::endl;
|
|
||||||
std::cout << "LIGHTMODE: " << (int)m_mouse->getLightMode() << std::endl;
|
|
||||||
|
|
||||||
m_mouse->setLightMode(LIGHT_MODE::COLORFUL_STREAMING, 1, 2);
|
|
||||||
m_mouse->writeConfigToDevice(CONF_TYPE::LIGHT);
|
|
||||||
sleep(2);
|
|
||||||
|
|
||||||
m_mouse->setMultimediaButton(2, "media_volume_up");
|
|
||||||
// does not work for some reason
|
|
||||||
m_mouse->setMultimediaButton(6, "dpi-cycle");
|
|
||||||
m_mouse->setButton(7, "Volume_Up", 0);
|
|
||||||
m_mouse->setButton(8, "b", 2);
|
|
||||||
m_mouse->setButton(9, "c", 4);
|
|
||||||
m_mouse->setButton(10, "d", 8);
|
|
||||||
m_mouse->setButton(11, "e", 3);
|
|
||||||
m_mouse->setButton(12, "f", 5);
|
|
||||||
m_mouse->setButton(13, "g", 7);
|
|
||||||
m_mouse->setButton(14, "h", 9);
|
|
||||||
// dont know if every keycode is working
|
|
||||||
int bid = 0;
|
|
||||||
std::cout << "Button " << bid << m_mouse->getButton(bid).name << std::endl;
|
|
||||||
|
|
||||||
m_mouse->writeConfigToDevice(CONF_TYPE::KEY);
|
|
||||||
std::cout << m_mouse->getButton(3).name << std::endl;
|
|
||||||
|
|
||||||
m_mouse->setLightMode(LIGHT_MODE::BREATHING, 4, 4);
|
|
||||||
|
|
||||||
unsigned char *cols;
|
|
||||||
cols = m_mouse->getLightModeColors(LIGHT_MODE::BREATHING);
|
|
||||||
for (int i = 0; i < 21; i++)
|
|
||||||
{
|
{
|
||||||
std::cout << cols[i];
|
appendMacroToFile(macros[i], "macrofileappend");
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
}
|
||||||
m_mouse->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};
|
|
||||||
m_mouse->setLightModeColors(LIGHT_MODE::BREATHING, cols2);
|
|
||||||
unsigned char cols3[3] = {0xff, 0x00, 0x00};
|
|
||||||
m_mouse->setDPI(DPI_MODE::DPI_1, cols3, 800, 5);
|
|
||||||
cols3[0] = 0x0;
|
|
||||||
cols3[1] = 0xff;
|
|
||||||
m_mouse->setDPI(DPI_MODE::DPI_2, cols3, 1000, 5);
|
|
||||||
cols3[1] = 0x0;
|
|
||||||
cols3[2] = 0xff;
|
|
||||||
m_mouse->setDPI(DPI_MODE::DPI_3, cols3, 1200, 5);
|
|
||||||
cols3[0] = 0xff;
|
|
||||||
cols3[2] = 0xff;
|
|
||||||
m_mouse->setDPI(DPI_MODE::DPI_4, cols3, 1400, 5);
|
|
||||||
cols3[0] = 0xff;
|
|
||||||
cols3[1] = 0xff;
|
|
||||||
cols3[2] = 0xff;
|
|
||||||
m_mouse->setDPI(DPI_MODE::DPI_5, cols3, 1500, 5);
|
|
||||||
// m_mouse->writeConfigToDevice(CONF_TYPE::KEY);
|
|
||||||
std::cout << "DPI at this: " << m_mouse->getDPI(DPI_MODE::DPI_1) << std::endl;
|
|
||||||
|
|
||||||
std::cout << "Battery capacity:" << std::dec << m_mouse->getBatteryCapacity() << std::endl;
|
int Conf::lightMode()
|
||||||
m_mouse->writeConfigToDevice(CONF_TYPE::LIGHT);
|
{
|
||||||
|
return m_conf1->light_mode;
|
||||||
|
}
|
||||||
|
|
||||||
m_mouse->readMacrosFromDevice(4);
|
void Conf::setLightMode(int mode)
|
||||||
|
{
|
||||||
|
m_conf1->light_mode = (unsigned char)mode;
|
||||||
|
std::cout << (int)m_conf1->light_mode << std::endl;
|
||||||
|
Q_EMIT lightModeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::restoreConfigs()
|
||||||
|
{
|
||||||
|
unsigned char _data[8] = {0x05, 0x40, 0x01, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
CHK(connection->setReport(0x0305, (unsigned char *)_data, 8));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::deviceConfig()
|
||||||
|
{
|
||||||
|
unsigned char _data[8] = {0x05, 0x22, 0, 0, 0, 0, 0, 0};
|
||||||
|
/*if(!connection->isWireless())
|
||||||
|
_data[1] = 0x12;*/
|
||||||
|
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
CHK(connection->setReport(0x0305, (unsigned char *)_data, 8));
|
||||||
|
CHK(connection->getReport(0x0308, (unsigned char *)0x0, 520));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Conf::setDeviceConfig(ssize_t stat)
|
||||||
|
{
|
||||||
|
std::cout << "Setting new conf" << std::endl;
|
||||||
|
writeConfigToDevice(m_conf1);
|
||||||
|
writeConfigToDevice(m_conf2);
|
||||||
|
Q_EMIT deviceConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Conf::writeConfigToFile(const char *filePath)
|
ssize_t Conf::writeConfigToFile(const char *filePath)
|
||||||
|
|
@ -219,6 +195,184 @@ ssize_t Conf::writeConfigToFile(const char *filePath)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::writeConfigToDevice(conf_2 *conf)
|
||||||
|
{
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
conf->req_type = 0x50;
|
||||||
|
CHK(connection->setReport(0x0308, (unsigned char *)conf, 520));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::writeConfigToDevice(conf_1 *conf)
|
||||||
|
{
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
conf->req_type = 0x92;
|
||||||
|
CHK(connection->setReport(0x0308, (unsigned char *)conf, 520));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::readConfigFromDevice(conf_2 *conf)
|
||||||
|
{
|
||||||
|
unsigned char _data[8] = {0x05, 0x22, 0, 0, 0, 0, 0, 0};
|
||||||
|
/*if(!connection->isWireless())
|
||||||
|
_data[1] = 0x12;*/
|
||||||
|
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
CHK(connection->setReport(0x0305, (unsigned char *)_data, 8));
|
||||||
|
CHK(connection->getReport(0x0308, (unsigned char *)conf, 520));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::batteryStatus()
|
||||||
|
{
|
||||||
|
unsigned char dat[8];
|
||||||
|
memset(dat, 0, 8 * sizeof(unsigned char));
|
||||||
|
|
||||||
|
unsigned char _data[8] = {0x05, 0x90, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
CHK(connection->setReport(0x0305, (unsigned char *)_data, 8));
|
||||||
|
CHK(connection->getReport(0x0305, (unsigned char *)dat, 8));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
std::cout << std::hex << (int)dat[i] << "\t";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
if (dat[2] == 0x10 && dat[3] == 0x01)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (int)dat[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Conf::setBatteryStatus(ssize_t bat)
|
||||||
|
{
|
||||||
|
m_bat = batteryStatus();
|
||||||
|
Q_EMIT batteryStatusChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::readMacroFromDevice(macro *_macro, int id)
|
||||||
|
{
|
||||||
|
if (id > 255)
|
||||||
|
{
|
||||||
|
std::cout << "No more than 255 macros on device" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(_macro, 0, 520 * sizeof(unsigned char));
|
||||||
|
|
||||||
|
unsigned char _data[8] = {0x05, 0x31, id, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
CHK(connection->setReport(0x0305, (unsigned char *)_data, 8));
|
||||||
|
CHK(connection->getReport(0x0308, (unsigned char *)_macro, 520));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
std::cout << std::hex << (int)_macro->macro_nr << "\t";
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::writeMacroToDevice(macro *_macro)
|
||||||
|
{
|
||||||
|
|
||||||
|
// conf_1
|
||||||
|
_macro->set_report_req[0] = 0x80;
|
||||||
|
_macro->set_report_req[1] = 0x30;
|
||||||
|
_macro->set_report_req[2] = 0x02;
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
CHK(connection->setReport(0x0308, (unsigned char *)_macro, 520));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::readMacrosFromDevice(macro **¯os, int cnt)
|
||||||
|
{
|
||||||
|
if (cnt > 255)
|
||||||
|
{
|
||||||
|
std::cout << "No more than 255 macros on device" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
macros = (macro **)malloc(cnt * sizeof(macro *));
|
||||||
|
|
||||||
|
connection->open();
|
||||||
|
connection->keepConnection(true);
|
||||||
|
|
||||||
|
for (int i = 1; i <= cnt; i++)
|
||||||
|
{
|
||||||
|
// get macro
|
||||||
|
// ist das bissl kacke weil immer neuer handle und detach und attach hmm
|
||||||
|
macros[i - 1] = (macro *)malloc(sizeof(macro));
|
||||||
|
readMacroFromDevice(macros[i - 1], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
connection->keepConnection(false);
|
||||||
|
connection->close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::readAssignedMacrosFromDevice()
|
||||||
|
{
|
||||||
|
// check all the keys for macro mod
|
||||||
|
int macroCnt = 0;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (m_conf2->side[i].pref == 0x70 || (m_conf2->mouse_buttons[i].pref == 0x70 && i < 6))
|
||||||
|
macroCnt++;
|
||||||
|
}
|
||||||
|
std::cout << macroCnt << std::endl;
|
||||||
|
|
||||||
|
unsigned char conf[520];
|
||||||
|
memset(conf, 0, 520 * sizeof(unsigned char));
|
||||||
|
|
||||||
|
unsigned char _data[8] = {0x05, 0x31, 1, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
ssize_t r;
|
||||||
|
CHK(connection->open());
|
||||||
|
for (int i = 1; i <= macroCnt; i++)
|
||||||
|
{
|
||||||
|
_data[2] = i;
|
||||||
|
CHK(connection->setReport(0x0305, _data, 8));
|
||||||
|
CHK(connection->getReport(0x0308, (unsigned char *)conf, 520));
|
||||||
|
}
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t Conf::readConfigFromDevice(conf_1 *conf)
|
||||||
|
{
|
||||||
|
unsigned char _data[8] = {0x05, 0x21, 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(0x0308, (unsigned char *)conf, 520));
|
||||||
|
CHK(connection->close());
|
||||||
|
|
||||||
|
return ssize_t(0);
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t Conf::writeConfigToFile()
|
ssize_t Conf::writeConfigToFile()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getSaveFileName(nullptr, i18n("Save File As"));
|
QString path = QFileDialog::getSaveFileName(nullptr, i18n("Save File As"));
|
||||||
|
|
@ -262,17 +416,16 @@ ssize_t Conf::readConfigFromFile(const char *filePath, conf_1 *conf)
|
||||||
if (infile == NULL)
|
if (infile == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nError opening file\n");
|
fprintf(stderr, "\nError opening file\n");
|
||||||
return ssize_t(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reading to read_struct
|
// reading to read_struct
|
||||||
if (sizeof(struct conf_1) > fread(conf, sizeof(struct conf_1), 1, infile))
|
fread(conf, sizeof(struct conf_1), 1, infile);
|
||||||
fprintf(stderr, "\nError file\n");
|
|
||||||
|
|
||||||
// close file
|
// close file
|
||||||
fclose(infile);
|
fclose(infile);
|
||||||
|
|
||||||
return ssize_t(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Conf::readConfigFromFile(const char *filePath, conf_2 *conf)
|
ssize_t Conf::readConfigFromFile(const char *filePath, conf_2 *conf)
|
||||||
|
|
@ -284,17 +437,16 @@ ssize_t Conf::readConfigFromFile(const char *filePath, conf_2 *conf)
|
||||||
if (infile == NULL)
|
if (infile == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nError opening file\n");
|
fprintf(stderr, "\nError opening file\n");
|
||||||
return ssize_t(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reading to read_struct
|
// reading to read_struct
|
||||||
if (sizeof(struct conf_2) > fread(conf, sizeof(struct conf_2), 1, infile))
|
fread(conf, sizeof(struct conf_2), 1, infile);
|
||||||
fprintf(stderr, "\nError file\n");
|
|
||||||
|
|
||||||
// close file
|
// close file
|
||||||
fclose(infile);
|
fclose(infile);
|
||||||
|
|
||||||
return ssize_t(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Conf::readConfigFromFile(const char *filePath)
|
ssize_t Conf::readConfigFromFile(const char *filePath)
|
||||||
|
|
@ -305,12 +457,11 @@ ssize_t Conf::readConfigFromFile(const char *filePath)
|
||||||
if (infile == NULL)
|
if (infile == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nError opening file\n");
|
fprintf(stderr, "\nError opening file\n");
|
||||||
return ssize_t(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeof(struct conf_1) > fread(m_conf1, sizeof(struct conf_1), 1, infile) ||
|
fread(m_conf1, sizeof(struct conf_1), 1, infile);
|
||||||
sizeof(struct conf_2) > fread(m_conf2, sizeof(struct conf_2), 1, infile))
|
fread(m_conf2, sizeof(struct conf_2), 1, infile);
|
||||||
fprintf(stderr, "\nError file\n");
|
|
||||||
|
|
||||||
fclose(infile);
|
fclose(infile);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -326,4 +477,4 @@ ssize_t Conf::readConfigFromFile()
|
||||||
readConfigFromFile(path.toUtf8().constData());
|
readConfigFromFile(path.toUtf8().constData());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
31
src/conf.h
31
src/conf.h
|
|
@ -12,18 +12,30 @@
|
||||||
#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"
|
||||||
|
|
||||||
class Conf : public QObject
|
class Conf : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(ssize_t deviceConfig READ deviceConfig WRITE setDeviceConfig NOTIFY deviceConfigChanged)
|
||||||
|
Q_PROPERTY(int lightMode READ lightMode WRITE setLightMode NOTIFY lightModeChanged)
|
||||||
|
Q_PROPERTY(ssize_t batteryStatus READ batteryStatus WRITE setBatteryStatus NOTIFY batteryStatusChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Conf(QObject *parent = nullptr);
|
explicit Conf(QObject *parent = nullptr);
|
||||||
|
ssize_t deviceConfig();
|
||||||
|
Q_INVOKABLE void setDeviceConfig(ssize_t stat);
|
||||||
|
Q_SIGNAL void deviceConfigChanged();
|
||||||
|
|
||||||
|
int lightMode();
|
||||||
|
Q_INVOKABLE void setLightMode(int mode);
|
||||||
|
Q_SIGNAL void lightModeChanged();
|
||||||
|
|
||||||
|
Q_INVOKABLE ssize_t restoreConfigs();
|
||||||
|
|
||||||
Q_INVOKABLE ssize_t writeConfigToFile();
|
Q_INVOKABLE ssize_t writeConfigToFile();
|
||||||
ssize_t writeConfigToFile(const char *filePath);
|
ssize_t writeConfigToFile(const char *filePath);
|
||||||
|
|
@ -35,22 +47,37 @@ public:
|
||||||
ssize_t writeConfigToFile(conf_2 *conf, const char *filePath);
|
ssize_t writeConfigToFile(conf_2 *conf, const char *filePath);
|
||||||
ssize_t readConfigFromFile(const char *filePath, conf_1 *conf);
|
ssize_t readConfigFromFile(const char *filePath, conf_1 *conf);
|
||||||
ssize_t readConfigFromFile(const char *filePath, conf_2 *conf);
|
ssize_t readConfigFromFile(const char *filePath, conf_2 *conf);
|
||||||
|
ssize_t writeConfigToDevice(conf_1 *conf);
|
||||||
|
ssize_t writeConfigToDevice(conf_2 *conf);
|
||||||
|
ssize_t readConfigFromDevice(conf_1 *conf);
|
||||||
|
ssize_t readConfigFromDevice(conf_2 *conf);
|
||||||
|
|
||||||
|
Q_INVOKABLE ssize_t readAssignedMacrosFromDevice();
|
||||||
|
|
||||||
|
Q_INVOKABLE ssize_t readMacrosFromDevice(macro **¯os, int cnt);
|
||||||
|
Q_INVOKABLE ssize_t readMacroFromDevice(macro *_macro, int id);
|
||||||
|
Q_INVOKABLE ssize_t writeMacroToDevice(macro *_macro);
|
||||||
|
|
||||||
Q_INVOKABLE ssize_t appendMacroToFile(macro *_macro, const char *filePath);
|
Q_INVOKABLE ssize_t appendMacroToFile(macro *_macro, const char *filePath);
|
||||||
Q_INVOKABLE ssize_t deleteMacroFromFile(macro *_macro, const char *filePath);
|
Q_INVOKABLE ssize_t deleteMacroFromFile(macro *_macro, const char *filePath);
|
||||||
|
|
||||||
|
ssize_t batteryStatus();
|
||||||
|
Q_INVOKABLE void setBatteryStatus(ssize_t bat);
|
||||||
|
Q_SIGNAL void batteryStatusChanged();
|
||||||
|
|
||||||
Q_INVOKABLE void testFunc();
|
Q_INVOKABLE void testFunc();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
macro **m_macros;
|
macro **m_macros;
|
||||||
A811 *m_mouse;
|
|
||||||
ssize_t m_stat;
|
ssize_t m_stat;
|
||||||
ssize_t m_bat;
|
ssize_t m_bat;
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,242 +0,0 @@
|
||||||
#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,9 +16,7 @@ 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 __uff[0x2c - 0x16]; // 22*something i fucking stayed up a night for
|
uint8_t __u5[0x44 - 0x16]; // 0x17 - 0x44 ????? zeros
|
||||||
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 ???
|
||||||
|
|
@ -35,8 +33,8 @@ struct conf_1
|
||||||
struct key_conf
|
struct key_conf
|
||||||
{
|
{
|
||||||
uint8_t pref;
|
uint8_t pref;
|
||||||
uint8_t mod; // or macro id
|
uint8_t mod; // or macro id
|
||||||
uint8_t keycode; // for macro cycle type
|
uint8_t keycode; // for macro cycle type
|
||||||
uint8_t macro_cycle; // for macro cycle count
|
uint8_t macro_cycle; // for macro cycle count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -61,8 +59,7 @@ 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;
|
||||||
|
|
@ -70,7 +67,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;
|
||||||
|
|
@ -85,12 +82,4 @@ 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,8 +39,6 @@ ssize_t Connection::findDevice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
libusb_free_device_list(list, 1);
|
libusb_free_device_list(list, 1);
|
||||||
|
|
||||||
if(!found_device)
|
if(!found_device)
|
||||||
|
|
@ -89,7 +87,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, wLength, 2000)) < 0)
|
if ((r = libusb_control_transfer(handle, 0x21, 0x09, wValue, 1, send_data, 8, 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