Add backend for the M686

This commit is contained in:
dokutan 2021-10-17 17:41:44 +02:00
parent 1a4476c5f2
commit 8066172567
13 changed files with 1918 additions and 3 deletions

View file

@ -46,6 +46,14 @@ target_sources(mouse_m908
include/m607/readers.cpp
include/m607/setters.cpp
include/m607/writers.cpp
include/m686/constructor.cpp
include/m686/data.cpp
include/m686/getters.cpp
include/m686/helpers.cpp
include/m686/mouse_m686.h
include/m686/readers.cpp
include/m686/setters.cpp
include/m686/writers.cpp
include/m709/constructor.cpp
include/m709/data.cpp
include/m709/getters.cpp

View file

@ -41,6 +41,7 @@ Redragon M908 Impact | complete | 0x04d9:0xfc4d |
Redragon M719 Invader | complete | 0x04d9:0xfc4f |
Redragon M607 Griffin | complete | 0x04d9:0xfc38 |
Redragon M913 | partial | 0x25a7:0xfa07<br>0x25a7:0xfa08 | See [this issue](https://github.com/dokutan/mouse_m908/issues/15)<br>- Uses a different and unique protocol<br>- Not all features are implemented
Redragon M686 | experimental | 0x25a7:0xfa34<br>0x25a7:0xfa35 | See [this issue](https://github.com/dokutan/mouse_m908/issues/29)
Redragon M709 Tiger | 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<br>- Macros are untested<br>- Reading the settings is not properly implemented due to a lack of data
Redragon M711 Cobra (FPS) | experimental | 0x04d9:0xfc30 | See [this issue](https://github.com/dokutan/mouse_m908/issues/2)<br>- Nothing is tested<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
Redragon M715 Dagger | experimental | 0x04d9:0xfc39 | Nothing is tested<br>- The device specific code is copied from the M711 and mostly unmodified

View file

@ -6,10 +6,10 @@ This document contains a list of thing that need to be changed or added when add
- class declaration (at the top)
- mouse\_variant typedef
- #include new header file (at the bottom)
- include/rd\_mouse.cpp
- rd\_mouse::detect() only needs changing for mice that have more than 1 PID (e.g. generic)
- makefile
- Add new m\* target
- CMakeLists.txt
- Add new files to target_sources
- documentation:
- README (supported models)
- create new config in examples/

View file

@ -0,0 +1,48 @@
/*
* 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 "../rd_mouse.h"
// Constructor, set the default settings
mouse_m686::mouse_m686(){
//default settings
_s_profile = rd_mouse::rd_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 );
// dpi
_s_dpi_enabled.fill( {true, true, true, true, true} );
_s_dpi_levels.fill( {{ {0x04, 0x00}, {0x16, 0x00}, {0x2d, 0x00}, {0x43, 0x00}, {0x8c, 0x00} }} );
_s_report_rates.fill( r_125Hz );
/* missing data
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++;
}
*/
}

369
include/m686/data.cpp Normal file
View file

@ -0,0 +1,369 @@
/*
* 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 "../rd_mouse.h"
const std::string mouse_m686::_c_name = "686";
// usb device vars
const uint16_t mouse_m686::_c_mouse_vid = 0x25a7;
std::set< uint16_t > mouse_m686::_c_all_pids = {
0xfa34, // wireless connection
0xfa35 // wired connection
};
// Names of the physical buttons
std::map< int, std::string > mouse_m686::_c_button_names = {
{ 0, "button_1" },
{ 1, "button_2" },
{ 2, "button_3" },
{ 3, "button_4" },
{ 4, "button_5" },
{ 5, "button_6" },
{ 6, "button_right" },
{ 7, "button_left" },
{ 8, "button_7" },
{ 9, "button_8" },
{ 10, "button_middle" },
{ 11, "button_fire" },
{ 12, "button_9" },
{ 13, "button_10" },
{ 14, "button_11" },
{ 15, "button_12" }
};
std::map< std::string, std::array<uint8_t, 4> > mouse_m686::_c_keycodes = {
{ "left", { 0x01, 0x01, 0x00, 0x53 } },
{ "right", { 0x01, 0x02, 0x00, 0x52 } },
{ "middle", { 0x01, 0x04, 0x00, 0x50 } },
{ "backward", { 0x01, 0x08, 0x00, 0x4c } },
{ "forward", { 0x01, 0x10, 0x00, 0x44 } },
{ "led_toggle", { 0x08, 0x00, 0x00, 0x4d } },
{ "report_rate", { 0x07, 0x00, 0x00, 0x4e } },
{ "dpi-", { 0x02, 0x03, 0x00, 0x50 } },
{ "dpi+", { 0x02, 0x02, 0x00, 0x51 } },
{ "dpi-cycle", { 0x02, 0x01, 0x00, 0x52 } },
{ "default", { 0x05, 0x00, 0x00, 0x50 } },
{ "none", { 0x00, 0x00, 0x00, 0x55 } },
};
// DPI → bytecode
std::map< int, std::array<uint8_t,3> > mouse_m686::_c_dpi_codes = {
{ 100, { 0x00, 0x00, 0x55 } }, // minimum DPI
{ 200, { 0x02, 0x02, 0x51 } },
{ 300, { 0x03, 0x03, 0x4f } },
{ 400, { 0x04, 0x04, 0x4d } },
{ 500, { 0x05, 0x05, 0x4b } },
{ 600, { 0x06, 0x06, 0x49 } },
{ 700, { 0x07, 0x07, 0x47 } },
{ 800, { 0x09, 0x09, 0x43 } },
{ 900, { 0x0a, 0x0a, 0x41 } },
{ 1000, { 0x0b, 0x0b, 0x3f } },
{ 1100, { 0x0c, 0x0c, 0x3d } },
{ 1200, { 0x0d, 0x0d, 0x3b } },
{ 1300, { 0x0e, 0x0e, 0x39 } },
{ 1400, { 0x10, 0x10, 0x35 } },
{ 1500, { 0x11, 0x11, 0x33 } },
{ 1600, { 0x12, 0x12, 0x31 } },
{ 1700, { 0x13, 0x13, 0x2f } },
{ 1800, { 0x14, 0x14, 0x2d } },
{ 1900, { 0x16, 0x16, 0x29 } },
{ 2000, { 0x17, 0x17, 0x27 } },
{ 2100, { 0x18, 0x18, 0x25 } },
{ 2200, { 0x19, 0x19, 0x23 } },
{ 2300, { 0x1a, 0x1a, 0x21 } },
{ 2400, { 0x1b, 0x1b, 0x1f } },
{ 2500, { 0x1d, 0x1d, 0x1b } },
{ 2600, { 0x1e, 0x1e, 0x19 } },
{ 2700, { 0x1f, 0x1f, 0x17 } },
{ 2800, { 0x20, 0x20, 0x15 } },
{ 2900, { 0x21, 0x21, 0x13 } },
{ 3000, { 0x23, 0x23, 0x0f } },
{ 3100, { 0x25, 0x25, 0x0b } },
{ 3200, { 0x26, 0x26, 0x09 } },
{ 3300, { 0x27, 0x27, 0x07 } },
{ 3400, { 0x28, 0x28, 0x05 } },
{ 3500, { 0x29, 0x29, 0x03 } },
{ 3600, { 0x2a, 0x2a, 0x01 } },
{ 3700, { 0x2c, 0x2c, 0xfd } },
{ 3800, { 0x2d, 0x2d, 0xfb } },
{ 3900, { 0x2e, 0x2e, 0xf9 } },
{ 4000, { 0x2f, 0x2f, 0xf7 } },
{ 4100, { 0x30, 0x30, 0xf5 } },
{ 4200, { 0x32, 0x32, 0xf1 } },
{ 4300, { 0x33, 0x33, 0xef } },
{ 4400, { 0x34, 0x34, 0xed } },
{ 4500, { 0x35, 0x35, 0xeb } },
{ 4600, { 0x36, 0x36, 0xe9 } },
{ 4700, { 0x38, 0x38, 0xe5 } },
{ 4800, { 0x39, 0x39, 0xe3 } },
{ 4900, { 0x3a, 0x3a, 0xe1 } },
{ 5000, { 0x3b, 0x3b, 0xdf } },
{ 5100, { 0x3c, 0x3c, 0xdd } },
{ 5200, { 0x3e, 0x3e, 0xd9 } },
{ 5300, { 0x3f, 0x3f, 0xd7 } },
{ 5400, { 0x40, 0x40, 0xd5 } },
{ 5500, { 0x41, 0x41, 0xd3 } },
{ 5600, { 0x42, 0x42, 0xd1 } },
{ 5700, { 0x44, 0x44, 0xcd } },
{ 5800, { 0x45, 0x45, 0xcb } },
{ 5900, { 0x46, 0x46, 0xc9 } },
{ 6000, { 0x47, 0x47, 0xc7 } },
{ 6100, { 0x49, 0x49, 0xc3 } },
{ 6200, { 0x4a, 0x4a, 0xc1 } },
{ 6300, { 0x4b, 0x4b, 0xbf } },
{ 6400, { 0x4c, 0x4c, 0xbd } },
{ 6500, { 0x4d, 0x4d, 0xbb } },
{ 6600, { 0x4f, 0x4f, 0xb7 } },
{ 6700, { 0x50, 0x50, 0xb5 } },
{ 6800, { 0x51, 0x51, 0xb3 } },
{ 6900, { 0x52, 0x52, 0xb1 } },
{ 7000, { 0x53, 0x53, 0xaf } },
{ 7100, { 0x55, 0x55, 0xab } },
{ 7200, { 0x56, 0x56, 0xa9 } },
{ 7300, { 0x57, 0x57, 0xa7 } },
{ 7400, { 0x58, 0x58, 0xa5 } },
{ 7500, { 0x59, 0x59, 0xa3 } },
{ 7600, { 0x5b, 0x5b, 0x9f } },
{ 7700, { 0x5c, 0x5c, 0x9d } },
{ 7800, { 0x5d, 0x5d, 0x9b } },
{ 7900, { 0x5e, 0x5e, 0x99 } },
{ 8000, { 0x5f, 0x5f, 0x97 } },
{ 8100, { 0x61, 0x61, 0x93 } },
{ 8200, { 0x62, 0x62, 0x91 } },
{ 8300, { 0x63, 0x63, 0x8f } },
{ 8400, { 0x64, 0x64, 0x8d } },
{ 8500, { 0x65, 0x65, 0x8b } },
{ 8600, { 0x67, 0x67, 0x87 } },
{ 8700, { 0x68, 0x68, 0x85 } },
{ 8800, { 0x69, 0x69, 0x83 } },
{ 8900, { 0x6a, 0x6a, 0x81 } },
{ 9000, { 0x6b, 0x6b, 0x7f } },
{ 9100, { 0x6d, 0x6d, 0x7b } },
{ 9200, { 0x6e, 0x6e, 0x79 } },
{ 9300, { 0x6f, 0x6f, 0x77 } },
{ 9400, { 0x70, 0x70, 0x75 } },
{ 9500, { 0x71, 0x71, 0x73 } },
{ 9600, { 0x73, 0x73, 0x6f } },
{ 9700, { 0x74, 0x74, 0x6d } },
{ 9800, { 0x75, 0x75, 0x6b } },
{ 9900, { 0x76, 0x76, 0x69 } },
{ 10000, { 0x77, 0x77, 0x67 } },
{ 10100, { 0x79, 0x79, 0x63 } },
{ 10200, { 0x7a, 0x7a, 0x61 } },
{ 10300, { 0x7b, 0x7b, 0x5f } },
{ 10400, { 0x7c, 0x7c, 0x5d } },
{ 10500, { 0x7d, 0x7d, 0x5b } },
{ 10600, { 0x7f, 0x7f, 0x57 } },
{ 10700, { 0x80, 0x80, 0x55 } },
{ 10800, { 0x81, 0x81, 0x53 } },
{ 10900, { 0x82, 0x82, 0x51 } },
{ 11000, { 0x83, 0x83, 0x4f } },
{ 11100, { 0x85, 0x85, 0x4b } },
{ 11200, { 0x86, 0x86, 0x49 } },
{ 11300, { 0x87, 0x87, 0x47 } },
{ 11400, { 0x88, 0x88, 0x45 } },
{ 11500, { 0x89, 0x89, 0x43 } },
{ 11600, { 0x8b, 0x8b, 0x3f } },
{ 11700, { 0x8c, 0x8c, 0x3d } },
{ 11800, { 0x8d, 0x8d, 0x3b } },
{ 11900, { 0x8e, 0x8e, 0x39 } },
{ 12000, { 0x8f, 0x8f, 0x37 } },
{ 12100, { 0x91, 0x91, 0x33 } },
{ 12200, { 0x92, 0x92, 0x31 } },
{ 12300, { 0x93, 0x93, 0x2f } },
{ 12400, { 0x94, 0x94, 0x2d } },
{ 12500, { 0x95, 0x95, 0x2b } },
{ 12600, { 0x97, 0x97, 0x27 } },
{ 12700, { 0x98, 0x98, 0x25 } },
{ 12800, { 0x99, 0x99, 0x23 } },
{ 12900, { 0x9a, 0x9a, 0x21 } },
{ 13000, { 0x9b, 0x9b, 0x1f } },
{ 13100, { 0x9d, 0x9d, 0x1b } },
{ 13200, { 0x9e, 0x9e, 0x19 } },
{ 13300, { 0x9f, 0x9f, 0x17 } },
{ 13400, { 0xa0, 0xa0, 0x15 } },
{ 13500, { 0xa1, 0xa1, 0x13 } },
{ 13600, { 0xa3, 0xa3, 0x0f } },
{ 13700, { 0xa4, 0xa4, 0x0d } },
{ 13800, { 0xa5, 0xa5, 0x0b } },
{ 13900, { 0xa6, 0xa6, 0x09 } },
{ 14000, { 0xa7, 0xa7, 0x07 } },
{ 14100, { 0xa8, 0xa8, 0x05 } },
{ 14200, { 0xaa, 0xaa, 0x01 } },
{ 14300, { 0xab, 0xab, 0xff } },
{ 14400, { 0xac, 0xac, 0xfd } },
{ 14500, { 0xad, 0xad, 0xfb } },
{ 14600, { 0xae, 0xae, 0xf9 } },
{ 14700, { 0xb0, 0xb0, 0xf5 } },
{ 14800, { 0xb1, 0xb1, 0xf3 } },
{ 14900, { 0xb2, 0xb2, 0xf1 } },
{ 15000, { 0xb3, 0xb3, 0xef } },
{ 15100, { 0xb4, 0xb4, 0xed } },
{ 15200, { 0xb5, 0xb5, 0xeb } },
{ 15300, { 0xb6, 0xb6, 0xe9 } },
{ 15400, { 0xb7, 0xb7, 0xe7 } },
{ 15500, { 0xb8, 0xb8, 0xe5 } },
{ 15600, { 0xb9, 0xb9, 0xe3 } },
{ 15700, { 0xba, 0xba, 0xe1 } },
{ 15800, { 0xbb, 0xbb, 0xdf } },
{ 15900, { 0xbc, 0xbc, 0xdd } },
{ 16000, { 0xbd, 0xbd, 0xdb } } // maximum DPI
};
//usb data packets
uint8_t mouse_m686::_c_data_unknown_1[9][17] = {
{0x08, 0x07, 0x00, 0x01, 0x60, 0x08, 0x02, 0x81, 0x21, 0x00, 0x41, 0x21, 0x00, 0x4f, 0x00, 0x00, 0x88},
{0x08, 0x07, 0x00, 0x01, 0x80, 0x08, 0x02, 0x81, 0x22, 0x00, 0x41, 0x22, 0x00, 0x4d, 0x00, 0x00, 0x68},
{0x08, 0x07, 0x00, 0x01, 0xa0, 0x08, 0x02, 0x81, 0x23, 0x00, 0x41, 0x23, 0x00, 0x4b, 0x00, 0x00, 0x48},
{0x08, 0x07, 0x00, 0x02, 0x00, 0x08, 0x02, 0x81, 0x24, 0x00, 0x41, 0x24, 0x00, 0x49, 0x00, 0x00, 0xe7},
{0x08, 0x07, 0x00, 0x02, 0x20, 0x08, 0x02, 0x81, 0x25, 0x00, 0x41, 0x25, 0x00, 0x47, 0x00, 0x00, 0xc7},
{0x08, 0x07, 0x00, 0x02, 0x80, 0x08, 0x02, 0x81, 0x26, 0x00, 0x41, 0x26, 0x00, 0x45, 0x00, 0x00, 0x67},
{0x08, 0x07, 0x00, 0x02, 0xa0, 0x08, 0x02, 0x81, 0x27, 0x00, 0x41, 0x27, 0x00, 0x43, 0x00, 0x00, 0x47},
{0x08, 0x07, 0x00, 0x02, 0xc0, 0x08, 0x02, 0x81, 0x57, 0x00, 0x41, 0x57, 0x00, 0xe3, 0x00, 0x00, 0x27},
{0x08, 0x07, 0x00, 0x02, 0xe0, 0x08, 0x02, 0x81, 0x56, 0x00, 0x41, 0x56, 0x00, 0xe5, 0x00, 0x00, 0x07},
};
uint8_t mouse_m686::_c_data_button_mapping[8][17] = {
{0x08, 0x07, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x55, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0x34},
{0x08, 0x07, 0x00, 0x00, 0x68, 0x08, 0x05, 0x00, 0x00, 0x50, 0x01, 0x08, 0x00, 0x4c, 0x00, 0x00, 0x2c},
{0x08, 0x07, 0x00, 0x00, 0x70, 0x08, 0x05, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0x24},
{0x08, 0x07, 0x00, 0x00, 0x78, 0x08, 0x01, 0x02, 0x00, 0x52, 0x01, 0x01, 0x00, 0x53, 0x00, 0x00, 0x1c},
{0x08, 0x07, 0x00, 0x00, 0x80, 0x08, 0x05, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0x14},
{0x08, 0x07, 0x00, 0x00, 0x88, 0x08, 0x01, 0x04, 0x00, 0x50, 0x04, 0x14, 0x03, 0x3a, 0x00, 0x00, 0x0c},
{0x08, 0x07, 0x00, 0x00, 0x90, 0x08, 0x05, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0x04},
{0x08, 0x07, 0x00, 0x00, 0x98, 0x08, 0x05, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x50, 0x00, 0x00, 0xfc},
};
uint8_t mouse_m686::_c_data_dpi[4][17]= {
{0x08, 0x07, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x55, 0x02, 0x02, 0x00, 0x51, 0x00, 0x00, 0x88},
{0x08, 0x07, 0x00, 0x00, 0x14, 0x08, 0x03, 0x03, 0x00, 0x4f, 0x04, 0x04, 0x00, 0x4d, 0x00, 0x00, 0x80},
{0x08, 0x07, 0x00, 0x00, 0x1c, 0x04, 0x05, 0x05, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1},
{0x08, 0x07, 0x00, 0x00, 0x02, 0x02, 0x05, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed},
};
uint8_t mouse_m686::_c_data_unknown_2[3][17] = {
{0x08, 0x07, 0x00, 0x00, 0x2c, 0x08, 0xff, 0x00, 0x00, 0x56, 0x00, 0x00, 0xff, 0x56, 0x00, 0x00, 0x68},
{0x08, 0x07, 0x00, 0x00, 0x34, 0x08, 0x00, 0xff, 0x00, 0x56, 0xff, 0xff, 0x00, 0x57, 0x00, 0x00, 0x60},
{0x08, 0x07, 0x00, 0x00, 0x3c, 0x04, 0xff, 0x55, 0x7d, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1},
};
uint8_t mouse_m686::_c_data_led_static[3][17] = {
{0x08, 0x07, 0x00, 0x00, 0x54, 0x08, 0xff, 0x00, 0x00, 0x57, 0x01, 0x54, 0xff, 0x56, 0x00, 0x00, 0xeb},
{0x08, 0x07, 0x00, 0x00, 0x00, 0x02, 0x02, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef},
{0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49},
};
uint8_t mouse_m686::_c_data_led_breathing[3][17] = {
{0x08, 0x07, 0x00, 0x00, 0x54, 0x08, 0xff, 0x00, 0x00, 0x57, 0x01, 0x54, 0xff, 0x56, 0x00, 0x00, 0xeb},
{0x08, 0x07, 0x00, 0x00, 0x5c, 0x02, 0x03, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93},
{0x08, 0x07, 0x00, 0x00, 0x00, 0x02, 0x01, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef},
};
uint8_t mouse_m686::_c_data_led_off[2][17] = {
{0x08, 0x07, 0x00, 0x00, 0x58, 0x02, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97},
{0x08, 0x07, 0x00, 0x00, 0x00, 0x02, 0x01, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef},
};
uint8_t mouse_m686::_c_data_led_rainbow[3][17] = {
{0x08, 0x07, 0x00, 0x00, 0x54, 0x08, 0xff, 0x00, 0xff, 0x57, 0x03, 0x52, 0x80, 0xd5, 0x00, 0x00, 0xeb},
{0x08, 0x07, 0x00, 0x00, 0x5c, 0x02, 0x03, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93},
{0x08, 0x07, 0x00, 0x00, 0x00, 0x02, 0x02, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef},
};
// TODO! remove?
uint8_t mouse_m686::_c_data_unknown_3[1][17] = {
//{0x08, 0x07, 0x00, 0x00, 0x5c, 0x02, 0x03, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93},
{0x08, 0x07, 0x00, 0x00, 0x00, 0x02, 0x02, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef},
};
uint8_t mouse_m686::_c_data_read[69][17] = {
{0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a},
{0x08, 0x01, 0x00, 0x00, 0x00, 0x04, 0x34, 0x2e, 0x4c, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43},
{0x08, 0x08, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f},
{0x08, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49},
{0x08, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b},
{0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31},
{0x08, 0x08, 0x00, 0x00, 0x14, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27},
{0x08, 0x08, 0x00, 0x00, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d},
{0x08, 0x08, 0x00, 0x00, 0x28, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13},
{0x08, 0x08, 0x00, 0x00, 0x32, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09},
{0x08, 0x08, 0x00, 0x00, 0x3c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff},
{0x08, 0x08, 0x00, 0x00, 0x46, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5},
{0x08, 0x08, 0x00, 0x00, 0x50, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb},
{0x08, 0x08, 0x00, 0x00, 0x5a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1},
{0x08, 0x08, 0x00, 0x00, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7},
{0x08, 0x08, 0x00, 0x00, 0x6e, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd},
{0x08, 0x08, 0x00, 0x00, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3},
{0x08, 0x08, 0x00, 0x00, 0x82, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9},
{0x08, 0x08, 0x00, 0x00, 0x8c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf},
{0x08, 0x08, 0x00, 0x00, 0x96, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5},
{0x08, 0x08, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a},
{0x08, 0x08, 0x00, 0x01, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30},
{0x08, 0x08, 0x00, 0x01, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a},
{0x08, 0x08, 0x00, 0x01, 0x2a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
{0x08, 0x08, 0x00, 0x01, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa},
{0x08, 0x08, 0x00, 0x01, 0x4a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0},
{0x08, 0x08, 0x00, 0x01, 0x60, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda},
{0x08, 0x08, 0x00, 0x01, 0x6a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0},
{0x08, 0x08, 0x00, 0x01, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba},
{0x08, 0x08, 0x00, 0x01, 0x8a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0},
{0x08, 0x08, 0x00, 0x01, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a},
{0x08, 0x08, 0x00, 0x01, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90},
{0x08, 0x08, 0x00, 0x01, 0xc0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a},
{0x08, 0x08, 0x00, 0x01, 0xca, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70},
{0x08, 0x08, 0x00, 0x01, 0xe0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a},
{0x08, 0x08, 0x00, 0x01, 0xea, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50},
{0x08, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39},
{0x08, 0x08, 0x00, 0x02, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f},
{0x08, 0x08, 0x00, 0x02, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19},
{0x08, 0x08, 0x00, 0x02, 0x2a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f},
{0x08, 0x08, 0x00, 0x02, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9},
{0x08, 0x08, 0x00, 0x02, 0x4a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef},
{0x08, 0x08, 0x00, 0x02, 0x60, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9},
{0x08, 0x08, 0x00, 0x02, 0x6a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf},
{0x08, 0x08, 0x00, 0x02, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9},
{0x08, 0x08, 0x00, 0x02, 0x8a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf},
{0x08, 0x08, 0x00, 0x02, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99},
{0x08, 0x08, 0x00, 0x02, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f},
{0x08, 0x08, 0x00, 0x02, 0xc0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79},
{0x08, 0x08, 0x00, 0x02, 0xca, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f},
{0x08, 0x08, 0x00, 0x02, 0xe0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59},
{0x08, 0x08, 0x00, 0x02, 0xea, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f},
{0x08, 0x08, 0x00, 0x03, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37},
{0x08, 0x08, 0x00, 0x04, 0x81, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6},
{0x08, 0x08, 0x00, 0x06, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34},
{0x08, 0x08, 0x00, 0x07, 0x81, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3},
{0x08, 0x08, 0x00, 0x09, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31},
{0x08, 0x08, 0x00, 0x0a, 0x81, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0},
{0x08, 0x08, 0x00, 0x0c, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e},
{0x08, 0x08, 0x00, 0x0d, 0x81, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad},
{0x08, 0x08, 0x00, 0x0f, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b},
{0x08, 0x08, 0x00, 0x10, 0x81, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa},
{0x08, 0x08, 0x00, 0x12, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28},
{0x08, 0x08, 0x00, 0x13, 0x81, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7},
{0x08, 0x08, 0x00, 0x15, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25},
{0x08, 0x08, 0x00, 0x16, 0x81, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4},
{0x08, 0x08, 0x00, 0x18, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22},
{0x08, 0x08, 0x00, 0x19, 0x81, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1},
{0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49},
};

133
include/m686/getters.cpp Normal file
View file

@ -0,0 +1,133 @@
/*
* 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 "../rd_mouse.h"
mouse_m686::rd_profile mouse_m686::get_profile(){
return _s_profile;
}
uint8_t mouse_m686::get_scrollspeed( rd_profile profile ){
return _s_scrollspeeds[profile];
}
mouse_m686::rd_lightmode mouse_m686::get_lightmode( rd_profile profile ){
mouse_m686::rd_lightmode l = mouse_m686::rd_lightmode::lightmode_static;
switch(_s_lightmodes[profile]){
case mouse_m686::m686_lightmode::lightmode_off: l = mouse_m686::rd_lightmode::lightmode_off; break;
case mouse_m686::m686_lightmode::lightmode_breathing: l = mouse_m686::rd_lightmode::lightmode_breathing; break;
case mouse_m686::m686_lightmode::lightmode_rainbow: l = mouse_m686::rd_lightmode::lightmode_rainbow; break;
default: l = mouse_m686::rd_lightmode::lightmode_static; break;
}
return l;
}
void mouse_m686::get_color( rd_profile profile, std::array<uint8_t, 3> &color ){
color = _s_colors[profile];
}
uint8_t mouse_m686::get_brightness( rd_profile profile ){
return _s_brightness_levels[profile];
}
uint8_t mouse_m686::get_speed( rd_profile profile ){
return _s_speed_levels[profile];
}
bool mouse_m686::get_dpi_enable( rd_profile profile, int level ){
// check DPI level bounds
if( level < _c_level_min || level > _c_level_max )
return false;
return _s_dpi_enabled[profile][level];
}
int mouse_m686::get_dpi( rd_profile profile, int level, std::array<uint8_t, 2>& dpi ){
// check DPI level bounds
if( level < _c_level_min || level > _c_level_max )
return 1;
dpi[0] = _s_dpi_levels[profile][level][0];
dpi[1] = _s_dpi_levels[profile][level][1];
return 0;
}
mouse_m686::rd_report_rate mouse_m686::get_report_rate( rd_profile profile ){
return _s_report_rates[profile];
}
int mouse_m686::get_key_mapping_raw( mouse_m686::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_m686::get_key_mapping( mouse_m686::rd_profile profile, int key, std::string& mapping ){
// valid key ?
if( _c_button_names[key] == "" )
return 1;
std::array< uint8_t, 4 > bytes = {
_s_keymap_data[profile][key][0],
_s_keymap_data[profile][key][1],
_s_keymap_data[profile][key][2],
_s_keymap_data[profile][key][3]
};
_i_decode_button_mapping( bytes, mapping );
return 0;
}
int mouse_m686::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_m686::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;
std::vector< uint8_t > macro_bytes;
std::copy( _s_macro_data[number-1].begin(), _s_macro_data[number-1].end(), std::back_inserter(macro_bytes) );
_i_decode_macro( macro_bytes, output, "", 8 );
macro = output.str();
return 0;
}

355
include/m686/helpers.cpp Normal file
View file

@ -0,0 +1,355 @@
/*
* 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 "../rd_mouse.h"
//helper functions
// Maps rd_profile to m686_profile
mouse_m686::m686_profile mouse_m686::rd_profile_to_m686_profile( rd_profile profile ){
return profile == rd_mouse::rd_profile::profile_1 ? mouse_m686::m686_profile::profile_1 : mouse_m686::m686_profile::profile_2;
}
//init libusb and open mouse
int mouse_m686::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;
}
}
}
//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;
}
return res;
}
// init libusb and open mouse by bus and device
int mouse_m686::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;
}
}
}
//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;
}
return res;
}
// close mouse
int mouse_m686::close_mouse(){
// release interfaces 0 and 1
libusb_release_interface( _i_handle, 0 );
libusb_release_interface( _i_handle, 1 );
// 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 );
}
// exit libusb
libusb_exit( NULL );
return 0;
}
// print current configuration
int mouse_m686::print_settings( std::ostream& output ){
// print configuration
output << "# Configuration created by mouse_m686::print_settings().\n";
output << "# Currently active profile: " << _s_profile << "\n";
for( int i = 1; i < 3; 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{
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-1] )
output << "dpi" << j << "_enable=1\n";
else
output << "dpi" << j << "_enable=0\n";
// DPI value
std::array<uint8_t, 3> dpi_bytes = {_s_dpi_levels[i-1][j-1][0], _s_dpi_levels[i-1][j-1][1], _s_dpi_levels[i-1][j-1][2]};
std::string dpi_string = "";
if( _i_decode_dpi( dpi_bytes, dpi_string ) == 0 )
output << "dpi" << j << "=" << dpi_string << "\n";
else
output << "\n";
}
// button mapping
output << "\n# Button mapping\n";
for( int j = 0; j < 8; j++ ){
std::array< uint8_t, 4 > bytes = {
_s_keymap_data[i-1][j][0],
_s_keymap_data[i-1][j][1],
_s_keymap_data[i-1][j][2],
_s_keymap_data[i-1][j][3]
};
std::string mapping;
_i_decode_button_mapping( bytes, mapping );
output << _c_button_names[j] << "=" << mapping << std::endl;
}
}
// macros
output << "\n# Macros\n";
for( int i = 0; i < 15; i++ ){
// is macro not defined ?
if( _s_macro_data[i][8] == 0 && _s_macro_data[i][9] == 0 && _s_macro_data[i][10] == 0 )
continue;
// _i_decode_macros takes a vector as argument, copy array to vector
std::vector< uint8_t > macro_bytes( _s_macro_data[i].begin(), _s_macro_data[i].end() );
// print macro (macro data starts at byte 8)
output << "\n;## macro" << i+1 << "\n";
_i_decode_macro( macro_bytes, output, ";# ", 8 );
}
return 0;
}
// decode the button mapping
int mouse_m686::_i_decode_button_mapping( const std::array<uint8_t, 4>& bytes, std::string& mapping ){
int ret = 1;
std::stringstream mapping_stream;
// known keycode ?
for( auto keycode : _c_keycodes ){
if(
bytes.at(0) == keycode.second.at(0) &&
bytes.at(1) == keycode.second.at(1) &&
bytes.at(2) == keycode.second.at(2) &&
bytes.at(3) == keycode.second.at(3)
){
ret = 0;
mapping_stream << keycode.first;
}
}
// unknown keycode
if( ret != 0 ){
mapping_stream
<< "unknown, please report as bug: "
<< " " << std::hex << (int)bytes.at(0) << " "
<< " " << std::hex << (int)bytes.at(1) << " "
<< " " << std::hex << (int)bytes.at(2) << " "
<< " " << std::hex << (int)bytes.at(3)
<< std::dec;
}
mapping = mapping_stream.str();
return ret;
}
int mouse_m686::_i_decode_dpi( const std::array<uint8_t, 3>& dpi_bytes, std::string& dpi_string ){
// is dpi value known?
for( auto dpi_value : _c_dpi_codes ){
if( dpi_value.second[0] == dpi_bytes[0] && dpi_value.second[1] == dpi_bytes[1] && dpi_value.second[2] == dpi_bytes[2] ){
dpi_string = std::to_string( dpi_value.first );
return 0;
}
}
// unknown dpi value
std::stringstream conversion_stream;
conversion_stream << std::setfill('0') << std::hex;
conversion_stream << "0x";
conversion_stream << std::setw(2) << (int)dpi_bytes[0] << std::setw(2) << (int)dpi_bytes[1] << std::setw(2) << (int)dpi_bytes[2];
conversion_stream << std::setfill(' ') << std::setw(0) << std::dec;
dpi_string = conversion_stream.str();
return 0;
}

354
include/m686/mouse_m686.h Normal file
View file

@ -0,0 +1,354 @@
/*
* 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_M686
#define MOUSE_M686
#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>
/**
* The main class representing the M686 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_m686 : public rd_mouse{
public:
/// The default constructor. Sets the default settings.
mouse_m686();
//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 or invalid dpi
*/
int set_dpi( rd_profile profile, int level, std::string dpi );
int set_dpi( rd_profile profile, int level, std::array<uint8_t, 3> 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 );
/// Set USB vendor id, does nothing
void set_vid( uint16_t vid ){
(void)vid;
}
/// Set USB product id
void set_pid( uint16_t pid ){
_c_mouse_pid = pid;
}
//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
int get_dpi( rd_profile profile, int level, std::array<uint8_t, 2>& dpi );
/// Get USB poll rate of specified profile
rd_report_rate get_report_rate( rd_profile profile );
/// 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 );
/// Checks if the mouse has the given vendor and product id
static bool has_vid_pid( uint16_t vid, uint16_t pid ){
return vid == _c_mouse_vid && _c_all_pids.find(pid) != _c_all_pids.end();
}
/// Get mouse name
static std::string get_name(){
return _c_name;
}
//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 );
//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_m686 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_m686 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:
/// The m686 has only two profiles.
enum m686_profile{
profile_1 = 0,
profile_2 = 1,
};
/// The m686 has different light modes from the other mice
enum m686_lightmode{
lightmode_off,
lightmode_static,
lightmode_breathing,
lightmode_rainbow
};
uint8_t _c_brightness_min = 0x00;
uint8_t _c_brightness_max = 0xff;
/// Maps rd_profile to m686_profile
m686_profile rd_profile_to_m686_profile( rd_profile profile );
/// Write raw data
int write_data(uint8_t data[][17], size_t rows);
/// Write the button mapping to the mouse
int write_button_mapping( m686_profile profile );
/// Write the DPI settings to the mouse
int write_dpi_settings( m686_profile profile );
/// Write the LED settings to the mouse
int write_led_settings( m686_profile profile );
/** \brief Decodes the bytes describing a button mapping
* \arg bytes the 4 bytes descriping the mapping
* \arg mapping string to hold the result
* \return 0 if valid button mapping
* \see _i_encode_button_mapping
*/
static int _i_decode_button_mapping( const std::array<uint8_t, 4>& bytes, std::string& mapping );
/** Convert raw dpi bytes to a string representation (doesn't validate dpi value)
* This function overloads the implementation from rd_mouse and supports actual DPI values.
* \return 0 if no error
*/
static int _i_decode_dpi( const std::array<uint8_t, 3>& dpi_bytes, std::string& dpi_string );
/// Names of the physical buttons
static std::map< int, std::string > _c_button_names;
/// The model name
static const std::string _c_name;
//usb device vars
static std::set< uint16_t > _c_all_pids;
/// USB vendor id
static const uint16_t _c_mouse_vid;
/// USB product id, needs to be explicitly set
uint16_t _c_mouse_pid = 0;
/// DPI → bytecode
static std::map< int, std::array<uint8_t,3> > _c_dpi_codes;
/// Values/keycodes of mouse buttons and special button functions
static std::map< std::string, std::array<uint8_t, 4> > _c_keycodes;
//setting vars
rd_profile _s_profile;
std::array<uint8_t, 2> _s_scrollspeeds;
std::array<m686_lightmode, 2> _s_lightmodes;
std::array<std::array<uint8_t, 3>, 2> _s_colors;
std::array<uint8_t, 2> _s_brightness_levels;
std::array<uint8_t, 2> _s_speed_levels;
std::array<std::array<bool, 5>, 2> _s_dpi_enabled;
std::array<std::array<std::array<uint8_t, 3>, 5>, 2> _s_dpi_levels;
std::array<std::array<std::array<uint8_t, 4>, 16>, 2> _s_keymap_data;
std::array<rd_report_rate, 2> _s_report_rates;
std::array<std::array<uint8_t, 256>, 15> _s_macro_data;
//usb data packets
/// Unknown function
static uint8_t _c_data_unknown_1[9][17];
/// button mapping
static uint8_t _c_data_button_mapping[8][17];
/// DPI values
static uint8_t _c_data_dpi[4][17];
/// Unknown function
static uint8_t _c_data_unknown_2[3][17];
/// LED settings
static uint8_t _c_data_led_static[3][17];
/// LED settings
static uint8_t _c_data_led_breathing[3][17];
/// LED settings
static uint8_t _c_data_led_off[2][17];
/// LED settings
static uint8_t _c_data_led_rainbow[3][17];
/// Unknown function
static uint8_t _c_data_unknown_3[1][17];
/// Used to read the settigs from the mouse
static uint8_t _c_data_read[69][17];
};
#endif

131
include/m686/readers.cpp Normal file
View file

@ -0,0 +1,131 @@
/*
* 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 "../rd_mouse.h"
//reader functions (get settings from mouse)
int mouse_m686::dump_settings( std::ostream& output ){
int ret = 0;
size_t rows = sizeof(_c_data_read) / sizeof(_c_data_read[0]);
uint8_t buffer_in[17];
for( size_t i = 0; i < rows; i++ ){
ret += libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0308, 0x0001, _c_data_read[i], 17, 1000 );
ret += libusb_interrupt_transfer( _i_handle, 0x82, buffer_in, 17, NULL, 1000 );
for( size_t j = 0; j < 17; j++ )
output << std::hex << std::setw(2) << std::setfill('0') << (int)buffer_in[j] << " ";
output << "\n";
}
output << std::dec << std::setw(0) << std::setfill(' ');
return ret;
}
int mouse_m686::read_and_print_settings( std::ostream& output ){
int ret = 0;
// read settings
size_t rows = sizeof(_c_data_read) / sizeof(_c_data_read[0]);
uint8_t buffer_in[rows][17];
for( size_t i = 0; i < rows; i++ ){
ret += libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0308, 0x0001, _c_data_read[i], 17, 1000 );
ret += libusb_interrupt_transfer( _i_handle, 0x82, buffer_in[i], 17, NULL, 1000 );
}
// decode and print the settings
output
<< "# Configuration created with mouse_m908 -R.\n"
<< "# This configuration can be send to the mouse with mouse_m908 -c.\n"
<< "# Note: this feature is incomplete for the m686.\n\n";
output
<< "# The m686 has two profiles that can be switched using the 'mode switch' button on the bottom of the mouse.\n"
<< "# Reading the settings can only be done for the active profile, therefore only profile1 is used in this config.\n"
<< "[profile1]\n\n";
output << "report_rate=";
switch(buffer_in[4][6]){
case 0x1: output << "1000\n"; break;
case 0x2: output << "500\n"; break;
case 0x4: output << "250\n"; break;
case 0x8: output << "125\n"; break;
default: output << "unknown\n"; break;
}
// DPI
output << "\n# DPI settings\n";
output << "# Currently active DPI level: " << (int)(buffer_in[2][6] + 1) << "\n";
std::string dpi = "";
_i_decode_dpi({buffer_in[5][8], buffer_in[5][9], buffer_in[5][11]}, dpi);
output << "dpi1=" << dpi << "\n";
_i_decode_dpi({buffer_in[5][12], buffer_in[5][13], buffer_in[5][15]}, dpi);
output << "dpi2=" << dpi << "\n";
_i_decode_dpi({buffer_in[6][6], buffer_in[6][7], buffer_in[6][9]}, dpi);
output << "dpi3=" << dpi << "\n";
_i_decode_dpi({buffer_in[6][10], buffer_in[6][11], buffer_in[6][13]}, dpi);
output << "dpi4=" << dpi << "\n";
_i_decode_dpi({buffer_in[6][14], buffer_in[6][15], buffer_in[7][7]}, dpi);
output << "dpi5=" << dpi << "\n";
// button mapping
output << "\n# Button mapping\n";
std::string mapping = "";
_i_decode_button_mapping({buffer_in[16][10], buffer_in[16][11], buffer_in[16][12], buffer_in[16][13]}, mapping);
output << "button_left=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[16][6], buffer_in[16][7], buffer_in[16][8], buffer_in[16][9]}, mapping);
output << "button_right=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[17][12], buffer_in[17][13], buffer_in[17][14], buffer_in[17][15]}, mapping);
output << "button_middle=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[18][6], buffer_in[18][7], buffer_in[18][8], buffer_in[18][9]}, mapping);
output << "button_fire=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[13][12], buffer_in[13][13], buffer_in[13][14], buffer_in[13][15]}, mapping);
output << "button_1=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[14][6], buffer_in[14][7], buffer_in[14][8], buffer_in[14][9]}, mapping);
output << "button_2=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[14][10], buffer_in[14][11], buffer_in[14][12], buffer_in[14][13]}, mapping);
output << "button_3=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[14][14], buffer_in[14][15], buffer_in[15][6], buffer_in[15][7]}, mapping);
output << "button_4=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[15][8], buffer_in[15][9], buffer_in[15][10], buffer_in[15][11]}, mapping);
output << "button_5=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[15][12], buffer_in[15][13], buffer_in[15][14], buffer_in[15][15]}, mapping);
output << "button_6=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[16][14], buffer_in[16][15], buffer_in[17][6], buffer_in[17][7]}, mapping);
output << "button_7=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[17][8], buffer_in[17][9], buffer_in[17][10], buffer_in[17][11]}, mapping);
output << "button_8=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[18][10], buffer_in[18][11], buffer_in[18][12], buffer_in[18][13]}, mapping);
output << "button_9=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[18][14], buffer_in[18][15], buffer_in[19][6], buffer_in[19][7]}, mapping);
output << "button_10=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[19][8], buffer_in[19][9], buffer_in[19][10], buffer_in[19][11]}, mapping);
output << "button_11=" << mapping << "\n";
_i_decode_button_mapping({buffer_in[19][12], buffer_in[19][13], buffer_in[19][14], buffer_in[19][15]}, mapping);
output << "button_12=" << mapping << "\n";
return ret;
}
int mouse_m686::read_settings(){
// currently not implemented
return 1;
}

256
include/m686/setters.cpp Normal file
View file

@ -0,0 +1,256 @@
/*
* 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 "../rd_mouse.h"
//setter functions
int mouse_m686::set_profile( rd_profile profile ){
_s_profile = profile;
return 0;
}
int mouse_m686::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[rd_profile_to_m686_profile(profile)] = speed;
return 0;
}
int mouse_m686::set_lightmode( rd_profile profile, rd_lightmode lightmode ){
mouse_m686::m686_lightmode l = mouse_m686::m686_lightmode::lightmode_static;
switch(lightmode){
case rd_mouse::rd_lightmode::lightmode_off: l = mouse_m686::m686_lightmode::lightmode_off; break;
case rd_mouse::rd_lightmode::lightmode_breathing: l = mouse_m686::m686_lightmode::lightmode_breathing; break;
case rd_mouse::rd_lightmode::lightmode_rainbow: l = mouse_m686::m686_lightmode::lightmode_rainbow; break;
default: l = mouse_m686::m686_lightmode::lightmode_static; break;
}
_s_lightmodes[rd_profile_to_m686_profile(profile)] = l;
return 0;
}
int mouse_m686::set_color( rd_profile profile, std::array<uint8_t, 3> color ){
_s_colors[rd_profile_to_m686_profile(profile)] = color;
return 0;
}
int mouse_m686::set_brightness( rd_profile profile, uint8_t brightness ){
//check bounds
if( brightness < _c_brightness_min || brightness > _c_brightness_max ){
return 1;
}
_s_brightness_levels[rd_profile_to_m686_profile(profile)] = brightness;
return 0;
}
int mouse_m686::set_speed( rd_profile profile, uint8_t speed ){
//check bounds
if( speed < _c_speed_min || speed > _c_speed_max ){
return 1;
}
_s_speed_levels[rd_profile_to_m686_profile(profile)] = speed;
return 0;
}
int mouse_m686::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[rd_profile_to_m686_profile(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[rd_profile_to_m686_profile(profile)][i] ){
sum++;
}
}
// if no level enabled: reenable specified level
if( sum == 0 ){
_s_dpi_enabled[rd_profile_to_m686_profile(profile)][level] = true;
return 1;
}
return 0;
}
int mouse_m686::set_dpi( rd_profile profile, int level, std::string dpi ){
// check DPI level bounds
if( level < _c_level_min || level > _c_level_max )
return 1;
// current assumption: only one profile
profile = rd_mouse::rd_profile::profile_1;
// check format: 0xABCD (raw bytes), TODO! enable or remove
/*
if( std::regex_match( dpi, std::regex("0x[[:xdigit:]]{4}") ) ){
uint8_t b0 = (uint8_t)stoi( dpi.substr(2,2), 0, 16 );
uint8_t b1 = (uint8_t)stoi( dpi.substr(4,2), 0, 16 );
//check bounds, bounds currently unknown TODO!
//if( b0 < _c_dpi_min || b0 > _c_dpi_max || b1 < _c_dpi_2_min || b1 > _c_dpi_2_max )
// return 1;
_s_dpi_levels[profile][level][0] = b0;
_s_dpi_levels[profile][level][1] = b1;
return 0;
}
*/
// check format: 1234 (real DPI)
if( std::regex_match( dpi, std::regex("[[:digit:]]+") ) ){
if( _c_dpi_codes.find( std::stoi(dpi) ) != _c_dpi_codes.end() ){
_s_dpi_levels[rd_profile_to_m686_profile(profile)][level] = _c_dpi_codes.at( std::stoi(dpi) );
return 0;
}
}
return 1;
}
int mouse_m686::set_dpi( rd_profile profile, int level, std::array<uint8_t, 3> dpi ){
// check DPI level bounds
if( level < _c_level_min || level > _c_level_max )
return 1;
// current assumption: only one profile
profile = rd_mouse::rd_profile::profile_1;
_s_dpi_levels[rd_profile_to_m686_profile(profile)][level] = dpi;
return 0;
}
int mouse_m686::set_key_mapping( rd_profile profile, int key, std::array<uint8_t, 4> mapping ){
_s_keymap_data[rd_profile_to_m686_profile(profile)][key][0] = mapping[0];
_s_keymap_data[rd_profile_to_m686_profile(profile)][key][1] = mapping[1];
_s_keymap_data[rd_profile_to_m686_profile(profile)][key][2] = mapping[2];
_s_keymap_data[rd_profile_to_m686_profile(profile)][key][3] = mapping[3];
return 0;
}
int mouse_m686::set_key_mapping( rd_profile profile, int key, std::string mapping ){
// valid key ?
if( _c_button_names[key] == "" )
return 1;
// current assumption: only one profile
profile = rd_mouse::rd_profile::profile_1;
// the m686 uses different keycodes, therefore the decoding is done here
if( _c_keycodes.find(mapping) != _c_keycodes.end() ){
_s_keymap_data[rd_profile_to_m686_profile(profile)][key] = _c_keycodes[mapping];
}
return 0;
}
int mouse_m686::set_report_rate( rd_profile profile, rd_report_rate report_rate ){
_s_report_rates[rd_profile_to_m686_profile(profile)] = report_rate;
return 0;
}
int mouse_m686::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;
}
std::array< uint8_t, 256 > macro_bytes;
_i_encode_macro( macro_bytes, config_in, 8 );
std::copy( macro_bytes.begin()+8, macro_bytes.end(), _s_macro_data[macro_number-1].begin()+8 );
config_in.close();
return 0;
}
int mouse_m686::set_all_macros( std::string file ){
//open file
std::ifstream config_in( file );
if( !config_in.is_open() ){
return 1;
}
int macro_number = 0; // initially invalid
std::array< std::stringstream, 15 > macro_streams;
// get all macros from file
for( std::string line; std::getline(config_in, line); ){
// empty line → skip
if( line.length() == 0 )
continue;
// macro header → set macro_number
if( std::regex_match( line, std::regex(";## macro[0-9]*") ) ){
macro_number = stoi( std::regex_replace( line, std::regex(";## macro"), "" ), 0, 10 );
}
// macro action
if( std::regex_match( line, std::regex(";# .*") ) ){
// valid macronumber ?
if( macro_number < 1 || macro_number > 15 )
continue;
macro_streams.at( macro_number-1 ) << std::regex_replace( line, std::regex(";# "), "" ) << "\n";
}
}
// encode and store all macros
for( int i = 0; i < 15; i++ ){
std::array< uint8_t, 256 > macro_bytes;
_i_encode_macro( macro_bytes, macro_streams.at(i), 8 );
std::copy( macro_bytes.begin()+8, macro_bytes.end(), _s_macro_data.at(i).begin()+8 );
}
return 0;
}

