forked from denis/a811
Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42520f3399 | ||
|
|
6b154d7f7b | ||
|
|
c1fc9140a7 | ||
|
|
342b8098ed | ||
|
|
efbeeac8d5 | ||
|
|
535588bb2e |
16
README.md
16
README.md
|
|
@ -10,4 +10,18 @@ write a nixos module that also sets udev rules
|
|||
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
|
||||
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??
|
||||
48
hexdump_analysis/Untitled-1.py
Normal file
48
hexdump_analysis/Untitled-1.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
|
||||
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,10 +46,11 @@ First Part
|
|||
0x04-0x07 ??
|
||||
0x08-0x09 0x64 0x17 Profil 1, 0x64 0x01 Profil 2 ?????
|
||||
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 ?
|
||||
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
|
||||
0x46 0-4 Brightness und 0-4 Speed bei colorful 0x(br)(sp)
|
||||
0x47 ?
|
||||
|
|
@ -133,7 +134,7 @@ Tastenbelegung
|
|||
ThreeClick -> 0x31 0x01 0x32 0x03, whatever this is?
|
||||
RGB on/off -> 0x50 0x02 0x00 0x00 -> hat die letzten bytes mit 0 geschrieben
|
||||
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
|
||||
Media Player -> 0x22 0x00 0x01 0x00
|
||||
|
|
|
|||
BIN
macrofileappend
BIN
macrofileappend
Binary file not shown.
|
|
@ -10,6 +10,8 @@ target_sources(kirigami-hello
|
|||
main.cpp
|
||||
conf.cpp conf.h
|
||||
usb_thingy.cpp usb_thingy.h
|
||||
a811.cpp a811.h
|
||||
le_buttons.cpp
|
||||
)
|
||||
|
||||
ecm_target_qml_sources(kirigami-hello
|
||||
|
|
|
|||
535
src/a811.cpp
Normal file
535
src/a811.cpp
Normal file
|
|
@ -0,0 +1,535 @@
|
|||
#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
Normal file
337
src/a811.h
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
#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,7 +31,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (Connection::getInstance().findDevice())
|
||||
{
|
||||
std::cerr << "ERROR: Device not found!";
|
||||
std::cerr << "ERROR: Device not found!"
|
||||
<< "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
345
src/conf.cpp
345
src/conf.cpp
|
|
@ -1,8 +1,8 @@
|
|||
#include "conf.h"
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
#include <qfiledialog.h>
|
||||
#include <iostream>
|
||||
#include <klocalizedstring.h>
|
||||
#include <qfiledialog.h>
|
||||
|
||||
#define CHK(X) \
|
||||
if ((r = (X)) != 0) \
|
||||
|
|
@ -12,16 +12,20 @@ Conf::Conf(QObject *parent) : QObject(parent)
|
|||
{
|
||||
m_conf1 = (conf_1 *)malloc(sizeof(conf_1));
|
||||
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_conf2, 0, sizeof(conf_2));
|
||||
|
||||
connection = &(Connection::getInstance());
|
||||
connection->findDevice();
|
||||
|
||||
|
||||
// read initial config from device
|
||||
readConfigFromDevice(m_conf1);
|
||||
readConfigFromDevice(m_conf2);
|
||||
connection = &(Connection::getInstance());
|
||||
if (connection->findDevice())
|
||||
{
|
||||
std::cerr << "ERROR: device not found" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
m_mouse = new A811();
|
||||
}
|
||||
|
||||
ssize_t Conf::appendMacroToFile(macro *macro, const char *filePath)
|
||||
|
|
@ -76,7 +80,8 @@ ssize_t Conf::deleteMacroFromFile(macro *_macro, const char *filePath)
|
|||
// Read each macro from the original file
|
||||
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)
|
||||
{
|
||||
fwrite(&temp_macro, sizeof(macro), 1, tempfile);
|
||||
|
|
@ -92,8 +97,9 @@ ssize_t Conf::deleteMacroFromFile(macro *_macro, const char *filePath)
|
|||
fclose(tempfile);
|
||||
|
||||
// Replace the original file with the temp file
|
||||
remove(filePath); // Delete the original file
|
||||
rename("tempfile.bin", filePath); // Rename the temp file to the original file name
|
||||
remove(filePath); // Delete the original file
|
||||
rename("tempfile.bin",
|
||||
filePath); // Rename the temp file to the original file name
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -102,59 +108,77 @@ ssize_t Conf::deleteMacroFromFile(macro *_macro, const char *filePath)
|
|||
|
||||
void Conf::testFunc()
|
||||
{
|
||||
macro **macros;
|
||||
readMacrosFromDevice(macros, 4);
|
||||
for (int i = 0; i < 4; i++)
|
||||
|
||||
m_mouse->readConfigFromDevice(CONF_TYPE::BATTERY);
|
||||
m_mouse->readConfigFromDevice(CONF_TYPE::LIGHT);
|
||||
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++)
|
||||
{
|
||||
appendMacroToFile(macros[i], "macrofileappend");
|
||||
std::cout << cols[i];
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
int Conf::lightMode()
|
||||
{
|
||||
return m_conf1->light_mode;
|
||||
}
|
||||
std::cout << "Battery capacity:" << std::dec << m_mouse->getBatteryCapacity() << std::endl;
|
||||
m_mouse->writeConfigToDevice(CONF_TYPE::LIGHT);
|
||||
|
||||
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();
|
||||
m_mouse->readMacrosFromDevice(4);
|
||||
}
|
||||
|
||||
ssize_t Conf::writeConfigToFile(const char *filePath)
|
||||
|
|
@ -195,184 +219,6 @@ ssize_t Conf::writeConfigToFile(const char *filePath)
|
|||
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()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(nullptr, i18n("Save File As"));
|
||||
|
|
@ -416,16 +262,17 @@ ssize_t Conf::readConfigFromFile(const char *filePath, conf_1 *conf)
|
|||
if (infile == NULL)
|
||||
{
|
||||
fprintf(stderr, "\nError opening file\n");
|
||||
exit(1);
|
||||
return ssize_t(1);
|
||||
}
|
||||
|
||||
// reading to read_struct
|
||||
fread(conf, sizeof(struct conf_1), 1, infile);
|
||||
if (sizeof(struct conf_1) > fread(conf, sizeof(struct conf_1), 1, infile))
|
||||
fprintf(stderr, "\nError file\n");
|
||||
|
||||
// close file
|
||||
fclose(infile);
|
||||
|
||||
return 0;
|
||||
return ssize_t(0);
|
||||
}
|
||||
|
||||
ssize_t Conf::readConfigFromFile(const char *filePath, conf_2 *conf)
|
||||
|
|
@ -437,16 +284,17 @@ ssize_t Conf::readConfigFromFile(const char *filePath, conf_2 *conf)
|
|||
if (infile == NULL)
|
||||
{
|
||||
fprintf(stderr, "\nError opening file\n");
|
||||
exit(1);
|
||||
return ssize_t(1);
|
||||
}
|
||||
|
||||
// reading to read_struct
|
||||
fread(conf, sizeof(struct conf_2), 1, infile);
|
||||
if (sizeof(struct conf_2) > fread(conf, sizeof(struct conf_2), 1, infile))
|
||||
fprintf(stderr, "\nError file\n");
|
||||
|
||||
// close file
|
||||
fclose(infile);
|
||||
|
||||
return 0;
|
||||
return ssize_t(0);
|
||||
}
|
||||
|
||||
ssize_t Conf::readConfigFromFile(const char *filePath)
|
||||
|
|
@ -457,11 +305,12 @@ ssize_t Conf::readConfigFromFile(const char *filePath)
|
|||
if (infile == NULL)
|
||||
{
|
||||
fprintf(stderr, "\nError opening file\n");
|
||||
exit(1);
|
||||
return ssize_t(1);
|
||||
}
|
||||
|
||||
fread(m_conf1, sizeof(struct conf_1), 1, infile);
|
||||
fread(m_conf2, sizeof(struct conf_2), 1, infile);
|
||||
if (sizeof(struct conf_1) > fread(m_conf1, sizeof(struct conf_1), 1, infile) ||
|
||||
sizeof(struct conf_2) > fread(m_conf2, sizeof(struct conf_2), 1, infile))
|
||||
fprintf(stderr, "\nError file\n");
|
||||
|
||||
fclose(infile);
|
||||
return 0;
|
||||
|
|
@ -477,4 +326,4 @@ ssize_t Conf::readConfigFromFile()
|
|||
readConfigFromFile(path.toUtf8().constData());
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
src/conf.h
31
src/conf.h
|
|
@ -12,30 +12,18 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "structs.h"
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#include <unistd.h>
|
||||
#include "usb_thingy.h"
|
||||
#include "a811.h"
|
||||
|
||||
#define CONF_FILE "conf.bin"
|
||||
|
||||
class Conf : public QObject
|
||||
{
|
||||
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:
|
||||
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();
|
||||
ssize_t writeConfigToFile(const char *filePath);
|
||||
|
|
@ -47,37 +35,22 @@ public:
|
|||
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_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 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_SIGNALS:
|
||||
|
||||
private:
|
||||
macro **m_macros;
|
||||
A811 *m_mouse;
|
||||
ssize_t m_stat;
|
||||
ssize_t m_bat;
|
||||
int m_lightMode;
|
||||
conf_1 *m_conf1;
|
||||
conf_2 *m_conf2;
|
||||
libusb_device *m_device = NULL;
|
||||
libusb_context *m_ctx = NULL;
|
||||
QString m_fileName;
|
||||
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 __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 __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 col_brightness_speed; // 0x46 0-4 Brightness und 0-4 Speed bei colorful 0x(br)(sp)
|
||||
uint8_t __u8; // 0x47 ???
|
||||
|
|
@ -33,8 +35,8 @@ struct conf_1
|
|||
struct key_conf
|
||||
{
|
||||
uint8_t pref;
|
||||
uint8_t mod; // or macro id
|
||||
uint8_t keycode; // for macro cycle type
|
||||
uint8_t mod; // or macro id
|
||||
uint8_t keycode; // for macro cycle type
|
||||
uint8_t macro_cycle; // for macro cycle count
|
||||
};
|
||||
|
||||
|
|
@ -59,7 +61,8 @@ struct conf_2
|
|||
uint8_t __u5[0x207 - 0x47]; // 0x48-0x58 ?? 0x58-end zeros
|
||||
};
|
||||
|
||||
struct macro_event{
|
||||
struct macro_event
|
||||
{
|
||||
uint8_t updown_plus_delay_upper;
|
||||
uint8_t delay_lower;
|
||||
uint8_t keycode;
|
||||
|
|
@ -67,7 +70,7 @@ struct macro_event{
|
|||
|
||||
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 macro_nr;
|
||||
uint8_t __u2;
|
||||
|
|
@ -82,4 +85,12 @@ struct conf_12
|
|||
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
|
||||
|
|
@ -39,6 +39,8 @@ ssize_t Connection::findDevice()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
libusb_free_device_list(list, 1);
|
||||
|
||||
if(!found_device)
|
||||
|
|
@ -87,7 +89,7 @@ ssize_t Connection::setReport(uint16_t wValue, unsigned char *send_data, uint16_
|
|||
{
|
||||
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 ssize_t(0);
|
||||
|
|
|
|||
Loading…
Reference in a new issue