Various internal improvements
This commit is contained in:
parent
2f9073bbc3
commit
21a9a8a265
8 changed files with 509 additions and 25 deletions
|
@ -57,7 +57,7 @@ mouse_m908 -c example.ini
|
|||
``
|
||||
- Read the configuration from the mouse and store it in config.ini:
|
||||
``
|
||||
mouse_m908 -R > config.ini
|
||||
mouse_m908 -R config.ini
|
||||
``
|
||||
- Set active profile to number 3:
|
||||
``
|
||||
|
|
10
TODO.md
Normal file
10
TODO.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
- [ ] add support for reading macros from --read output
|
||||
- [ ] update documentation
|
||||
- [x] add file option to -D and -R
|
||||
- [ ] read settings → memory
|
||||
- [x] print settings ← memory
|
||||
- [x] read scrollspeed? not supported by the official software/firmware
|
||||
- [ ] unify makefile
|
||||
- [x] check setters and getters
|
||||
- [ ] add getter for macros
|
||||
- [ ] release 2.0
|
|
@ -221,6 +221,29 @@ std::map< std::string, uint8_t > mouse_m908::_keyboard_key_values = {
|
|||
{ "F23", 0x72 },
|
||||
{ "F24", 0x73 } };
|
||||
|
||||
// Names of the physical buttons
|
||||
std::map< int, std::string > mouse_m908::_button_names = {
|
||||
{ 0, "button_left" },
|
||||
{ 1, "button_right" },
|
||||
{ 2, "button_middle" },
|
||||
{ 3, "button_fire" },
|
||||
{ 4, "button_dpi_up" },
|
||||
{ 5, "button_dpi_down" },
|
||||
{ 6, "button_1" },
|
||||
{ 7, "button_2" },
|
||||
{ 8, "button_3" },
|
||||
{ 9, "button_4" },
|
||||
{ 10, "button_5" },
|
||||
{ 11, "button_6" },
|
||||
{ 12, "button_7" },
|
||||
{ 13, "button_8" },
|
||||
{ 14, "button_9" },
|
||||
{ 15, "button_10" },
|
||||
{ 16, "button_11" },
|
||||
{ 17, "button_12" },
|
||||
{ 18, "scroll_up" },
|
||||
{ 19, "scroll_down" } };
|
||||
|
||||
//usb data packets
|
||||
uint8_t mouse_m908::_data_profile[6][16] = {
|
||||
{0x02, 0xf3, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
|
|
|
@ -63,3 +63,140 @@ uint8_t mouse_m908::get_macro_repeat( int macro_number ){
|
|||
|
||||
return _macro_repeat[macro_number];
|
||||
}
|
||||
|
||||
bool mouse_m908::get_detach_kernel_driver(){
|
||||
return _detach_kernel_driver;
|
||||
}
|
||||
|
||||
int mouse_m908::get_key_mapping_raw( mouse_m908::m908_profile profile, int key, std::array<uint8_t, 4>& mapping ){
|
||||
|
||||
if( key < 0 || key > 19 ) // valid key ?
|
||||
return 1;
|
||||
|
||||
mapping[0] = _keymap_data[profile][key][0];
|
||||
mapping[1] = _keymap_data[profile][key][1];
|
||||
mapping[2] = _keymap_data[profile][key][2];
|
||||
mapping[3] = _keymap_data[profile][key][3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mouse_m908::get_key_mapping( mouse_m908::m908_profile profile, int key, std::string& mapping ){
|
||||
|
||||
if( key < 0 || key > 19 ) // valid key ?
|
||||
return 1;
|
||||
|
||||
uint8_t b1 = _keymap_data[profile][key][0];
|
||||
uint8_t b2 = _keymap_data[profile][key][1];
|
||||
uint8_t b3 = _keymap_data[profile][key][2];
|
||||
uint8_t b4 = _keymap_data[profile][key][3];
|
||||
bool found_name = false;
|
||||
|
||||
mapping = "";
|
||||
|
||||
// fire button
|
||||
if( b1 == 0x99 ){
|
||||
|
||||
mapping += "fire:";
|
||||
|
||||
// button
|
||||
if( b2 == 0x81 )
|
||||
mapping += "mouse_left:";
|
||||
else if( b2 == 0x82 )
|
||||
mapping += "mouse_right:";
|
||||
else if( b2 == 0x84 )
|
||||
mapping += "mouse_middle:";
|
||||
else{
|
||||
|
||||
// iterate over _keyboard_key_values
|
||||
for( auto keycode : _keyboard_key_values ){
|
||||
|
||||
if( keycode.second == b2 ){
|
||||
|
||||
mapping += keycode.first;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
mapping += ":";
|
||||
}
|
||||
|
||||
// repeats
|
||||
mapping += std::to_string( (int)b3 ) + ":";
|
||||
|
||||
// delay
|
||||
mapping += std::to_string( (int)b4 );
|
||||
|
||||
found_name = true;
|
||||
|
||||
// keyboard key
|
||||
} else if( b1 == 0x90 ){
|
||||
|
||||
// iterate over _keyboard_key_values
|
||||
for( auto keycode : _keyboard_key_values ){
|
||||
|
||||
if( keycode.second == b3 ){
|
||||
|
||||
mapping += keycode.first;
|
||||
found_name = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// modifiers + keyboard key
|
||||
} else if( b1 == 0x8f ){
|
||||
|
||||
// iterate over _keyboard_modifier_values
|
||||
for( auto modifier : _keyboard_modifier_values ){
|
||||
|
||||
if( modifier.second & b2 ){
|
||||
mapping += modifier.first;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// iterate over _keyboard_key_values
|
||||
for( auto keycode : _keyboard_key_values ){
|
||||
|
||||
if( keycode.second == b3 ){
|
||||
|
||||
mapping += keycode.first;
|
||||
found_name = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else{ // mousebutton or special function ?
|
||||
|
||||
// iterate over _keycodes
|
||||
for( auto keycode : _keycodes ){
|
||||
|
||||
if( keycode.second[0] == b1 &&
|
||||
keycode.second[1] == b2 &&
|
||||
keycode.second[2] == b3 ){
|
||||
|
||||
mapping += keycode.first;
|
||||
found_name = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !found_name ){
|
||||
mapping += "unknown, please report as bug: ";
|
||||
mapping += " " + std::to_string( (int)b1 ) + " ";
|
||||
mapping += " " + std::to_string( (int)b2 ) + " ";
|
||||
mapping += " " + std::to_string( (int)b3 ) + " ";
|
||||
mapping += " " + std::to_string( (int)b4 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -214,3 +214,328 @@ int mouse_m908::close_mouse(){
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// print current configuration
|
||||
int mouse_m908::print_settings( std::ostream& output ){
|
||||
|
||||
// print configuration
|
||||
output << "# Configuration created by mouse_m908::print_settings().\n";
|
||||
output << "# Currently active profile: " << _profile << "\n";
|
||||
|
||||
for( int i = 1; i < 6; i++ ){
|
||||
|
||||
// section header
|
||||
output << "\n[profile" << i << "]\n";
|
||||
|
||||
output << "\n# LED settings\n";
|
||||
|
||||
// color
|
||||
output << "color=";
|
||||
output << std::setfill('0') << std::setw(2) << std::hex << (int)_colors[i-1][0];
|
||||
output << std::setfill('0') << std::setw(2) << std::hex << (int)_colors[i-1][1];
|
||||
output << std::setfill('0') << std::setw(2) << std::hex << (int)_colors[i-1][2];
|
||||
output << std::setfill(' ') << std::setw(0) << std::dec << "\n";
|
||||
|
||||
// brightness
|
||||
output << "brightness=" << (int)_brightness_levels[i-1] << "\n";
|
||||
|
||||
// speed
|
||||
output << "speed=" << (int)_speed_levels[i-1] << "\n";
|
||||
|
||||
// lightmode
|
||||
output << "lightmode=";
|
||||
if( _lightmodes[i-1] == lightmode_off )
|
||||
output << "off\n";
|
||||
else if( _lightmodes[i-1] == lightmode_breathing )
|
||||
output << "breathing\n";
|
||||
else if( _lightmodes[i-1] == lightmode_rainbow )
|
||||
output << "rainbow\n";
|
||||
else if( _lightmodes[i-1] == lightmode_static )
|
||||
output << "static\n";
|
||||
else if( _lightmodes[i-1] == lightmode_wave )
|
||||
output << "wave\n";
|
||||
else if( _lightmodes[i-1] == lightmode_alternating )
|
||||
output << "alternating\n";
|
||||
else if( _lightmodes[i-1] == lightmode_reactive )
|
||||
output << "reactive\n";
|
||||
else if( _lightmodes[i-1] == lightmode_flashing )
|
||||
output << "flashing\n";
|
||||
else{
|
||||
output << "unknown, please report as bug\n";
|
||||
}
|
||||
|
||||
// polling rate (report rate)
|
||||
output << "\n";
|
||||
if( _report_rates[i-1] == r_125Hz )
|
||||
output << "report_rate=125\n";
|
||||
else if( _report_rates[i-1] == r_250Hz )
|
||||
output << "report_rate=250\n";
|
||||
else if( _report_rates[i-1] == r_500Hz )
|
||||
output << "report_rate=500\n";
|
||||
else if( _report_rates[i-1] == r_1000Hz )
|
||||
output << "report_rate=1000\n";
|
||||
else{
|
||||
output << "# report rate unknown, please report as bug\n";
|
||||
}
|
||||
|
||||
// scrollspeed
|
||||
output << "scrollspeed=" << std::hex << (int)_scrollspeeds[i-1] << std::dec << "\n";
|
||||
|
||||
// dpi
|
||||
output << "\n# DPI settings\n";
|
||||
for( int j = 1; j < 6; j++ ){
|
||||
|
||||
if( _dpi_enabled[i-1][j] )
|
||||
output << "dpi" << j << "_enable=1\n";
|
||||
else
|
||||
output << "dpi" << j << "_enable=0\n";
|
||||
|
||||
output << std::setfill('0') << std::setw(2) << std::hex;
|
||||
output << "dpi" << j << "=" << (int)_dpi_levels[i-1][j-1] << "\n";
|
||||
output << std::setfill(' ') << std::setw(0) << std::dec;
|
||||
}
|
||||
|
||||
// button mapping
|
||||
output << "\n# Button mapping\n";
|
||||
|
||||
for( int j = 0; j < 20; j++ ){
|
||||
|
||||
uint8_t b1 = _keymap_data[i-1][j][0];
|
||||
uint8_t b2 = _keymap_data[i-1][j][1];
|
||||
uint8_t b3 = _keymap_data[i-1][j][2];
|
||||
uint8_t b4 = _keymap_data[i-1][j][3];
|
||||
bool found_name = false;
|
||||
|
||||
output << _button_names[j] << "=";
|
||||
|
||||
// fire button
|
||||
if( b1 == 0x99 ){
|
||||
|
||||
output << "fire:";
|
||||
|
||||
// button
|
||||
if( b2 == 0x81 )
|
||||
output << "mouse_left:";
|
||||
else if( b2 == 0x82 )
|
||||
output << "mouse_right:";
|
||||
else if( b2 == 0x84 )
|
||||
output << "mouse_middle:";
|
||||
else{
|
||||
|
||||
// iterate over _keyboard_key_values
|
||||
for( auto keycode : _keyboard_key_values ){
|
||||
|
||||
if( keycode.second == b2 ){
|
||||
|
||||
output << keycode.first;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
output << ":";
|
||||
}
|
||||
|
||||
// repeats
|
||||
output << (int)b3 << ":";
|
||||
|
||||
// delay
|
||||
output << (int)b4 << "\n";
|
||||
|
||||
found_name = true;
|
||||
|
||||
// keyboard key
|
||||
} else if( b1 == 0x90 ){
|
||||
|
||||
// iterate over _keyboard_key_values
|
||||
for( auto keycode : _keyboard_key_values ){
|
||||
|
||||
if( keycode.second == b3 ){
|
||||
|
||||
output << keycode.first << "\n";
|
||||
found_name = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// modifiers + keyboard key
|
||||
} else if( b1 == 0x8f ){
|
||||
|
||||
// iterate over _keyboard_modifier_values
|
||||
for( auto modifier : _keyboard_modifier_values ){
|
||||
|
||||
if( modifier.second & b2 ){
|
||||
output << modifier.first;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// iterate over _keyboard_key_values
|
||||
for( auto keycode : _keyboard_key_values ){
|
||||
|
||||
if( keycode.second == b3 ){
|
||||
|
||||
output << keycode.first << "\n";
|
||||
found_name = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else{ // mousebutton or special function ?
|
||||
|
||||
// iterate over _keycodes
|
||||
for( auto keycode : _keycodes ){
|
||||
|
||||
if( keycode.second[0] == b1 &&
|
||||
keycode.second[1] == b2 &&
|
||||
keycode.second[2] == b3 ){
|
||||
|
||||
output << keycode.first << "\n";
|
||||
found_name = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !found_name ){
|
||||
output << "unknown, please report as bug: ";
|
||||
output << " " << std::hex << (int)b1 << " ";
|
||||
output << " " << std::hex << (int)b2 << " ";
|
||||
output << " " << std::hex << (int)b3 << " ";
|
||||
output << " " << std::hex << (int)b4;
|
||||
output << std::dec << "\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// macros
|
||||
output << "\n# Macros\n";
|
||||
for( int i = 0; i < 15; i++ ){
|
||||
|
||||
// macro undefined?
|
||||
if( _macro_data[i][8] == 0 && _macro_data[i][9] == 0 && _macro_data[i][10] == 0 )
|
||||
continue;
|
||||
|
||||
output << "\n;## macro" << i+1 << "\n";
|
||||
|
||||
for( long unsigned int j = 8; j < _macro_data[i].size(); ){
|
||||
|
||||
// failsafe
|
||||
if( j >= _macro_data[i].size() )
|
||||
break;
|
||||
|
||||
if( _macro_data[i][j] == 0x81 ){ // mouse button down
|
||||
|
||||
if( _macro_data[i][j] == 0x01 )
|
||||
output << ";# down\tmouse_left\n";
|
||||
else if( _macro_data[i][j] == 0x02 )
|
||||
output << ";# down\tmouse_right\n";
|
||||
else if( _macro_data[i][j] == 0x04 )
|
||||
output << ";# down\tmouse_middle\n";
|
||||
else{
|
||||
output << ";# unknown, please report as bug: ";
|
||||
output << std::hex << (int)_macro_data[i][j] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+1] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+2];
|
||||
output << std::dec << "\n";
|
||||
}
|
||||
|
||||
} else if( _macro_data[i][j] == 0x01 ){ // mouse button up
|
||||
|
||||
if( _macro_data[i][j] == 0x01 )
|
||||
output << ";# up\tmouse_left\n";
|
||||
else if( _macro_data[i][j] == 0x02 )
|
||||
output << ";# up\tmouse_right\n";
|
||||
else if( _macro_data[i][j] == 0x04 )
|
||||
output << ";# up\tmouse_middle\n";
|
||||
else{
|
||||
output << ";# unknown, please report as bug: ";
|
||||
output << std::hex << (int)_macro_data[i][j] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+1] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+2];
|
||||
output << std::dec << "\n";
|
||||
}
|
||||
|
||||
} else if( _macro_data[i][j] == 0x84 ){ // keyboard key down
|
||||
|
||||
bool found_name = false;
|
||||
|
||||
// iterate over _keyboard_key_values
|
||||
for( auto keycode : _keyboard_key_values ){
|
||||
|
||||
if( keycode.second == _macro_data[i][j+1] ){
|
||||
|
||||
output << ";# down\t" << keycode.first << "\n";
|
||||
found_name = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !found_name ){
|
||||
output << ";# unknown, please report as bug: ";
|
||||
output << std::hex << (int)_macro_data[i][j] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+1] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+2];
|
||||
output << std::dec << "\n";
|
||||
}
|
||||
|
||||
} else if( _macro_data[i][j] == 0x04 ){ // keyboard key up
|
||||
|
||||
bool found_name = false;
|
||||
|
||||
// iterate over _keyboard_key_values
|
||||
for( auto keycode : _keyboard_key_values ){
|
||||
|
||||
if( keycode.second == _macro_data[i][j+1] ){
|
||||
|
||||
output << ";# up\t" << keycode.first << "\n";
|
||||
found_name = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !found_name ){
|
||||
output << ";# unknown, please report as bug: ";
|
||||
output << std::hex << (int)_macro_data[i][j] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+1] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+2];
|
||||
output << std::dec << "\n";
|
||||
}
|
||||
|
||||
} else if( _macro_data[i][j] == 0x06 ){ // delay
|
||||
|
||||
output << ";# delay\t" << (int)_macro_data[i][j+1] << "\n";
|
||||
|
||||
} else if( _macro_data[i][j] == 0x00 ){ // padding
|
||||
|
||||
j++;
|
||||
|
||||
} else{
|
||||
output << ";# unknown, please report as bug: ";
|
||||
output << std::hex << (int)_macro_data[i][j] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+1] << " ";
|
||||
output << std::hex << (int)_macro_data[i][j+2];
|
||||
output << std::dec << "\n";
|
||||
}
|
||||
|
||||
// increment
|
||||
j+=3;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -190,7 +190,9 @@ class mouse_m908{
|
|||
uint8_t get_dpi( m908_profile profile, int level );
|
||||
m908_report_rate get_report_rate( m908_profile profile );
|
||||
uint8_t get_macro_repeat( int macro_number );
|
||||
|
||||
bool get_detach_kernel_driver();
|
||||
int get_key_mapping( m908_profile profile, int key, std::string& mapping );
|
||||
int get_key_mapping_raw( m908_profile profile, int key, std::array<uint8_t, 4>& mapping );
|
||||
|
||||
|
||||
//writer functions (apply settings to mouse)
|
||||
|
@ -232,6 +234,11 @@ class mouse_m908{
|
|||
*/
|
||||
int close_mouse();
|
||||
|
||||
/**
|
||||
* Print the current configuration in .ini format to output
|
||||
*/
|
||||
int print_settings( std::ostream& output );
|
||||
|
||||
|
||||
//reader functions (get settings from the mouse)
|
||||
/**
|
||||
|
@ -284,6 +291,8 @@ class mouse_m908{
|
|||
static const std::map< std::string, uint8_t > _keyboard_modifier_values;
|
||||
/// Values/keycodes of keyboard keys
|
||||
static std::map< std::string, uint8_t > _keyboard_key_values;
|
||||
/// Names of the physical buttons
|
||||
static std::map< int, std::string > _button_names;
|
||||
|
||||
//usb data packets
|
||||
/// Used for changing the active profile
|
||||
|
|
|
@ -174,7 +174,7 @@ int mouse_m908::read_and_print_settings( std::ostream& output ){
|
|||
|
||||
// print configuration
|
||||
output << "# Configuration created with mouse_m908 -R.\n";
|
||||
output << "# This function is experimental, not all settings are read.\n";
|
||||
output << "# Reading the scrollspeed is not supported.\n";
|
||||
output << "# Currently active profile: " << (int)buffer_in1[0][8]+1 << "\n";
|
||||
|
||||
for( int i = 1; i < 6; i++ ){
|
||||
|
@ -271,27 +271,6 @@ int mouse_m908::read_and_print_settings( std::ostream& output ){
|
|||
|
||||
// button mapping
|
||||
output << "\n# Button mapping\n";
|
||||
std::map< int, std::string > button_names = {
|
||||
{ 0, "button_left" },
|
||||
{ 1, "button_right" },
|
||||
{ 2, "button_middle" },
|
||||
{ 3, "button_fire" },
|
||||
{ 4, "button_dpi_up" },
|
||||
{ 5, "button_dpi_down" },
|
||||
{ 6, "button_1" },
|
||||
{ 7, "button_2" },
|
||||
{ 8, "button_3" },
|
||||
{ 9, "button_4" },
|
||||
{ 10, "button_5" },
|
||||
{ 11, "button_6" },
|
||||
{ 12, "button_7" },
|
||||
{ 13, "button_8" },
|
||||
{ 14, "button_9" },
|
||||
{ 15, "button_10" },
|
||||
{ 16, "button_11" },
|
||||
{ 17, "button_12" },
|
||||
{ 18, "scroll_up" },
|
||||
{ 19, "scroll_down" } };
|
||||
|
||||
for( int j = 0; j < 20; j++ ){
|
||||
|
||||
|
@ -301,7 +280,7 @@ int mouse_m908::read_and_print_settings( std::ostream& output ){
|
|||
uint8_t b4 = buffer_in3[j+(20*(i-1))][11];
|
||||
bool found_name = false;
|
||||
|
||||
output << button_names[j] << "=";
|
||||
output << _button_names[j] << "=";
|
||||
|
||||
// fire button
|
||||
if( b1 == 0x99 ){
|
||||
|
|
|
@ -129,6 +129,7 @@ int mouse_m908::set_key_mapping( m908_profile profile, int key, std::string mapp
|
|||
std::string value1 = "", value2 = "", value3 = "";
|
||||
uint8_t keycode, repeats = 1, delay = 0;
|
||||
|
||||
// the repeated value1 line is not a mistake, it skips the "fire:"
|
||||
std::getline( mapping_stream, value1, ':' );
|
||||
std::getline( mapping_stream, value1, ':' );
|
||||
std::getline( mapping_stream, value2, ':' );
|
||||
|
|
Loading…
Reference in a new issue