Add experimental support for the M711

This commit is contained in:
dokutan 2020-07-31 18:41:47 +02:00
parent c04fb5fb5b
commit f67a356c9d
19 changed files with 3548 additions and 11 deletions

View file

@ -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"

View file

@ -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)<br>- Changing the profile works<br>- Changing the settings is untested but implemented<br>- Macros are untested<br>- 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<br>- Implemented: led color, mode, brightness and speed, changing profiles, macros, reading settings<br>- 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.

View file

@ -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

View file

@ -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/

116
examples/example_m711.ini Normal file
View file

@ -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

View file

@ -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 );
}

687
include/m711/data.cpp Normal file
View file

@ -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}
};

336
include/m711/getters.cpp Normal file
View file

@ -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<uint8_t, 3> &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<uint8_t, 4>& 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<uint8_t, 256>& 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;
}

541
include/m711/helpers.cpp Normal file
View file

@ -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;
}

319
include/m711/mouse_m711.h Normal file
View file

@ -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 <libusb.h>
#include <map>
#include <array>
#include <string>
#include <algorithm>
#include <exception>
#include <regex>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <iomanip>
#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<uint8_t, 3> 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<uint8_t, 4> 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<uint8_t, 3> &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<uint8_t, 4>& 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<uint8_t, 256>& 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<uint8_t, 5> _s_scrollspeeds;
std::array<rd_lightmode, 5> _s_lightmodes;
std::array<std::array<uint8_t, 3>, 5> _s_colors;
std::array<uint8_t, 5> _s_brightness_levels;
std::array<uint8_t, 5> _s_speed_levels;
std::array<std::array<bool, 5>, 5> _s_dpi_enabled;
std::array<std::array<uint8_t, 5>, 5> _s_dpi_levels;
std::array<std::array<std::array<uint8_t, 4>, 8>, 5> _s_keymap_data;
std::array<rd_report_rate, 5> _s_report_rates;
std::array<std::array<uint8_t, 256>, 15> _s_macro_data;
std::array<uint8_t, 15> _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

756
include/m711/readers.cpp Normal file
View file

@ -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;
}

418
include/m711/setters.cpp Normal file
View file

@ -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<uint8_t, 3> 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<uint8_t, 4> 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;
}

253
include/m711/writers.cpp Normal file
View file

@ -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;
}

View file

@ -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";
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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"