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>
|
2019-11-08 17:10:30 -07:00
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
* There are 3 main types of functions:
|
|
|
|
* - set_*: setters
|
|
|
|
* - get_*: getters
|
|
|
|
* - write_*: write the settings to 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()
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
class mouse_m908{
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2020-05-05 14:50:31 -06:00
|
|
|
// constructor
|
2019-11-08 17:10:30 -07:00
|
|
|
mouse_m908();
|
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
|
2020-05-05 14:50:31 -06:00
|
|
|
// enums
|
|
|
|
/// The available profiles
|
2019-11-08 17:10:30 -07:00
|
|
|
enum m908_profile{
|
|
|
|
profile_1 = 0,
|
|
|
|
profile_2 = 1,
|
|
|
|
profile_3 = 2,
|
|
|
|
profile_4 = 3,
|
|
|
|
profile_5 = 4,
|
|
|
|
};
|
2020-05-05 14:50:31 -06:00
|
|
|
|
|
|
|
/// The available led modes
|
2019-11-08 17:10:30 -07:00
|
|
|
enum m908_lightmode{
|
|
|
|
lightmode_breathing,
|
|
|
|
lightmode_rainbow,
|
|
|
|
lightmode_static,
|
|
|
|
lightmode_wave,
|
|
|
|
lightmode_alternating,
|
|
|
|
lightmode_reactive,
|
|
|
|
lightmode_flashing,
|
|
|
|
lightmode_off,
|
|
|
|
};
|
2020-05-05 14:50:31 -06:00
|
|
|
|
|
|
|
/// The available USB report rates (polling rates)
|
2019-11-11 15:41:35 -07:00
|
|
|
enum m908_report_rate{
|
|
|
|
r_125Hz,
|
|
|
|
r_250Hz,
|
|
|
|
r_500Hz,
|
|
|
|
r_1000Hz
|
|
|
|
};
|
2019-11-08 17:10:30 -07:00
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//setter functions
|
2020-05-08 15:17:44 -06:00
|
|
|
/** Set the currently active profile
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_profile( m908_profile profile );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set the scrollspeed for the specified profile
|
|
|
|
* \see _scrollspeed_min
|
|
|
|
* \see _scrollspeed_max
|
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_scrollspeed( m908_profile profile, uint8_t speed );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set the led mode for the specified profile
|
|
|
|
* \see m908_lightmode
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_lightmode( m908_profile profile, m908_lightmode lightmode );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set the led color for the specified profile
|
|
|
|
* \param color color as {r, g, b}
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_color( m908_profile profile, std::array<uint8_t, 3> color );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set the led brightness for the specified profile
|
|
|
|
* \see _brightness_min
|
|
|
|
* \see _brightness_max
|
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_brightness( m908_profile profile, uint8_t brightness );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set the led animation speed for the specified profile
|
|
|
|
* \see _speed_min
|
|
|
|
* \see _speed_max
|
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_speed( m908_profile profile, uint8_t speed );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Enables/Disables a dpi level for the specified profile
|
|
|
|
* \see _level_min
|
|
|
|
* \see _level_max
|
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_dpi_enable( m908_profile profile, int level, bool enabled );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set the value of a dpi level for the specified profile
|
|
|
|
* \see _dpi_min
|
|
|
|
* \see _dpi_max
|
|
|
|
* \see _level_min
|
|
|
|
* \see _level_max
|
|
|
|
* \return 0 if successful, 1 if out of bounds
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_dpi( m908_profile profile, int level, uint8_t dpi );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set a mapping for a button for the specified profile
|
|
|
|
* \param mapping 4 bytes for the usb data packets
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-12-12 19:02:46 -07:00
|
|
|
int set_key_mapping( m908_profile profile, int key, std::array<uint8_t, 4> mapping );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** 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
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int set_key_mapping( m908_profile profile, int key, std::string mapping );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set the USB poll rate for the specified profile
|
|
|
|
* \see m908_report_rate
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-11-11 15:41:35 -07:00
|
|
|
int set_report_rate( m908_profile profile, m908_report_rate report_rate );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Load the macro from the specified file into the specified slot
|
|
|
|
* \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
|
|
|
|
|
|
|
/** Set how many times the specified macro should be repeated
|
|
|
|
* \param macro_number macro slot (1-15)
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-12-12 19:02:46 -07:00
|
|
|
int set_macro_repeat( int macro_number, uint8_t repeat );
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
/** Set whether to try to detach the kernel driver when opening the mouse
|
|
|
|
*/
|
2020-02-08 14:54:45 -07:00
|
|
|
int set_detach_kernel_driver( bool detach_kernel_driver );
|
2019-11-08 17:10:30 -07:00
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//getter functions
|
|
|
|
m908_profile get_profile();
|
|
|
|
uint8_t get_scrollspeed( m908_profile profile );
|
|
|
|
m908_lightmode get_lightmode( m908_profile profile );
|
|
|
|
void get_color( m908_profile profile, std::array<uint8_t, 3> &color );
|
|
|
|
uint8_t get_brightness( m908_profile profile );
|
|
|
|
uint8_t get_speed( m908_profile profile );
|
|
|
|
bool get_dpi_enable( m908_profile profile, int level );
|
|
|
|
uint8_t get_dpi( m908_profile profile, int level );
|
2019-11-11 15:41:35 -07:00
|
|
|
m908_report_rate get_report_rate( m908_profile profile );
|
2019-12-12 19:02:46 -07:00
|
|
|
uint8_t get_macro_repeat( int macro_number );
|
2019-11-08 17:10:30 -07:00
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//writer functions (apply settings to mouse)
|
2020-05-05 14:50:31 -06:00
|
|
|
/** Write the currently active profile to the mouse
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int write_profile();
|
2020-05-05 14:50:31 -06:00
|
|
|
|
|
|
|
/** Write the settings (leds, button mapping, dpi, etc.) to the mouse
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int write_settings();
|
2020-05-05 14:50:31 -06:00
|
|
|
|
|
|
|
/** Write a macro to the mouse
|
|
|
|
* \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
|
|
|
|
|
|
|
/** Write the number of repeats for a macro to the mouse
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-12-12 19:02:46 -07:00
|
|
|
int write_macro_repeat( int macro_number );
|
2019-11-08 17:10:30 -07:00
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//helper functions
|
2020-05-05 14:50:31 -06:00
|
|
|
/** Init libusb and open the mouse by its USB VID and PID
|
|
|
|
* \return 0 if successful
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int open_mouse();
|
2020-05-05 14:50:31 -06:00
|
|
|
|
|
|
|
/** Init libusb and open the mouse by the USB bus and device adress
|
|
|
|
* \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
|
|
|
|
|
|
|
/** Close the mouse and libusb
|
|
|
|
* \return 0 if successful (always at the moment)
|
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
int close_mouse();
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2020-02-08 14:54:45 -07:00
|
|
|
// whether to detach kernel driver
|
|
|
|
bool _detach_kernel_driver = true;
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//usb device vars
|
2020-05-08 15:17:44 -06:00
|
|
|
static const uint16_t _mouse_vid;
|
|
|
|
static const uint16_t _mouse_pid;
|
2019-11-08 17:10:30 -07:00
|
|
|
libusb_device_handle* _handle;
|
|
|
|
bool _detached_driver_0 = false;
|
|
|
|
bool _detached_driver_1 = false;
|
|
|
|
bool _detached_driver_2 = false;
|
|
|
|
|
2020-05-08 15:17:44 -06:00
|
|
|
//setting min and max values
|
|
|
|
static const uint8_t _scrollspeed_min, _scrollspeed_max;
|
|
|
|
static const uint8_t _brightness_min, _brightness_max;
|
|
|
|
static const uint8_t _speed_min, _speed_max;
|
|
|
|
static const uint8_t _level_min, _level_max;
|
|
|
|
static const uint8_t _dpi_min, _dpi_max;
|
|
|
|
|
2019-11-08 17:10:30 -07:00
|
|
|
//setting vars
|
|
|
|
m908_profile _profile;
|
|
|
|
std::array<uint8_t, 5> _scrollspeeds;
|
|
|
|
std::array<m908_lightmode, 5> _lightmodes;
|
|
|
|
std::array<std::array<uint8_t, 3>, 5> _colors;
|
|
|
|
std::array<uint8_t, 5> _brightness_levels;
|
|
|
|
std::array<uint8_t, 5> _speed_levels;
|
|
|
|
std::array<std::array<bool, 5>, 5> _dpi_enabled;
|
|
|
|
std::array<std::array<uint8_t, 5>, 5> _dpi_levels;
|
2019-12-12 19:02:46 -07:00
|
|
|
std::array<std::array<std::array<uint8_t, 4>, 20>, 5> _keymap_data;
|
2019-11-11 15:41:35 -07:00
|
|
|
std::array<m908_report_rate, 5> _report_rates;
|
2019-12-07 17:52:41 -07:00
|
|
|
std::array<std::array<uint8_t, 256>, 15> _macro_data;
|
2019-12-12 19:02:46 -07:00
|
|
|
std::array<uint8_t, 15> _macro_repeat;
|
2019-11-08 17:10:30 -07:00
|
|
|
|
|
|
|
//mapping of button names to values
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Values/keycodes of mouse buttons and special button functions
|
|
|
|
static std::map< std::string, std::array<uint8_t, 3> > _keycodes;
|
|
|
|
/// Values of keyboard modifiers
|
|
|
|
static const std::map< std::string, uint8_t > _keyboard_modifier_values;
|
|
|
|
/// Values/keycodes of keyboard keys
|
|
|
|
static std::map< std::string, uint8_t > _keyboard_key_values;
|
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-04-08 07:39:30 -06:00
|
|
|
static uint8_t _data_profile[6][16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending the settings, part 1/3
|
2020-04-08 07:39:30 -06:00
|
|
|
static uint8_t _data_settings_1[15][16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending the settings, part 2/3
|
2019-11-08 17:10:30 -07:00
|
|
|
static uint8_t _data_settings_2[64];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending the settings, part 3/3
|
2020-04-08 07:39:30 -06:00
|
|
|
static uint8_t _data_settings_3[140][16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending a macro, part 1/3
|
2019-12-07 17:52:41 -07:00
|
|
|
static uint8_t _data_macros_1[16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending a macro, part 2/3
|
2019-12-07 17:52:41 -07:00
|
|
|
static uint8_t _data_macros_2[256];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used for sending a macro, part 3/3
|
2019-12-07 17:52:41 -07:00
|
|
|
static uint8_t _data_macros_3[16];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Lookup table for used when specifying which slot to send a macro to
|
2019-12-07 17:52:41 -07:00
|
|
|
static uint8_t _data_macros_codes[15][2];
|
2020-05-08 15:17:44 -06:00
|
|
|
/// Used to send the number repeats for a macro
|
2019-12-12 19:02:46 -07:00
|
|
|
static uint8_t _data_macros_repeat[16];
|
2019-11-08 17:10:30 -07:00
|
|
|
};
|
|
|
|
|
2020-04-08 07:39:30 -06:00
|
|
|
/* the files are now compiled individually
|
2019-11-08 17:10:30 -07:00
|
|
|
#include "data.cpp"
|
|
|
|
#include "constructor.cpp"
|
|
|
|
#include "helpers.cpp"
|
|
|
|
#include "getters.cpp"
|
|
|
|
#include "setters.cpp"
|
|
|
|
#include "writers.cpp"
|
2020-04-08 07:39:30 -06:00
|
|
|
*/
|
2019-11-08 17:10:30 -07:00
|
|
|
|
|
|
|
#endif
|