Add fire button and investigate macro repetition
This commit is contained in:
parent
7f7c15e00a
commit
792dccfe97
11 changed files with 129 additions and 12 deletions
10
README.md
10
README.md
|
@ -1,6 +1,10 @@
|
|||
# mouse_m908
|
||||
Control the Redragon M908 Impact gaming mouse from Linux
|
||||
|
||||
## Status
|
||||
All settings from the official software are implemented, except repeating macros, which seems to be broken in the official software and is therefore currently disabled in this program.
|
||||
As a result there will be no changes to this program, unless I overlooked some features or find a bug.
|
||||
|
||||
## Installing
|
||||
- Install the dependencies:
|
||||
- libusb
|
||||
|
@ -46,7 +50,6 @@ There is space for 15 macros on the mouse, these are shared over all profiles. E
|
|||
2. Add macro⟨N⟩ to the button mapping configuration to set a button to the ⟨N⟩th macro
|
||||
3. Apply the configuration: mouse_m908 -c ⟨config.ini⟩
|
||||
4. Apply the specific macro: mouse_m908 -m ⟨macrofile⟩ -n ⟨N⟩
|
||||
|
||||
#### Macro file
|
||||
Each line contains an action and a parameter separated by a tab. Supported actions are:
|
||||
- down ⟨key⟩
|
||||
|
@ -58,8 +61,3 @@ example.macro for an example, keymap.md section Keyboard keys/Keys for a list of
|
|||
- mouse_right
|
||||
- mouse_middle
|
||||
|
||||
## TODO
|
||||
~~Button remapping is not (yet) fully supported: macros and keyboard keys aren't implemented.~~ Macros are currently missing some features:
|
||||
- [x] delay between keys
|
||||
- [x] mousebuttons
|
||||
- [ ] repeat
|
||||
|
|
|
@ -39,7 +39,7 @@ report_rate=500
|
|||
button_left=left
|
||||
button_right=right
|
||||
button_middle=middle
|
||||
button_fire=left
|
||||
button_fire=fire:mouse_left:5:1
|
||||
button_dpi_up=dpi+
|
||||
button_dpi_down=dpi-
|
||||
scroll_up=scroll_up
|
||||
|
@ -51,8 +51,8 @@ button_4=dpi-cycle
|
|||
button_5=report_rate+
|
||||
button_6=report_rate-
|
||||
button_7=profile_switch
|
||||
button_8=a
|
||||
button_9=b
|
||||
button_8=fire:a:5:1
|
||||
button_9=a
|
||||
button_10=super_l+shift_l+2
|
||||
button_11=ctrl_l+a
|
||||
button_12=super_l+3
|
||||
|
|
|
@ -48,6 +48,7 @@ mouse_m908::mouse_m908(){
|
|||
_keymap_data[i][j][0] = _data_settings_3[35+(20*i)+j][8];
|
||||
_keymap_data[i][j][1] = _data_settings_3[35+(20*i)+j][9];
|
||||
_keymap_data[i][j][2] = _data_settings_3[35+(20*i)+j][10];
|
||||
_keymap_data[i][j][3] = _data_settings_3[35+(20*i)+j][11];
|
||||
}
|
||||
}
|
||||
_report_rates.fill( r_125Hz );
|
||||
|
@ -58,6 +59,7 @@ mouse_m908::mouse_m908(){
|
|||
i[3] = _data_macros_codes[count][1];
|
||||
count++;
|
||||
}
|
||||
_macro_repeat.fill( 0x01 );
|
||||
|
||||
//name → keycode
|
||||
_keycodes = {
|
||||
|
|
|
@ -236,3 +236,6 @@ uint8_t mouse_m908::_data_macros_codes[15][2] = {
|
|||
{0xd8, 0x0d},
|
||||
{0xa0, 0x0e},
|
||||
{0x68, 0x0f} };
|
||||
|
||||
uint8_t mouse_m908::_data_macros_repeat[16] =
|
||||
{0x02, 0xf3, 0xa2, 0x00, 0x04, 0x00, 0x00, 0x00, 0x91, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
|
|
@ -51,3 +51,13 @@ uint8_t mouse_m908::get_dpi( m908_profile profile, int level ){
|
|||
mouse_m908::m908_report_rate mouse_m908::get_report_rate( m908_profile profile ){
|
||||
return _report_rates[profile];
|
||||
}
|
||||
|
||||
uint8_t mouse_m908::get_macro_repeat( int macro_number ){
|
||||
|
||||
//check if macro_number is valid
|
||||
if( macro_number < 1 || macro_number > 15 ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
return _macro_repeat[macro_number];
|
||||
}
|
||||
|
|
|
@ -71,10 +71,11 @@ class mouse_m908{
|
|||
int set_speed( m908_profile profile, uint8_t speed );
|
||||
int set_dpi_enable( m908_profile profile, int level, bool enabled );
|
||||
int set_dpi( m908_profile profile, int level, uint8_t dpi );
|
||||
int set_key_mapping( m908_profile profile, int key, std::array<uint8_t, 3> mapping );
|
||||
int set_key_mapping( m908_profile profile, int key, std::array<uint8_t, 4> mapping );
|
||||
int set_key_mapping( m908_profile profile, int key, std::string mapping );
|
||||
int set_report_rate( m908_profile profile, m908_report_rate report_rate );
|
||||
int set_macro( int macro_number, std::string file );
|
||||
int set_macro_repeat( int macro_number, uint8_t repeat );
|
||||
|
||||
//getter functions
|
||||
m908_profile get_profile();
|
||||
|
@ -86,11 +87,13 @@ class mouse_m908{
|
|||
bool get_dpi_enable( m908_profile profile, int level );
|
||||
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 );
|
||||
|
||||
//writer functions (apply settings to mouse)
|
||||
int write_profile();
|
||||
int write_settings();
|
||||
int write_macro( int macro_number );
|
||||
int write_macro_repeat( int macro_number );
|
||||
|
||||
//helper functions
|
||||
int open_mouse();
|
||||
|
@ -115,9 +118,10 @@ class mouse_m908{
|
|||
std::array<uint8_t, 5> _speed_levels;
|
||||
std::array<std::array<bool, 5>, 5> _dpi_enabled;
|
||||
std::array<std::array<uint8_t, 5>, 5> _dpi_levels;
|
||||
std::array<std::array<std::array<uint8_t, 3>, 20>, 5> _keymap_data;
|
||||
std::array<std::array<std::array<uint8_t, 4>, 20>, 5> _keymap_data;
|
||||
std::array<m908_report_rate, 5> _report_rates;
|
||||
std::array<std::array<uint8_t, 256>, 15> _macro_data;
|
||||
std::array<uint8_t, 15> _macro_repeat;
|
||||
|
||||
//setting min and max values
|
||||
uint8_t _scrollspeed_min, _scrollspeed_max;
|
||||
|
@ -140,6 +144,7 @@ class mouse_m908{
|
|||
static uint8_t _data_macros_2[256];
|
||||
static uint8_t _data_macros_3[16];
|
||||
static uint8_t _data_macros_codes[15][2];
|
||||
static uint8_t _data_macros_repeat[16];
|
||||
};
|
||||
|
||||
#include "data.cpp"
|
||||
|
|
|
@ -26,4 +26,5 @@ void print_help(){
|
|||
std::cout << "-p --profile\n\tSets currently active profile (1-5).\n";
|
||||
std::cout << "-m --macro\n\tSelects macro file for sending.\n";
|
||||
std::cout << "-n --number\n\tSelects macro slot for sending (1-15).\n";
|
||||
//std::cout << "-r --repeat\n\tSets number of times the macro will be repeated (1-255).\n";
|
||||
}
|
||||
|
|
|
@ -89,10 +89,11 @@ int mouse_m908::set_dpi( m908_profile profile, int level, uint8_t dpi ){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mouse_m908::set_key_mapping( m908_profile profile, int key, std::array<uint8_t, 3> mapping ){
|
||||
int mouse_m908::set_key_mapping( m908_profile profile, int key, std::array<uint8_t, 4> mapping ){
|
||||
_keymap_data[profile][key][0] = mapping[0];
|
||||
_keymap_data[profile][key][1] = mapping[1];
|
||||
_keymap_data[profile][key][2] = mapping[2];
|
||||
_keymap_data[profile][key][3] = mapping[3];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -103,6 +104,40 @@ int mouse_m908::set_key_mapping( m908_profile profile, int key, std::string mapp
|
|||
_keymap_data[profile][key][0] = _keycodes[mapping][0];
|
||||
_keymap_data[profile][key][1] = _keycodes[mapping][1];
|
||||
_keymap_data[profile][key][2] = _keycodes[mapping][2];
|
||||
_keymap_data[profile][key][3] = 0x00;
|
||||
} else if( mapping.find("fire") == 0 ){
|
||||
// fire button (multiple keypresses)
|
||||
|
||||
std::stringstream mapping_stream(mapping);
|
||||
std::string value1 = "", value2 = "", value3 = "";
|
||||
uint8_t keycode, repeats = 1, delay = 0;
|
||||
|
||||
std::getline( mapping_stream, value1, ':' );
|
||||
std::getline( mapping_stream, value1, ':' );
|
||||
std::getline( mapping_stream, value2, ':' );
|
||||
std::getline( mapping_stream, value3, ':' );
|
||||
|
||||
if( value1 == "mouse_left" ){
|
||||
keycode = 0x81;
|
||||
} else if( value1 == "mouse_right" ){
|
||||
keycode = 0x82;
|
||||
} else if( value1 == "mouse_middle" ){
|
||||
keycode = 0x84;
|
||||
} else if( _keyboard_key_values.find(value1) != _keyboard_key_values.end() ){
|
||||
keycode = _keyboard_key_values[value1];
|
||||
} else{
|
||||
return 1;
|
||||
}
|
||||
|
||||
repeats = (uint8_t)stoi(value2);
|
||||
delay = (uint8_t)stoi(value3);
|
||||
|
||||
// store values
|
||||
_keymap_data[profile][key][0] = 0x99;
|
||||
_keymap_data[profile][key][1] = keycode;
|
||||
_keymap_data[profile][key][2] = repeats;
|
||||
_keymap_data[profile][key][3] = delay;
|
||||
|
||||
} else{
|
||||
// string is not a key in _keycodes: keyboard key?
|
||||
|
||||
|
@ -123,6 +158,7 @@ int mouse_m908::set_key_mapping( m908_profile profile, int key, std::string mapp
|
|||
_keymap_data[profile][key][0] = first_value;
|
||||
_keymap_data[profile][key][1] = modifier_value;
|
||||
_keymap_data[profile][key][2] = _keyboard_key_values[std::regex_replace( mapping, modifier_regex, "" )];
|
||||
_keymap_data[profile][key][3] = 0x00;
|
||||
//std::cout << std::regex_replace( mapping, modifier_regex, "" ) << "\n";
|
||||
} catch( std::exception& f ){
|
||||
return 1;
|
||||
|
@ -230,3 +266,14 @@ int mouse_m908::set_macro( int macro_number, std::string file ){
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mouse_m908::set_macro_repeat( int macro_number, uint8_t repeat ){
|
||||
|
||||
//check if macro_number is valid
|
||||
if( macro_number < 1 || macro_number > 15 ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
_macro_repeat[macro_number] = repeat;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -127,6 +127,8 @@ int mouse_m908::write_settings(){
|
|||
buffer3[35+(20*i)+j][8] = _keymap_data[i][j][0];
|
||||
buffer3[35+(20*i)+j][9] = _keymap_data[i][j][1];
|
||||
buffer3[35+(20*i)+j][10] = _keymap_data[i][j][2];
|
||||
buffer3[35+(20*i)+j][11] = _keymap_data[i][j][3];
|
||||
//std::cout << (int)_keymap_data[i][j][0] << " " << (int)_keymap_data[i][j][1] << " " << (int)_keymap_data[i][j][2] << " " << (int)_keymap_data[i][j][3] << "\n";
|
||||
}
|
||||
}
|
||||
//usb report rate
|
||||
|
@ -204,3 +206,22 @@ int mouse_m908::write_macro( int macro_number ){
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mouse_m908::write_macro_repeat( int macro_number ){
|
||||
|
||||
//check if macro_number is valid
|
||||
if( macro_number < 1 || macro_number > 15 ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
//prepare data
|
||||
uint8_t buffer[16];
|
||||
std::copy(std::begin(_data_macros_repeat), std::end(_data_macros_repeat), std::begin(buffer));
|
||||
|
||||
buffer[10] = _macro_repeat[macro_number];
|
||||
|
||||
//send data
|
||||
libusb_control_transfer( _handle, 0x21, 0x09, 0x0302, 0x0002, buffer, 16, 1000 );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
12
keymap.md
12
keymap.md
|
@ -1,6 +1,18 @@
|
|||
# keymap.md
|
||||
This documents all options for button mapping.
|
||||
|
||||
## Fire button (simulates multiple nutton presses)
|
||||
fire:⟨button⟩:⟨repeats⟩:⟨delay⟩
|
||||
|
||||
⟨button⟩ can be:
|
||||
- mouse_left
|
||||
- mouse_right
|
||||
- mouse_middle
|
||||
- a keyboard key
|
||||
|
||||
⟨repeats⟩ can be 1-255
|
||||
⟨delay⟩ can be 1-255
|
||||
|
||||
## Mousebuttons and special functions
|
||||
forward
|
||||
backward
|
||||
|
|
|
@ -41,16 +41,20 @@ int main( int argc, char **argv ){
|
|||
{"profile", required_argument, 0, 'p'},
|
||||
{"macro", required_argument, 0, 'm'},
|
||||
{"number", required_argument, 0, 'n'},
|
||||
//{"repeat", required_argument, 0, 'r'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
bool flag_config = false, flag_profile = false;
|
||||
bool flag_macro = false, flag_number = false;
|
||||
//bool flag_repeat;
|
||||
std::string string_config, string_profile;
|
||||
std::string string_macro, string_number;
|
||||
//std::string string_repeat;
|
||||
|
||||
//parse command line options
|
||||
int c, option_index = 0;
|
||||
//while( (c = getopt_long( argc, argv, "hc:p:m:n:r:",
|
||||
while( (c = getopt_long( argc, argv, "hc:p:m:n:",
|
||||
long_options, &option_index ) ) != -1 ){
|
||||
|
||||
|
@ -75,6 +79,10 @@ int main( int argc, char **argv ){
|
|||
flag_number = true;
|
||||
string_number = optarg;
|
||||
break;
|
||||
//case 'r':
|
||||
// flag_repeat = true;
|
||||
// string_repeat = optarg;
|
||||
// break;
|
||||
case '?':
|
||||
break;
|
||||
default:
|
||||
|
@ -438,6 +446,16 @@ int main( int argc, char **argv ){
|
|||
|
||||
m.write_macro(number);
|
||||
|
||||
/*if( flag_repeat ){
|
||||
int repeat = (int)stoi(string_repeat);
|
||||
r = m.set_macro_repeat( number, repeat );
|
||||
if( r != 0 ){
|
||||
std::cout << "Invalid repeats\n";
|
||||
return 1;
|
||||
}
|
||||
m.write_macro_repeat( number );
|
||||
}*/
|
||||
|
||||
m.close_mouse();
|
||||
|
||||
} else if( flag_macro || flag_number ){
|
||||
|
|
Loading…
Reference in a new issue