2019-11-08 17:10:30 -07:00
|
|
|
/*
|
|
|
|
* 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_M908
|
|
|
|
#define MOUSE_M908
|
|
|
|
|
2020-04-19 06:51:05 -06:00
|
|
|
#include <libusb.h>
|
2019-11-08 17:10:30 -07:00
|
|
|
#include <map>
|
|
|
|
#include <array>
|
|
|
|
#include <string>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <exception>
|
2019-11-30 16:01:15 -07:00
|
|
|
#include <regex>
|
2019-12-07 17:52:41 -07:00
|
|
|
#include <fstream>
|
2020-04-19 06:53:31 -06:00
|
|
|
#include <sstream>
|
2019-12-07 17:52:41 -07:00
|
|
|
#include <utility>
|
2020-05-09 14:33:14 -06:00
|
|
|
#include <iostream>
|
2020-05-09 15:36:23 -06:00
|
|
|
#include <iomanip>
|
2019-11-08 17:10:30 -07:00
|
|
|
|
2020-07-12 12:35:13 -06:00
|
|
|
#include "../rd_mouse.h"
|
|
|
|
|
2020-05-05 14:50:31 -06:00
|
|
|
/**
|
|
|
|
* The main class representing the M908 mouse.
|
|
|
|
* This class has member functions to open, close and apply settings to the mouse.
|
|
|
|
*
|
2020-05-21 16:13:37 -06:00
|
|
|
* There are 4 main types of functions:
|
2020-05-05 14:50:31 -06:00
|
|
|
* - set_*: setters
|
|
|
|
* - get_*: getters
|
|
|
|
* - write_*: write the settings to the mouse
|
2020-05-21 16:13:37 -06:00
|
|
|
* - read_*: read the sttings from the mouse
|
2020-05-05 14:50:31 -06:00
|
|
|
*
|
|
|
|
* 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()
|
2020-05-21 16:13:37 -06:00
|
|
|
*
|
2020-05-21 16:50:02 -06:00
|
|
|
* 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)
|
2020-05-05 14:50:31 -06:00
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
class mouse_m908 : public rd_mouse{
|
2019-11-08 17:10:30 -07:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/// The default constructor. Sets the default settings.
|
2019-11-08 17:10:30 -07:00
|
|
|
mouse_m908();
|
|
|
|
|
|
|
|
//setter functions
|
2020-05-21 16:13:37 -06:00
|
|
|
/// Set the currently active profile
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_profile( rd_profile profile );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set the scrollspeed for the specified profile
|
2020-05-21 16:50:02 -06:00
|
|
|
* \see _c_scrollspeed_min
|
|
|
|
* \see _c_scrollspeed_max
|
2020-05-08 15:17:44 -06:00
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_scrollspeed( rd_profile profile, uint8_t speed );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set the led mode for the specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
* \see rd_lightmode
|
2020-05-08 15:17:44 -06:00
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_lightmode( rd_profile profile, rd_lightmode lightmode );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set the led color for the specified profile
|
2020-05-08 15:17:44 -06:00
|
|
|
* \param color color as {r, g, b}
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_color( rd_profile profile, std::array<uint8_t, 3> color );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set the led brightness for the specified profile
|
2020-05-21 16:50:02 -06:00
|
|
|
* \see _c_brightness_min
|
|
|
|
* \see _c_brightness_max
|
2020-05-08 15:17:44 -06:00
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_brightness( rd_profile profile, uint8_t brightness );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set the led animation speed for the specified profile
|
2020-05-21 16:50:02 -06:00
|
|
|
* \see _c_speed_min
|
|
|
|
* \see _c_speed_max
|
2020-05-08 15:17:44 -06:00
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_speed( rd_profile profile, uint8_t speed );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Enables/Disables a dpi level for the specified profile
|
2020-05-21 16:50:02 -06:00
|
|
|
* \see _c_level_min
|
|
|
|
* \see _c_level_max
|
2020-05-08 15:17:44 -06:00
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_dpi_enable( rd_profile profile, int level, bool enabled );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set the value of a dpi level for the specified profile
|
2020-05-21 16:50:02 -06:00
|
|
|
* \see _c_dpi_min
|
|
|
|
* \see _c_dpi_max
|
|
|
|
* \see _c_level_min
|
|
|
|
* \see _c_level_max
|
2020-09-21 13:16:14 -06:00
|
|
|
* \return 0 if successful, 1 if out of bounds or invalid dpi
|
2020-05-08 15:17:44 -06:00
|
|
|
*/
|
2020-09-21 13:16:14 -06:00
|
|
|
int set_dpi( rd_profile profile, int level, std::string dpi );
|
2020-09-22 10:24:07 -06:00
|
|
|
int set_dpi( rd_profile profile, int level, std::array<uint8_t, 2> dpi );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set a mapping for a button for the specified profile
|
2020-05-08 15:17:44 -06:00
|
|
|
* \param mapping 4 bytes for the usb data packets
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_key_mapping( rd_profile profile, int key, std::array<uint8_t, 4> mapping );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set a mapping for a button for the specified profile
|
2020-05-08 15:17:44 -06:00
|
|
|
* \param mapping button name (see keymap.md)
|
|
|
|
* \return 0 if successful, 1 if mapping is invalid
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_key_mapping( rd_profile profile, int key, std::string mapping );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Set the USB poll rate for the specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
* \see rd_report_rate
|
2020-05-08 15:17:44 -06:00
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2020-07-12 12:35:13 -06:00
|
|
|
int set_report_rate( rd_profile profile, rd_report_rate report_rate );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Load the macro from the specified file into the specified slot
|
2020-05-08 15:17:44 -06:00
|
|
|
* \param macro_number macro slot (1-15)
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-12-07 17:52:41 -07:00
|
|
|
int set_macro( int macro_number, std::string file );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Load all macros from the specified .ini file
|
2020-05-13 11:28:09 -06:00
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
|
|
|
int set_all_macros( std::string file );
|
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//getter functions
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get currently active profile
|
2020-07-12 12:35:13 -06:00
|
|
|
rd_profile get_profile();
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get scrollspeed of specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
uint8_t get_scrollspeed( rd_profile profile );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get led mode of specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
rd_lightmode get_lightmode( rd_profile profile );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get led color of specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
void get_color( rd_profile profile, std::array<uint8_t, 3> &color );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get led brightness of specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
uint8_t get_brightness( rd_profile profile );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get led animation speed of specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
uint8_t get_speed( rd_profile profile );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get dpi level enabled/disabled status of specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
bool get_dpi_enable( rd_profile profile, int level );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get dpi value of specified level and profile
|
2020-09-22 10:24:07 -06:00
|
|
|
int get_dpi( rd_profile profile, int level, std::array<uint8_t, 2>& dpi );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get USB poll rate of specified profile
|
2020-07-12 12:35:13 -06:00
|
|
|
rd_report_rate get_report_rate( rd_profile profile );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get button mapping as a string
|
2020-07-12 12:35:13 -06:00
|
|
|
int get_key_mapping( rd_profile profile, int key, std::string& mapping );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get button mapping as a 4-byte value
|
2020-07-12 12:35:13 -06:00
|
|
|
int get_key_mapping_raw( rd_profile profile, int key, std::array<uint8_t, 4>& mapping );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get macro as a string
|
2020-05-11 13:29:19 -06:00
|
|
|
int get_macro( int number, std::string& macro );
|
2020-05-11 14:12:38 -06:00
|
|
|
/// Get raw macro bytecode
|
2020-05-11 13:29:19 -06:00
|
|
|
int get_macro_raw( int number, std::array<uint8_t, 256>& macro );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2020-08-14 11:33:57 -06:00
|
|
|
/// Get USB vendor id
|
|
|
|
static uint16_t get_vid(){
|
|
|
|
return _c_mouse_vid;
|
|
|
|
}
|
|
|
|
/// Get USB product id
|
|
|
|
static uint16_t get_pid(){
|
|
|
|
return _c_mouse_pid;
|
|
|
|
}
|
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//writer functions (apply settings to mouse)
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Write the currently active profile to the mouse
|
2020-05-05 14:50:31 -06:00
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int write_profile();
|
2020-05-05 14:50:31 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Write the settings (leds, button mapping, dpi, etc.) to the mouse
|
2020-05-05 14:50:31 -06:00
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2020-09-22 14:18:34 -06:00
|
|
|
int write_settings();
|
2020-05-05 14:50:31 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Write a macro to the mouse
|
2020-05-05 14:50:31 -06:00
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-12-07 17:52:41 -07:00
|
|
|
int write_macro( int macro_number );
|
2020-05-05 14:50:31 -06:00
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//helper functions
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Init libusb and open the mouse by its USB VID and PID
|
2020-05-05 14:50:31 -06:00
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int open_mouse();
|
2020-05-05 14:50:31 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Init libusb and open the mouse by the USB bus and device adress
|
2020-05-05 14:50:31 -06:00
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2020-02-07 20:34:17 -07:00
|
|
|
int open_mouse_bus_device( uint8_t bus, uint8_t device );
|
2020-05-05 14:50:31 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/** \brief Close the mouse and libusb
|
2020-05-05 14:50:31 -06:00
|
|
|
* \return 0 if successful (always at the moment)
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int close_mouse();
|
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
/// Print the current configuration in .ini format to output
|
2020-09-22 14:18:34 -06:00
|
|
|
int print_settings( std::ostream& output );
|
|
|
|
|
|
|
|
/** Convert raw dpi bytes to a string representation (doesn't validate dpi value)
|
|
|
|
* \return 0 if no error
|
|
|
|
*/
|
2020-09-24 09:23:34 -06:00
|
|
|
int dpi_bytes_to_string( std::array<uint8_t, 2>& dpi_bytes, std::string& dpi_string );
|
2020-05-11 11:02:26 -06:00
|
|
|
|
2020-05-09 14:33:14 -06:00
|
|
|
|
2020-05-21 16:13:37 -06:00
|
|
|
|
2020-05-09 14:33:14 -06:00
|
|
|
//reader functions (get settings from the mouse)
|
2020-05-21 16:13:37 -06:00
|
|
|
/// Read the settings and print the raw data to output
|
2020-05-11 08:49:58 -06:00
|
|
|
int dump_settings( std::ostream& output );
|
2020-05-09 15:36:23 -06:00
|
|
|
/**
|
2020-05-21 16:13:37 -06:00
|
|
|
* \brief Read the settings and print the configuration in .ini format to output.
|
2020-05-11 14:12:38 -06:00
|
|
|
* This does not alter the internal settings of the mouse_m908 class.
|
2020-05-09 15:36:23 -06:00
|
|
|
*/
|
2020-05-11 08:49:58 -06:00
|
|
|
int read_and_print_settings( std::ostream& output );
|
2020-05-11 14:12:38 -06:00
|
|
|
/**
|
2020-05-21 16:13:37 -06:00
|
|
|
* \brief Read the settings and print the configuration in .ini format to output.
|
2020-05-11 14:12:38 -06:00
|
|
|
* This updates the internal settings of the mouse_m908 class.
|
|
|
|
*/
|
|
|
|
int read_settings();
|
|
|
|
|
2020-07-20 12:28:10 -06:00
|
|
|
|
|
|
|
|
|
|
|
/// Returns a reference to _c_button_names (physical button names)
|
|
|
|
std::map< int, std::string >& button_names(){ return _c_button_names; }
|
2020-05-09 14:33:14 -06:00
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
private:
|
|
|
|
|
2020-07-20 12:28:10 -06:00
|
|
|
/// Names of the physical buttons
|
|
|
|
static std::map< int, std::string > _c_button_names;
|
|
|
|
|
2020-09-24 09:23:34 -06:00
|
|
|
/// Mapping of real DPI values to bytecode
|
|
|
|
static std::map< unsigned int, std::array<uint8_t, 2> > _c_dpi_codes;
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//usb device vars
|
2020-05-11 14:12:38 -06:00
|
|
|
/// USB vendor id
|
2020-05-21 16:50:02 -06:00
|
|
|
static const uint16_t _c_mouse_vid;
|
2020-05-11 14:12:38 -06:00
|
|
|
/// USB product id
|
2020-05-21 16:50:02 -06:00
|
|
|
static const uint16_t _c_mouse_pid;
|
2019-11-08 17:10:30 -07:00
|
|
|
|
|
|
|
//setting vars
|
2020-07-12 12:35:13 -06:00
|
|
|
rd_profile _s_profile;
|
2020-05-21 16:50:02 -06:00
|
|
|
std::array<uint8_t, 5> _s_scrollspeeds;
|
2020-07-12 12:35:13 -06:00
|
|
|
std::array<rd_lightmode, 5> _s_lightmodes;
|
2020-05-21 16:50:02 -06:00
|
|
|
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;
|
2020-09-21 13:16:14 -06:00
|
|
|
std::array<std::array<std::array<uint8_t, 2>, 5>, 5> _s_dpi_levels;
|
2020-05-21 16:50:02 -06:00
|
|
|
std::array<std::array<std::array<uint8_t, 4>, 20>, 5> _s_keymap_data;
|
2020-07-12 12:35:13 -06:00
|
|
|
std::array<rd_report_rate, 5> _s_report_rates;
|
2020-05-21 16:50:02 -06:00
|
|
|
std::array<std::array<uint8_t, 256>, 15> _s_macro_data;
|
2019-11-08 17:10:30 -07:00
|
|
|
|
|
|
|
//usb data packets
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for changing the active profile
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_s_profile[6][16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending the settings, part 1/3
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_settings_1[15][16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending the settings, part 2/3
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_settings_2[64];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending the settings, part 3/3
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_settings_3[140][16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending a macro, part 1/3
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_macros_1[16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending a macro, part 2/3
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_macros_2[256];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending a macro, part 3/3
|
2020-05-21 16:50:02 -06:00
|
|
|
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];
|
2020-05-09 14:33:14 -06:00
|
|
|
/// Used to read the settings, part 1/3
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_read_1[9][16];
|
2020-05-09 14:33:14 -06:00
|
|
|
/// Used to read the settings, part 2/3
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_read_2[85][64];
|
2020-05-09 14:33:14 -06:00
|
|
|
/// Used to read the settings, part 3/3
|
2020-05-21 16:50:02 -06:00
|
|
|
static uint8_t _c_data_read_3[101][16];
|
2019-11-08 17:10:30 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|