234
include/m686/writers.cpp Normal file
View file

@ -0,0 +1,234 @@
/*
* 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 "../rd_mouse.h"
//writer functions (apply changes to mouse)
int mouse_m686::write_profile(){
// missing data
throw std::string( "Changing profiles is not support for the M686, use the 'mode switch' button on the mouse instead." );
return 0;
}
int mouse_m686::write_data(uint8_t data[][17], size_t rows){
int ret = 0;
uint8_t buffer_in[17];
for( size_t i = 0; i < rows; i++ ){
ret += libusb_control_transfer( _i_handle, 0x21, 0x09, 0x0308, 0x0001, data[i], 17, 1000 );
ret += libusb_interrupt_transfer( _i_handle, 0x82, buffer_in, 17, NULL, 1000 );
}
return ret;
}
int mouse_m686::write_button_mapping( m686_profile profile ){
int ret = 0;
// part 1 (unknown function)
size_t rows_1 = sizeof(_c_data_unknown_1) / sizeof(_c_data_unknown_1[0]);
uint8_t buffer_1[rows_1][17];
for( size_t i = 0; i < rows_1; i++ ){
std::copy(std::begin(_c_data_unknown_1[i]), std::end(_c_data_unknown_1[i]), std::begin(buffer_1[i]));
}
ret += write_data(buffer_1, rows_1);
// part 2 (button mapping)
size_t rows_2 = sizeof(_c_data_button_mapping) / sizeof(_c_data_button_mapping[0]);
uint8_t buffer_2[rows_2][17];
for( size_t i = 0; i < rows_2; i++ ){
std::copy(std::begin(_c_data_button_mapping[i]), std::end(_c_data_button_mapping[i]), std::begin(buffer_2[i]));
}
// two buttons per packet
for( int i=0; i<16; i+=2 ){
int j = i/2;
buffer_2[j][6] = _s_keymap_data[profile][i][0];
buffer_2[j][7] = _s_keymap_data[profile][i][1];
buffer_2[j][8] = _s_keymap_data[profile][i][2];
buffer_2[j][9] = _s_keymap_data[profile][i][3];
buffer_2[j][10] = _s_keymap_data[profile][i+1][0];
buffer_2[j][11] = _s_keymap_data[profile][i+1][1];
buffer_2[j][12] = _s_keymap_data[profile][i+1][2];
buffer_2[j][13] = _s_keymap_data[profile][i+1][3];
}
ret += write_data(buffer_2, rows_2);
return ret;
}
int mouse_m686::write_dpi_settings( m686_profile profile ){
int ret = 0;
// part 1 (DPI)
size_t rows_1 = sizeof(_c_data_dpi) / sizeof(_c_data_dpi[0]);
uint8_t buffer_1[rows_1][17];
for( size_t i = 0; i < rows_1; i++ ){
std::copy(std::begin(_c_data_dpi[i]), std::end(_c_data_dpi[i]), std::begin(buffer_1[i]));
}
// DPI level 1
buffer_1[0][6] = _s_dpi_levels[profile][0][0];
buffer_1[0][7] = _s_dpi_levels[profile][0][1];
buffer_1[0][9] = _s_dpi_levels[profile][0][2];
// DPI level 2
buffer_1[0][10] = _s_dpi_levels[profile][1][0];
buffer_1[0][11] = _s_dpi_levels[profile][1][1];
buffer_1[0][13] = _s_dpi_levels[profile][1][2];
// DPI level 3
buffer_1[1][6] = _s_dpi_levels[profile][2][0];
buffer_1[1][7] = _s_dpi_levels[profile][2][1];
buffer_1[1][9] = _s_dpi_levels[profile][2][2];
// DPI level 4
buffer_1[1][10] = _s_dpi_levels[profile][3][0];
buffer_1[1][11] = _s_dpi_levels[profile][3][1];
buffer_1[1][13] = _s_dpi_levels[profile][3][2];
// DPI level 5
buffer_1[2][6] = _s_dpi_levels[profile][4][0];
buffer_1[2][7] = _s_dpi_levels[profile][4][1];
buffer_1[2][9] = _s_dpi_levels[profile][4][2];
// enabled DPI levels
uint8_t enabled_dpi_levels_1 = 0x05;
uint8_t enabled_dpi_levels_2 = 0x50;
if(!_s_dpi_enabled.at(profile).at(4)){
enabled_dpi_levels_1 = 0x04;
enabled_dpi_levels_2 = 0x51;
}
if(!_s_dpi_enabled.at(profile).at(3)){
enabled_dpi_levels_1 = 0x03;
enabled_dpi_levels_2 = 0x52;
}
if(!_s_dpi_enabled.at(profile).at(2)){
enabled_dpi_levels_1 = 0x02;
enabled_dpi_levels_2 = 0x53;
}
if(!_s_dpi_enabled.at(profile).at(1)){
enabled_dpi_levels_1 = 0x01;
enabled_dpi_levels_2 = 0x54;
}
buffer_1[3][6] = enabled_dpi_levels_1;
buffer_1[3][7] = enabled_dpi_levels_2;
ret += write_data(buffer_1, rows_1);
// part 2 (unknown function)
size_t rows_2 = sizeof(_c_data_unknown_2) / sizeof(_c_data_unknown_2[0]);
uint8_t buffer_2[rows_2][17];
for( size_t i = 0; i < rows_2; i++ ){
std::copy(std::begin(_c_data_unknown_2[i]), std::end(_c_data_unknown_2[i]), std::begin(buffer_2[i]));
}
ret += write_data(buffer_2, rows_2);
return ret;
}
int mouse_m686::write_led_settings( m686_profile profile ){
int ret = 0;
if(_s_lightmodes.at(profile) == mouse_m686::m686_lightmode::lightmode_off){
// part 1 (LED settings)
size_t rows_1 = sizeof(_c_data_led_off) / sizeof(_c_data_led_off[0]);
uint8_t buffer_1[rows_1][17];
for( size_t i = 0; i < rows_1; i++ ){
std::copy(std::begin(_c_data_led_off[i]), std::end(_c_data_led_off[i]), std::begin(buffer_1[i]));
}
ret += write_data(buffer_1, rows_1);
}else if(_s_lightmodes.at(profile) == mouse_m686::m686_lightmode::lightmode_breathing){
// part 1 (LED settings)
size_t rows_1 = sizeof(_c_data_led_breathing) / sizeof(_c_data_led_breathing[0]);
uint8_t buffer_1[rows_1][17];
for( size_t i = 0; i < rows_1; i++ ){
std::copy(std::begin(_c_data_led_breathing[i]), std::end(_c_data_led_breathing[i]), std::begin(buffer_1[i]));
}
ret += write_data(buffer_1, rows_1);
}else if(_s_lightmodes.at(profile) == mouse_m686::m686_lightmode::lightmode_rainbow){
// part 1 (LED settings)
size_t rows_1 = sizeof(_c_data_led_rainbow) / sizeof(_c_data_led_rainbow[0]);
uint8_t buffer_1[rows_1][17];
for( size_t i = 0; i < rows_1; i++ ){
std::copy(std::begin(_c_data_led_rainbow[i]), std::end(_c_data_led_rainbow[i]), std::begin(buffer_1[i]));
}
ret += write_data(buffer_1, rows_1);
}else{ // lightmode_static
// part 1 (LED settings)
size_t rows_1 = sizeof(_c_data_led_static) / sizeof(_c_data_led_static[0]);
uint8_t buffer_1[rows_1][17];
for( size_t i = 0; i < rows_1; i++ ){
std::copy(std::begin(_c_data_led_static[i]), std::end(_c_data_led_static[i]), std::begin(buffer_1[i]));
}
// TODO! fix
buffer_1[0][6] = _s_colors.at(profile).at(0);
buffer_1[0][7] = _s_colors.at(profile).at(1);
buffer_1[0][8] = _s_colors.at(profile).at(2);
buffer_1[0][12] = _s_brightness_levels[profile];
ret += write_data(buffer_1, rows_1);
}
/*
// part 2 (unknown function)
size_t rows_2 = sizeof(_c_data_unknown_3) / sizeof(_c_data_unknown_3[0]);
uint8_t buffer_2[rows_2][17];
for( size_t i = 0; i < rows_2; i++ ){
std::copy(std::begin(_c_data_unknown_3[i]), std::end(_c_data_unknown_3[i]), std::begin(buffer_2[i]));
}
ret += write_data(buffer_2, rows_2);
*/
return ret;
}
int mouse_m686::write_settings(){
// return value
int ret = 0;
ret += write_button_mapping(mouse_m686::m686_profile::profile_1);
ret += write_dpi_settings(mouse_m686::m686_profile::profile_1);
ret += write_led_settings(mouse_m686::m686_profile::profile_1);
// TODO! profile 2
return ret;
}
int mouse_m686::write_macro( int macro_number ){
// missing data
(void)macro_number;
throw std::string( "Macros are not supported for the M686." );
return 0;
}

