--- a/.hgignore Mon Aug 19 17:21:02 2019 +0200
+++ b/.hgignore Mon Aug 19 17:27:19 2019 +0200
@@ -7,7 +7,6 @@
^temp/
-^\.dep\.inc
-^dist/
-^build/
-^nbproject/private/
+^[^/]+/dist/
+^[^/]+/build/
+^[^/]+/nbproject/private/
--- a/CMakeLists.txt Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-project (cadMousePro)
-cmake_minimum_required(VERSION 2.8)
-add_subdirectory (src)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/CMakeLists.txt Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,3 @@
+project (cadMousePro-daemon)
+cmake_minimum_required(VERSION 2.8)
+add_subdirectory (src)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/nbproject/configurations.xml Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright (c) 2014, 2016 Oracle and/or its affiliates. All rights reserved.
+
+Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+Other names may be trademarks of their respective owners.
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+
+Contributor(s):
+-->
+<configurationDescriptor version="100">
+ <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
+ <df root="." name="0">
+ <df name="src">
+ <in>cadMousePro.cpp</in>
+ </df>
+ </df>
+ <logicalFolder name="ExternalFiles"
+ displayName="Important Files"
+ projectFiles="false"
+ kind="IMPORTANT_FILES_FOLDER">
+ <itemPath>CMakeLists.txt</itemPath>
+ <itemPath>build/Debug/Makefile</itemPath>
+ <itemPath>build/Release/Makefile</itemPath>
+ </logicalFolder>
+ </logicalFolder>
+ <sourceFolderFilter>^(nbproject|build)$</sourceFolderFilter>
+ <sourceRootList>
+ <Elem>.</Elem>
+ </sourceRootList>
+ <projectmakefile>build/Debug/Makefile</projectmakefile>
+ <confs>
+ <conf name="Debug" type="0">
+ <toolsSet>
+ <compilerSet>default</compilerSet>
+ <dependencyChecking>false</dependencyChecking>
+ <rebuildPropChanged>false</rebuildPropChanged>
+ </toolsSet>
+ <flagsDictionary>
+ <element flagsID="0" commonFlags="-fsanitize=address"/>
+ </flagsDictionary>
+ <codeAssistance>
+ </codeAssistance>
+ <makefileType>
+ <makeTool>
+ <buildCommandWorkingDir>build/Debug</buildCommandWorkingDir>
+ <buildCommand>${MAKE} -f Makefile</buildCommand>
+ <cleanCommand>${MAKE} -f Makefile clean</cleanCommand>
+ <executablePath>build/Debug/src/welcome</executablePath>
+ <ccTool>
+ <incDir>
+ <pElem>/usr/include/hidapi</pElem>
+ <pElem>build/Debug/src</pElem>
+ </incDir>
+ </ccTool>
+ </makeTool>
+ <preBuild>
+ <preBuildCommandWorkingDir>build/Debug</preBuildCommandWorkingDir>
+ <preBuildCommand>${CMAKE} -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${IDE_CC} -DCMAKE_CXX_COMPILER=${IDE_CXX} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../..</preBuildCommand>
+ <preBuildFirst>true</preBuildFirst>
+ </preBuild>
+ </makefileType>
+ <item path="src/cadMousePro.cpp" ex="false" tool="1" flavor2="0">
+ <ccTool flags="0">
+ </ccTool>
+ </item>
+ </conf>
+ <conf name="Release" type="0">
+ <toolsSet>
+ <compilerSet>default</compilerSet>
+ <dependencyChecking>false</dependencyChecking>
+ <rebuildPropChanged>false</rebuildPropChanged>
+ </toolsSet>
+ <flagsDictionary>
+ <element flagsID="0" commonFlags="-O3"/>
+ </flagsDictionary>
+ <codeAssistance>
+ </codeAssistance>
+ <makefileType>
+ <makeTool>
+ <buildCommandWorkingDir>build/Release</buildCommandWorkingDir>
+ <buildCommand>${MAKE} -f Makefile</buildCommand>
+ <cleanCommand>${MAKE} -f Makefile clean</cleanCommand>
+ <executablePath>build/Release/src/welcome</executablePath>
+ <ccTool>
+ <incDir>
+ <pElem>build/Release/src</pElem>
+ </incDir>
+ <preprocessorList>
+ <Elem>NDEBUG</Elem>
+ </preprocessorList>
+ </ccTool>
+ </makeTool>
+ <preBuild>
+ <preBuildCommandWorkingDir>build/Release</preBuildCommandWorkingDir>
+ <preBuildCommand>${CMAKE} -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=${IDE_CC} -DCMAKE_CXX_COMPILER=${IDE_CXX} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../..</preBuildCommand>
+ <preBuildFirst>true</preBuildFirst>
+ </preBuild>
+ </makefileType>
+ <item path="src/cadMousePro.cpp" ex="false" tool="1" flavor2="0">
+ <ccTool flags="0">
+ </ccTool>
+ </item>
+ </conf>
+ </confs>
+</configurationDescriptor>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/nbproject/project.xml Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright (c) 2014, 2016 Oracle and/or its affiliates. All rights reserved.
+
+Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+Other names may be trademarks of their respective owners.
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+
+Contributor(s):
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.cnd.makeproject</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/make-project/1">
+ <name>cadMousePro-daemon</name>
+ <c-extensions/>
+ <cpp-extensions>cpp</cpp-extensions>
+ <header-extensions>h</header-extensions>
+ <sourceEncoding>UTF-8</sourceEncoding>
+ <sourceRootList>
+ <sourceRootElem>.</sourceRootElem>
+ </sourceRootList>
+ <make-dep-projects/>
+ <sourceRootList>
+ <sourceRootElem>.</sourceRootElem>
+ </sourceRootList>
+ <confList>
+ <confElem>
+ <name>Debug</name>
+ <type>0</type>
+ </confElem>
+ <confElem>
+ <name>Release</name>
+ <type>0</type>
+ </confElem>
+ </confList>
+ <formatting>
+ <project-formatting-style>false</project-formatting-style>
+ </formatting>
+ </data>
+ </configuration>
+</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/src/CLI.h Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,80 @@
+/**
+ * cadMousePro
+ * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <locale.h>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <locale>
+#include <codecvt>
+#include <iostream>
+
+/**
+ * a common header-only library for CLI programs
+ */
+class CLI {
+public:
+
+ CLI(int argc, char* argv[]) {
+ setlocale(LC_ALL, "");
+
+ this->argc = &argc;
+ this->argv = &argv;
+
+ program = convertor.from_bytes(argv[0]);
+
+ for (int i = 1; i < argc; i++) {
+ args.insert(args.end(), convertor.from_bytes(argv[i]));
+ }
+
+ }
+
+ CLI(const CLI& orig) {
+ }
+
+ virtual ~CLI() {
+ }
+
+ const std::wstring programName() {
+ return (const std::wstring) program;
+ }
+
+ const std::vector<std::wstring> arguments() {
+ return (const std::vector<std::wstring>)args;
+ }
+
+ static const int EXIT_CODE_SUCCESS = 0;
+ static const int EXIT_CODE_UNEXPECTED_ERROR = 1;
+ static const int EXIT_CODE_BAD_CLI_ARGUMENTS = 6;
+
+ /**
+ * std::cin and std::cout are "tied" by default i.e. reading from std::cin causes flush of the std::cout.
+ * Call this to "untie" them and have less write() calls (better buffering).
+ */
+ static void untieStdIO() {
+ std::cin.tie(nullptr);
+ }
+
+private:
+ int* argc;
+ char*** argv;
+ std::wstring program;
+ std::vector<std::wstring> args;
+ std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/src/CLIConfiguration.h Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,30 @@
+/**
+ * cadMousePro
+ * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include "CadMouseConfig.h"
+
+class CLIConfiguration {
+public:
+
+
+ CadMouseConfig cadMouseConfig;
+
+ virtual ~CLIConfiguration() {
+ }
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/src/CLIException.h Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,41 @@
+/**
+ * cadMousePro
+ * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <string>
+
+#include "CLI.h"
+
+class CLIException {
+private:
+ std::wstring message;
+ int exitCode = CLI::EXIT_CODE_UNEXPECTED_ERROR;
+public:
+
+ CLIException(std::wstring message, int exitCode) : message(message), exitCode(exitCode) {
+ }
+
+ std::wstring getMessge() const {
+ return message;
+ }
+
+ int getExitCode() const {
+ return exitCode;
+ }
+
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/src/CLIParser.h Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,80 @@
+/**
+ * cadMousePro
+ * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <vector>
+
+#include "CLI.h"
+#include "CLIConfiguration.h"
+#include "CLIException.h"
+
+class CLIParser {
+private:
+
+ std::wstring readNext(std::vector<std::wstring> arguments, int& i) {
+ if (i < arguments.size()) return arguments[i++];
+ else throw CLIException(L"Missing CLI argument" + (i > 0 ? (L" after " + arguments[i - 1]) : L""), CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+ }
+
+ bool parseBoolean(std::wstring value) {
+ if (value == L"true") return true;
+ else if (value == L"false") return false;
+ else throw CLIException(L"Unable to parse boolean value „" + value + L"“ – expecting „true“ or „false“", CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+ }
+
+ Frequency parseFrequency(std::wstring value) {
+ if (value == L"125") return Frequency::Hz_0125;
+ else if (value == L"250") return Frequency::Hz_0250;
+ else if (value == L"500") return Frequency::Hz_0500;
+ else if (value == L"1000") return Frequency::Hz_1000;
+ else throw CLIException(L"Unable to parse frequency value „" + value + L"“ – expecting „125“ or „250“ or „500“ or „1000“", CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+ }
+
+public:
+
+ static const std::wstring OPTION_FREQUENCY;
+ static const std::wstring OPTION_SMART_SCROLLING;
+ static const std::wstring OPTION_LIFT_OFF_DETECTION;
+ static const std::wstring OPTION_KEEP_FILE;
+
+ CLIConfiguration parse(const std::vector<std::wstring>& arguments) {
+ CLIConfiguration c;
+
+ for (int i = 0; i < arguments.size();) {
+ std::wstring option = readNext(arguments, i);
+
+ if (option == OPTION_FREQUENCY) {
+ c.cadMouseConfig.setFrequency(parseFrequency(readNext(arguments, i)));
+ } else if (option == OPTION_SMART_SCROLLING) {
+ c.cadMouseConfig.setSmartScrolling(parseBoolean(readNext(arguments, i)));
+ } else if (option == OPTION_LIFT_OFF_DETECTION) {
+ c.cadMouseConfig.setLiftOffDetection(parseBoolean(readNext(arguments, i)));
+ } else throw CLIException(L"Unsupported CLI option: " + option, CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+ }
+
+ return c;
+ }
+
+ virtual ~CLIParser() {
+ }
+};
+
+
+const std::wstring CLIParser::OPTION_FREQUENCY = L"--frequency";
+const std::wstring CLIParser::OPTION_SMART_SCROLLING = L"--smart-scrolling";
+const std::wstring CLIParser::OPTION_LIFT_OFF_DETECTION = L"--lift-off-detection";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/src/CMakeLists.txt Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,21 @@
+set(EXECUTABLE_FILE "cadMousePro")
+
+# USB libraries:
+INCLUDE(FindPkgConfig)
+pkg_check_modules (USB_LIBS hidapi-hidraw)
+include_directories(${USB_LIBS_INCLUDE_DIRS})
+link_directories(${USB_LIBS_LIBRARY_DIRS})
+
+# Add ASan AddressSanitizer
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
+set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
+
+# Executable output:
+add_executable(
+ ${EXECUTABLE_FILE}
+ cadMousePro.cpp
+)
+
+# Link libraries:
+target_link_libraries(${EXECUTABLE_FILE} ${USB_LIBS_LIBRARIES})
+set_property(TARGET ${EXECUTABLE_FILE} PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/src/CadMouseConfig.h Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,99 @@
+/**
+ * cadMousePro
+ * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <type_traits>
+
+#include "HID.h"
+
+enum class Frequency : uint8_t {
+ Hz_0125 = 8,
+ Hz_0250 = 4,
+ Hz_0500 = 2,
+ Hz_1000 = 1
+};
+
+using FrequencyType = std::underlying_type<Frequency>::type;
+
+class CadMouseConfig {
+private:
+ bool liftOffDetection = true;
+ bool smartScrolling = false;
+ Frequency frequency = Frequency::Hz_1000;
+public:
+
+ void setFrequency(Frequency frequency) {
+ this->frequency = frequency;
+ }
+
+ void setLiftOffDetection(bool liftOffDetection) {
+ this->liftOffDetection = liftOffDetection;
+ }
+
+ void setSmartScrolling(bool smartScrolling) {
+ this->smartScrolling = smartScrolling;
+ }
+
+ Packet serialize() {
+ Packet data;
+ data.reserve(32);
+
+ data.push_back(0x10); // report ID
+ data.push_back(0x00); // option
+
+ data.push_back(0x1c); // speed
+
+ data.push_back(liftOffDetection ? 0x00 : 0x1f);
+
+ if (smartScrolling) {
+ data.push_back(0x00);
+ data.push_back(0x00);
+ data.push_back(0x00);
+ data.push_back(0x01);
+ } else {
+ data.push_back(0x01);
+ data.push_back(0xff);
+ data.push_back(0x00);
+ data.push_back(0x00);
+ }
+
+ for (int i = 0; i < 8; i++) data.push_back(0x00); // constant padding or magic
+
+ // magic constants or unknown fields
+ data.push_back(0x00);
+ data.push_back(0x03);
+ data.push_back(0x00);
+ data.push_back(0x0a);
+ data.push_back(0x0b);
+ data.push_back(0x0c);
+ data.push_back(0x0c);
+ data.push_back(0x0e);
+ data.push_back(0x0d);
+ data.push_back(0x2f);
+ data.push_back(0x00);
+ data.push_back(0x1e);
+
+ data.push_back(0x00);
+ data.push_back(0x00);
+ data.push_back(0x00);
+ data.push_back(static_cast<FrequencyType> (frequency));
+
+ return data;
+ }
+
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/src/HID.h Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,91 @@
+/**
+ * cadMousePro
+ * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <array>
+#include <vector>
+#include <memory>
+#include <unistd.h>
+#include <cassert>
+
+#include <hidapi/hidapi.h>
+
+using Packet = std::vector<uint8_t>;
+static_assert(sizeof (uint8_t) == sizeof (unsigned char)); // unsigned char is used in the HID API library
+
+class HIDException {
+private:
+ std::wstring message;
+public:
+
+ HIDException(std::wstring message) : message(message) {
+ }
+
+ virtual ~HIDException() {
+ }
+
+ const std::wstring getMessage() const {
+ return message;
+ }
+
+};
+
+class HIDDevice {
+private:
+ std::shared_ptr<hid_device> handle;
+
+public:
+
+ HIDDevice(unsigned short vendorId, unsigned short productId, const wchar_t *serialNumber) {
+ int initError = hid_init(); // TODO: move to HIDContext class?
+ if (initError) throw HIDException(L"Unable to init HID API.");
+ handle.reset(hid_open(vendorId, productId, serialNumber), hid_close);
+ if (handle == nullptr) throw HIDException(L"Unable to open HID device. Are you root? Is the device present?");
+ }
+
+ virtual ~HIDDevice() {
+ hid_exit(); // TODO: move to HIDContext class?
+ }
+
+ const std::wstring getManufacturerName() const {
+ std::array<wchar_t, 200 > buffer;
+ int error = hid_get_manufacturer_string(handle.get(), buffer.data(), buffer.size());
+ if (error) throw HIDException(L"Unable to get manufacturer name.");
+ return buffer.data();
+ }
+
+ const std::wstring getProductName() const {
+ std::array<wchar_t, 200 > buffer;
+ int error = hid_get_product_string(handle.get(), buffer.data(), buffer.size());
+ if (error) throw HIDException(L"Unable to get product name.");
+ return buffer.data();
+ }
+
+ const std::wstring getSerialNumber() const {
+ std::array<wchar_t, 200 > buffer;
+ int error = hid_get_serial_number_string(handle.get(), buffer.data(), buffer.size());
+ if (error) throw HIDException(L"Unable to get serial number.");
+ return buffer.data();
+ }
+
+ void sendFeatureReport(Packet data) {
+ int written = hid_send_feature_report(handle.get(), data.data(), data.size());
+ if (written < 0) throw HIDException(L"Unable to send feature report.");
+ }
+
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cadMousePro-daemon/src/cadMousePro.cpp Mon Aug 19 17:27:19 2019 +0200
@@ -0,0 +1,50 @@
+/**
+ * cadMousePro
+ * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <iostream>
+
+#include "CadMouseConfig.h"
+#include "CLI.h"
+#include "CLIParser.h"
+#include "HID.h"
+
+int main(int argc, char** argv) {
+ try {
+ CLI cli(argc, argv);
+
+ std::wcout << L"cadMousePro" << std::endl;
+ HIDDevice mouse(0x256f, 0xc652, nullptr);
+ std::wcout << L"mouse opened" << std::endl;
+ std::wcout << L"manufacturer: " << mouse.getManufacturerName() << std::endl;
+ std::wcout << L"product: " << mouse.getProductName() << std::endl;
+ // std::wcout << L"serial number: " << mouse.getSerialNumber() << std::endl; // throws exception
+
+ CLIParser cliParser;
+ CLIConfiguration configuration = cliParser.parse(cli.arguments());
+
+ mouse.sendFeatureReport(configuration.cadMouseConfig.serialize());
+
+ return CLI::EXIT_CODE_SUCCESS;
+ } catch (const HIDException& e) {
+ std::wcout << L"HIDException: " << e.getMessage() << std::endl;
+ return CLI::EXIT_CODE_UNEXPECTED_ERROR;
+ } catch (const CLIException& e) {
+ std::wcout << L"CLIException: " << e.getMessge() << std::endl;
+ return e.getExitCode();
+ }
+
+}
--- a/nbproject/configurations.xml Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
-
-Copyright (c) 2014, 2016 Oracle and/or its affiliates. All rights reserved.
-
-Oracle and Java are registered trademarks of Oracle and/or its affiliates.
-Other names may be trademarks of their respective owners.
-
-The contents of this file are subject to the terms of either the GNU
-General Public License Version 2 only ("GPL") or the Common
-Development and Distribution License("CDDL") (collectively, the
-"License"). You may not use this file except in compliance with the
-License. You can obtain a copy of the License at
-http://www.netbeans.org/cddl-gplv2.html
-or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
-specific language governing permissions and limitations under the
-License. When distributing the software, include this License Header
-Notice in each file and include the License file at
-nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the GPL Version 2 section of the License file that
-accompanied this code. If applicable, add the following below the
-License Header, with the fields enclosed by brackets [] replaced by
-your own identifying information:
-"Portions Copyrighted [year] [name of copyright owner]"
-
-If you wish your version of this file to be governed by only the CDDL
-or only the GPL Version 2, indicate your decision by adding
-"[Contributor] elects to include this software in this distribution
-under the [CDDL or GPL Version 2] license." If you do not indicate a
-single choice of license, a recipient has the option to distribute
-your version of this file under either the CDDL, the GPL Version 2 or
-to extend the choice of license to its licensees as provided above.
-However, if you add GPL Version 2 code and therefore, elected the GPL
-Version 2 license, then the option applies only if the new code is
-made subject to such option by the copyright holder.
-
-Contributor(s):
--->
-<configurationDescriptor version="100">
- <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
- <df root="." name="0">
- <df name="src">
- <in>cadMousePro.cpp</in>
- </df>
- </df>
- <logicalFolder name="ExternalFiles"
- displayName="Important Files"
- projectFiles="false"
- kind="IMPORTANT_FILES_FOLDER">
- <itemPath>CMakeLists.txt</itemPath>
- <itemPath>build/Debug/Makefile</itemPath>
- <itemPath>build/Release/Makefile</itemPath>
- </logicalFolder>
- </logicalFolder>
- <sourceFolderFilter>^(nbproject|build)$</sourceFolderFilter>
- <sourceRootList>
- <Elem>.</Elem>
- </sourceRootList>
- <projectmakefile>build/Debug/Makefile</projectmakefile>
- <confs>
- <conf name="Debug" type="0">
- <toolsSet>
- <compilerSet>default</compilerSet>
- <dependencyChecking>false</dependencyChecking>
- <rebuildPropChanged>false</rebuildPropChanged>
- </toolsSet>
- <flagsDictionary>
- <element flagsID="0" commonFlags="-fsanitize=address"/>
- </flagsDictionary>
- <codeAssistance>
- </codeAssistance>
- <makefileType>
- <makeTool>
- <buildCommandWorkingDir>build/Debug</buildCommandWorkingDir>
- <buildCommand>${MAKE} -f Makefile</buildCommand>
- <cleanCommand>${MAKE} -f Makefile clean</cleanCommand>
- <executablePath>build/Debug/src/welcome</executablePath>
- <ccTool>
- <incDir>
- <pElem>/usr/include/hidapi</pElem>
- <pElem>build/Debug/src</pElem>
- </incDir>
- </ccTool>
- </makeTool>
- <preBuild>
- <preBuildCommandWorkingDir>build/Debug</preBuildCommandWorkingDir>
- <preBuildCommand>${CMAKE} -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${IDE_CC} -DCMAKE_CXX_COMPILER=${IDE_CXX} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../..</preBuildCommand>
- <preBuildFirst>true</preBuildFirst>
- </preBuild>
- </makefileType>
- <item path="src/cadMousePro.cpp" ex="false" tool="1" flavor2="0">
- <ccTool flags="0">
- </ccTool>
- </item>
- </conf>
- <conf name="Release" type="0">
- <toolsSet>
- <compilerSet>default</compilerSet>
- <dependencyChecking>false</dependencyChecking>
- <rebuildPropChanged>false</rebuildPropChanged>
- </toolsSet>
- <flagsDictionary>
- <element flagsID="0" commonFlags="-O3"/>
- </flagsDictionary>
- <codeAssistance>
- </codeAssistance>
- <makefileType>
- <makeTool>
- <buildCommandWorkingDir>build/Release</buildCommandWorkingDir>
- <buildCommand>${MAKE} -f Makefile</buildCommand>
- <cleanCommand>${MAKE} -f Makefile clean</cleanCommand>
- <executablePath>build/Release/src/welcome</executablePath>
- <ccTool>
- <incDir>
- <pElem>build/Release/src</pElem>
- </incDir>
- <preprocessorList>
- <Elem>NDEBUG</Elem>
- </preprocessorList>
- </ccTool>
- </makeTool>
- <preBuild>
- <preBuildCommandWorkingDir>build/Release</preBuildCommandWorkingDir>
- <preBuildCommand>${CMAKE} -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=${IDE_CC} -DCMAKE_CXX_COMPILER=${IDE_CXX} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../..</preBuildCommand>
- <preBuildFirst>true</preBuildFirst>
- </preBuild>
- </makefileType>
- <item path="src/cadMousePro.cpp" ex="false" tool="1" flavor2="0">
- <ccTool flags="0">
- </ccTool>
- </item>
- </conf>
- </confs>
-</configurationDescriptor>
--- a/nbproject/project.xml Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
-
-Copyright (c) 2014, 2016 Oracle and/or its affiliates. All rights reserved.
-
-Oracle and Java are registered trademarks of Oracle and/or its affiliates.
-Other names may be trademarks of their respective owners.
-
-The contents of this file are subject to the terms of either the GNU
-General Public License Version 2 only ("GPL") or the Common
-Development and Distribution License("CDDL") (collectively, the
-"License"). You may not use this file except in compliance with the
-License. You can obtain a copy of the License at
-http://www.netbeans.org/cddl-gplv2.html
-or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
-specific language governing permissions and limitations under the
-License. When distributing the software, include this License Header
-Notice in each file and include the License file at
-nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the GPL Version 2 section of the License file that
-accompanied this code. If applicable, add the following below the
-License Header, with the fields enclosed by brackets [] replaced by
-your own identifying information:
-"Portions Copyrighted [year] [name of copyright owner]"
-
-If you wish your version of this file to be governed by only the CDDL
-or only the GPL Version 2, indicate your decision by adding
-"[Contributor] elects to include this software in this distribution
-under the [CDDL or GPL Version 2] license." If you do not indicate a
-single choice of license, a recipient has the option to distribute
-your version of this file under either the CDDL, the GPL Version 2 or
-to extend the choice of license to its licensees as provided above.
-However, if you add GPL Version 2 code and therefore, elected the GPL
-Version 2 license, then the option applies only if the new code is
-made subject to such option by the copyright holder.
-
-Contributor(s):
--->
-<project xmlns="http://www.netbeans.org/ns/project/1">
- <type>org.netbeans.modules.cnd.makeproject</type>
- <configuration>
- <data xmlns="http://www.netbeans.org/ns/make-project/1">
- <name>cadMousePro</name>
- <c-extensions/>
- <cpp-extensions>cpp</cpp-extensions>
- <header-extensions>h</header-extensions>
- <sourceEncoding>UTF-8</sourceEncoding>
- <sourceRootList>
- <sourceRootElem>.</sourceRootElem>
- </sourceRootList>
- <make-dep-projects/>
- <sourceRootList>
- <sourceRootElem>.</sourceRootElem>
- </sourceRootList>
- <confList>
- <confElem>
- <name>Debug</name>
- <type>0</type>
- </confElem>
- <confElem>
- <name>Release</name>
- <type>0</type>
- </confElem>
- </confList>
- <formatting>
- <project-formatting-style>false</project-formatting-style>
- </formatting>
- </data>
- </configuration>
-</project>
--- a/src/CLI.h Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/**
- * cadMousePro
- * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include <locale.h>
-#include <string>
-#include <vector>
-#include <sstream>
-#include <locale>
-#include <codecvt>
-#include <iostream>
-
-/**
- * a common header-only library for CLI programs
- */
-class CLI {
-public:
-
- CLI(int argc, char* argv[]) {
- setlocale(LC_ALL, "");
-
- this->argc = &argc;
- this->argv = &argv;
-
- program = convertor.from_bytes(argv[0]);
-
- for (int i = 1; i < argc; i++) {
- args.insert(args.end(), convertor.from_bytes(argv[i]));
- }
-
- }
-
- CLI(const CLI& orig) {
- }
-
- virtual ~CLI() {
- }
-
- const std::wstring programName() {
- return (const std::wstring) program;
- }
-
- const std::vector<std::wstring> arguments() {
- return (const std::vector<std::wstring>)args;
- }
-
- static const int EXIT_CODE_SUCCESS = 0;
- static const int EXIT_CODE_UNEXPECTED_ERROR = 1;
- static const int EXIT_CODE_BAD_CLI_ARGUMENTS = 6;
-
- /**
- * std::cin and std::cout are "tied" by default i.e. reading from std::cin causes flush of the std::cout.
- * Call this to "untie" them and have less write() calls (better buffering).
- */
- static void untieStdIO() {
- std::cin.tie(nullptr);
- }
-
-private:
- int* argc;
- char*** argv;
- std::wstring program;
- std::vector<std::wstring> args;
- std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
-};
--- a/src/CLIConfiguration.h Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/**
- * cadMousePro
- * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include "CadMouseConfig.h"
-
-class CLIConfiguration {
-public:
-
-
- CadMouseConfig cadMouseConfig;
-
- virtual ~CLIConfiguration() {
- }
-};
--- a/src/CLIException.h Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/**
- * cadMousePro
- * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include <string>
-
-#include "CLI.h"
-
-class CLIException {
-private:
- std::wstring message;
- int exitCode = CLI::EXIT_CODE_UNEXPECTED_ERROR;
-public:
-
- CLIException(std::wstring message, int exitCode) : message(message), exitCode(exitCode) {
- }
-
- std::wstring getMessge() const {
- return message;
- }
-
- int getExitCode() const {
- return exitCode;
- }
-
-};
--- a/src/CLIParser.h Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/**
- * cadMousePro
- * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include <vector>
-
-#include "CLI.h"
-#include "CLIConfiguration.h"
-#include "CLIException.h"
-
-class CLIParser {
-private:
-
- std::wstring readNext(std::vector<std::wstring> arguments, int& i) {
- if (i < arguments.size()) return arguments[i++];
- else throw CLIException(L"Missing CLI argument" + (i > 0 ? (L" after " + arguments[i - 1]) : L""), CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
- }
-
- bool parseBoolean(std::wstring value) {
- if (value == L"true") return true;
- else if (value == L"false") return false;
- else throw CLIException(L"Unable to parse boolean value „" + value + L"“ – expecting „true“ or „false“", CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
- }
-
- Frequency parseFrequency(std::wstring value) {
- if (value == L"125") return Frequency::Hz_0125;
- else if (value == L"250") return Frequency::Hz_0250;
- else if (value == L"500") return Frequency::Hz_0500;
- else if (value == L"1000") return Frequency::Hz_1000;
- else throw CLIException(L"Unable to parse frequency value „" + value + L"“ – expecting „125“ or „250“ or „500“ or „1000“", CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
- }
-
-public:
-
- static const std::wstring OPTION_FREQUENCY;
- static const std::wstring OPTION_SMART_SCROLLING;
- static const std::wstring OPTION_LIFT_OFF_DETECTION;
- static const std::wstring OPTION_KEEP_FILE;
-
- CLIConfiguration parse(const std::vector<std::wstring>& arguments) {
- CLIConfiguration c;
-
- for (int i = 0; i < arguments.size();) {
- std::wstring option = readNext(arguments, i);
-
- if (option == OPTION_FREQUENCY) {
- c.cadMouseConfig.setFrequency(parseFrequency(readNext(arguments, i)));
- } else if (option == OPTION_SMART_SCROLLING) {
- c.cadMouseConfig.setSmartScrolling(parseBoolean(readNext(arguments, i)));
- } else if (option == OPTION_LIFT_OFF_DETECTION) {
- c.cadMouseConfig.setLiftOffDetection(parseBoolean(readNext(arguments, i)));
- } else throw CLIException(L"Unsupported CLI option: " + option, CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
- }
-
- return c;
- }
-
- virtual ~CLIParser() {
- }
-};
-
-
-const std::wstring CLIParser::OPTION_FREQUENCY = L"--frequency";
-const std::wstring CLIParser::OPTION_SMART_SCROLLING = L"--smart-scrolling";
-const std::wstring CLIParser::OPTION_LIFT_OFF_DETECTION = L"--lift-off-detection";
--- a/src/CMakeLists.txt Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-set(EXECUTABLE_FILE "cadMousePro")
-
-# USB libraries:
-INCLUDE(FindPkgConfig)
-pkg_check_modules (USB_LIBS hidapi-hidraw)
-include_directories(${USB_LIBS_INCLUDE_DIRS})
-link_directories(${USB_LIBS_LIBRARY_DIRS})
-
-# Add ASan AddressSanitizer
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
-set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
-
-# Executable output:
-add_executable(
- ${EXECUTABLE_FILE}
- cadMousePro.cpp
-)
-
-# Link libraries:
-target_link_libraries(${EXECUTABLE_FILE} ${USB_LIBS_LIBRARIES})
-set_property(TARGET ${EXECUTABLE_FILE} PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
--- a/src/CadMouseConfig.h Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/**
- * cadMousePro
- * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include <type_traits>
-
-#include "HID.h"
-
-enum class Frequency : uint8_t {
- Hz_0125 = 8,
- Hz_0250 = 4,
- Hz_0500 = 2,
- Hz_1000 = 1
-};
-
-using FrequencyType = std::underlying_type<Frequency>::type;
-
-class CadMouseConfig {
-private:
- bool liftOffDetection = true;
- bool smartScrolling = false;
- Frequency frequency = Frequency::Hz_1000;
-public:
-
- void setFrequency(Frequency frequency) {
- this->frequency = frequency;
- }
-
- void setLiftOffDetection(bool liftOffDetection) {
- this->liftOffDetection = liftOffDetection;
- }
-
- void setSmartScrolling(bool smartScrolling) {
- this->smartScrolling = smartScrolling;
- }
-
- Packet serialize() {
- Packet data;
- data.reserve(32);
-
- data.push_back(0x10); // report ID
- data.push_back(0x00); // option
-
- data.push_back(0x1c); // speed
-
- data.push_back(liftOffDetection ? 0x00 : 0x1f);
-
- if (smartScrolling) {
- data.push_back(0x00);
- data.push_back(0x00);
- data.push_back(0x00);
- data.push_back(0x01);
- } else {
- data.push_back(0x01);
- data.push_back(0xff);
- data.push_back(0x00);
- data.push_back(0x00);
- }
-
- for (int i = 0; i < 8; i++) data.push_back(0x00); // constant padding or magic
-
- // magic constants or unknown fields
- data.push_back(0x00);
- data.push_back(0x03);
- data.push_back(0x00);
- data.push_back(0x0a);
- data.push_back(0x0b);
- data.push_back(0x0c);
- data.push_back(0x0c);
- data.push_back(0x0e);
- data.push_back(0x0d);
- data.push_back(0x2f);
- data.push_back(0x00);
- data.push_back(0x1e);
-
- data.push_back(0x00);
- data.push_back(0x00);
- data.push_back(0x00);
- data.push_back(static_cast<FrequencyType> (frequency));
-
- return data;
- }
-
-};
--- a/src/HID.h Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/**
- * cadMousePro
- * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include <array>
-#include <vector>
-#include <memory>
-#include <unistd.h>
-#include <cassert>
-
-#include <hidapi/hidapi.h>
-
-using Packet = std::vector<uint8_t>;
-static_assert(sizeof (uint8_t) == sizeof (unsigned char)); // unsigned char is used in the HID API library
-
-class HIDException {
-private:
- std::wstring message;
-public:
-
- HIDException(std::wstring message) : message(message) {
- }
-
- virtual ~HIDException() {
- }
-
- const std::wstring getMessage() const {
- return message;
- }
-
-};
-
-class HIDDevice {
-private:
- std::shared_ptr<hid_device> handle;
-
-public:
-
- HIDDevice(unsigned short vendorId, unsigned short productId, const wchar_t *serialNumber) {
- int initError = hid_init(); // TODO: move to HIDContext class?
- if (initError) throw HIDException(L"Unable to init HID API.");
- handle.reset(hid_open(vendorId, productId, serialNumber), hid_close);
- if (handle == nullptr) throw HIDException(L"Unable to open HID device. Are you root? Is the device present?");
- }
-
- virtual ~HIDDevice() {
- hid_exit(); // TODO: move to HIDContext class?
- }
-
- const std::wstring getManufacturerName() const {
- std::array<wchar_t, 200 > buffer;
- int error = hid_get_manufacturer_string(handle.get(), buffer.data(), buffer.size());
- if (error) throw HIDException(L"Unable to get manufacturer name.");
- return buffer.data();
- }
-
- const std::wstring getProductName() const {
- std::array<wchar_t, 200 > buffer;
- int error = hid_get_product_string(handle.get(), buffer.data(), buffer.size());
- if (error) throw HIDException(L"Unable to get product name.");
- return buffer.data();
- }
-
- const std::wstring getSerialNumber() const {
- std::array<wchar_t, 200 > buffer;
- int error = hid_get_serial_number_string(handle.get(), buffer.data(), buffer.size());
- if (error) throw HIDException(L"Unable to get serial number.");
- return buffer.data();
- }
-
- void sendFeatureReport(Packet data) {
- int written = hid_send_feature_report(handle.get(), data.data(), data.size());
- if (written < 0) throw HIDException(L"Unable to send feature report.");
- }
-
-};
--- a/src/cadMousePro.cpp Mon Aug 19 17:21:02 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/**
- * cadMousePro
- * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-#include <iostream>
-
-#include "CadMouseConfig.h"
-#include "CLI.h"
-#include "CLIParser.h"
-#include "HID.h"
-
-int main(int argc, char** argv) {
- try {
- CLI cli(argc, argv);
-
- std::wcout << L"cadMousePro" << std::endl;
- HIDDevice mouse(0x256f, 0xc652, nullptr);
- std::wcout << L"mouse opened" << std::endl;
- std::wcout << L"manufacturer: " << mouse.getManufacturerName() << std::endl;
- std::wcout << L"product: " << mouse.getProductName() << std::endl;
- // std::wcout << L"serial number: " << mouse.getSerialNumber() << std::endl; // throws exception
-
- CLIParser cliParser;
- CLIConfiguration configuration = cliParser.parse(cli.arguments());
-
- mouse.sendFeatureReport(configuration.cadMouseConfig.serialize());
-
- return CLI::EXIT_CODE_SUCCESS;
- } catch (const HIDException& e) {
- std::wcout << L"HIDException: " << e.getMessage() << std::endl;
- return CLI::EXIT_CODE_UNEXPECTED_ERROR;
- } catch (const CLIException& e) {
- std::wcout << L"CLIException: " << e.getMessge() << std::endl;
- return e.getExitCode();
- }
-
-}