Eric Betts 2 лет назад
Родитель
Сommit
a8b472282f
4 измененных файлов с 58 добавлено и 8 удалено
  1. 2 8
      ccid.c
  2. 11 0
      scenes/seader_scene_sam_present.c
  3. 43 0
      seader_worker.c
  4. 2 0
      seader_worker_i.h

+ 2 - 8
ccid.c

@@ -227,17 +227,11 @@ size_t processCCID(SeaderWorker* seader_worker, uint8_t* cmd, size_t cmd_len) {
                 if(memcmp(SAM_ATR, message.payload, sizeof(SAM_ATR)) == 0) {
                     FURI_LOG_I(TAG, "SAM ATR!");
                     hasSAM = true;
-                    if(seader_worker->callback) {
-                        seader_worker->callback(
-                            SeaderWorkerEventSamPresent, seader_worker->context);
-                    }
+                    seader_worker_send_version(seader_worker);
                 } else if(memcmp(SAM_ATR2, message.payload, sizeof(SAM_ATR2)) == 0) {
                     FURI_LOG_I(TAG, "SAM ATR2!");
                     hasSAM = true;
-                    if(seader_worker->callback) {
-                        seader_worker->callback(
-                            SeaderWorkerEventSamPresent, seader_worker->context);
-                    }
+                    seader_worker_send_version(seader_worker);
                 } else {
                     FURI_LOG_W(TAG, "Unknown ATR");
                     if(seader_worker->callback) {

+ 11 - 0
scenes/seader_scene_sam_present.c

@@ -3,6 +3,7 @@ enum SubmenuIndex {
     SubmenuIndexReadPicopass,
     SubmenuIndexRead14a,
     SubmenuIndexSaved,
+    SubmenuIndexFwVersion,
 };
 
 void seader_scene_sam_present_submenu_callback(void* context, uint32_t index) {
@@ -12,6 +13,7 @@ void seader_scene_sam_present_submenu_callback(void* context, uint32_t index) {
 
 void seader_scene_sam_present_on_enter(void* context) {
     Seader* seader = context;
+    SeaderWorker* seader_worker = seader->worker;
 
     Submenu* submenu = seader->submenu;
 
@@ -30,6 +32,15 @@ void seader_scene_sam_present_on_enter(void* context) {
     submenu_add_item(
         submenu, "Load", SubmenuIndexSaved, seader_scene_sam_present_submenu_callback, seader);
 
+    if (seader_worker->sam_version[0] != 0 && seader_worker->sam_version[1] != 0) {
+        FuriString* fw_str = furi_string_alloc();
+        furi_string_cat_printf(
+            fw_str, "FW %d.%d", seader_worker->sam_version[0], seader_worker->sam_version[1]);
+        submenu_add_item(
+            submenu, furi_string_get_cstr(fw_str), SubmenuIndexFwVersion, seader_scene_sam_present_submenu_callback, seader);
+        furi_string_free(fw_str);
+    }
+
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(seader->scene_manager, SeaderSceneSamPresent));
 

+ 43 - 0
seader_worker.c

@@ -47,6 +47,7 @@ SeaderWorker* seader_worker_alloc() {
     seader_worker->callback = NULL;
     seader_worker->context = NULL;
     seader_worker->storage = furi_record_open(RECORD_STORAGE);
+    memset(seader_worker->sam_version, 0, sizeof(seader_worker->sam_version));
 
     seader_worker_change_state(seader_worker, SeaderWorkerStateReady);
 
@@ -404,6 +405,44 @@ bool unpack_pacs(
     return rtn;
 }
 
+//    800201298106683d052026b6820101
+//300F800201298106683D052026B6820101
+bool parseVersion(SeaderWorker* seader_worker, uint8_t* buf, size_t size) {
+    UNUSED(seader_worker); // TODO: add either a SAM struct or the firmware to the worker or something
+    SamVersion_t* version = 0;
+    version = calloc(1, sizeof *version);
+    assert(version);
+
+    bool rtn = false;
+    if (size > 30) {
+        // Too large to handle now
+        FURI_LOG_W(TAG, "Version of %d is to long to parse", size);
+        return false;
+    }
+    // Add sequence prefix
+    uint8_t seq[32] = {0x30};
+    seq[1] = (uint8_t)size;
+    memcpy(seq+2, buf, size);
+
+    asn_dec_rval_t rval = asn_decode(0, ATS_DER, &asn_DEF_SamVersion, (void**)&version, seq, size+2);
+
+    if(rval.code == RC_OK) {
+        char versionDebug[128] = {0};
+        (&asn_DEF_SamVersion)->op->print_struct(&asn_DEF_SamVersion, version, 1, toString, versionDebug);
+        if(strlen(versionDebug) > 0) {
+            FURI_LOG_D(TAG, "Received version: %s", versionDebug);
+        }
+        if (version->version.size == 2) {
+            memcpy(seader_worker->sam_version, version->version.buf, version->version.size);
+        }
+
+        rtn = true;
+    }
+
+    ASN_STRUCT_FREE(asn_DEF_SamVersion, version);
+    return rtn;
+}
+
 bool parseSamResponse(SeaderWorker* seader_worker, SamResponse_t* samResponse) {
     SeaderUartBridge* seader_uart = seader_worker->uart;
     SeaderCredential* credential = seader_worker->credential;
@@ -419,6 +458,10 @@ bool parseSamResponse(SeaderWorker* seader_worker, SamResponse_t* samResponse) {
                 seader_worker->callback(SeaderWorkerEventFail, seader_worker->context);
             }
         }
+    } else if(parseVersion(seader_worker, samResponse->buf, samResponse->size)) {
+        if(seader_worker->callback) {
+            seader_worker->callback(SeaderWorkerEventSamPresent, seader_worker->context);
+        }
     } else if(unpack_pacs(seader_worker, credential, samResponse->buf, samResponse->size)) {
         if(seader_worker->callback) {
             seader_worker->callback(SeaderWorkerEventSuccess, seader_worker->context);

+ 2 - 0
seader_worker_i.h

@@ -13,11 +13,13 @@
 
 #include <platform.h>
 #include <PAC.h>
+#include <SamVersion.h>
 
 struct SeaderWorker {
     FuriThread* thread;
     Storage* storage;
     Stream* dict_stream;
+    uint8_t sam_version[2];
 
     SeaderUartBridge* uart;
     SeaderCredential* credential;