From 74d64a2dc4c60d9d30996a3e7382eb959461807d Mon Sep 17 00:00:00 2001
From: dokutan <54861821+dokutan@users.noreply.github.com>
Date: Tue, 1 Jun 2021 22:58:16 +0200
Subject: [PATCH] Add initial support for actual DPI values for the M711

---
 include/m711/data.cpp     | 100 ++++++++++++++++++++++++++++++++++++++
 include/m711/helpers.cpp  |  25 ++++++++++
 include/m711/mouse_m711.h |   9 ++++
 include/m711/setters.cpp  |  13 +++++
 4 files changed, 147 insertions(+)

diff --git a/include/m711/data.cpp b/include/m711/data.cpp
index 30621fd..925db48 100644
--- a/include/m711/data.cpp
+++ b/include/m711/data.cpp
@@ -39,6 +39,106 @@ std::map< int, std::string > mouse_m711::_c_button_names = {
 	{ 6, "scroll_up" },
 	{ 7, "scroll_down" } };
 
+// Mapping of real DPI values to bytecode
+std::map< unsigned int, std::array<uint8_t, 2> > mouse_m711::_c_dpi_codes = {
+	{ 100, {0x2, 0x00} },
+	{ 200, {0x4, 0x00} },
+	{ 300, {0x6, 0x00} },
+	{ 400, {0x9, 0x00} },
+	{ 500, {0xb, 0x00} },
+	
+	// copied from the M908
+	/* 
+	{ 600, {0xd, 0x00} },
+	{ 700, {0xf, 0x00} },
+	{ 800, {0x12, 0x00} },
+	{ 900, {0x14, 0x00} },
+	{ 1000, {0x16, 0x00} },
+	{ 1100, {0x18, 0x00} },
+	{ 1200, {0x1b, 0x00} },
+	{ 1300, {0x1d, 0x00} },
+	{ 1400, {0x1f, 0x00} },
+	{ 1500, {0x21, 0x00} },
+	{ 1600, {0x24, 0x00} },
+	{ 1700, {0x26, 0x00} },
+	{ 1800, {0x28, 0x00} },
+	{ 1900, {0x2b, 0x00} },
+	{ 2000, {0x2d, 0x00} },
+	{ 2100, {0x2f, 0x00} },
+	{ 2200, {0x31, 0x00} },
+	{ 2300, {0x34, 0x00} },
+	{ 2400, {0x36, 0x00} },
+	{ 2500, {0x38, 0x00} },
+	{ 2600, {0x3a, 0x00} },
+	{ 2700, {0x3d, 0x00} },
+	{ 2800, {0x3f, 0x00} },
+	{ 2900, {0x41, 0x00} },
+	{ 3000, {0x43, 0x00} },
+	{ 3100, {0x46, 0x00} },
+	{ 3200, {0x48, 0x00} },
+	{ 3300, {0x4a, 0x00} },
+	{ 3400, {0x4d, 0x00} },
+	{ 3500, {0x4f, 0x00} },
+	{ 3600, {0x51, 0x00} },
+	{ 3700, {0x53, 0x00} },
+	{ 3800, {0x56, 0x00} },
+	{ 3900, {0x58, 0x00} },
+	{ 4000, {0x5a, 0x00} },
+	{ 4100, {0x5c, 0x00} },
+	{ 4200, {0x5f, 0x00} },
+	{ 4300, {0x61, 0x00} },
+	{ 4400, {0x63, 0x00} },
+	{ 4500, {0x66, 0x00} },
+	{ 4600, {0x68, 0x00} },
+	{ 4700, {0x6a, 0x00} },
+	{ 4800, {0x6c, 0x00} },
+	{ 4900, {0x6f, 0x00} },
+	{ 5000, {0x71, 0x00} },
+	{ 5100, {0x73, 0x00} },
+	{ 5200, {0x75, 0x00} },
+	{ 5300, {0x78, 0x00} },
+	{ 5400, {0x7a, 0x00} },
+	{ 5500, {0x7c, 0x00} },
+	{ 5600, {0x7f, 0x00} },
+	{ 5700, {0x81, 0x00} },
+	{ 5800, {0x83, 0x00} },
+	{ 5900, {0x85, 0x00} },
+	{ 6000, {0x87, 0x00} },
+	{ 6100, {0x8a, 0x00} },
+	{ 6200, {0x8c, 0x00} },
+	{ 6400, {0x48, 0x01} },
+	{ 6600, {0x4a, 0x01} },
+	{ 6800, {0x4d, 0x01} },
+	{ 7000, {0x4f, 0x01} },
+	{ 7200, {0x51, 0x01} },
+	{ 7400, {0x53, 0x01} },
+	{ 7600, {0x56, 0x01} },
+	{ 7800, {0x58, 0x01} },
+	{ 8000, {0x5a, 0x01} },
+	{ 8200, {0x5c, 0x01} },
+	{ 8400, {0x5f, 0x01} },
+	{ 8600, {0x61, 0x01} },
+	{ 8800, {0x63, 0x01} },
+	{ 9000, {0x66, 0x01} },
+	{ 9200, {0x68, 0x01} },
+	{ 9400, {0x6a, 0x01} },
+	{ 9600, {0x6c, 0x01} },
+	{ 9800, {0x6f, 0x01} },
+	{ 10000, {0x71, 0x01} },
+	{ 10200, {0x73, 0x01} },
+	{ 10400, {0x75, 0x01} },
+	{ 10600, {0x78, 0x01} },
+	{ 10800, {0x7a, 0x01} },
+	{ 11000, {0x7c, 0x01} },
+	{ 11200, {0x7f, 0x01} },
+	{ 11400, {0x81, 0x01} },
+	{ 11600, {0x83, 0x01} },
+	{ 11800, {0x85, 0x01} },
+	{ 12000, {0x87, 0x01} },
+	{ 12200, {0x8a, 0x01} },
+	{ 12400, {0x8c, 0x01} }*/
+};
+
 //usb data packets
 uint8_t mouse_m711::_c_data_s_profile[6][16] = {
 	{0x02, 0xf3, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
diff --git a/include/m711/helpers.cpp b/include/m711/helpers.cpp
index 189138b..ed5a42e 100644
--- a/include/m711/helpers.cpp
+++ b/include/m711/helpers.cpp
@@ -156,3 +156,28 @@ int mouse_m711::print_settings( std::ostream& output ){
 	
 	return 0;
 }
+
+int mouse_m711::_i_decode_dpi( std::array<uint8_t, 2>& 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_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];
+	conversion_stream << std::setfill(' ') << std::setw(0) << std::dec;
+	
+	dpi_string = conversion_stream.str();
+	
+	return 0;
+}
\ No newline at end of file
diff --git a/include/m711/mouse_m711.h b/include/m711/mouse_m711.h
index bcb502c..8debac0 100644
--- a/include/m711/mouse_m711.h
+++ b/include/m711/mouse_m711.h
@@ -258,6 +258,9 @@ class mouse_m711 : public rd_mouse{
 		
 		/// Names of the physical buttons
 		static std::map< int, std::string > _c_button_names;
+
+		/// Mapping of real DPI values to bytecode
+		static std::map< unsigned int, std::array<uint8_t, 2> > _c_dpi_codes;
 		
 		/// The model name
 		static const std::string _c_name;
@@ -307,6 +310,12 @@ class mouse_m711 : public rd_mouse{
 		static uint8_t _c_data_read_2[85][64];
 		/// Used to read the settings, part 3/3 
 		static uint8_t _c_data_read_3[46][16];
+
+		/** 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( std::array<uint8_t, 2>& dpi_bytes, std::string& dpi_string );
 };
 
 #endif
diff --git a/include/m711/setters.cpp b/include/m711/setters.cpp
index 5a368dc..20a5f2a 100644
--- a/include/m711/setters.cpp
+++ b/include/m711/setters.cpp
@@ -117,6 +117,19 @@ int mouse_m711::set_dpi( rd_profile profile, int level, std::string dpi ){
 		return 0;
 		
 	}
+
+	// check format: 1234 (real DPI)
+	else if( std::regex_match( dpi, std::regex("[[:digit:]]+") ) ){
+		
+		if( _c_dpi_codes.find( std::stoi(dpi) ) != _c_dpi_codes.end() ){
+			
+			_s_dpi_levels[profile][level][0] = _c_dpi_codes.at( std::stoi(dpi) )[0];
+			_s_dpi_levels[profile][level][1] = _c_dpi_codes.at( std::stoi(dpi) )[1];
+			
+			return 0;
+		}
+		
+	}
 	
 	return 1;
 }