/* * 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_m715.h" //reader functions (get settings from mouse) int mouse_m715::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_m715::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+1] == 0x01 ) output << ";# down\tmouse_left\n"; else if( macro_bytes[i][j+1] == 0x02 ) output << ";# down\tmouse_right\n"; else if( macro_bytes[i][j+1] == 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+1] == 0x01 ) output << ";# up\tmouse_left\n"; else if( macro_bytes[i][j+1] == 0x02 ) output << ";# up\tmouse_right\n"; else if( macro_bytes[i][j+1] == 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_m715::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; }