From 1236bcee420da713e373a4a6b8cec279749c3d74 Mon Sep 17 00:00:00 2001
From: Szczepan Zalega <szczepan@nitrokey.com>
Date: Sat, 1 Dec 2018 16:01:54 +0100
Subject: Connect with serial

Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
---
 .idea/vcs.xml                 |  2 ++
 NK_C_API.cc                   |  7 +++++++
 NitrokeyManager.cc            | 16 ++++++++++++++++
 device.cc                     | 13 ++++++++++++-
 libnitrokey/NitrokeyManager.h |  1 +
 libnitrokey/device.h          |  5 ++++-
 6 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..efdb874 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,7 @@
 <project version="4">
   <component name="VcsDirectoryMappings">
     <mapping directory="$PROJECT_DIR$" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/hidapi" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/unittest/Catch" vcs="Git" />
   </component>
 </project>
\ No newline at end of file
diff --git a/NK_C_API.cc b/NK_C_API.cc
index 7d0a10e..396171c 100644
--- a/NK_C_API.cc
+++ b/NK_C_API.cc
@@ -125,6 +125,13 @@ extern "C" {
 		return _copy;
 	}
 
+	NK_C_API int NK_login_with_serial(const char *serial) {
+		auto m = NitrokeyManager::instance();
+		return get_with_result([&]() {
+			return m->connect_with_serial(serial);
+		});
+	}
+
 	NK_C_API int NK_login(const char *device_model) {
 		auto m = NitrokeyManager::instance();
 		try {
diff --git a/NitrokeyManager.cc b/NitrokeyManager.cc
index a950e4b..9ba270e 100644
--- a/NitrokeyManager.cc
+++ b/NitrokeyManager.cc
@@ -231,6 +231,22 @@ using nitrokey::misc::strcpyT;
         return true;
     }
 
+    bool NitrokeyManager::connect_with_serial(std::string serial) {
+        std::lock_guard<std::mutex> lock(mex_dev_com_manager);
+        vector< shared_ptr<Device> > devices = { make_shared<Stick10>(), make_shared<Stick20>() };
+        for (shared_ptr<Device> & p : devices){
+            p->set_path(serial);
+            if(p->connect()){
+              device = p; //previous device will be disconnected automatically
+              current_device_id = serial;
+              nitrokey::log::Log::setPrefix(serial);
+              LOGD1("Device successfully changed");
+              return true;
+            }
+        }
+        return false;
+    }
+
     bool NitrokeyManager::connect() {
         std::lock_guard<std::mutex> lock(mex_dev_com_manager);
         vector< shared_ptr<Device> > devices = { make_shared<Stick10>(), make_shared<Stick20>() };
diff --git a/device.cc b/device.cc
index 80e4b38..ef295e8 100644
--- a/device.cc
+++ b/device.cc
@@ -29,6 +29,7 @@
 #include "libnitrokey/device.h"
 #include "libnitrokey/log.h"
 #include <mutex>
+#include <codecvt>
 #include "DeviceCommunicationExceptions.h"
 #include "device.h"
 
@@ -96,7 +97,13 @@ bool Device::_connect() {
 
 //   hid_init(); // done automatically on hid_open
   if (m_path.empty()){
-    mp_devhandle = hid_open(m_vid, m_pid, nullptr);
+    const wchar_t* serial = nullptr;
+    if (!m_serial.empty()){
+      std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
+      auto wstr = converter.from_bytes(m_serial.c_str());
+      serial = wstr.c_str();
+    }
+    mp_devhandle = hid_open(m_vid, m_pid, serial);
   } else {
     mp_devhandle = hid_open_path(m_path.c_str());
   }
@@ -105,6 +112,10 @@ bool Device::_connect() {
   return success;
 }
 
+void Device::set_serial(const std::string serial){
+  m_serial = serial;
+}
+
 void Device::set_path(const std::string path){
   m_path = path;
 }
diff --git a/libnitrokey/NitrokeyManager.h b/libnitrokey/NitrokeyManager.h
index d6e5df4..983b94c 100644
--- a/libnitrokey/NitrokeyManager.h
+++ b/libnitrokey/NitrokeyManager.h
@@ -91,6 +91,7 @@ char * strndup(const char* str, size_t maxlen);
          */
         bool connect_with_ID(const std::string id);
         bool connect_with_path (std::string path);
+        bool connect_with_serial(std::string serial);
         bool connect(const char *device_model);
         bool connect(device::DeviceModel device_model);
         bool connect();
diff --git a/libnitrokey/device.h b/libnitrokey/device.h
index f6d2380..99e02bb 100644
--- a/libnitrokey/device.h
+++ b/libnitrokey/device.h
@@ -125,9 +125,11 @@ public:
   static void set_default_device_speed(int delay);
   void setDefaultDelay();
   void set_path(const std::string path);
+  void set_serial(const std::string serial);
 
 
-        private:
+
+    private:
   std::atomic<uint8_t> last_command_status;
   void _reconnect();
   bool _connect();
@@ -149,6 +151,7 @@ protected:
   std::chrono::milliseconds m_send_receive_delay;
   std::atomic<hid_device *>mp_devhandle;
   std::string m_path;
+  std::string m_serial;
 
   static std::atomic_int instances_count;
   static std::chrono::milliseconds default_delay ;
-- 
cgit v1.2.3