support also the wired version of CadMouse Pro v_0 tip
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 03 Apr 2021 17:39:35 +0200
branchv_0
changeset 33 0dc4e2942840
parent 32 09d20a946a01
support also the wired version of CadMouse Pro currently, there is a simple autodetection: we enumerate HID devices and look for the wireless version, if not found, we look for the wired version
cadMousePro-daemon/src/Daemon.h
cadMousePro-daemon/src/HID.h
cadMousePro-daemon/src/cadMousePro.cpp
--- a/cadMousePro-daemon/src/Daemon.h	Tue Jun 09 22:13:44 2020 +0200
+++ b/cadMousePro-daemon/src/Daemon.h	Sat Apr 03 17:39:35 2021 +0200
@@ -30,19 +30,28 @@
 
 private:
 
-	HIDDevice getMouse() {
-		return HIDDevice(VENDOR_ID, PRODUCT_ID, nullptr);
-	}
+	static unsigned short const VENDOR_ID = 0x256f;
+	static unsigned short const PRODUCT_ID_WIRELESS = 0xc652;
+	static unsigned short const PRODUCT_ID_WIRED = 0xc656;
 
 	void logException(const HIDException& e) {
 		std::wcout << L"HIDException: " << e.getMessage() << std::endl;
 	}
 public:
 
-	static unsigned short const VENDOR_ID = 0x256f;
-	static unsigned short const PRODUCT_ID = 0xc652;
+	Daemon(QObject* parent = nullptr) : QObject(parent) {
+	}
 
-	Daemon(QObject* parent = nullptr) : QObject(parent) {
+	static HIDDevice getMouse() {
+		// TODO: multiple mouse support, better mouse selection, specific settings for particular type…
+		// (probably after future redesign/rewrite – this is just a simple tool written for 3DConnexion CadMouse Pro)
+		std::vector<HIDDeviceInfo> devices = HIDDeviceInfo::enumerate();
+		for (auto pid :{PRODUCT_ID_WIRELESS, PRODUCT_ID_WIRED}) {
+			for (HIDDeviceInfo device : devices) {
+				if (device.matches(VENDOR_ID, pid)) return device.open();
+			}
+		}
+		throw HIDException(L"No suitable mouse found.");
 	}
 
 	Q_PROPERTY(bool devicePresent READ devicePresent)
--- a/cadMousePro-daemon/src/HID.h	Tue Jun 09 22:13:44 2020 +0200
+++ b/cadMousePro-daemon/src/HID.h	Sat Apr 03 17:39:35 2021 +0200
@@ -21,6 +21,8 @@
 #include <memory>
 #include <unistd.h>
 #include <cassert>
+#include <string>
+#include <vector>
 
 #include <hidapi/hidapi.h>
 
@@ -88,3 +90,49 @@
 	}
 
 };
+
+class HIDDeviceInfo {
+private:
+	unsigned short vendorId;
+	unsigned short productId;
+	std::wstring serialNumber;
+public:
+
+	HIDDeviceInfo(unsigned short vendorId, unsigned short productId, std::wstring serialNumber) : vendorId(vendorId), productId(productId), serialNumber(serialNumber) {
+	}
+
+	virtual ~HIDDeviceInfo() {
+	}
+
+	HIDDevice open() {
+		return HIDDevice(vendorId, productId, serialNumber.size() ? serialNumber.c_str() : nullptr);
+	}
+
+	bool matches(unsigned short vendorId, unsigned short productId) {
+		return vendorId == this->vendorId && productId == this->productId;
+	}
+
+	bool matches(unsigned short vendorId, unsigned short productId, std::wstring serialNumber) {
+		return matches(vendorId, productId) && serialNumber == this->serialNumber;
+	}
+
+	unsigned short getProductId() const {
+		return productId;
+	}
+
+	std::wstring getSerialNumber() const {
+		return serialNumber;
+	}
+
+	unsigned short getVendorId() const {
+		return vendorId;
+	}
+
+	static std::vector<HIDDeviceInfo> enumerate(unsigned short vendorId = 0, unsigned short productId = 0) {
+		std::vector<HIDDeviceInfo> result;
+		std::shared_ptr<hid_device_info> rawList(hid_enumerate(vendorId, productId), hid_free_enumeration);
+		// n.b. for single USB device there might be multiple HID devices different just in di->path
+		for (hid_device_info* di = rawList.get(); di; di = di->next) result.push_back({di->vendor_id, di->product_id, di->serial_number});
+		return result;
+	}
+};
--- a/cadMousePro-daemon/src/cadMousePro.cpp	Tue Jun 09 22:13:44 2020 +0200
+++ b/cadMousePro-daemon/src/cadMousePro.cpp	Sat Apr 03 17:39:35 2021 +0200
@@ -55,7 +55,7 @@
 			return qtApplication.exec();
 
 		} else {
-			HIDDevice mouse(Daemon::VENDOR_ID, Daemon::PRODUCT_ID, nullptr);
+			HIDDevice mouse = Daemon::getMouse();
 			std::wcout << L"mouse opened" << std::endl;
 			std::wcout << L"manufacturer:  " << mouse.getManufacturerName() << std::endl;
 			std::wcout << L"product:       " << mouse.getProductName() << std::endl;