From 9601681dd9aea8a87444d36711e0a908ad4ec7d2 Mon Sep 17 00:00:00 2001
From: Szczepan Zalega <szczepan@nitrokey.com>
Date: Thu, 28 Jun 2018 11:30:05 +0200
Subject: Handle command for getting production data

Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
---
 NK_C_API.cc                   | 39 ++++++++++++++++++++++++++++++++++++++-
 NK_C_API.h                    | 27 +++++++++++++++++++++++----
 NitrokeyManager.cc            |  5 +++++
 libnitrokey/NitrokeyManager.h |  2 ++
 4 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/NK_C_API.cc b/NK_C_API.cc
index 103f34d..1d9ff4f 100644
--- a/NK_C_API.cc
+++ b/NK_C_API.cc
@@ -631,7 +631,44 @@ extern "C" {
 		return 0;
 	}
 
-	NK_C_API char* NK_get_SD_usage_data_as_string() {
+  NK_C_API int NK_get_storage_production_info(NK_storage_ProductionTest * out){
+    if (out == nullptr) {
+      return -1;
+    }
+    auto m = NitrokeyManager::instance();
+    auto result = get_with_status([&]() {
+      return m->production_info();
+    }, proto::stick20::ProductionTest::ResponsePayload());
+
+		auto error_code = std::get<0>(result);
+		if (error_code != 0) {
+			return error_code;
+		}
+
+		stick20::ProductionTest::ResponsePayload status = std::get<1>(result);
+		// Cannot use memcpy without declaring C API struct packed
+    // (which is not parsed by Python's CFFI apparently), hence the manual way.
+#define a(x) out->x = status.x;
+		 a(FirmwareVersion_au8[0]);
+		 a(FirmwareVersion_au8[1]);
+		 a(FirmwareVersionInternal_u8);
+		 a(SD_Card_Size_u8);
+		 a(CPU_CardID_u32);
+		 a(SmartCardID_u32);
+		 a(SD_CardID_u32);
+		 a(SC_UserPwRetryCount);
+		 a(SC_AdminPwRetryCount);
+		 a(SD_Card_ManufacturingYear_u8);
+		 a(SD_Card_ManufacturingMonth_u8);
+		 a(SD_Card_OEM_u16);
+		 a(SD_WriteSpeed_u16);
+		 a(SD_Card_Manufacturer_u8);
+#undef a
+		return 0;
+  }
+
+
+NK_C_API char* NK_get_SD_usage_data_as_string() {
 		auto m = NitrokeyManager::instance();
 		return get_with_string_result([&]() {
 			return m->get_SD_usage_data_as_string();
diff --git a/NK_C_API.h b/NK_C_API.h
index c991d4c..ecfab1a 100644
--- a/NK_C_API.h
+++ b/NK_C_API.h
@@ -122,10 +122,29 @@ extern "C" {
 		bool stick_initialized;
         };
 
-	/**
-	 * Set debug level of messages written on stderr
-	 * @param state state=True - most messages, state=False - only errors level
-	 */
+   struct NK_storage_ProductionTest{
+    uint8_t FirmwareVersion_au8[2];
+    uint8_t FirmwareVersionInternal_u8;
+    uint8_t SD_Card_Size_u8;
+    uint32_t CPU_CardID_u32;
+    uint32_t SmartCardID_u32;
+    uint32_t SD_CardID_u32;
+    uint8_t SC_UserPwRetryCount;
+    uint8_t SC_AdminPwRetryCount;
+    uint8_t SD_Card_ManufacturingYear_u8;
+    uint8_t SD_Card_ManufacturingMonth_u8;
+    uint16_t SD_Card_OEM_u16;
+    uint16_t SD_WriteSpeed_u16;
+    uint8_t SD_Card_Manufacturer_u8;
+  };
+
+  NK_C_API int NK_get_storage_production_info(struct NK_storage_ProductionTest * out);
+
+
+/**
+ * Set debug level of messages written on stderr
+ * @param state state=True - most messages, state=False - only errors level
+ */
 	NK_C_API void NK_set_debug(bool state);
 
 	/**
diff --git a/NitrokeyManager.cc b/NitrokeyManager.cc
index 600193d..a950e4b 100644
--- a/NitrokeyManager.cc
+++ b/NitrokeyManager.cc
@@ -1141,4 +1141,9 @@ using nitrokey::misc::strcpyT;
     stick20::Wink::CommandTransaction::run(device);
   };
 
+  stick20::ProductionTest::ResponsePayload NitrokeyManager::production_info(){
+    auto data = stick20::ProductionTest::CommandTransaction::run(device);
+    return data.data();
+  };
+
 }
diff --git a/libnitrokey/NitrokeyManager.h b/libnitrokey/NitrokeyManager.h
index b48afc5..d6e5df4 100644
--- a/libnitrokey/NitrokeyManager.h
+++ b/libnitrokey/NitrokeyManager.h
@@ -293,6 +293,8 @@ char * strndup(const char* str, size_t maxlen);
        * Blink red and green LED alternatively and infinitely (until device is reconnected).
        */
       void wink();
+
+      stick20::ProductionTest::ResponsePayload production_info();
     };
 }
 
-- 
cgit v1.2.3