From 73d2d64898baca802fc981caa8b077daba0e5114 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Sat, 7 Mar 2026 13:30:01 -0800 Subject: [PATCH] SeaderWorker tweaks ref #30 --- lib/asn1/FrameProtocol.c | 1 - seader_worker.c | 123 ++++++++++++++++++++++++++++++++++++++- seader_worker.h | 2 + 3 files changed, 124 insertions(+), 2 deletions(-) diff --git a/lib/asn1/FrameProtocol.c b/lib/asn1/FrameProtocol.c index cde62a7..593dde0 100644 --- a/lib/asn1/FrameProtocol.c +++ b/lib/asn1/FrameProtocol.c @@ -47,4 +47,3 @@ asn_TYPE_descriptor_t asn_DEF_FrameProtocol = { 0, 0, /* Defined elsewhere */ &asn_SPC_FrameProtocol_specs_1 /* Additional specs */ }; - diff --git a/seader_worker.c b/seader_worker.c index 2cd256f..7231d3f 100644 --- a/seader_worker.c +++ b/seader_worker.c @@ -1,4 +1,5 @@ #include "seader_worker_i.h" +#include "trace_log.h" #include #include @@ -85,6 +86,42 @@ void seader_worker_change_state(SeaderWorker* seader_worker, SeaderWorkerState s seader_worker->state = state; } +void seader_worker_cancel_poller_session(SeaderWorker* seader_worker) { + furi_assert(seader_worker); + FURI_LOG_D( + TAG, + "Cancel poller session stage=%d queued=%ld", + seader_worker->stage, + furi_message_queue_get_count(seader_worker->messages)); + seader_trace( + TAG, + "cancel stage=%d queued=%ld", + seader_worker->stage, + furi_message_queue_get_count(seader_worker->messages)); + seader_worker->stage = SeaderPollerEventTypeComplete; +} + +void seader_worker_reset_poller_session(SeaderWorker* seader_worker) { + furi_assert(seader_worker); + FURI_LOG_D( + TAG, + "Reset poller session stage=%d queued=%ld", + seader_worker->stage, + furi_message_queue_get_count(seader_worker->messages)); + seader_trace( + TAG, + "reset stage=%d queued=%ld", + seader_worker->stage, + furi_message_queue_get_count(seader_worker->messages)); + + if(furi_mutex_acquire(seader_worker->mq_mutex, FuriWaitForever) == FuriStatusOk) { + furi_message_queue_reset(seader_worker->messages); + furi_mutex_release(seader_worker->mq_mutex); + } + + seader_worker->stage = SeaderPollerEventTypeCardDetect; +} + /***************************** Seader Worker Thread *******************************/ bool seader_process_success_response(Seader* seader, uint8_t* apdu, size_t len) { @@ -93,7 +130,33 @@ bool seader_process_success_response(Seader* seader, uint8_t* apdu, size_t len) if(seader_process_success_response_i(seader, apdu, len, false, NULL)) { // no-op, message was processed } else { - FURI_LOG_I(TAG, "Enqueue SAM message, %d bytes", len); + if(seader_worker->state != SeaderWorkerStateVirtualCredential && + seader_worker->stage != SeaderPollerEventTypeConversation) { + FURI_LOG_I( + TAG, + "Discard stale SAM message outside active conversation, %d bytes, stage=%d, sam=%d", + len, + seader_worker->stage, + seader->samCommand); + seader_trace( + TAG, + "discard len=%d stage=%d sam=%d state=%d intent=%d", + len, + seader_worker->stage, + seader->samCommand, + seader->sam_state, + seader->sam_intent); + return true; + } + + FURI_LOG_I( + TAG, + "Enqueue SAM message, %d bytes, stage=%d, sam=%d", + len, + seader_worker->stage, + seader->samCommand); + seader_trace( + TAG, "enqueue len=%d stage=%d sam=%d", len, seader_worker->stage, seader->samCommand); uint32_t space = furi_message_queue_get_space(seader_worker->messages); if(space > 0) { SeaderAPDU seaderApdu = {}; @@ -126,6 +189,16 @@ bool seader_worker_process_sam_message(Seader* seader, uint8_t* apdu, uint32_t l snprintf(display + (i * 2), sizeof(display), "%02x", apdu[i]); } FURI_LOG_I(TAG, "APDU: %s", display); + seader_trace( + TAG, + "sam apdu len=%lu stage=%d sam=%d state=%d intent=%d sw=%02x%02x", + len, + seader_worker->stage, + seader->samCommand, + seader->sam_state, + seader->sam_intent, + apdu[len - 2], + apdu[len - 1]); free(display); uint8_t SW1 = apdu[len - 2]; @@ -227,12 +300,18 @@ int32_t seader_worker_task(void* context) { void seader_worker_poller_conversation(Seader* seader, SeaderPollerContainer* spc) { SeaderWorker* seader_worker = seader->worker; + seader_trace( + TAG, + "conversation stage=%d queued=%ld", + seader_worker->stage, + furi_message_queue_get_count(seader_worker->messages)); if(furi_mutex_acquire(seader_worker->mq_mutex, 0) == FuriStatusOk) { furi_thread_set_current_priority(FuriThreadPriorityHighest); uint32_t count = furi_message_queue_get_count(seader_worker->messages); if(count > 0) { FURI_LOG_I(TAG, "Dequeue SAM message [%ld messages]", count); + seader_trace(TAG, "dequeue count=%ld", count); SeaderAPDU seaderApdu = {}; FuriStatus status = @@ -272,9 +351,20 @@ NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) { if(seader_worker->stage == SeaderPollerEventTypeCardDetect) { + FURI_LOG_D(TAG, "14a stage CardDetect -> Conversation"); + seader_trace(TAG, "14a CardDetect->Conversation"); view_dispatcher_send_custom_event( seader->view_dispatcher, SeaderCustomEventPollerDetect); + if(!seader_sam_can_accept_card(seader)) { + seader_trace( + TAG, + "14a defer detect sam_state=%d intent=%d", + seader->sam_state, + seader->sam_intent); + return NfcCommandContinue; + } + nfc_device_set_data( seader->nfc_device, NfcProtocolIso14443_4a, nfc_poller_get_data(seader->poller)); @@ -322,6 +412,7 @@ NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void seader_worker_card_detect( seader, sak, (uint8_t*)iso14443_3a_data->atqa, uid, uid_len, ats, ats_len); + seader_trace(TAG, "14a card_detect sent uid_len=%d sak=%d", uid_len, sak); free(ats); @@ -329,10 +420,13 @@ NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void furi_thread_set_current_priority(FuriThreadPriorityLowest); seader_worker->stage = SeaderPollerEventTypeConversation; } else if(seader_worker->stage == SeaderPollerEventTypeConversation) { + seader_trace(TAG, "14a ready in Conversation"); seader_worker_poller_conversation(seader, &spc); } else if(seader_worker->stage == SeaderPollerEventTypeComplete) { + seader_trace(TAG, "14a ready in Complete"); ret = NfcCommandStop; } else if(seader_worker->stage == SeaderPollerEventTypeFail) { + seader_trace(TAG, "14a ready in Fail"); ret = NfcCommandStop; view_dispatcher_send_custom_event( seader->view_dispatcher, SeaderCustomEventWorkerExit); @@ -342,6 +436,7 @@ NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void Iso14443_4aPollerEventData* data = iso14443_4a_event->data; Iso14443_4aError error = data->error; FURI_LOG_W(TAG, "Iso14443_4aError %i", error); + seader_trace(TAG, "14a error=%d stage=%d", error, seader_worker->stage); // I was hoping to catch MFC here, but it seems to be treated the same (None) as no card being present. switch(error) { case Iso14443_4aErrorNone: @@ -371,9 +466,20 @@ NfcCommand seader_worker_poller_callback_mfc(NfcGenericEvent event, void* contex if(mfc_event->type == MfClassicPollerEventTypeSuccess) { if(seader_worker->stage == SeaderPollerEventTypeCardDetect) { + FURI_LOG_D(TAG, "MFC stage CardDetect -> Conversation"); + seader_trace(TAG, "mfc CardDetect->Conversation"); view_dispatcher_send_custom_event( seader->view_dispatcher, SeaderCustomEventPollerDetect); + if(!seader_sam_can_accept_card(seader)) { + seader_trace( + TAG, + "mfc defer detect sam_state=%d intent=%d", + seader->sam_state, + seader->sam_intent); + return NfcCommandContinue; + } + const MfClassicData* mfc_data = nfc_poller_get_data(seader->poller); uint8_t sak = iso14443_3a_get_sak(mfc_data->iso14443_3a_data); size_t uid_len = 0; @@ -386,9 +492,14 @@ NfcCommand seader_worker_poller_callback_mfc(NfcGenericEvent event, void* contex } else if(seader_worker->stage == SeaderPollerEventTypeComplete) { ret = NfcCommandStop; } else if(seader_worker->stage == SeaderPollerEventTypeFail) { + seader_trace(TAG, "mfc ready in Fail"); + view_dispatcher_send_custom_event( + seader->view_dispatcher, SeaderCustomEventWorkerExit); ret = NfcCommandStop; } } else if(mfc_event->type == MfClassicPollerEventTypeFail) { + seader_trace(TAG, "mfc poller event fail"); + view_dispatcher_send_custom_event(seader->view_dispatcher, SeaderCustomEventWorkerExit); ret = NfcCommandStop; } @@ -409,8 +520,18 @@ NfcCommand seader_worker_poller_callback_picopass(PicopassPollerEvent event, voi seader_worker->stage = SeaderPollerEventTypeCardDetect; } else if(event.type == PicopassPollerEventTypeSuccess) { if(seader_worker->stage == SeaderPollerEventTypeCardDetect) { + FURI_LOG_D(TAG, "Picopass stage CardDetect -> Conversation"); + seader_trace(TAG, "picopass CardDetect->Conversation"); view_dispatcher_send_custom_event( seader->view_dispatcher, SeaderCustomEventPollerDetect); + if(!seader_sam_can_accept_card(seader)) { + seader_trace( + TAG, + "picopass defer detect sam_state=%d intent=%d", + seader->sam_state, + seader->sam_intent); + return NfcCommandContinue; + } uint8_t* csn = picopass_poller_get_csn(instance); seader_worker_card_detect(seader, 0, NULL, csn, sizeof(PicopassSerialNum), NULL, 0); furi_thread_set_current_priority(FuriThreadPriorityLowest); diff --git a/seader_worker.h b/seader_worker.h index 1634533..81e45e8 100644 --- a/seader_worker.h +++ b/seader_worker.h @@ -69,6 +69,8 @@ void seader_worker_start( void seader_worker_stop(SeaderWorker* seader_worker); bool seader_worker_process_sam_message(Seader* seader, uint8_t* apdu, uint32_t len); void seader_worker_send_version(Seader* seader); +void seader_worker_cancel_poller_session(SeaderWorker* seader_worker); +void seader_worker_reset_poller_session(SeaderWorker* seader_worker); NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void* context); NfcCommand seader_worker_poller_callback_mfc(NfcGenericEvent event, void* context);