Просмотр исходного кода

WIP: reduce thread priority and use a message queue

Eric Betts 2 лет назад
Родитель
Сommit
99c04ee2ed
9 измененных файлов с 191 добавлено и 80 удалено
  1. 3 2
      ccid.c
  2. 1 1
      ccid.h
  3. 5 3
      scenes/seader_scene_read_14a.c
  4. 8 6
      scenes/seader_scene_sam_present.c
  5. 0 2
      seader_i.h
  6. 165 61
      seader_worker.c
  7. 2 2
      seader_worker.h
  8. 6 1
      seader_worker_i.h
  9. 1 2
      uart.c

+ 3 - 2
ccid.c

@@ -130,7 +130,8 @@ void seader_ccid_XfrBlockToSlot(
     furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx);
 }
 
-size_t seader_ccid_process(SeaderWorker* seader_worker, uint8_t* cmd, size_t cmd_len) {
+size_t seader_ccid_process(Seader* seader, uint8_t* cmd, size_t cmd_len) {
+    SeaderWorker* seader_worker = seader->worker;
     SeaderUartBridge* seader_uart = seader_worker->uart;
     CCID_Message message;
     message.consumed = 0;
@@ -302,7 +303,7 @@ size_t seader_ccid_process(SeaderWorker* seader_worker, uint8_t* cmd, size_t cmd
         if(message.bMessageType == CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock) {
             if(hasSAM) {
                 if(message.bSlot == sam_slot) {
-                    seader_worker_process_sam_message(seader_worker, &message);
+                    seader_worker_process_sam_message(seader, &message);
                 } else {
                     FURI_LOG_D(TAG, "Discarding message on non-sam slot");
                 }

+ 1 - 1
ccid.h

@@ -103,4 +103,4 @@ void seader_ccid_XfrBlockToSlot(
     uint8_t slot,
     uint8_t* data,
     size_t len);
-size_t seader_ccid_process(SeaderWorker* seader_worker, uint8_t* cmd, size_t cmd_len);
+size_t seader_ccid_process(Seader* seader, uint8_t* cmd, size_t cmd_len);

+ 5 - 3
scenes/seader_scene_read_14a.c

@@ -20,6 +20,8 @@ void seader_scene_read_14a_on_enter(void* context) {
     view_dispatcher_switch_to_view(seader->view_dispatcher, SeaderViewPopup);
 
     seader->poller = nfc_poller_alloc(seader->nfc, NfcProtocolIso14443_4a);
+
+    //nfc_config(seader->nfc, NfcModePoller, NfcTechIso14443a);
     nfc_poller_start(seader->poller, seader_worker_poller_callback_iso14443_4a, seader);
 
     seader_blink_start(seader);
@@ -46,9 +48,9 @@ bool seader_scene_read_14a_on_event(void* context, SceneManagerEvent event) {
 void seader_scene_read_14a_on_exit(void* context) {
     Seader* seader = context;
 
-    if (seader->poller) {
-      nfc_poller_stop(seader->poller);
-      nfc_poller_free(seader->poller);
+    if(seader->poller) {
+        nfc_poller_stop(seader->poller);
+        nfc_poller_free(seader->poller);
     }
 
     // Clear view

+ 8 - 6
scenes/seader_scene_sam_present.c

@@ -21,12 +21,14 @@ void seader_scene_sam_present_on_update(void* context) {
     Submenu* submenu = seader->submenu;
     submenu_reset(submenu);
 
+    /*
     submenu_add_item(
         submenu,
         "Read Picopass",
         SubmenuIndexReadPicopass,
         seader_scene_sam_present_submenu_callback,
         seader);
+        */
     submenu_add_item(
         submenu,
         "Read 14443A",
@@ -66,14 +68,14 @@ bool seader_scene_sam_present_on_event(void* context, SceneManagerEvent event) {
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == SubmenuIndexReadPicopass) {
-                scene_manager_set_scene_state(
-                    seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexReadPicopass);
-                scene_manager_next_scene(seader->scene_manager, SeaderSceneReadPicopass);
+            scene_manager_set_scene_state(
+                seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexReadPicopass);
+            scene_manager_next_scene(seader->scene_manager, SeaderSceneReadPicopass);
             consumed = true;
         } else if(event.event == SubmenuIndexRead14a) {
-                scene_manager_set_scene_state(
-                    seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexRead14a);
-                scene_manager_next_scene(seader->scene_manager, SeaderSceneRead14a);
+            scene_manager_set_scene_state(
+                seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexRead14a);
+            scene_manager_next_scene(seader->scene_manager, SeaderSceneRead14a);
             consumed = true;
         } else if(event.event == SubmenuIndexSamInfo) {
             scene_manager_set_scene_state(

+ 0 - 2
seader_i.h

@@ -26,7 +26,6 @@
 #include <lib/nfc/protocols/iso14443_3a/iso14443_3a.h>
 
 #include <nfc/nfc_poller.h>
-#include <nfc/nfc_scanner.h>
 
 #include <nfc/nfc_device.h>
 #include <nfc/helpers/nfc_data_generator.h>
@@ -106,7 +105,6 @@ struct Seader {
 
     Nfc* nfc;
     NfcPoller* poller;
-    NfcScanner* scanner;
 
     NfcDevice* nfc_device;
 };

+ 165 - 61
seader_worker.c

@@ -16,7 +16,10 @@
 // TODO: const
 uint8_t GET_RESPONSE[] = {0x00, 0xc0, 0x00, 0x00, 0xff};
 
+#ifdef ASN1_DEBUG
 char payloadDebug[384] = {0};
+#endif
+
 char display[SEADER_UART_RX_BUF_SIZE * 2 + 1] = {0};
 char asn1_log[SEADER_UART_RX_BUF_SIZE] = {0};
 bool requestPacs = true;
@@ -32,6 +35,7 @@ SeaderWorker* seader_worker_alloc() {
     // Worker thread attributes
     seader_worker->thread =
         furi_thread_alloc_ex("SeaderWorker", 8192, seader_worker_task, seader_worker);
+    seader_worker->messages = furi_message_queue_alloc(2, SEADER_UART_RX_BUF_SIZE);
 
     seader_worker->callback = NULL;
     seader_worker->context = NULL;
@@ -47,6 +51,7 @@ void seader_worker_free(SeaderWorker* seader_worker) {
     furi_assert(seader_worker);
 
     furi_thread_free(seader_worker->thread);
+    furi_message_queue_free(seader_worker->messages);
 
     furi_record_close(RECORD_STORAGE);
 
@@ -83,7 +88,8 @@ void seader_worker_stop(SeaderWorker* seader_worker) {
         return;
     }
     // seader_worker_disable_field();
-
+    // nfc_poller_stop(poller);
+    // nfc_poller_free(poller);
     seader_worker_change_state(seader_worker, SeaderWorkerStateStop);
     furi_thread_join(seader_worker->thread);
 }
@@ -98,8 +104,6 @@ void* calloc(size_t count, size_t size) {
     return malloc(count * size);
 }
 
-
-
 bool seader_send_apdu(
     SeaderUartBridge* seader_uart,
     uint8_t CLA,
@@ -139,7 +143,7 @@ static int seader_asn_to_string(const void* buffer, size_t size, void* app_key)
 }
 
 bool seader_read_nfc(SeaderUartBridge* seader_uart) {
-  UNUSED(seader_uart);
+    UNUSED(seader_uart);
     return false;
 }
 
@@ -446,8 +450,42 @@ void seader_send_nfc_rx(SeaderUartBridge* seader_uart, uint8_t* buffer, size_t l
     ASN_STRUCT_FREE(asn_DEF_Response, response);
 }
 
-bool seader_parse_nfc_command_transmit(SeaderWorker* seader_worker, NFCSend_t* nfcSend) {
-  UNUSED(seader_worker);
+/* Assumes this is called in the context of the NFC API callback */
+bool seader_iso14443a_transmit(
+    Seader* seader,
+    uint8_t* buffer,
+    size_t len,
+    uint16_t timeout,
+    uint8_t format[3]) {
+    UNUSED(timeout);
+    UNUSED(format);
+    UNUSED(seader);
+    UNUSED(buffer);
+    UNUSED(len);
+
+    BitBuffer* tx_buffer = bit_buffer_alloc(len);
+    BitBuffer* rx_buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE);
+
+    do {
+        bit_buffer_append_bytes(tx_buffer, buffer, len);
+        NfcError error = nfc_poller_trx(seader->nfc, tx_buffer, rx_buffer, SEADER_POLLER_MAX_FWT);
+        if(error != NfcErrorNone) {
+            FURI_LOG_W(TAG, "nfc_poller_trx error %d", error);
+            //ret = iso14443_3a_poller_process_error(error);
+            break;
+        }
+
+        FURI_LOG_I(TAG, "NFC incoming %d bytes", bit_buffer_get_size_bytes(rx_buffer));
+
+    } while(false);
+
+    bit_buffer_free(tx_buffer);
+    bit_buffer_free(rx_buffer);
+
+    return true;
+}
+
+bool seader_parse_nfc_command_transmit(Seader* seader, NFCSend_t* nfcSend) {
     long timeOut = nfcSend->timeOut;
     Protocol_t protocol = nfcSend->protocol;
     FrameProtocol_t frameProtocol = protocol.buf[1];
@@ -474,17 +512,20 @@ bool seader_parse_nfc_command_transmit(SeaderWorker* seader_worker, NFCSend_t* n
 #endif
 
     if(frameProtocol == FrameProtocol_iclass) {
-      // TODO
+        // TODO
     } else if(frameProtocol == FrameProtocol_nfc) {
-      // TODO
+        return seader_iso14443a_transmit(
+            seader, nfcSend->data.buf, nfcSend->data.size, (uint16_t)timeOut, nfcSend->format->buf);
     }
     return false;
 }
 
-bool seader_parse_nfc_off(SeaderUartBridge* seader_uart) {
+NfcCommand seader_parse_nfc_off(SeaderUartBridge* seader_uart) {
     FURI_LOG_D(TAG, "Set Field Off");
     // seader_worker_disable_field();
     // seader_nfc_scene_field_on_exit();
+    // nfc_poller_stop(poller);
+    // nfc_poller_free(poller);
 
     NFCResponse_t* nfcResponse = 0;
     nfcResponse = calloc(1, sizeof *nfcResponse);
@@ -504,14 +545,17 @@ bool seader_parse_nfc_off(SeaderUartBridge* seader_uart) {
     ASN_STRUCT_FREE(asn_DEF_Response, response);
     ASN_STRUCT_FREE(asn_DEF_NFCResponse, nfcResponse);
 
-    return false;
+    return NfcCommandStop;
 }
 
-bool seader_parse_nfc_command(SeaderWorker* seader_worker, NFCCommand_t* nfcCommand) {
+bool seader_parse_nfc_command(Seader* seader, NFCCommand_t* nfcCommand) {
+    // TODO: THIS IS WHERE I WANT TO PUSH EVENTS TO MESSAGE QUEUE
+
+    SeaderWorker* seader_worker = seader->worker;
     SeaderUartBridge* seader_uart = seader_worker->uart;
     switch(nfcCommand->present) {
     case NFCCommand_PR_nfcSend:
-        seader_parse_nfc_command_transmit(seader_worker, &nfcCommand->choice.nfcSend);
+        //seader_parse_nfc_command_transmit(seader, &nfcCommand->choice.nfcSend);
         break;
     case NFCCommand_PR_nfcOff:
         seader_parse_nfc_off(seader_uart);
@@ -524,13 +568,15 @@ bool seader_parse_nfc_command(SeaderWorker* seader_worker, NFCCommand_t* nfcComm
     return false;
 }
 
-bool seader_worker_state_machine(SeaderWorker* seader_worker, Payload_t* payload) {
+bool seader_worker_state_machine(Seader* seader, Payload_t* payload) {
+    SeaderWorker* seader_worker = seader->worker;
+    FURI_LOG_D(TAG, "seader_worker_state_machine");
     switch(payload->present) {
     case Payload_PR_response:
         seader_parse_response(seader_worker, &payload->choice.response);
         break;
     case Payload_PR_nfcCommand:
-        seader_parse_nfc_command(seader_worker, &payload->choice.nfcCommand);
+        seader_parse_nfc_command(seader, &payload->choice.nfcCommand);
         break;
     case Payload_PR_errorResponse:
         // TODO: screen saying this was a failure, or maybe start over?
@@ -546,10 +592,11 @@ bool seader_worker_state_machine(SeaderWorker* seader_worker, Payload_t* payload
     return false;
 }
 
-bool seader_process_success_response(SeaderWorker* seader_worker, uint8_t* apdu, size_t len) {
+bool seader_process_success_response_i(Seader* seader, uint8_t* apdu, size_t len) {
     Payload_t* payload = 0;
     payload = calloc(1, sizeof *payload);
     assert(payload);
+    FURI_LOG_D(TAG, "seader_process_success_response_i");
 
     asn_dec_rval_t rval =
         asn_decode(0, ATS_DER, &asn_DEF_Payload, (void**)&payload, apdu + 6, len - 6);
@@ -562,32 +609,52 @@ bool seader_process_success_response(SeaderWorker* seader_worker, uint8_t* apdu,
             FURI_LOG_D(TAG, "Received payload: %s", payloadDebug);
         }
 #endif
-        seader_worker_state_machine(seader_worker, payload);
+        seader_worker_state_machine(seader, payload);
     }
 
     ASN_STRUCT_FREE(asn_DEF_Payload, payload);
     return (rval.code == RC_OK);
 }
 
-bool seader_process_apdu(SeaderWorker* seader_worker, uint8_t* apdu, size_t len) {
+bool seader_process_success_response(Seader* seader, uint8_t* apdu, size_t len) {
+    SeaderWorker* seader_worker = seader->worker;
+
+    // FIXME: use a more semantic method to break nfc related stuff out
+    if (seader->poller) {
+      FURI_LOG_I(TAG, "New SAM Message, %d bytes", len);
+      uint32_t space = furi_message_queue_get_space(seader_worker->messages);
+      if(space > 0) {
+          BitBuffer* buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE);
+          bit_buffer_append_bytes(buffer, apdu, len);
+
+          furi_message_queue_put(seader_worker->messages, buffer, SEADER_MQ_TIMEOUT);
+          bit_buffer_free(buffer);
+      }
+    } else {
+      seader_process_success_response_i(seader, apdu, len);
+    }
+    return true;
+}
+
+
+bool seader_process_apdu(Seader* seader, uint8_t* apdu, size_t len) {
+    SeaderWorker* seader_worker = seader->worker;
     SeaderUartBridge* seader_uart = seader_worker->uart;
     if(len < 2) {
         return false;
     }
-    /*
     memset(display, 0, sizeof(display));
     for(uint8_t i = 0; i < len; i++) {
         snprintf(display + (i * 2), sizeof(display), "%02x", apdu[i]);
     }
     FURI_LOG_I(TAG, "APDU: %s", display);
-    */
 
     uint8_t SW1 = apdu[len - 2];
     uint8_t SW2 = apdu[len - 1];
 
     switch(SW1) {
     case 0x61:
-        // FURI_LOG_I(TAG, "Request %d bytes", SW2);
+        FURI_LOG_I(TAG, "Request %d bytes", SW2);
         GET_RESPONSE[4] = SW2;
         seader_ccid_XfrBlock(seader_uart, GET_RESPONSE, sizeof(GET_RESPONSE));
         return true;
@@ -596,7 +663,7 @@ bool seader_process_apdu(SeaderWorker* seader_worker, uint8_t* apdu, size_t len)
     case 0x90:
         if(SW2 == 0x00) {
             if(len > 2) {
-                return seader_process_success_response(seader_worker, apdu, len - 2);
+                return seader_process_success_response(seader, apdu, len - 2);
             }
         }
         break;
@@ -605,20 +672,8 @@ bool seader_process_apdu(SeaderWorker* seader_worker, uint8_t* apdu, size_t len)
     return false;
 }
 
-void seader_worker_process_sam_message(SeaderWorker* seader_worker, CCID_Message* message) {
-    if(seader_process_apdu(seader_worker, message->payload, message->dwLength)) {
-        // no-op
-    } else {
-        memset(display, 0, sizeof(display));
-        for(uint8_t i = 0; i < message->dwLength; i++) {
-            snprintf(display + (i * 2), sizeof(display), "%02x", message->payload[i]);
-        }
-
-        FURI_LOG_W(TAG, "Unknown block: [%ld] %s", message->dwLength, display);
-        if(seader_worker->callback) {
-            seader_worker->callback(SeaderWorkerEventFail, seader_worker->context);
-        }
-    }
+void seader_worker_process_sam_message(Seader* seader, CCID_Message* message) {
+    seader_process_apdu(seader, message->payload, message->dwLength);
 }
 
 int32_t seader_worker_task(void* context) {
@@ -650,44 +705,93 @@ int32_t seader_worker_task(void* context) {
     return 0;
 }
 
+typedef enum {
+    SeaderPollerEventTypeCardDetect,
+    SeaderPollerEventTypeConversation,
+    SeaderPollerEventTypeComplete,
+
+    SeaderPollerEventTypeSuccess,
+    SeaderPollerEventTypeFail,
+} SeaderPollerEventType;
+
+SeaderPollerEventType stage = SeaderPollerEventTypeCardDetect;
+
 NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void* context) {
     furi_assert(event.protocol == NfcProtocolIso14443_4a);
 
     Seader* seader = context;
     SeaderUartBridge* seader_uart = seader->uart;
+    SeaderWorker* seader_worker = seader->worker;
+
     const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data;
 
     if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
-        nfc_device_set_data(seader->nfc_device, NfcProtocolIso14443_4a, nfc_poller_get_data(seader->poller));
-        FURI_LOG_D(TAG, "poller 14a ready");
-
-        size_t uid_len;
-        const uint8_t* uid = nfc_device_get_uid(seader->nfc_device, &uid_len);
-
-        // const Iso14443_4aData* iso14443_4a_data = nfc_device_get_data(seader->nfc_device, NfcProtocolIso14443_4a);
-        //const Iso14443_3aData* iso14443_3a_data = iso14443_4a_data->iso14443_3a_data;
-        const Iso14443_3aData* iso14443_3a_data = nfc_device_get_data(seader->nfc_device, NfcProtocolIso14443_3a);
-        uint8_t sak_val = iso14443_3a_get_sak(iso14443_3a_data);
-
-        CardDetails_t* cardDetails = 0;
-        cardDetails = calloc(1, sizeof *cardDetails);
-        assert(cardDetails);
-
-        OCTET_STRING_fromBuf(&cardDetails->csn, (const char*)uid, uid_len);
-        uint8_t protocolBytes[] = {0x00, FrameProtocol_nfc};
-        OCTET_STRING_fromBuf(&cardDetails->protocol, (const char*)protocolBytes, sizeof(protocolBytes));
-
-        OCTET_STRING_t sak = {.buf = &sak_val, .size = 1};
-        cardDetails->sak = &sak;
+        if(stage == SeaderPollerEventTypeCardDetect) {
+            FURI_LOG_D(TAG, "Card Detect");
+            nfc_device_set_data(
+                seader->nfc_device, NfcProtocolIso14443_4a, nfc_poller_get_data(seader->poller));
+
+            size_t uid_len;
+            const uint8_t* uid = nfc_device_get_uid(seader->nfc_device, &uid_len);
+
+            // const Iso14443_4aData* iso14443_4a_data = nfc_device_get_data(seader->nfc_device, NfcProtocolIso14443_4a);
+            //const Iso14443_3aData* iso14443_3a_data = iso14443_4a_data->iso14443_3a_data;
+            const Iso14443_3aData* iso14443_3a_data =
+                nfc_device_get_data(seader->nfc_device, NfcProtocolIso14443_3a);
+            uint8_t sak_val = iso14443_3a_get_sak(iso14443_3a_data);
+
+            CardDetails_t* cardDetails = 0;
+            cardDetails = calloc(1, sizeof *cardDetails);
+            assert(cardDetails);
+
+            OCTET_STRING_fromBuf(&cardDetails->csn, (const char*)uid, uid_len);
+            uint8_t protocolBytes[] = {0x00, FrameProtocol_nfc};
+            OCTET_STRING_fromBuf(
+                &cardDetails->protocol, (const char*)protocolBytes, sizeof(protocolBytes));
+
+            OCTET_STRING_t sak = {.buf = &sak_val, .size = 1};
+            cardDetails->sak = &sak;
+
+            OCTET_STRING_t atqa = {.buf = (uint8_t*)iso14443_3a_data->atqa, .size = 2};
+            cardDetails->atqa = &atqa;
+
+            seader_send_card_detected(seader_uart, cardDetails);
+
+            ASN_STRUCT_FREE(asn_DEF_CardDetails, cardDetails);
+
+            stage = SeaderPollerEventTypeConversation;
+        } else if(stage == SeaderPollerEventTypeConversation) {
+            UNUSED(seader_worker);
+            uint32_t count = furi_message_queue_get_count(seader_worker->messages);
+            if(count > 0) {
+                furi_thread_set_current_priority(FuriThreadPriorityHighest);
+                FURI_LOG_D(TAG, "Conversation: %ld messages", count);
+
+                BitBuffer* message = bit_buffer_alloc(furi_message_queue_get_message_size(seader_worker->messages));
+                FuriStatus status =
+                    furi_message_queue_get(seader_worker->messages, message, SEADER_MQ_TIMEOUT);
+                if(status != FuriStatusOk) {
+                    FURI_LOG_D(TAG, "furi_message_queue_get fail %d", status);
+                    return NfcCommandStop;
+                }
+                size_t len = bit_buffer_get_size_bytes(message);
+                uint8_t* payload = (uint8_t*)bit_buffer_get_data(message);
+                FURI_LOG_D(TAG, "Conversation: message length %d: %p", len, payload);
 
-        OCTET_STRING_t atqa = {.buf = (uint8_t*)iso14443_3a_data->atqa, .size = 2};
-        cardDetails->atqa = &atqa;
+                seader_process_success_response_i(seader, payload, len);
+                bit_buffer_free(message);
+            }
 
-        seader_send_card_detected(seader_uart, cardDetails);
+            furi_thread_set_current_priority(FuriThreadPriorityLowest);
 
-        ASN_STRUCT_FREE(asn_DEF_CardDetails, cardDetails);
+            // TESTING
+            //return NfcCommandStop;
 
-        return NfcCommandStop;
+            //stage = SeaderPollerEventTypeComplete;
+        } else if(stage == SeaderPollerEventTypeComplete) {
+            FURI_LOG_D(TAG, "Complete");
+            return NfcCommandStop;
+        }
     }
 
     return NfcCommandContinue;

+ 2 - 2
seader_worker.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h>
+
 #include "seader_credential.h"
 #include "seader_bridge.h"
 
@@ -51,8 +52,7 @@ void seader_worker_start(
     void* context);
 
 void seader_worker_stop(SeaderWorker* seader_worker);
-void seader_worker_process_sam_message(SeaderWorker* seader_worker, CCID_Message* message);
+void seader_worker_process_sam_message(Seader* seader, CCID_Message* message);
 void seader_worker_send_version(SeaderWorker* seader_worker);
 
-
 NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void* context);

+ 6 - 1
seader_worker_i.h

@@ -1,7 +1,7 @@
 #pragma once
 
-#include "seader_worker.h"
 #include "seader_i.h"
+#include "seader_worker.h"
 
 #include <furi.h>
 #include <lib/toolbox/stream/file_stream.h>
@@ -13,10 +13,15 @@
 #include <PAC.h>
 #include <SamVersion.h>
 
+#define SEADER_POLLER_MAX_FWT (200000U)
+#define SEADER_POLLER_MAX_BUFFER_SIZE (64U)
+#define SEADER_MQ_TIMEOUT FuriWaitForever
+
 struct SeaderWorker {
     FuriThread* thread;
     Storage* storage;
     uint8_t sam_version[2];
+    FuriMessageQueue* messages;
 
     SeaderUartBridge* uart;
     SeaderCredential* credential;

+ 1 - 2
uart.c

@@ -39,7 +39,6 @@ void seader_uart_set_baudrate(SeaderUartBridge* seader_uart, uint32_t baudrate)
 }
 
 size_t seader_uart_process_buffer(Seader* seader, uint8_t* cmd, size_t cmd_len) {
-    SeaderWorker* seader_worker = seader->worker;
     SeaderUartBridge* seader_uart = seader->uart;
     if(cmd_len < 2) {
         return cmd_len;
@@ -47,7 +46,7 @@ size_t seader_uart_process_buffer(Seader* seader, uint8_t* cmd, size_t cmd_len)
 
     size_t consumed = 0;
     do {
-        consumed = seader_ccid_process(seader_worker, cmd, cmd_len);
+        consumed = seader_ccid_process(seader, cmd, cmd_len);
 
         if(consumed > 0) {
             memset(cmd, 0, consumed);