View file

@ -43,6 +43,7 @@
*/
class mouse_generic;
class mouse_m607;
class mouse_m686;
class mouse_m709;
class mouse_m711;
class mouse_m715;
@ -127,6 +128,7 @@ class rd_mouse{
typedef std::variant<
rd_mouse::monostate,
mouse_m607,
mouse_m686,
mouse_m709,
mouse_m711,
mouse_m715,
@ -285,6 +287,7 @@ class rd_mouse{
// include header files for the individual models
#include "m607/mouse_m607.h"
#include "m686/mouse_m686.h"
#include "m709/mouse_m709.h"
#include "m711/mouse_m711.h"
#include "m715/mouse_m715.h"

View file

@ -14,7 +14,7 @@ LIBS != pkg-config --libs libusb-1.0
VERSION_STRING = "\"3.2\""
# compile
build: m607 m908 m709 m711 m715 m719 m721 m913 m990 m990chroma generic data_rd.o rd_mouse.o load_config.o mouse_m908.o
build: m607 m686 m908 m709 m711 m715 m719 m721 m913 m990 m990chroma generic data_rd.o rd_mouse.o load_config.o mouse_m908.o
$(CC) *.o -o mouse_m908 $(LIBS) $(CC_OPTIONS)
# copy all files to their correct location
@ -75,6 +75,8 @@ hpkg:
# targets for the different mice
m607: constructor_m607.o data_m607.o getters_m607.o helpers_m607.o setters_m607.o writers_m607.o readers_m607.o
m686: constructor_m686.o data_m686.o getters_m686.o helpers_m686.o setters_m686.o writers_m686.o readers_m686.o
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
@ -129,6 +131,27 @@ writers_m607.o:
readers_m607.o:
$(CC) -c include/m607/readers.cpp $(CC_OPTIONS) -o readers_m607.o
constructor_m686.o:
$(CC) -c include/m686/constructor.cpp $(CC_OPTIONS) -o constructor_m686.o
data_m686.o:
$(CC) -c include/m686/data.cpp $(CC_OPTIONS) -o data_m686.o
getters_m686.o:
$(CC) -c include/m686/getters.cpp $(CC_OPTIONS) -o getters_m686.o
helpers_m686.o:
$(CC) -c include/m686/helpers.cpp $(CC_OPTIONS) -o helpers_m686.o
setters_m686.o:
$(CC) -c include/m686/setters.cpp $(CC_OPTIONS) -o setters_m686.o
writers_m686.o:
$(CC) -c include/m686/writers.cpp $(CC_OPTIONS) -o writers_m686.o
readers_m686.o:
$(CC) -c include/m686/readers.cpp $(CC_OPTIONS) -o readers_m686.o
constructor_m908.o:
$(CC) -c include/m908/constructor.cpp $(CC_OPTIONS) -o constructor_m908.o