src/cadMousePro.cpp
branchv_0
changeset 5 6799cec5c2f8
parent 4 405aa9de65d2
child 6 975f38eb1e12
equal deleted inserted replaced
4:405aa9de65d2 5:6799cec5c2f8
     1 #include <iostream>
     1 #include <iostream>
     2 #include <array>
       
     3 #include <vector>
       
     4 #include <memory>
       
     5 #include <unistd.h>
       
     6 #include <cassert>
       
     7 #include <type_traits>
       
     8 
     2 
     9 #include <hidapi/hidapi.h>
     3 #include "CadMouseConfig.h"
    10 
     4 #include "HID.h"
    11 using Packet = std::vector<uint8_t>;
       
    12 static_assert(sizeof (uint8_t) == sizeof (unsigned char)); // unsigned char is used in the HID API library
       
    13 
       
    14 class HIDException {
       
    15 private:
       
    16 	std::wstring message;
       
    17 public:
       
    18 
       
    19 	HIDException(std::wstring message) : message(message) {
       
    20 	}
       
    21 
       
    22 	virtual ~HIDException() {
       
    23 	}
       
    24 
       
    25 	const std::wstring getMessage() const {
       
    26 		return message;
       
    27 	}
       
    28 
       
    29 };
       
    30 
       
    31 class HIDDevice {
       
    32 private:
       
    33 	std::shared_ptr<hid_device> handle;
       
    34 
       
    35 public:
       
    36 
       
    37 	HIDDevice(unsigned short vendorId, unsigned short productId, const wchar_t *serialNumber) {
       
    38 		int initError = hid_init(); // TODO: move to HIDContext class?
       
    39 		if (initError) throw HIDException(L"Unable to init HID API.");
       
    40 		handle.reset(hid_open(vendorId, productId, serialNumber), hid_close);
       
    41 		if (handle == nullptr) throw HIDException(L"Unable to open HID device. Are you root? Is mouse present?");
       
    42 	}
       
    43 
       
    44 	virtual ~HIDDevice() {
       
    45 		hid_exit(); // TODO: move to HIDContext class?
       
    46 	}
       
    47 
       
    48 	const std::wstring getManufacturerName() const {
       
    49 		std::array<wchar_t, 200 > buffer;
       
    50 		int error = hid_get_manufacturer_string(handle.get(), buffer.data(), buffer.size());
       
    51 		if (error) throw HIDException(L"Unable to get manufacturer name.");
       
    52 		return buffer.data();
       
    53 	}
       
    54 
       
    55 	const std::wstring getProductName() const {
       
    56 		std::array<wchar_t, 200 > buffer;
       
    57 		int error = hid_get_product_string(handle.get(), buffer.data(), buffer.size());
       
    58 		if (error) throw HIDException(L"Unable to get product name.");
       
    59 		return buffer.data();
       
    60 	}
       
    61 
       
    62 	const std::wstring getSerialNumber() const {
       
    63 		std::array<wchar_t, 200 > buffer;
       
    64 		int error = hid_get_serial_number_string(handle.get(), buffer.data(), buffer.size());
       
    65 		if (error) throw HIDException(L"Unable to get serial number.");
       
    66 		return buffer.data();
       
    67 	}
       
    68 
       
    69 	void sendFeatureReport(Packet data) {
       
    70 		int written = hid_send_feature_report(handle.get(), data.data(), data.size());
       
    71 		if (written < 0) throw HIDException(L"Unable to send feature report.");
       
    72 	}
       
    73 
       
    74 };
       
    75 
       
    76 enum class Frequency : uint8_t {
       
    77 	Hz_0125 = 8,
       
    78 	Hz_0250 = 4,
       
    79 	Hz_0500 = 2,
       
    80 	Hz_1000 = 1
       
    81 };
       
    82 
       
    83 using FrequencyType = std::underlying_type<Frequency>::type;
       
    84 
       
    85 class CadMouseConfig {
       
    86 private:
       
    87 	bool liftOffDetection = true;
       
    88 	bool smartScrolling = false;
       
    89 	Frequency frequency = Frequency::Hz_1000;
       
    90 public:
       
    91 
       
    92 	void setFrequency(Frequency frequency) {
       
    93 		this->frequency = frequency;
       
    94 	}
       
    95 
       
    96 	void setLiftOffDetection(bool liftOffDetection) {
       
    97 		this->liftOffDetection = liftOffDetection;
       
    98 	}
       
    99 
       
   100 	void setSmartScrolling(bool smartScrolling) {
       
   101 		this->smartScrolling = smartScrolling;
       
   102 	}
       
   103 
       
   104 	Packet serialize() {
       
   105 		Packet data;
       
   106 		data.reserve(32);
       
   107 
       
   108 		data.push_back(0x10); // report ID
       
   109 		data.push_back(0x00); // option
       
   110 
       
   111 		data.push_back(0x1c); // speed
       
   112 
       
   113 		data.push_back(liftOffDetection ? 0x00 : 0x1f);
       
   114 
       
   115 		if (smartScrolling) {
       
   116 			data.push_back(0x00);
       
   117 			data.push_back(0x00);
       
   118 			data.push_back(0x00);
       
   119 			data.push_back(0x01);
       
   120 		} else {
       
   121 			data.push_back(0x01);
       
   122 			data.push_back(0xff);
       
   123 			data.push_back(0x00);
       
   124 			data.push_back(0x00);
       
   125 		}
       
   126 
       
   127 		for (int i = 0; i < 8; i++) data.push_back(0x00); // constant padding or magic
       
   128 
       
   129 		// magic constants or unknown fields
       
   130 		data.push_back(0x00);
       
   131 		data.push_back(0x03);
       
   132 		data.push_back(0x00);
       
   133 		data.push_back(0x0a);
       
   134 		data.push_back(0x0b);
       
   135 		data.push_back(0x0c);
       
   136 		data.push_back(0x0c);
       
   137 		data.push_back(0x0e);
       
   138 		data.push_back(0x0d);
       
   139 		data.push_back(0x2f);
       
   140 		data.push_back(0x00);
       
   141 		data.push_back(0x1e);
       
   142 
       
   143 		data.push_back(0x00);
       
   144 		data.push_back(0x00);
       
   145 		data.push_back(0x00);
       
   146 		data.push_back(static_cast<FrequencyType> (frequency));
       
   147 
       
   148 		return data;
       
   149 	}
       
   150 
       
   151 };
       
   152 
     5 
   153 int main(int argc, char** argv) {
     6 int main(int argc, char** argv) {
   154 	try {
     7 	try {
   155 
     8 
   156 		std::wcout << L"cadMousePro" << std::endl;
     9 		std::wcout << L"cadMousePro" << std::endl;