diff --git a/Haiku/.PackageInfo b/Haiku/.PackageInfo index f7329bc..9f1139c 100644 --- a/Haiku/.PackageInfo +++ b/Haiku/.PackageInfo @@ -2,8 +2,8 @@ name mouse_m908 version 2.2-1 architecture any -summary "Control the Redragon M908 Impact and M709 gaming mice" -description "Change the button mapping, LED lighting and more on the Redragon M908 Impact and M709 gaming mice" +summary "Control the Redragon M908 Impact, M709 and M711 gaming mice" +description "Change the button mapping, LED lighting and more on the Redragon M908 Impact, M709 and M711 gaming mice" packager "dokutan" vendor "dokutan" diff --git a/README.md b/README.md index e369f46..7b1ae19 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # mouse_m908 -Control the Redragon M908 Impact and M709 gaming mice from Linux, BSD and Haiku +Control the Redragon M908 Impact, M709 and M711 gaming mice from Linux, BSD and Haiku **Disclaimer: This software is not supported by the manufacturer of the hardware in any way, and relies completely on information from reverse-engineering. There is no warranty, especially in case of damage to the hardware.** @@ -18,13 +18,14 @@ Control the Redragon M908 Impact and M709 gaming mice from Linux, BSD and Haiku - [License](#license) ## Status -For the M908: 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. +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. ### Supported mice Name | Support | VID:PID | Additional notes ---|---|---|--- M908 | complete | 0x04d9:0xfc4d | M709 | experimental | 0x04d9:0xfc2a | See [this issue](https://github.com/dokutan/mouse_m908/issues/1)
- Changing the profile works
- Changing the settings is untested but implemented
- Macros are untested
- Reading the settings is currently not properly implemented due to a lack of captured data +M711 | experimental | 0x04d9:0xfc30 | Nothing is tested, please report your results
- Implemented: led color, mode, brightness and speed, changing profiles, macros, reading settings
- No usb capture available, therefore missing: button mapping, dpi, scrollspeed, usb poll rate If you have a compatible device sold under a different name, or with a different VID or PID, please let me know so the readme can be updated. diff --git a/TODO.md b/TODO.md index 7be0447..3f85a1a 100644 --- a/TODO.md +++ b/TODO.md @@ -1,2 +1,8 @@ - Completeley support the M709, requires captured data + - --read and --dump are unchanged from the M908 +- Completeley support the M711, requires captured data + - write_settings() is incomplete + - read_and_print_settings & read_settings: keymapping is not implemented + - _c_button_names is unchanged from the M709 - Investigate methods to deduplicate code between mouse_m* classes, move code to rd_mouse +- Maybe add support for the M715 (PID 0xfc39), currently lacking information diff --git a/documentation/how-to-add-a-new-device.md b/documentation/how-to-add-a-new-device.md new file mode 100644 index 0000000..db63e00 --- /dev/null +++ b/documentation/how-to-add-a-new-device.md @@ -0,0 +1,17 @@ +# How to add support for a new device +This document contains a list of thing that need to be changed or added when adding a new device. + +- New class for the device (mouse_m*) inherited form rd_mouse, copy an existing include/m* directory to get started +- main program (mmouse_m908.cpp): + - new model +- include/rd_mouse.h + - #include new header file +- makefile + - Add new m* target +- udev rules +- documentation: + - README (supported models) + - manpage (supported models) + - help message (supported models) + - Haiku/.PackageInfo (supported models) + - create new config in examples/ diff --git a/examples/example_m711.ini b/examples/example_m711.ini new file mode 100644 index 0000000..c64f866 --- /dev/null +++ b/examples/example_m711.ini @@ -0,0 +1,116 @@ +# Example configuration for the M711 mouse +# +# 5 different profiles (1-5) are stored on the mouse +# if a particular option is not specified a default value will be used +# all numbers are specified in hexadecimal without a prefix unless specified + +[profile1] +# led mode: +# breathing, rainbow, static, wave, alternating, reactive, flashing, off +lightmode=static +# led color +color=50ff00 +# led brightness level (1-3) +brightness=2 +# led animation speed (1-8) +speed=1 + +# CURRENTLY NOT IMPLEMENTED, MISSING CAPTURED DATA +# scrollspeed (1-3f) +scrollspeed=1 + +# CURRENTLY NOT IMPLEMENTED, MISSING CAPTURED DATA +# Each profile has 5 dpi levels (1-5) that can be individually set and enabled/disabled +# Set dpiX_enable=0 to disable a particular dpi level +# It is not possible to disable all DPI levels, at least one will remain enabled +dpi1_enable=0 +dpi2_enable=1 +dpi3_enable=1 +dpi4_enable=1 +dpi5_enable=0 +# dpi (4-8c) +dpi1=04 +dpi2=16 +dpi3=2d +dpi4=43 +dpi5=8c + +# CURRENTLY NOT IMPLEMENTED, MISSING CAPTURED DATA +# usb report rate (125, 250, 500, 1000) Hz +report_rate=500 + +# CURRENTLY NOT IMPLEMENTED, MISSING CAPTURED DATA +# button mapping: there is a total of ? programmable buttons. +# keymap.md for full details +button_left=left +button_right=right +button_middle=middle +button_dpi=dpi-cycle +button_backward=backward +button_forward=forward +scroll_up=scroll_up +scroll_down=scroll_down + +[profile2] +lightmode=breathing +color=5000ff +brightness=3 + +[profile3] + +[profile4] + +[profile5] + +# NOT TESTED, NO DATA CAPTURES AVAILABLE +# Macro definitions +# Each macro (1-15) is defined in its own section, starting with ";## macro" +# Each action is prefixed by ";# " +# A tab ('\t') is used to separate the action from the value +# There are 3 different possible actions: +# down (key) +# up (key) +# delay (time in 10ms) + +;## macro1 +;# down m +;# up m +;# down a +;# up a +;# down c +;# up c +;# down r +;# up r +;# down o +;# up o +;# down 1 +;# up 1 + +;## macro2 +;# down m +;# up m +;# down a +;# up a +;# down c +;# up c +;# down r +;# up r +;# down o +;# up o +;# down 2 +;# up 2 + +;## macro3 +;# down m +;# up m +;# down a +;# up a +;# down c +;# up c +;# down r +;# up r +;# down o +;# up o +;# down 3 +;# up 3 + diff --git a/include/m711/constructor.cpp b/include/m711/constructor.cpp new file mode 100644 index 0000000..090e0b4 --- /dev/null +++ b/include/m711/constructor.cpp @@ -0,0 +1,51 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "mouse_m711.h" + +// Constructor, set the default settings +mouse_m711::mouse_m711(){ + + //default settings + _s_profile = profile_1; + _s_scrollspeeds.fill( 0x01 ); + _s_lightmodes.fill( lightmode_static ); + _s_colors.fill( {0xff, 0xff, 0xff} ); + _s_brightness_levels.fill( 0x03 ); + _s_speed_levels.fill( 0x08 ); + _s_dpi_enabled.fill( {true, true, true, true, true} ); + _s_dpi_levels.fill( {0x04, 0x16, 0x2d, 0x43, 0x8c} ); + for( int i = 0; i < 5; i++ ){ + for( int j = 0; j < 8; j++ ){ + _s_keymap_data[i][j][0] = _c_data_settings_3[35+(8*i)+j][8]; + _s_keymap_data[i][j][1] = _c_data_settings_3[35+(8*i)+j][9]; + _s_keymap_data[i][j][2] = _c_data_settings_3[35+(8*i)+j][10]; + _s_keymap_data[i][j][3] = _c_data_settings_3[35+(8*i)+j][11]; + } + } + _s_report_rates.fill( r_125Hz ); + int count = 0; + for( auto &i : _s_macro_data ){ + std::copy(std::begin(_c_data_macros_2), std::end(_c_data_macros_2), std::begin(i)); + i[2] = _c_data_macros_codes[count][0]; + i[3] = _c_data_macros_codes[count][1]; + count++; + } + _s_macro_repeat.fill( 0x01 ); + +} diff --git a/include/m711/data.cpp b/include/m711/data.cpp new file mode 100644 index 0000000..9e3e3c6 --- /dev/null +++ b/include/m711/data.cpp @@ -0,0 +1,687 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +/* + * This file contains internal constants and lookup tables + */ + +#include "mouse_m711.h" + +// usb device vars +const uint16_t mouse_m711::_c_mouse_vid = 0x04d9; +const uint16_t mouse_m711::_c_mouse_pid = 0xfc30; + +// Names of the physical buttons, TODO! +std::map< int, std::string > mouse_m711::_c_button_names = { + { 0, "button_left" }, + { 1, "button_right" }, + { 2, "button_middle" }, + { 3, "button_forward" }, + { 4, "button_backward" }, + { 5, "button_dpi" }, + { 6, "scroll_up" }, + { 7, "scroll_down" } }; + +//usb data packets +uint8_t mouse_m711::_c_data_s_profile[6][16] = { + {0x02, 0xf3, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +uint8_t mouse_m711::_c_data_settings_1[12][16] = { + {0x02, 0xf3, 0x46, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x49, 0x04, 0x06, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x4f, 0x04, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x51, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x08, 0x04, 0x00, 0x00}, + {0x02, 0xf3, 0x57, 0x04, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x59, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x08, 0x04, 0x00, 0x00}, + {0x02, 0xf3, 0x5f, 0x04, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x61, 0x04, 0x06, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x01, 0x08, 0x04, 0x00, 0x00}, + {0x02, 0xf3, 0x67, 0x04, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x69, 0x04, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x08, 0x04, 0x00, 0x00}, + {0x02, 0xf3, 0x6f, 0x04, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +// Currently not used, no capture available +uint8_t mouse_m711::_c_data_settings_2[64] = { + 0x03, 0xf3, 0x20, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +// Currently not used, no capture available +uint8_t mouse_m711::_c_data_settings_3[80][16] = { + {0x02, 0xf3, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xb2, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x62, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x12, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x44, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x04, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xb4, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x64, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x14, 0x03, 0x04, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x4a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x0a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xba, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x6a, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x1a, 0x03, 0x04, 0x00, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x50, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x10, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xc0, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x70, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x20, 0x03, 0x04, 0x00, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x56, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x16, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xc6, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x76, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x26, 0x03, 0x04, 0x00, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x5c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x1c, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xcc, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x7c, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x2c, 0x03, 0x04, 0x00, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x82, 0x00, 0x04, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x86, 0x00, 0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x8a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x9a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x90, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x9e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x90, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x92, 0x00, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xd2, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xd6, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x42, 0x01, 0x04, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x46, 0x01, 0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x4a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x5a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x52, 0x01, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x92, 0x01, 0x04, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x96, 0x01, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xf2, 0x01, 0x04, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xf6, 0x01, 0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xfa, 0x01, 0x04, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x0a, 0x02, 0x04, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x0e, 0x02, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x42, 0x02, 0x04, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x46, 0x02, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xa2, 0x02, 0x04, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xa6, 0x02, 0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xaa, 0x02, 0x04, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xba, 0x02, 0x04, 0x00, 0x00, 0x00, 0x90, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xbe, 0x02, 0x04, 0x00, 0x00, 0x00, 0x90, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xb2, 0x02, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xf2, 0x02, 0x04, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xf6, 0x02, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x52, 0x03, 0x04, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x56, 0x03, 0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x5a, 0x03, 0x04, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x6a, 0x03, 0x04, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x6e, 0x03, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0x62, 0x03, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xa2, 0x03, 0x04, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf3, 0xa6, 0x03, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf1, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +uint8_t mouse_m711::_c_data_macros_1[16] = + {0x02, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +uint8_t mouse_m711::_c_data_macros_2[256] = { + 0x04, 0xf3, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +uint8_t mouse_m711::_c_data_macros_3[16] = + {0x02, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +uint8_t mouse_m711::_c_data_macros_codes[15][2] = { + {0x78, 0x04}, + {0x40, 0x05}, + {0x08, 0x06}, + {0xd0, 0x06}, + {0x98, 0x07}, + {0x60, 0x08}, + {0x28, 0x09}, + {0xf0, 0x09}, + {0xb8, 0x0a}, + {0x80, 0x0b}, + {0x48, 0x0c}, + {0x10, 0x0d}, + {0xd8, 0x0d}, + {0xa0, 0x0e}, + {0x68, 0x0f} }; + +uint8_t mouse_m711::_c_data_macros_repeat[16] = + {0x02, 0xf3, 0xa2, 0x00, 0x04, 0x00, 0x00, 0x00, 0x91, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + +uint8_t mouse_m711::_c_data_read_1[9][16] = { + {0x02, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x2c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x49, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x51, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x59, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x61, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x69, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x38, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +uint8_t mouse_m711::_c_data_read_2[85][64] = { + {0x03, 0xf2, 0x42, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x02, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xb2, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x62, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x12, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x78, 0x04, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xaa, 0x04, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xdc, 0x04, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x0e, 0x05, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x40, 0x05, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x72, 0x05, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xa4, 0x05, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xd6, 0x05, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x08, 0x06, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x3a, 0x06, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x6c, 0x06, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x9e, 0x06, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xd0, 0x06, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x02, 0x07, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x34, 0x07, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x66, 0x07, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x98, 0x07, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xca, 0x07, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xfc, 0x07, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x2e, 0x08, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x60, 0x08, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x92, 0x08, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xc4, 0x08, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xf6, 0x08, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x28, 0x09, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x5a, 0x09, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x8c, 0x09, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xbe, 0x09, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xf0, 0x09, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x22, 0x0a, 0x32, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x54, 0x0a, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x86, 0x0a, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xb8, 0x0a, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xea, 0x0a, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x1c, 0x0b, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x4e, 0x0b, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x80, 0x0b, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xb2, 0x0b, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xe4, 0x0b, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x16, 0x0c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x48, 0x0c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x7a, 0x0c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xac, 0x0c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xde, 0x0c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x10, 0x0d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x42, 0x0d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x74, 0x0d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xa6, 0x0d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xd8, 0x0d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x0a, 0x0e, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x3c, 0x0e, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x6e, 0x0e, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xa0, 0x0e, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xd2, 0x0e, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x04, 0x0f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x36, 0x0f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x68, 0x0f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x9a, 0x0f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xcc, 0x0f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xfe, 0x0f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x30, 0x10, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x62, 0x10, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x94, 0x10, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xc6, 0x10, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xf8, 0x10, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x2a, 0x11, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x5c, 0x11, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x8e, 0x11, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xc0, 0x11, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xf2, 0x11, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x24, 0x12, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x56, 0x12, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x88, 0x12, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xba, 0x12, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xec, 0x12, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x1e, 0x13, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x50, 0x13, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0x82, 0x13, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xb4, 0x13, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + {0x03, 0xf2, 0xe6, 0x13, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; + +uint8_t mouse_m711::_c_data_read_3[46][16] = { + {0x02, 0xf2, 0x82, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x86, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x8a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x8e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x92, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x96, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x9a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x9e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xaa, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x42, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x46, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x4a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x4e, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x52, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x56, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x5a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x6a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xf2, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xf6, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xfa, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xfe, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x06, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x0a, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x0e, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x1a, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xa2, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xa6, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xaa, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xae, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xb2, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xb6, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xba, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xbe, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0xca, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x52, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x56, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x5a, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x5e, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x62, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x66, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x6a, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x6e, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf2, 0x7a, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; diff --git a/include/m711/getters.cpp b/include/m711/getters.cpp new file mode 100644 index 0000000..a6fed2f --- /dev/null +++ b/include/m711/getters.cpp @@ -0,0 +1,336 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "mouse_m711.h" + +mouse_m711::rd_profile mouse_m711::get_profile(){ + return _s_profile; +} + +uint8_t mouse_m711::get_scrollspeed( rd_profile profile ){ + return _s_scrollspeeds[profile]; +} + +mouse_m711::rd_lightmode mouse_m711::get_lightmode( rd_profile profile ){ + return _s_lightmodes[profile]; +} + +void mouse_m711::get_color( rd_profile profile, std::array &color ){ + color = _s_colors[profile]; +} + +uint8_t mouse_m711::get_brightness( rd_profile profile ){ + return _s_brightness_levels[profile]; +} + +uint8_t mouse_m711::get_speed( rd_profile profile ){ + return _s_speed_levels[profile]; +} + +bool mouse_m711::get_dpi_enable( rd_profile profile, int level ){ + return _s_dpi_enabled[profile][level]; +} + +uint8_t mouse_m711::get_dpi( rd_profile profile, int level ){ + return _s_dpi_levels[profile][level]; +} + +mouse_m711::rd_report_rate mouse_m711::get_report_rate( rd_profile profile ){ + return _s_report_rates[profile]; +} + +uint8_t mouse_m711::get_macro_repeat( int macro_number ){ + + //check if macro_number is valid + if( macro_number < 1 || macro_number > 15 ){ + return 1; + } + + return _s_macro_repeat[macro_number]; +} + +bool mouse_m711::get_detach_kernel_driver(){ + return _i_detach_kernel_driver; +} + +int mouse_m711::get_key_mapping_raw( mouse_m711::rd_profile profile, int key, std::array& mapping ){ + + // valid key ? + if( _c_button_names[key] == "" ) + return 1; + + mapping[0] = _s_keymap_data[profile][key][0]; + mapping[1] = _s_keymap_data[profile][key][1]; + mapping[2] = _s_keymap_data[profile][key][2]; + mapping[3] = _s_keymap_data[profile][key][3]; + + return 0; +} + +int mouse_m711::get_key_mapping( mouse_m711::rd_profile profile, int key, std::string& mapping ){ + + // valid key ? + if( _c_button_names[key] == "" ) + return 1; + + uint8_t b1 = _s_keymap_data[profile][key][0]; + uint8_t b2 = _s_keymap_data[profile][key][1]; + uint8_t b3 = _s_keymap_data[profile][key][2]; + uint8_t b4 = _s_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 _c_keyboard_key_values + for( auto keycode : _c_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 _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == b3 ){ + + mapping += keycode.first; + found_name = true; + break; + + } + + } + + // modifiers + keyboard key + } else if( b1 == 0x8f ){ + + // iterate over _c_keyboard_modifier_values + for( auto modifier : _c_keyboard_modifier_values ){ + + if( modifier.second & b2 ){ + mapping += modifier.first; + } + + } + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == b3 ){ + + mapping += keycode.first; + found_name = true; + break; + + } + + } + + } else{ // mousebutton or special function ? + + // iterate over _c_keycodes + for( auto keycode : _c_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: (dec) "; + 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; +} + +int mouse_m711::get_macro_raw( int number, std::array& macro ){ + + //check if macro_number is valid + if( number < 1 || number > 15 ) + return 1; + + std::copy( _s_macro_data[number-1].begin(), _s_macro_data[number-1].end(), macro.begin() ); + + return 0; +} + +int mouse_m711::get_macro( int number, std::string& macro ){ + + std::stringstream output; + + // macro undefined? + if( _s_macro_data[number-1][8] == 0 && _s_macro_data[number-1][9] == 0 && _s_macro_data[number-1][10] == 0 ) + return 0; + + for( long unsigned int j = 8; j < _s_macro_data[number-1].size(); ){ + + // failsafe + if( j >= _s_macro_data[number-1].size() ) + break; + + if( _s_macro_data[number-1][j] == 0x81 ){ // mouse button down + + if( _s_macro_data[number-1][j] == 0x01 ) + output << "down\tmouse_left\n"; + else if( _s_macro_data[number-1][j] == 0x02 ) + output << "down\tmouse_right\n"; + else if( _s_macro_data[number-1][j] == 0x04 ) + output << "down\tmouse_middle\n"; + else{ + output << "unknown, please report as bug: "; + output << std::hex << (int)_s_macro_data[number-1][j] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+1] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+2]; + output << std::dec << "\n"; + } + + } else if( _s_macro_data[number-1][j] == 0x01 ){ // mouse button up + + if( _s_macro_data[number-1][j] == 0x01 ) + output << "up\tmouse_left\n"; + else if( _s_macro_data[number-1][j] == 0x02 ) + output << "up\tmouse_right\n"; + else if( _s_macro_data[number-1][j] == 0x04 ) + output << "up\tmouse_middle\n"; + else{ + output << "unknown, please report as bug: "; + output << std::hex << (int)_s_macro_data[number-1][j] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+1] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+2]; + output << std::dec << "\n"; + } + + } else if( _s_macro_data[number-1][j] == 0x84 ){ // keyboard key down + + bool found_name = false; + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == _s_macro_data[number-1][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)_s_macro_data[number-1][j] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+1] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+2]; + output << std::dec << "\n"; + } + + } else if( _s_macro_data[number-1][j] == 0x04 ){ // keyboard key up + + bool found_name = false; + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == _s_macro_data[number-1][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)_s_macro_data[number-1][j] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+1] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+2]; + output << std::dec << "\n"; + } + + } else if( _s_macro_data[number-1][j] == 0x06 ){ // delay + + output << "delay\t" << (int)_s_macro_data[number-1][j+1] << "\n"; + + } else if( _s_macro_data[number-1][j] == 0x00 ){ // padding + + j++; + + } else{ + output << "unknown, please report as bug: "; + output << std::hex << (int)_s_macro_data[number-1][j] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+1] << " "; + output << std::hex << (int)_s_macro_data[number-1][j+2]; + output << std::dec << "\n"; + } + + // increment + j+=3; + + } + + macro = output.str(); + return 0; +} diff --git a/include/m711/helpers.cpp b/include/m711/helpers.cpp new file mode 100644 index 0000000..f48e1df --- /dev/null +++ b/include/m711/helpers.cpp @@ -0,0 +1,541 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "mouse_m711.h" + +//helper functions + +//init libusb and open mouse +int mouse_m711::open_mouse(){ + + //vars + int res = 0; + + //libusb init + res = libusb_init( NULL ); + if( res < 0 ){ + return res; + } + + //open device + _i_handle = libusb_open_device_with_vid_pid( NULL, _c_mouse_vid, + _c_mouse_pid ); + if( !_i_handle ){ + return 1; + } + + if( _i_detach_kernel_driver ){ + //detach kernel driver on interface 0 if active + if( libusb_kernel_driver_active( _i_handle, 0 ) ){ + res += libusb_detach_kernel_driver( _i_handle, 0 ); + if( res == 0 ){ + _i_detached_driver_0 = true; + } else{ + return res; + } + } + + //detach kernel driver on interface 1 if active + if( libusb_kernel_driver_active( _i_handle, 1 ) ){ + res += libusb_detach_kernel_driver( _i_handle, 1 ); + if( res == 0 ){ + _i_detached_driver_1 = true; + } else{ + return res; + } + } + + //detach kernel driver on interface 2 if active + if( libusb_kernel_driver_active( _i_handle, 2 ) ){ + res += libusb_detach_kernel_driver( _i_handle, 2 ); + if( res == 0 ){ + _i_detached_driver_2 = true; + } else{ + return res; + } + } + } + + //claim interface 0 + res += libusb_claim_interface( _i_handle, 0 ); + if( res != 0 ){ + return res; + } + + //claim interface 1 + res += libusb_claim_interface( _i_handle, 1 ); + if( res != 0 ){ + return res; + } + + //claim interface 2 + res += libusb_claim_interface( _i_handle, 2 ); + if( res != 0 ){ + return res; + } + + return res; +} + +// init libusb and open mouse by bus and device +int mouse_m711::open_mouse_bus_device( uint8_t bus, uint8_t device ){ + + //vars + int res = 0; + + //libusb init + res = libusb_init( NULL ); + if( res < 0 ){ + return res; + } + + //open device (_i_handle) + libusb_device **dev_list; // device list + ssize_t num_devs = libusb_get_device_list(NULL, &dev_list); //get device list + + if( num_devs < 0 ) + return 1; + + for( ssize_t i = 0; i < num_devs; i++ ){ + + // check if correct bus and device + if( bus == libusb_get_bus_number( dev_list[i] ) && + device == libusb_get_device_address( dev_list[i] ) ){ + + // open device + if( libusb_open( dev_list[i], &_i_handle ) != 0 ){ + return 1; + } else{ + break; + } + + } + + } + + //free device list, unreference devices + libusb_free_device_list( dev_list, 1 ); + + + if( _i_detach_kernel_driver ){ + //detach kernel driver on interface 0 if active + if( libusb_kernel_driver_active( _i_handle, 0 ) ){ + res += libusb_detach_kernel_driver( _i_handle, 0 ); + if( res == 0 ){ + _i_detached_driver_0 = true; + } else{ + return res; + } + } + + //detach kernel driver on interface 1 if active + if( libusb_kernel_driver_active( _i_handle, 1 ) ){ + res += libusb_detach_kernel_driver( _i_handle, 1 ); + if( res == 0 ){ + _i_detached_driver_1 = true; + } else{ + return res; + } + } + + //detach kernel driver on interface 2 if active + if( libusb_kernel_driver_active( _i_handle, 2 ) ){ + res += libusb_detach_kernel_driver( _i_handle, 2 ); + if( res == 0 ){ + _i_detached_driver_2 = true; + } else{ + return res; + } + } + } + + //claim interface 0 + res += libusb_claim_interface( _i_handle, 0 ); + if( res != 0 ){ + return res; + } + + //claim interface 1 + res += libusb_claim_interface( _i_handle, 1 ); + if( res != 0 ){ + return res; + } + + //claim interface 2 + res += libusb_claim_interface( _i_handle, 2 ); + if( res != 0 ){ + return res; + } + + return res; +} + +//close mouse +int mouse_m711::close_mouse(){ + + //release interfaces 0, 1 and 2 + libusb_release_interface( _i_handle, 0 ); + libusb_release_interface( _i_handle, 1 ); + libusb_release_interface( _i_handle, 2 ); + + //attach kernel driver for interface 0 + if( _i_detached_driver_0 ){ + libusb_attach_kernel_driver( _i_handle, 0 ); + } + + //attach kernel driver for interface 1 + if( _i_detached_driver_1 ){ + libusb_attach_kernel_driver( _i_handle, 1 ); + } + + + //attach kernel driver for interface 2 + if( _i_detached_driver_2 ){ + libusb_attach_kernel_driver( _i_handle, 2); + } + + //exit libusb + libusb_exit( NULL ); + + return 0; +} + +// print current configuration +int mouse_m711::print_settings( std::ostream& output ){ + + // print configuration + output << "# Configuration created by mouse_m711::print_settings().\n"; + output << "# Currently active profile: " << _s_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)_s_colors[i-1][0]; + output << std::setfill('0') << std::setw(2) << std::hex << (int)_s_colors[i-1][1]; + output << std::setfill('0') << std::setw(2) << std::hex << (int)_s_colors[i-1][2]; + output << std::setfill(' ') << std::setw(0) << std::dec << "\n"; + + // brightness + output << "brightness=" << (int)_s_brightness_levels[i-1] << "\n"; + + // speed + output << "speed=" << (int)_s_speed_levels[i-1] << "\n"; + + // lightmode + output << "lightmode="; + if( _s_lightmodes[i-1] == lightmode_off ) + output << "off\n"; + else if( _s_lightmodes[i-1] == lightmode_breathing ) + output << "breathing\n"; + else if( _s_lightmodes[i-1] == lightmode_rainbow ) + output << "rainbow\n"; + else if( _s_lightmodes[i-1] == lightmode_static ) + output << "static\n"; + else if( _s_lightmodes[i-1] == lightmode_wave ) + output << "wave\n"; + else if( _s_lightmodes[i-1] == lightmode_alternating ) + output << "alternating\n"; + else if( _s_lightmodes[i-1] == lightmode_reactive ) + output << "reactive\n"; + else if( _s_lightmodes[i-1] == lightmode_flashing ) + output << "flashing\n"; + else{ + output << "unknown, please report as bug\n"; + } + + // polling rate (report rate) + output << "\n"; + if( _s_report_rates[i-1] == r_125Hz ) + output << "report_rate=125\n"; + else if( _s_report_rates[i-1] == r_250Hz ) + output << "report_rate=250\n"; + else if( _s_report_rates[i-1] == r_500Hz ) + output << "report_rate=500\n"; + else if( _s_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)_s_scrollspeeds[i-1] << std::dec << "\n"; + + // dpi + output << "\n# DPI settings\n"; + for( int j = 1; j < 6; j++ ){ + + if( _s_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)_s_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 < 8; j++ ){ + + uint8_t b1 = _s_keymap_data[i-1][j][0]; + uint8_t b2 = _s_keymap_data[i-1][j][1]; + uint8_t b3 = _s_keymap_data[i-1][j][2]; + uint8_t b4 = _s_keymap_data[i-1][j][3]; + bool found_name = false; + + output << _c_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 _c_keyboard_key_values + for( auto keycode : _c_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 _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == b3 ){ + + output << keycode.first << "\n"; + found_name = true; + break; + + } + + } + + // modifiers + keyboard key + } else if( b1 == 0x8f ){ + + // iterate over _c_keyboard_modifier_values + for( auto modifier : _c_keyboard_modifier_values ){ + + if( modifier.second & b2 ){ + output << modifier.first; + } + + } + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == b3 ){ + + output << keycode.first << "\n"; + found_name = true; + break; + + } + + } + + } else{ // mousebutton or special function ? + + // iterate over _c_keycodes + for( auto keycode : _c_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( _s_macro_data[i][8] == 0 && _s_macro_data[i][9] == 0 && _s_macro_data[i][10] == 0 ) + continue; + + output << "\n;## macro" << i+1 << "\n"; + + for( long unsigned int j = 8; j < _s_macro_data[i].size(); ){ + + // failsafe + if( j >= _s_macro_data[i].size() ) + break; + + if( _s_macro_data[i][j] == 0x81 ){ // mouse button down + + if( _s_macro_data[i][j] == 0x01 ) + output << ";# down\tmouse_left\n"; + else if( _s_macro_data[i][j] == 0x02 ) + output << ";# down\tmouse_right\n"; + else if( _s_macro_data[i][j] == 0x04 ) + output << ";# down\tmouse_middle\n"; + else{ + output << ";# unknown, please report as bug: "; + output << std::hex << (int)_s_macro_data[i][j] << " "; + output << std::hex << (int)_s_macro_data[i][j+1] << " "; + output << std::hex << (int)_s_macro_data[i][j+2]; + output << std::dec << "\n"; + } + + } else if( _s_macro_data[i][j] == 0x01 ){ // mouse button up + + if( _s_macro_data[i][j] == 0x01 ) + output << ";# up\tmouse_left\n"; + else if( _s_macro_data[i][j] == 0x02 ) + output << ";# up\tmouse_right\n"; + else if( _s_macro_data[i][j] == 0x04 ) + output << ";# up\tmouse_middle\n"; + else{ + output << ";# unknown, please report as bug: "; + output << std::hex << (int)_s_macro_data[i][j] << " "; + output << std::hex << (int)_s_macro_data[i][j+1] << " "; + output << std::hex << (int)_s_macro_data[i][j+2]; + output << std::dec << "\n"; + } + + } else if( _s_macro_data[i][j] == 0x84 ){ // keyboard key down + + bool found_name = false; + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == _s_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)_s_macro_data[i][j] << " "; + output << std::hex << (int)_s_macro_data[i][j+1] << " "; + output << std::hex << (int)_s_macro_data[i][j+2]; + output << std::dec << "\n"; + } + + } else if( _s_macro_data[i][j] == 0x04 ){ // keyboard key up + + bool found_name = false; + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == _s_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)_s_macro_data[i][j] << " "; + output << std::hex << (int)_s_macro_data[i][j+1] << " "; + output << std::hex << (int)_s_macro_data[i][j+2]; + output << std::dec << "\n"; + } + + } else if( _s_macro_data[i][j] == 0x06 ){ // delay + + output << ";# delay\t" << (int)_s_macro_data[i][j+1] << "\n"; + + } else if( _s_macro_data[i][j] == 0x00 ){ // padding + + j++; + + } else{ + output << ";# unknown, please report as bug: "; + output << std::hex << (int)_s_macro_data[i][j] << " "; + output << std::hex << (int)_s_macro_data[i][j+1] << " "; + output << std::hex << (int)_s_macro_data[i][j+2]; + output << std::dec << "\n"; + } + + // increment + j+=3; + + } + + } + + return 0; +} diff --git a/include/m711/mouse_m711.h b/include/m711/mouse_m711.h new file mode 100644 index 0000000..4b5ba5f --- /dev/null +++ b/include/m711/mouse_m711.h @@ -0,0 +1,319 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +//main class +#ifndef MOUSE_M711 +#define MOUSE_M711 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../rd_mouse.h" + +/** + * The main class representing the M711 mouse. + * This class has member functions to open, close and apply settings to the mouse. + * + * There are 4 main types of functions: + * - set_*: setters + * - get_*: getters + * - write_*: write the settings to the mouse + * - read_*: read the sttings from the mouse + * + * Therefore the general procedure when changing settings on the mouse is as follows: + * 1. open_mouse() or open_mouse_bus_device() + * 2. set_* (this step only changes the internal state of the class) + * 3. write_* (this step sends the internal state of the class to the mouse) + * 4. close_mouse() + * + * Private member variables are named as follows: + * - \_i\_* for internal variables that determine how the mouse is opened, etc. + * - \_s\_* for variables that describe the settings on the mouse + * - \_c\_* for constants like keycodes, USB data, minimum and maximum values, etc. (these are not neccessarily defined as const) + */ +class mouse_m711 : public rd_mouse{ + + public: + + /// The default constructor. Sets the default settings. + mouse_m711(); + + //setter functions + /// Set the currently active profile + int set_profile( rd_profile profile ); + + /** \brief Set the scrollspeed for the specified profile + * \see _c_scrollspeed_min + * \see _c_scrollspeed_max + * \return 0 if successful, 1 if out of bounds + */ + int set_scrollspeed( rd_profile profile, uint8_t speed ); + + /** \brief Set the led mode for the specified profile + * \see rd_lightmode + * \return 0 if successful + */ + int set_lightmode( rd_profile profile, rd_lightmode lightmode ); + + /** \brief Set the led color for the specified profile + * \param color color as {r, g, b} + * \return 0 if successful + */ + int set_color( rd_profile profile, std::array color ); + + /** \brief Set the led brightness for the specified profile + * \see _c_brightness_min + * \see _c_brightness_max + * \return 0 if successful, 1 if out of bounds + */ + int set_brightness( rd_profile profile, uint8_t brightness ); + + /** \brief Set the led animation speed for the specified profile + * \see _c_speed_min + * \see _c_speed_max + * \return 0 if successful, 1 if out of bounds + */ + int set_speed( rd_profile profile, uint8_t speed ); + + /** \brief Enables/Disables a dpi level for the specified profile + * \see _c_level_min + * \see _c_level_max + * \return 0 if successful, 1 if out of bounds + */ + int set_dpi_enable( rd_profile profile, int level, bool enabled ); + + /** \brief Set the value of a dpi level for the specified profile + * \see _c_dpi_min + * \see _c_dpi_max + * \see _c_level_min + * \see _c_level_max + * \return 0 if successful, 1 if out of bounds + */ + int set_dpi( rd_profile profile, int level, uint8_t dpi ); + + /** \brief Set a mapping for a button for the specified profile + * \param mapping 4 bytes for the usb data packets + * \return 0 if successful + */ + int set_key_mapping( rd_profile profile, int key, std::array mapping ); + + /** \brief Set a mapping for a button for the specified profile + * \param mapping button name (see keymap.md) + * \return 0 if successful, 1 if mapping is invalid + */ + int set_key_mapping( rd_profile profile, int key, std::string mapping ); + + /** \brief Set the USB poll rate for the specified profile + * \see rd_report_rate + * \return 0 if successful + */ + int set_report_rate( rd_profile profile, rd_report_rate report_rate ); + + /** \brief Load the macro from the specified file into the specified slot + * \param macro_number macro slot (1-15) + * \return 0 if successful + */ + int set_macro( int macro_number, std::string file ); + + /** \brief Load all macros from the specified .ini file + * \return 0 if successful + */ + int set_all_macros( std::string file ); + + /** \brief Set how many times the specified macro should be repeated + * \param macro_number macro slot (1-15) + * \return 0 if successful + */ + int set_macro_repeat( int macro_number, uint8_t repeat ); + + /** \brief Set whether to try to detach the kernel driver when opening the mouse + */ + int set_detach_kernel_driver( bool detach_kernel_driver ); + + + + //getter functions + /// Get currently active profile + rd_profile get_profile(); + /// Get scrollspeed of specified profile + uint8_t get_scrollspeed( rd_profile profile ); + /// Get led mode of specified profile + rd_lightmode get_lightmode( rd_profile profile ); + /// Get led color of specified profile + void get_color( rd_profile profile, std::array &color ); + /// Get led brightness of specified profile + uint8_t get_brightness( rd_profile profile ); + /// Get led animation speed of specified profile + uint8_t get_speed( rd_profile profile ); + /// Get dpi level enabled/disabled status of specified profile + bool get_dpi_enable( rd_profile profile, int level ); + /// Get dpi value of specified level and profile + uint8_t get_dpi( rd_profile profile, int level ); + /// Get USB poll rate of specified profile + rd_report_rate get_report_rate( rd_profile profile ); + /// Get macro repeat number of specified profile + uint8_t get_macro_repeat( int macro_number ); + /// Get _i_detach_kernel_driver + bool get_detach_kernel_driver(); + /// Get button mapping as a string + int get_key_mapping( rd_profile profile, int key, std::string& mapping ); + /// Get button mapping as a 4-byte value + int get_key_mapping_raw( rd_profile profile, int key, std::array& mapping ); + /// Get macro as a string + int get_macro( int number, std::string& macro ); + /// Get raw macro bytecode + int get_macro_raw( int number, std::array& macro ); + + + //writer functions (apply settings to mouse) + /** \brief Write the currently active profile to the mouse + * \return 0 if successful + */ + int write_profile(); + + /** \brief Write the settings (leds, button mapping, dpi, etc.) to the mouse + * \return 0 if successful + */ + int write_settings(); + + /** \brief Write a macro to the mouse + * \return 0 if successful + */ + int write_macro( int macro_number ); + + /** \brief Write the number of repeats for a macro to the mouse + * \return 0 if successful + */ + int write_macro_repeat( int macro_number ); + + + + //helper functions + /** \brief Init libusb and open the mouse by its USB VID and PID + * \return 0 if successful + */ + int open_mouse(); + + /** \brief Init libusb and open the mouse by the USB bus and device adress + * \return 0 if successful + */ + int open_mouse_bus_device( uint8_t bus, uint8_t device ); + + /** \brief Close the mouse and libusb + * \return 0 if successful (always at the moment) + */ + 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) + /// Read the settings and print the raw data to output + int dump_settings( std::ostream& output ); + /** + * \brief Read the settings and print the configuration in .ini format to output. + * This does not alter the internal settings of the mouse_m711 class. + */ + int read_and_print_settings( std::ostream& output ); + /** + * \brief Read the settings and print the configuration in .ini format to output. + * This updates the internal settings of the mouse_m711 class. + */ + int read_settings(); + + + + /// Returns a reference to _c_button_names (physical button names) + std::map< int, std::string >& button_names(){ return _c_button_names; } + + private: + + /// Names of the physical buttons + static std::map< int, std::string > _c_button_names; + + /// whether to detach kernel driver + bool _i_detach_kernel_driver = true; + + //usb device vars + /// USB vendor id + static const uint16_t _c_mouse_vid; + /// USB product id + static const uint16_t _c_mouse_pid; + /// libusb device handle + libusb_device_handle* _i_handle; + /// set by open_mouse for close_mouse + bool _i_detached_driver_0 = false; + /// set by open_mouse for close_mouse + bool _i_detached_driver_1 = false; + /// set by open_mouse for close_mouse + bool _i_detached_driver_2 = false; + + //setting vars + rd_profile _s_profile; + std::array _s_scrollspeeds; + std::array _s_lightmodes; + std::array, 5> _s_colors; + std::array _s_brightness_levels; + std::array _s_speed_levels; + std::array, 5> _s_dpi_enabled; + std::array, 5> _s_dpi_levels; + std::array, 8>, 5> _s_keymap_data; + std::array _s_report_rates; + std::array, 15> _s_macro_data; + std::array _s_macro_repeat; + + //usb data packets + /// Used for changing the active profile + static uint8_t _c_data_s_profile[6][16]; + /// Used for sending the settings, part 1/3 + static uint8_t _c_data_settings_1[12][16]; + /// Used for sending the settings, part 2/3 + static uint8_t _c_data_settings_2[64]; + /// Used for sending the settings, part 3/3 + static uint8_t _c_data_settings_3[80][16]; + /// Used for sending a macro, part 1/3 + static uint8_t _c_data_macros_1[16]; + /// Used for sending a macro, part 2/3 + static uint8_t _c_data_macros_2[256]; + /// Used for sending a macro, part 3/3 + static uint8_t _c_data_macros_3[16]; + /// Lookup table used when specifying which slot to send a macro to + static uint8_t _c_data_macros_codes[15][2]; + /// Used to send the number repeats for a macro + static uint8_t _c_data_macros_repeat[16]; + /// Used to read the settings, part 1/3 + static uint8_t _c_data_read_1[9][16]; + /// Used to read the settings, part 2/3 + static uint8_t _c_data_read_2[85][64]; + /// Used to read the settings, part 3/3 + static uint8_t _c_data_read_3[46][16]; +}; + +#endif diff --git a/include/m711/readers.cpp b/include/m711/readers.cpp new file mode 100644 index 0000000..8af664e --- /dev/null +++ b/include/m711/readers.cpp @@ -0,0 +1,756 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "mouse_m711.h" + +//reader functions (get settings from mouse) + +int mouse_m711::dump_settings( std::ostream& output ){ + + //prepare data 1 + int rows1 = sizeof(_c_data_read_1) / sizeof(_c_data_read_1[0]); + uint8_t buffer1[rows1][16]; + for( int i = 0; i < rows1; i++ ){ + std::copy(std::begin(_c_data_read_1[i]), std::end(_c_data_read_1[i]), std::begin(buffer1[i])); + } + + //prepare data 2 + int rows2 = sizeof(_c_data_read_2) / sizeof(_c_data_read_2[0]); + uint8_t buffer2[rows2][64]; + for( int i = 0; i < rows2; i++ ){ + std::copy(std::begin(_c_data_read_2[i]), std::end(_c_data_read_2[i]), std::begin(buffer2[i])); + } + + //prepare data 3 + int rows3 = sizeof(_c_data_read_3) / sizeof(_c_data_read_3[0]); + uint8_t buffer3[rows3][16]; + for( int i = 0; i < rows3; i++ ){ + std::copy(std::begin(_c_data_read_3[i]), std::end(_c_data_read_3[i]), std::begin(buffer3[i])); + } + + output << "Part 1:\n\n"; + + //send data 1 + uint8_t buffer_in1[16]; + int num_bytes_in; + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer1[0], 16, 1000 ); + for( int i = 1; i < rows1; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer1[i], 16, 1000 ); + + // control in + num_bytes_in = libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0302, 0x0002, buffer_in1, 16, 1000 ); + + // hexdump + if ( num_bytes_in > 0 ){ + output << std::hex; + for( int j = 0; j < num_bytes_in; j++ ){ + output << std::setfill('0') << std::setw(2) << (int)buffer_in1[j] << " "; + } + output << "\n\n" << std::dec << std::setw(0) << std::setfill(' '); + } + } + + output << "Part 2:\n\n"; + + //send data 2 + uint8_t buffer_in2[64]; + for( int i = 0; i < rows2; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0303, 0x0002, buffer2[i], 64, 1000 ); + + // control in + num_bytes_in = libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0303, 0x0002, buffer_in2, 64, 1000 ); + + // hexdump + if ( num_bytes_in > 0 ){ + output << std::hex; + for( int j = 0; j < num_bytes_in; j++ ){ + output << std::setfill('0') << std::setw(2) << (int)buffer_in2[j] << " "; + } + output << "\n\n" << std::dec << std::setw(0) << std::setfill(' '); + } + } + + output << "Part 3:\n\n"; + + //send data 3 + uint8_t buffer_in3[16]; + for( int i = 0; i < rows3-1; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer3[i], 16, 1000 ); + + // control in + num_bytes_in = libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0302, 0x0002, buffer_in3, 16, 1000 ); + + // hexdump + if ( num_bytes_in > 0 ){ + output << std::hex; + for( int j = 0; j < num_bytes_in; j++ ){ + output << std::setfill('0') << std::setw(2) << (int)buffer_in3[j] << " "; + } + output << "\n\n" << std::dec << std::setw(0) << std::setfill(' '); + } + } + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer3[100], 16, 1000 ); + + return 0; +} + +int mouse_m711::read_and_print_settings( std::ostream& output ){ + + //prepare data 1 + int rows1 = sizeof(_c_data_read_1) / sizeof(_c_data_read_1[0]); + uint8_t buffer1[rows1][16]; + for( int i = 0; i < rows1; i++ ){ + std::copy(std::begin(_c_data_read_1[i]), std::end(_c_data_read_1[i]), std::begin(buffer1[i])); + } + + //prepare data 2 + int rows2 = sizeof(_c_data_read_2) / sizeof(_c_data_read_2[0]); + uint8_t buffer2[rows2][64]; + for( int i = 0; i < rows2; i++ ){ + std::copy(std::begin(_c_data_read_2[i]), std::end(_c_data_read_2[i]), std::begin(buffer2[i])); + } + + //prepare data 3 + int rows3 = sizeof(_c_data_read_3) / sizeof(_c_data_read_3[0]); + uint8_t buffer3[rows3][16]; + for( int i = 0; i < rows3; i++ ){ + std::copy(std::begin(_c_data_read_3[i]), std::end(_c_data_read_3[i]), std::begin(buffer3[i])); + } + + + //send data 1 + uint8_t buffer_in1[8][16] = {{0}}; + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer1[0], 16, 1000 ); + for( int i = 1; i < rows1; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer1[i], 16, 1000 ); + + // control in + libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0302, 0x0002, buffer_in1[i-1], 16, 1000 ); + + } + + //send data 2 + uint8_t buffer_in2[85][64] = {{0}}; + for( int i = 0; i < rows2; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0303, 0x0002, buffer2[i], 64, 1000 ); + + // control in + libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0303, 0x0002, buffer_in2[i], 64, 1000 ); + + } + + //send data 3 + uint8_t buffer_in3[45][16] = {{0}}; + for( int i = 0; i < rows3-1; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer3[i], 16, 1000 ); + + // control in + libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0302, 0x0002, buffer_in3[i], 16, 1000 ); + + } + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer3[100], 16, 1000 ); + + + // print configuration + output << "# Configuration created with mouse_m908 -R.\n"; + output << "# This configuration can be send to the mouse with mouse_m908 -c.\n"; + output << "# This feature is currently untested, please report your results.\n"; + output << "# Note: reading the scrollspeed is not supported by the mouse.\n"; + output << "\n# Currently active profile: " << (int)buffer_in1[0][8]+1 << "\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)buffer_in1[i][8]; + output << std::setfill('0') << std::setw(2) << std::hex << (int)buffer_in1[i][9]; + output << std::setfill('0') << std::setw(2) << std::hex << (int)buffer_in1[i][10]; + output << std::setfill(' ') << std::setw(0) << std::dec << "\n"; + + // brightness + output << "brightness=" << (int)buffer_in1[i][14] << "\n"; + + // speed + output << "speed=" << (int)buffer_in1[i][13] << "\n"; + + // lightmode + output << "lightmode="; + if( buffer_in1[i][11] == 0x00 && buffer_in1[i][13] == 0x00 ) + output << "off\n"; + else if( buffer_in1[i][11] == 0x01 && buffer_in1[i][13] == 0x04 ) + output << "breathing\n"; + else if( buffer_in1[i][11] == 0x01 && buffer_in1[i][13] == 0x08 ) + output << "rainbow\n"; + else if( buffer_in1[i][11] == 0x01 && buffer_in1[i][13] == 0x02 ) + output << "static\n"; + else if( buffer_in1[i][11] == 0x02 && buffer_in1[i][13] == 0x00 ) + output << "wave\n"; + else if( buffer_in1[i][11] == 0x06 && buffer_in1[i][13] == 0x00 ) + output << "alternating\n"; + else if( buffer_in1[i][11] == 0x07 && buffer_in1[i][13] == 0x00 ) + output << "reactive\n"; + else if( buffer_in1[i][11] == 0x01 && buffer_in1[i][13] == 0x10 ) + output << "flashing\n"; + else{ + output << "unknown, please report as bug: "; + output << std::hex << buffer_in1[i][11] << " "; + output << std::hex << buffer_in1[i][13] << std::dec << "\n"; + } + + // polling rate (report rate) + if( i < 4 ){ + + output << "\n"; + + if( buffer_in1[6][6+(2*i)] == 8 ) + output << "report_rate=125\n"; + else if( buffer_in1[6][6+(2*i)] == 4 ) + output << "report_rate=250\n"; + else if( buffer_in1[6][6+(2*i)] == 2 ) + output << "report_rate=500\n"; + else if( buffer_in1[6][6+(2*i)] == 1 ) + output << "report_rate=1000\n"; + else{ + output << "# report rate unknown, please report as bug: " + << (int)buffer_in1[6][6+(2*i)] << "\n"; + } + + } else{ + + output << "\n"; + + if( buffer_in1[7][(2*i)] == 8 ) + output << "report_rate=125\n"; + else if( buffer_in1[7][(2*i)] == 4 ) + output << "report_rate=250\n"; + else if( buffer_in1[7][(2*i)] == 2 ) + output << "report_rate=500\n"; + else if( buffer_in1[7][(2*i)] == 1 ) + output << "report_rate=1000\n"; + else{ + output << "# report rate unknown, please report as bug: " + << (int)buffer_in1[7][(2*i)] << "\n"; + } + + } + + + // dpi + output << "\n# DPI settings\n"; + output << "# Active dpi level for this profile: " << (int)buffer_in2[i-1][8]+1 << "\n"; + for( int j = 1; j < 6; j++ ){ + output << "dpi" << j << "_enable=" << (int)buffer_in2[i-1][4+(6*j)] << "\n"; + output << std::setfill('0') << std::setw(2) << std::hex; + output << "dpi" << j << "=" << (int)buffer_in2[i-1][5+(6*j)] << "\n"; + output << std::setfill(' ') << std::setw(0) << std::dec; + } + + output << "\n# Button mapping is not implemented due to a lack of captured data\n"; + /* Currently not implemented, missing captured data + * + // button mapping + output << "\n# Button mapping\n"; + + for( int j = 0; j < 8; j++ ){ + + uint8_t b1 = buffer_in3[j+(8*(i-1))][8]; + uint8_t b2 = buffer_in3[j+(8*(i-1))][9]; + uint8_t b3 = buffer_in3[j+(8*(i-1))][10]; + uint8_t b4 = buffer_in3[j+(8*(i-1))][11]; + bool found_name = false; + + output << _c_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 _c_keyboard_key_values + for( auto keycode : _c_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 _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == b3 ){ + + output << keycode.first << "\n"; + found_name = true; + break; + + } + + } + + // modifiers + keyboard key + } else if( b1 == 0x8f ){ + + // iterate over _c_keyboard_modifier_values + for( auto modifier : _c_keyboard_modifier_values ){ + + if( modifier.second & b2 ){ + output << modifier.first; + } + + } + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == b3 ){ + + output << keycode.first << "\n"; + found_name = true; + break; + + } + + } + + } else{ // mousebutton or special function ? + + // iterate over _c_keycodes + for( auto keycode : _c_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 + std::array< std::vector< uint8_t >, 15 > macro_bytes; + int macronumber = 1; + int counter = 0; + + // iterate over buffer_in2 + for( int i = 5; i < 85; i++ ){ + + // valid macronumber? + if( macronumber >= 1 && macronumber <= 15 ){ + + // extract bytes + for( int j = 8; j < 58; j++ ){ + macro_bytes[macronumber-1].push_back( buffer_in2[i][j] ); + } + + } + + // increment counter and macronumber + counter++; + if( counter == 4 ){ + counter = 0; + macronumber++; + } + + } + + // decode macros + output << "\n# Macros\n"; + for( int i = 0; i < 15; i++ ){ + + // macro undefined? + if( macro_bytes[i][0] == 0 && macro_bytes[i][1] == 0 && macro_bytes[i][2] == 0 ) + continue; + + output << "\n;## macro" << i+1 << "\n"; + + for( long unsigned int j = 0; j < macro_bytes[i].size(); ){ + + // failsafe + if( j >= macro_bytes[i].size() ) + break; + + if( macro_bytes[i][j] == 0x81 ){ // mouse button down + + if( macro_bytes[i][j] == 0x01 ) + output << ";# down\tmouse_left\n"; + else if( macro_bytes[i][j] == 0x02 ) + output << ";# down\tmouse_right\n"; + else if( macro_bytes[i][j] == 0x04 ) + output << ";# down\tmouse_middle\n"; + else{ + output << ";# unknown, please report as bug: "; + output << std::hex << (int)macro_bytes[i][j] << " "; + output << std::hex << (int)macro_bytes[i][j+1] << " "; + output << std::hex << (int)macro_bytes[i][j+2]; + output << std::dec << "\n"; + } + + } else if( macro_bytes[i][j] == 0x01 ){ // mouse button up + + if( macro_bytes[i][j] == 0x01 ) + output << ";# up\tmouse_left\n"; + else if( macro_bytes[i][j] == 0x02 ) + output << ";# up\tmouse_right\n"; + else if( macro_bytes[i][j] == 0x04 ) + output << ";# up\tmouse_middle\n"; + else{ + output << ";# unknown, please report as bug: "; + output << std::hex << (int)macro_bytes[i][j] << " "; + output << std::hex << (int)macro_bytes[i][j+1] << " "; + output << std::hex << (int)macro_bytes[i][j+2]; + output << std::dec << "\n"; + } + + } else if( macro_bytes[i][j] == 0x84 ){ // keyboard key down + + bool found_name = false; + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == macro_bytes[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_bytes[i][j] << " "; + output << std::hex << (int)macro_bytes[i][j+1] << " "; + output << std::hex << (int)macro_bytes[i][j+2]; + output << std::dec << "\n"; + } + + } else if( macro_bytes[i][j] == 0x04 ){ // keyboard key up + + bool found_name = false; + + // iterate over _c_keyboard_key_values + for( auto keycode : _c_keyboard_key_values ){ + + if( keycode.second == macro_bytes[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_bytes[i][j] << " "; + output << std::hex << (int)macro_bytes[i][j+1] << " "; + output << std::hex << (int)macro_bytes[i][j+2]; + output << std::dec << "\n"; + } + + } else if( macro_bytes[i][j] == 0x06 ){ // delay + + output << ";# delay\t" << (int)macro_bytes[i][j+1] << "\n"; + + } else if( macro_bytes[i][j] == 0x00 ){ // padding + + j++; + + } else{ + output << ";# unknown, please report as bug: "; + output << std::hex << (int)macro_bytes[i][j] << " "; + output << std::hex << (int)macro_bytes[i][j+1] << " "; + output << std::hex << (int)macro_bytes[i][j+2]; + output << std::dec << "\n"; + } + + // increment + j+=3; + + } + + } + + return 0; +} + +int mouse_m711::read_settings(){ + + //prepare data 1 + int rows1 = sizeof(_c_data_read_1) / sizeof(_c_data_read_1[0]); + uint8_t buffer1[rows1][16]; + for( int i = 0; i < rows1; i++ ){ + std::copy(std::begin(_c_data_read_1[i]), std::end(_c_data_read_1[i]), std::begin(buffer1[i])); + } + + //prepare data 2 + int rows2 = sizeof(_c_data_read_2) / sizeof(_c_data_read_2[0]); + uint8_t buffer2[rows2][64]; + for( int i = 0; i < rows2; i++ ){ + std::copy(std::begin(_c_data_read_2[i]), std::end(_c_data_read_2[i]), std::begin(buffer2[i])); + } + + //prepare data 3 + int rows3 = sizeof(_c_data_read_3) / sizeof(_c_data_read_3[0]); + uint8_t buffer3[rows3][16]; + for( int i = 0; i < rows3; i++ ){ + std::copy(std::begin(_c_data_read_3[i]), std::end(_c_data_read_3[i]), std::begin(buffer3[i])); + } + + + //send data 1 + uint8_t buffer_in1[8][16] = {{0}}; + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer1[0], 16, 1000 ); + for( int i = 1; i < rows1; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer1[i], 16, 1000 ); + + // control in + libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0302, 0x0002, buffer_in1[i-1], 16, 1000 ); + + } + + //send data 2 + uint8_t buffer_in2[85][64] = {{0}}; + for( int i = 0; i < rows2; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0303, 0x0002, buffer2[i], 64, 1000 ); + + // control in + libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0303, 0x0002, buffer_in2[i], 64, 1000 ); + + } + + //send data 3 + uint8_t buffer_in3[45][16] = {{0}}; + for( int i = 0; i < rows3-1; i++ ){ + // control out + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer3[i], 16, 1000 ); + + // control in + libusb_control_transfer( _i_handle, 0xa1, 0x01, 0x0302, 0x0002, buffer_in3[i], 16, 1000 ); + + } + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer3[100], 16, 1000 ); + + // parse received data + + if( buffer_in1[0][8]+1 == 1 ) + _s_profile = profile_1; + if( buffer_in1[0][8]+1 == 2 ) + _s_profile = profile_2; + if( buffer_in1[0][8]+1 == 3 ) + _s_profile = profile_3; + if( buffer_in1[0][8]+1 == 4 ) + _s_profile = profile_4; + if( buffer_in1[0][8]+1 == 5 ) + _s_profile = profile_5; + + for( int i = 1; i < 6; i++ ){ + + // color + _s_colors[i-1][0] = buffer_in1[i][8]; + _s_colors[i-1][1] = buffer_in1[i][9]; + _s_colors[i-1][2] = buffer_in1[i][10]; + + // brightness + _s_brightness_levels[i-1] = buffer_in1[i][14]; + + // speed + _s_speed_levels[i-1] = buffer_in1[i][13]; + + // lightmode + if( buffer_in1[i][11] == 0x00 && buffer_in1[i][13] == 0x00 ) + _s_lightmodes[i-1] = lightmode_off; + else if( buffer_in1[i][11] == 0x01 && buffer_in1[i][13] == 0x04 ) + _s_lightmodes[i-1] = lightmode_breathing; + else if( buffer_in1[i][11] == 0x01 && buffer_in1[i][13] == 0x08 ) + _s_lightmodes[i-1] = lightmode_rainbow; + else if( buffer_in1[i][11] == 0x01 && buffer_in1[i][13] == 0x02 ) + _s_lightmodes[i-1] = lightmode_static; + else if( buffer_in1[i][11] == 0x02 && buffer_in1[i][13] == 0x00 ) + _s_lightmodes[i-1] = lightmode_wave; + else if( buffer_in1[i][11] == 0x06 && buffer_in1[i][13] == 0x00 ) + _s_lightmodes[i-1] = lightmode_alternating; + else if( buffer_in1[i][11] == 0x07 && buffer_in1[i][13] == 0x00 ) + _s_lightmodes[i-1] = lightmode_reactive; + else if( buffer_in1[i][11] == 0x01 && buffer_in1[i][13] == 0x10 ) + _s_lightmodes[i-1] = lightmode_flashing; + + // polling rate (report rate) + if( i < 4 ){ + + if( buffer_in1[6][6+(2*i)] == 8 ) + _s_report_rates[i-1] = r_125Hz; + else if( buffer_in1[6][6+(2*i)] == 4 ) + _s_report_rates[i-1] = r_250Hz; + else if( buffer_in1[6][6+(2*i)] == 2 ) + _s_report_rates[i-1] = r_500Hz; + else if( buffer_in1[6][6+(2*i)] == 1 ) + _s_report_rates[i-1] = r_1000Hz; + + } else{ + + if( buffer_in1[7][(2*i)] == 8 ) + _s_report_rates[i-1] = r_125Hz; + else if( buffer_in1[7][(2*i)] == 4 ) + _s_report_rates[i-1] = r_250Hz; + else if( buffer_in1[7][(2*i)] == 2 ) + _s_report_rates[i-1] = r_500Hz; + else if( buffer_in1[7][(2*i)] == 1 ) + _s_report_rates[i-1] = r_1000Hz; + + } + + + // dpi + for( int j = 1; j < 6; j++ ){ + + if( buffer_in2[i-1][4+(6*j)] ) + _s_dpi_enabled[i-1][j-1] = true; + else + _s_dpi_enabled[i-1][j-1] = false; + + _s_dpi_levels[i-1][j-1] = buffer_in2[i-1][5+(6*j)]; + + } + + /* Currently not implemented, missing captured data + * + // button mapping + for( int j = 0; j < 8; j++ ){ + + _s_keymap_data[i-1][j][0] = buffer_in3[j+(8*(i-1))][8]; + _s_keymap_data[i-1][j][1] = buffer_in3[j+(8*(i-1))][9]; + _s_keymap_data[i-1][j][2] = buffer_in3[j+(8*(i-1))][10]; + _s_keymap_data[i-1][j][3] = buffer_in3[j+(8*(i-1))][11]; + + } + * + */ + } + + // macros + + // macros + std::array< std::vector< uint8_t >, 15 > macro_bytes; + int macronumber = 1; + int counter = 0; + + // iterate over buffer_in2 + for( int i = 5; i < 85; i++ ){ + + // This appears to be wrong + //int macronumber = buffer_in2[i][3] - 0x63; + + // valid macronumber? + if( macronumber >= 1 && macronumber <= 15 ){ + + // extract bytes + for( int j = 8; j < 58; j++ ){ // iterate over individual packet + macro_bytes[macronumber-1].push_back( buffer_in2[i][j] ); + } + + } + + // increment counter and macronumber + counter++; + if( counter == 4 ){ + counter = 0; + macronumber++; + } + + } + + // store extracted bytes in _s_macro_data + for( int i = 0; i < 15; i++ ){ // for each macro in macro_bytes + + // for each byte in the macro + for( unsigned int j = 0; j < macro_bytes[i].size(); j++ ){ + + // failsafe + if( j >= (_s_macro_data[i].size()+8) ) + break; + + _s_macro_data[i][j+8] = macro_bytes[i][j]; + + } + + } + + return 0; +} diff --git a/include/m711/setters.cpp b/include/m711/setters.cpp new file mode 100644 index 0000000..dfb4b9f --- /dev/null +++ b/include/m711/setters.cpp @@ -0,0 +1,418 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "mouse_m711.h" + +//setter functions + +int mouse_m711::set_profile( rd_profile profile ){ + _s_profile = profile; + return 0; +} + +int mouse_m711::set_scrollspeed( rd_profile profile, uint8_t speed ){ + + //check if bounds exceeded + if( speed < _c_scrollspeed_min || speed > _c_scrollspeed_max ){ + return 1; + } + + _s_scrollspeeds[profile] = speed; + + return 0; +} + +int mouse_m711::set_lightmode( rd_profile profile, rd_lightmode lightmode ){ + _s_lightmodes[profile] = lightmode; + return 0; +} + +int mouse_m711::set_color( rd_profile profile, std::array color ){ + _s_colors[profile] = color; + return 0; +} + +int mouse_m711::set_brightness( rd_profile profile, uint8_t brightness ){ + + //check bounds + if( brightness < _c_brightness_min || brightness > _c_brightness_max ){ + return 1; + } + + _s_brightness_levels[profile] = brightness; + return 0; +} + +int mouse_m711::set_speed( rd_profile profile, uint8_t speed ){ + + //check bounds + if( speed < _c_speed_min || speed > _c_speed_max ){ + return 1; + } + + _s_speed_levels[profile] = speed; + return 0; +} + +int mouse_m711::set_dpi_enable( rd_profile profile, int level, bool enabled ){ + + //check bounds + if( level < _c_level_min || level > _c_level_max ){ + return 1; + } + + _s_dpi_enabled[profile][level] = enabled; + + // check if at least one level enabled + int sum = 0; + for( int i = _c_level_min; i <= _c_level_max; i++ ){ + if( _s_dpi_enabled[profile][i] ){ + sum++; + } + } + + // if no level enabled: reenable specified level + if( sum == 0 ){ + _s_dpi_enabled[profile][level] = true; + return 1; + } + + return 0; +} + +int mouse_m711::set_dpi( rd_profile profile, int level, uint8_t dpi ){ + + //check bounds + if( dpi < _c_dpi_min || dpi > _c_dpi_max ){ + return 1; + } + + _s_dpi_levels[profile][level] = dpi; + return 0; +} + +int mouse_m711::set_key_mapping( rd_profile profile, int key, std::array mapping ){ + _s_keymap_data[profile][key][0] = mapping[0]; + _s_keymap_data[profile][key][1] = mapping[1]; + _s_keymap_data[profile][key][2] = mapping[2]; + _s_keymap_data[profile][key][3] = mapping[3]; + return 0; +} + +int mouse_m711::set_key_mapping( rd_profile profile, int key, std::string mapping ){ + + // valid key ? + if( _c_button_names[key] == "" ) + return 1; + + // is string in _c_keycodes? mousebuttons/special functions and media controls + if( _c_keycodes.find(mapping) != _c_keycodes.end() ){ + _s_keymap_data[profile][key][0] = _c_keycodes[mapping][0]; + _s_keymap_data[profile][key][1] = _c_keycodes[mapping][1]; + _s_keymap_data[profile][key][2] = _c_keycodes[mapping][2]; + _s_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; + + // 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, ':' ); + 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( _c_keyboard_key_values.find(value1) != _c_keyboard_key_values.end() ){ + keycode = _c_keyboard_key_values[value1]; + } else{ + return 1; + } + + repeats = (uint8_t)stoi(value2); + delay = (uint8_t)stoi(value3); + + // store values + _s_keymap_data[profile][key][0] = 0x99; + _s_keymap_data[profile][key][1] = keycode; + _s_keymap_data[profile][key][2] = repeats; + _s_keymap_data[profile][key][3] = delay; + + } else{ + // string is not a key in _c_keycodes: keyboard key? + + // search for modifiers and change values accordingly: ctrl, shift ... + uint8_t first_value = 0x90; + uint8_t modifier_value = 0x00; + for( auto i : _c_keyboard_modifier_values ){ + if( mapping.find( i.first ) != std::string::npos ){ + modifier_value += i.second; + first_value = 0x8f; + } + } + + // get key value and store everything + try{ + std::regex modifier_regex ("[a-z_]*\\+"); + // store values + _s_keymap_data[profile][key][0] = first_value; + _s_keymap_data[profile][key][1] = modifier_value; + _s_keymap_data[profile][key][2] = _c_keyboard_key_values[std::regex_replace( mapping, modifier_regex, "" )]; + _s_keymap_data[profile][key][3] = 0x00; + //std::cout << std::regex_replace( mapping, modifier_regex, "" ) << "\n"; + } catch( std::exception& f ){ + return 1; + } + } + + return 0; +} + +int mouse_m711::set_report_rate( rd_profile profile, rd_report_rate report_rate ){ + _s_report_rates[profile] = report_rate; + return 0; +} + + +int mouse_m711::set_macro( int macro_number, std::string file ){ + + //check if macro_number is valid + if( macro_number < 1 || macro_number > 15 ){ + return 1; + } + + //open file + std::ifstream config_in( file ); + if( !config_in.is_open() ){ + return 1; + } + + //process file + std::string value1 = ""; + std::string value2 = ""; + std::size_t position = 0; + int data_offset = 8; + + for( std::string line; std::getline(config_in, line); ){ + //process individual line + if( line.length() != 0 ){ + + position = 0; + position = line.find("\t", position); + value1 = line.substr(0, position); + value2 = line.substr(position+1); + + if( value1 == "down" && _c_keyboard_key_values.find(value2) != _c_keyboard_key_values.end() ){ + // keyboard key down + //std::cout << "down\n"; + _s_macro_data[macro_number-1][data_offset] = 0x84; + _s_macro_data[macro_number-1][data_offset+1] = _c_keyboard_key_values[value2]; + data_offset += 3; + } else if( value1 == "up" && _c_keyboard_key_values.find(value2) != _c_keyboard_key_values.end() ){ + // keyboard key up + //std::cout << "up\n"; + _s_macro_data[macro_number-1][data_offset] = 0x04; + _s_macro_data[macro_number-1][data_offset+1] = _c_keyboard_key_values[value2]; + data_offset += 3; + } else if( value1 == "down" && _c_keyboard_key_values.find(value2) == _c_keyboard_key_values.end() ){ + // mouse button down + //std::cout << "mouse down\n"; + if( value2 == "mouse_left" ){ + _s_macro_data[macro_number-1][data_offset] = 0x81; + _s_macro_data[macro_number-1][data_offset+1] = 0x01; + data_offset += 3; + } else if( value2 == "mouse_right" ){ + _s_macro_data[macro_number-1][data_offset] = 0x81; + _s_macro_data[macro_number-1][data_offset+1] = 0x02; + data_offset += 3; + } else if( value2 == "mouse_middle" ){ + _s_macro_data[macro_number-1][data_offset] = 0x81; + _s_macro_data[macro_number-1][data_offset+1] = 0x04; + data_offset += 3; + } + } else if( value1 == "up" && _c_keyboard_key_values.find(value2) == _c_keyboard_key_values.end() ){ + // mouse button up + //std::cout << "mouse up\n"; + if( value2 == "mouse_left" ){ + _s_macro_data[macro_number-1][data_offset] = 0x01; + _s_macro_data[macro_number-1][data_offset+1] = 0x01; + data_offset += 3; + } else if( value2 == "mouse_right" ){ + _s_macro_data[macro_number-1][data_offset] = 0x01; + _s_macro_data[macro_number-1][data_offset+1] = 0x02; + data_offset += 3; + } else if( value2 == "mouse_middle" ){ + _s_macro_data[macro_number-1][data_offset] = 0x01; + _s_macro_data[macro_number-1][data_offset+1] = 0x04; + data_offset += 3; + } + } else if( value1 == "delay" ){ + // delay + //std::cout << "delay\n"; + int duration = (uint8_t)stoi( value2, 0, 10); + if( duration >= 1 && duration <= 255 ){ + _s_macro_data[macro_number-1][data_offset] = 0x06; + _s_macro_data[macro_number-1][data_offset+1] = duration; + data_offset += 3; + } + } + + if(data_offset > 212){ + return 0; + } + + } + } + + return 0; +} + +int mouse_m711::set_macro_repeat( int macro_number, uint8_t repeat ){ + + //check if macro_number is valid + if( macro_number < 1 || macro_number > 15 ){ + return 1; + } + + _s_macro_repeat[macro_number] = repeat; + return 0; +} + +int mouse_m711::set_detach_kernel_driver( bool detach_kernel_driver ){ + + _i_detach_kernel_driver = detach_kernel_driver; + return 0; +} + + +int mouse_m711::set_all_macros( std::string file ){ + + //open file + std::ifstream config_in( file ); + if( !config_in.is_open() ){ + return 1; + } + + //process file + std::string value1 = ""; + std::string value2 = ""; + std::size_t position = 0; + int data_offset = 8; + int macro_number = 0; // initially invalid + + for( std::string line; std::getline(config_in, line); ){ + + // empty line → skip + if( line.length() == 0 ) + continue; + + // macro header → set macro_number, reset data_offset + if( std::regex_match( line, std::regex(";## macro[0-9]*") ) ){ + macro_number = stoi( std::regex_replace( line, std::regex(";## macro"), "" ), 0, 10 ); + data_offset = 8; + } + + // macro action + if( std::regex_match( line, std::regex(";# .*") ) ){ + + // valid macronumber ? + if( macro_number < 1 || macro_number > 15 ) + continue; + + // maximum size reached + if(data_offset > 212) + continue; + + // get action string + std::string action = std::regex_replace( line, std::regex(";# "), "" ); + + // get value substrings + position = 0; + position = action.find("\t", position); + value1 = action.substr(0, position); + value2 = action.substr(position+1); + + // encode values + if( value1 == "down" && _c_keyboard_key_values.find(value2) != _c_keyboard_key_values.end() ){ + // keyboard key down + //std::cout << "down\n"; + _s_macro_data[macro_number-1][data_offset] = 0x84; + _s_macro_data[macro_number-1][data_offset+1] = _c_keyboard_key_values[value2]; + data_offset += 3; + } else if( value1 == "up" && _c_keyboard_key_values.find(value2) != _c_keyboard_key_values.end() ){ + // keyboard key up + //std::cout << "up\n"; + _s_macro_data[macro_number-1][data_offset] = 0x04; + _s_macro_data[macro_number-1][data_offset+1] = _c_keyboard_key_values[value2]; + data_offset += 3; + } else if( value1 == "down" && _c_keyboard_key_values.find(value2) == _c_keyboard_key_values.end() ){ + // mouse button down + //std::cout << "mouse down\n"; + if( value2 == "mouse_left" ){ + _s_macro_data[macro_number-1][data_offset] = 0x81; + _s_macro_data[macro_number-1][data_offset+1] = 0x01; + data_offset += 3; + } else if( value2 == "mouse_right" ){ + _s_macro_data[macro_number-1][data_offset] = 0x81; + _s_macro_data[macro_number-1][data_offset+1] = 0x02; + data_offset += 3; + } else if( value2 == "mouse_middle" ){ + _s_macro_data[macro_number-1][data_offset] = 0x81; + _s_macro_data[macro_number-1][data_offset+1] = 0x04; + data_offset += 3; + } + } else if( value1 == "up" && _c_keyboard_key_values.find(value2) == _c_keyboard_key_values.end() ){ + // mouse button up + //std::cout << "mouse up\n"; + if( value2 == "mouse_left" ){ + _s_macro_data[macro_number-1][data_offset] = 0x01; + _s_macro_data[macro_number-1][data_offset+1] = 0x01; + data_offset += 3; + } else if( value2 == "mouse_right" ){ + _s_macro_data[macro_number-1][data_offset] = 0x01; + _s_macro_data[macro_number-1][data_offset+1] = 0x02; + data_offset += 3; + } else if( value2 == "mouse_middle" ){ + _s_macro_data[macro_number-1][data_offset] = 0x01; + _s_macro_data[macro_number-1][data_offset+1] = 0x04; + data_offset += 3; + } + } else if( value1 == "delay" ){ + // delay + //std::cout << "delay\n"; + int duration = (uint8_t)stoi( value2, 0, 10); + if( duration >= 1 && duration <= 255 ){ + _s_macro_data[macro_number-1][data_offset] = 0x06; + _s_macro_data[macro_number-1][data_offset+1] = duration; + data_offset += 3; + } + } + + } + + } + + return 0; +} diff --git a/include/m711/writers.cpp b/include/m711/writers.cpp new file mode 100644 index 0000000..ba46bdf --- /dev/null +++ b/include/m711/writers.cpp @@ -0,0 +1,253 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "mouse_m711.h" + +//writer functions (apply changes to mouse) + +int mouse_m711::write_profile(){ + + //prepare data + uint8_t buffer[6][16]; + for( int i = 0; i < 6; i++ ){ + std::copy(std::begin(_c_data_s_profile[i]), std::end(_c_data_s_profile[i]), std::begin(buffer[i])); + } + + //modify buffer from default to include specified profile + buffer[0][8] = _s_profile; + + //send data + for( int i = 0; i < 6; i++ ){ + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer[i], 16, 1000 ); + } + + return 0; +} + +int mouse_m711::write_settings(){ + + //prepare data 1 + int rows1 = sizeof(_c_data_settings_1) / sizeof(_c_data_settings_1[0]); + uint8_t buffer1[rows1][16]; + for( int i = 0; i < rows1; i++ ){ + std::copy(std::begin(_c_data_settings_1[i]), std::end(_c_data_settings_1[i]), std::begin(buffer1[i])); + } + + /* Currently no data capture available + * + //prepare data 2 + uint8_t buffer2[64]; + std::copy(std::begin(_c_data_settings_2), std::end(_c_data_settings_2), std::begin(buffer2)); + + //prepare data 3 + int rows3 = sizeof(_c_data_settings_3) / sizeof(_c_data_settings_3[0]); + uint8_t buffer3[rows3][16]; + for( int i = 0; i < rows3; i++ ){ + std::copy(std::begin(_c_data_settings_3[i]), std::end(_c_data_settings_3[i]), std::begin(buffer3[i])); + } + * + */ + + //modify buffers to include settings + + /* Currently no data capture available + * + //scrollspeed + for( int i = 0; i < 5; i++ ){ + buffer2[8+(2*i)] = _s_scrollspeeds[i]; + } + * + */ + + //lightmode + for( int i = 0; i < 5; i++ ){ + switch( _s_lightmodes[i] ){ + case lightmode_breathing: + buffer1[1+(2*i)][11] = 0x01; + buffer1[1+(2*i)][13] = 0x04; + break; + case lightmode_rainbow: + buffer1[1+(2*i)][11] = 0x01; + buffer1[1+(2*i)][13] = 0x08; + break; + case lightmode_static: + default: + buffer1[1+(2*i)][11] = 0x01; + buffer1[1+(2*i)][13] = 0x02; + break; + case lightmode_wave: + buffer1[1+(2*i)][11] = 0x02; + buffer1[1+(2*i)][13] = 0x00; + break; + case lightmode_alternating: + buffer1[1+(2*i)][11] = 0x06; + buffer1[1+(2*i)][13] = 0x00; + break; + case lightmode_reactive: + buffer1[1+(2*i)][11] = 0x07; + buffer1[1+(2*i)][13] = 0x00; + break; + case lightmode_flashing: + buffer1[1+(2*i)][11] = 0x01; + buffer1[1+(2*i)][13] = 0x10; + break; + case lightmode_off: + buffer1[1+(2*i)][11] = 0x00; + buffer1[1+(2*i)][13] = 0x00; + break; + } + } + //color + for( int i = 0; i < 5; i++ ){ + buffer1[1+(2*i)][8] = _s_colors[i].at(0); + buffer1[1+(2*i)][9] = _s_colors[i].at(1); + buffer1[1+(2*i)][10] = _s_colors[i].at(2); + } + //brightness + for( int i = 0; i < 5; i++ ){ + buffer1[2+(2*i)][8] = _s_brightness_levels[i]; + } + //speed + for( int i = 0; i < 5; i++ ){ + buffer1[1+(2*i)][12] = _s_speed_levels[i]; + } + + /* Currently no data capture available + * + //dpi + for( int i = 0; i < 5; i++ ){ + for( int j = 0; j < 5; j++ ){ + buffer3[7+(5*i)+j][8] = _s_dpi_enabled[j][i]; + buffer3[7+(5*i)+j][9] = _s_dpi_levels[j][i]; + } + } + + //key mapping + for( int i = 0; i < 5; i++ ){ + for( int j = 0; j < 8; j++ ){ + buffer3[35+(8*i)+j][8] = _s_keymap_data[i][j][0]; + buffer3[35+(8*i)+j][9] = _s_keymap_data[i][j][1]; + buffer3[35+(8*i)+j][10] = _s_keymap_data[i][j][2]; + buffer3[35+(8*i)+j][11] = _s_keymap_data[i][j][3]; + //std::cout << (int)_s_keymap_data[i][j][0] << " " << (int)_s_keymap_data[i][j][1] << " " << (int)_s_keymap_data[i][j][2] << " " << (int)_s_keymap_data[i][j][3] << "\n"; + } + } + * + */ + + /* Currently no data capture available + * + //usb report rate + for( int i = 0; i < 3; i++ ){ + switch( _s_report_rates[i] ){ + default: + case r_125Hz: + buffer1[13][8+(2*i)] = 0x08; break; + case r_250Hz: + buffer1[13][8+(2*i)] = 0x04; break; + case r_500Hz: + buffer1[13][8+(2*i)] = 0x02; break; + case r_1000Hz: + buffer1[13][8+(2*i)] = 0x01; break; + } + } + for( int i = 3; i < 5; i++ ){ + switch( _s_report_rates[i] ){ + default: + case r_125Hz: + buffer1[14][2+(2*i)] = 0x08; break; + case r_250Hz: + buffer1[14][2+(2*i)] = 0x04; break; + case r_500Hz: + buffer1[14][2+(2*i)] = 0x02; break; + case r_1000Hz: + buffer1[14][2+(2*i)] = 0x01; break; + } + } + * + */ + + //send data 1 + for( int i = 0; i < rows1; i++ ){ + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer1[i], 16, 1000 ); + } + + /* Currently no data capture available + * + //send data 2 + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer2, 64, 1000 ); + + //send data 3 + for( int i = 0; i < rows3; i++ ){ + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer3[i], 16, 1000 ); + } + * + */ + + return 0; +} + +int mouse_m711::write_macro( int macro_number ){ + + //check if macro_number is valid + if( macro_number < 1 || macro_number > 15 ){ + return 1; + } + + //prepare data 1 + uint8_t buffer1[16]; + std::copy(std::begin(_c_data_macros_1), std::end(_c_data_macros_1), std::begin(buffer1)); + + //prepare data 2 + uint8_t buffer2[265]; + std::copy(std::begin(_s_macro_data[macro_number-1]), std::end(_s_macro_data[macro_number-1]), std::begin(buffer2)); + + //prepare data 3 + uint8_t buffer3[16]; + std::copy(std::begin(_c_data_macros_3), std::end(_c_data_macros_3), std::begin(buffer3)); + + //send data 1 + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer1, 16, 1000 ); + + //send data 2 + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer2, 256, 1000 ); + + //send data 3 + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer3, 16, 1000 ); + + return 0; +} + +int mouse_m711::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(_c_data_macros_repeat), std::end(_c_data_macros_repeat), std::begin(buffer)); + + buffer[10] = _s_macro_repeat[macro_number]; + + //send data + libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0302, 0x0002, buffer, 16, 1000 ); + + return 0; +} diff --git a/include/print_help.cpp b/include/print_help.cpp index 5b6ed4f..a5e81ba 100644 --- a/include/print_help.cpp +++ b/include/print_help.cpp @@ -36,6 +36,6 @@ void print_help(){ std::cout << "-v --version\n\tPrint version.\n"; std::cout << "-R --read=arg\n\tRead settings from the mouse and print configuration to the specified file (\"-\" = stdout).\n"; std::cout << "-D --dump=arg\n\tRead settings from the mouse and dump the raw data to the specified file (\"-\" = stdout).\n"; - std::cout << "-M --model=arg\n\tSpecifies the mouse model (709, 908).\n"; + std::cout << "-M --model=arg\n\tSpecifies the mouse model (709, 711, 908).\n"; //std::cout << "-r --repeat\n\tSets number of times the macro will be repeated (1-255).\n"; } diff --git a/include/rd_mouse.h b/include/rd_mouse.h index ad1cbf4..7179347 100644 --- a/include/rd_mouse.h +++ b/include/rd_mouse.h @@ -96,5 +96,6 @@ class rd_mouse{ // include header files for the individual models #include "m908/mouse_m908.h" #include "m709/mouse_m709.h" +#include "m711/mouse_m711.h" #endif diff --git a/makefile b/makefile index 4f81b73..8e1e6f2 100644 --- a/makefile +++ b/makefile @@ -13,7 +13,7 @@ LIBS != pkg-config --libs libusb-1.0 VERSION_STRING = "\"2.2\"" # compile -build: m908 m709 data_rd.o load_config.o mouse_m908.o +build: m908 m709 m711 data_rd.o load_config.o mouse_m908.o $(CC) *.o -o mouse_m908 $(LIBS) $(CC_OPTIONS) # copy all files to their correct location @@ -63,11 +63,13 @@ hpkg: package create -b mouse_m908.hpkg; \ package add mouse_m908.hpkg bin documentation -# targets for different mice +# targets for the different mice m908: constructor_m908.o data_m908.o getters_m908.o helpers_m908.o setters_m908.o writers_m908.o readers_m908.o m709: constructor_m709.o data_m709.o getters_m709.o helpers_m709.o setters_m709.o writers_m709.o readers_m709.o +m711: constructor_m711.o data_m711.o getters_m711.o helpers_m711.o setters_m711.o writers_m711.o readers_m711.o + # individual files mouse_m908.o: $(CC) -c mouse_m908.cpp $(CC_OPTIONS) -D VERSION_STRING=$(VERSION_STRING) @@ -119,3 +121,24 @@ writers_m709.o: readers_m709.o: $(CC) -c include/m709/readers.cpp $(CC_OPTIONS) -o readers_m709.o + +constructor_m711.o: + $(CC) -c include/m711/constructor.cpp $(CC_OPTIONS) -o constructor_m711.o + +data_m711.o: + $(CC) -c include/m711/data.cpp $(CC_OPTIONS) -o data_m711.o + +getters_m711.o: + $(CC) -c include/m711/getters.cpp $(CC_OPTIONS) -o getters_m711.o + +helpers_m711.o: + $(CC) -c include/m711/helpers.cpp $(CC_OPTIONS) -o helpers_m711.o + +setters_m711.o: + $(CC) -c include/m711/setters.cpp $(CC_OPTIONS) -o setters_m711.o + +writers_m711.o: + $(CC) -c include/m711/writers.cpp $(CC_OPTIONS) -o writers_m711.o + +readers_m711.o: + $(CC) -c include/m711/readers.cpp $(CC_OPTIONS) -o readers_m711.o diff --git a/mouse_m908.1 b/mouse_m908.1 index f75a3ec..60136ae 100644 --- a/mouse_m908.1 +++ b/mouse_m908.1 @@ -1,6 +1,6 @@ .TH MOUSE_M908 1 .SH NAME -mouse_m908 \- control the Redragon M908 Impact and M709 gaming mice +mouse_m908 \- control the Redragon M908 Impact, M709 and M711 gaming mice .SH SYNOPSIS .B mouse_m908 [\fIOPTIONS\fR]... \fB\-c\fR \fIFILE\fR @@ -14,7 +14,7 @@ mouse_m908 \- control the Redragon M908 Impact and M709 gaming mice .B mouse_m908 \fB\-h\fR .SH DESCRIPTION -Change the LED lighting, the button mapping and the active profile of the Redragon M908 Impact and M709 gaming mice. Support for the M709 is currently experimental, see \fIREADME.md\fR for details. +Change the LED lighting, the button mapping and the active profile of the Redragon M908 Impact, M709 and M711 gaming mice. Support for the M709 and M711 is currently experimental, see \fIREADME.md\fR for details. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR @@ -51,7 +51,7 @@ Read settings from the mouse and print the configuration to the specfied file. U Read settings from the mouse and dump the raw data to the specfied file. Uses stdout when \fIFILE\fR is "-". Only useful for debugging and development. .TP \fB\-M\fR, \fB\-\-model\fR=\fINAME\fR -Specifies the model of the mouse (709, 908). +Specifies the model of the mouse (709, 711, 908). .SH EXAMPLES To send the configuration from example.ini .PP diff --git a/mouse_m908.cpp b/mouse_m908.cpp index 877de9f..51d4f8a 100644 --- a/mouse_m908.cpp +++ b/mouse_m908.cpp @@ -218,10 +218,20 @@ int main( int argc, char **argv ){ string_number, string_bus, string_device, string_dump, string_read ); + }else if( string_model == "711" ){ + + return perform_actions< mouse_m711 >( + flag_config, flag_profile, flag_macro, flag_number, + flag_bus, flag_device, flag_kernel_driver, + flag_dump_settings, flag_read_settings, + string_config, string_profile, string_macro, + string_number, string_bus, string_device, + string_dump, string_read ); + }else{ std::cout << "Unknown model, valid options are:\n"; - std::cout << "709\n908\n"; + std::cout << "709\n711\n908\n"; return 1; } diff --git a/mouse_m908.rules b/mouse_m908.rules index 9c23432..90748ee 100644 --- a/mouse_m908.rules +++ b/mouse_m908.rules @@ -2,3 +2,5 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="fc4d", MODE:="0666 SUBSYSTEM=="usb_device", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="fc4d", MODE:="0666" SUBSYSTEM=="usb", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="fc2a", MODE:="0666" SUBSYSTEM=="usb_device", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="fc2a", MODE:="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="fc30", MODE:="0666" +SUBSYSTEM=="usb_device", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="fc30", MODE:="0666"