diff --git a/applications/debug/unit_tests/nfc/nfc_transport.c b/applications/debug/unit_tests/nfc/nfc_transport.c index e9084ca20b93..c91c8b95873b 100644 --- a/applications/debug/unit_tests/nfc/nfc_transport.c +++ b/applications/debug/unit_tests/nfc/nfc_transport.c @@ -334,7 +334,7 @@ void nfc_start_listener(Nfc* instance, NfcEventCallback callback, void* context) furi_thread_start(instance->worker_thread); } -NfcError nfc_listener_sleep(Nfc* instance) { +NfcError nfc_listener_reset(Nfc* instance) { furi_assert(instance); furi_assert(poller_queue); diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 5573f3479f4d..90ad35b921e0 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,38.0,, +Version,+,38.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -2205,6 +2205,7 @@ Function,-,nfc_listener_abort,void,Nfc* Function,-,nfc_listener_alloc,NfcListener*,"Nfc*, NfcProtocol, const NfcDeviceData*" Function,-,nfc_listener_free,void,NfcListener* Function,-,nfc_listener_get_data,const NfcDeviceData*,"NfcListener*, NfcProtocol" +Function,-,nfc_listener_reset,NfcError,Nfc* Function,-,nfc_listener_set_col_res_data,NfcError,"Nfc*, uint8_t*, uint8_t, uint8_t*, uint8_t" Function,-,nfc_listener_sleep,NfcError,Nfc* Function,-,nfc_listener_start,void,"NfcListener*, NfcGenericCallback, void*" diff --git a/lib/nfc/nfc.c b/lib/nfc/nfc.c index 2073ee9dad2c..a416fb07ab4d 100644 --- a/lib/nfc/nfc.c +++ b/lib/nfc/nfc.c @@ -108,7 +108,7 @@ static int32_t nfc_worker_listener(void* context) { if(event & FHalNfcEventFieldOff) { nfc_event.type = NfcEventTypeFieldOff; instance->callback(nfc_event, instance->context); - nfc_listener_sleep(instance); + nfc_listener_reset(instance); } if(event & FHalNfcEventListenerActive) { f_hal_nfc_listener_disable_auto_col_res(); @@ -124,6 +124,8 @@ static int32_t nfc_worker_listener(void* context) { if(command == NfcCommandStop) { break; } else if(command == NfcCommandReset) { + nfc_listener_reset(instance); + } else if(command == NfcCommandSleep) { nfc_listener_sleep(instance); } } @@ -347,7 +349,7 @@ void nfc_stop(Nfc* instance) { furi_thread_join(instance->worker_thread); } -NfcError nfc_listener_sleep(Nfc* instance) { +NfcError nfc_listener_reset(Nfc* instance) { furi_assert(instance); furi_assert(instance->state == NfcStateListenerStarted); @@ -356,6 +358,15 @@ NfcError nfc_listener_sleep(Nfc* instance) { return NfcErrorNone; } +NfcError nfc_listener_sleep(Nfc* instance) { + furi_assert(instance); + furi_assert(instance->state == NfcStateListenerStarted); + + f_hal_nfc_listener_reset(); + + return NfcErrorNone; +} + NfcError nfc_listener_tx(Nfc* instance, const BitBuffer* tx_buffer) { furi_assert(instance); furi_assert(tx_buffer); diff --git a/lib/nfc/nfc.h b/lib/nfc/nfc.h index 0c7e63e96e55..d7aa4be0b3ee 100644 --- a/lib/nfc/nfc.h +++ b/lib/nfc/nfc.h @@ -34,6 +34,7 @@ typedef enum { NfcCommandContinue, NfcCommandReset, NfcCommandStop, + NfcCommandSleep, } NfcCommand; typedef NfcCommand (*NfcEventCallback)(NfcEvent event, void* context); @@ -92,6 +93,8 @@ void nfc_start_poller(Nfc* instance, NfcEventCallback callback, void* context); void nfc_start_listener(Nfc* instance, NfcEventCallback callback, void* context); +NfcError nfc_listener_reset(Nfc* instance); + NfcError nfc_listener_sleep(Nfc* instance); void nfc_listener_abort(Nfc* instance); diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c index d8472094ffc1..8ff2f1e0ab88 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c @@ -361,6 +361,45 @@ static MfUltralightCommand return command; } +static MfUltralightCommand + mf_ultralight_sector_select_handler_p2(MfUltralightListener* instance, BitBuffer* buffer) { + MfUltralightCommand command = MfUltralightCommandNotProcessedNAK; + UNUSED(instance); + UNUSED(buffer); + FURI_LOG_D(TAG, "CMD_SEC_SEL_2"); + + do { + if(bit_buffer_get_size_bytes(buffer) != 4) break; + uint8_t sector = bit_buffer_get_byte(buffer, 0); + if(sector == 0xFF) break; + + instance->sector = sector; + command = MfUltralightCommandProcessedSilent; + } while(false); + + return command; +} + +static MfUltralightCommand + mf_ultralight_sector_select_handler_p1(MfUltralightListener* instance, BitBuffer* buffer) { + MfUltralightCommand command = MfUltralightCommandNotProcessedNAK; + UNUSED(buffer); + FURI_LOG_D(TAG, "CMD_SEC_SEL_1"); + + do { + if(!mf_ultralight_support_feature( + instance->features, MfUltralightFeatureSupportSectorSelect) && + bit_buffer_get_byte(buffer, 1) == 0xFF) + break; + + command = MfUltralightCommandProcessed; + mf_ultralight_listener_send_short_resp(instance, MF_ULTRALIGHT_CMD_ACK); + mf_ultralight_composite_command_set_next(instance, mf_ultralight_sector_select_handler_p2); + } while(false); + + return command; +} + static const MfUltralightListenerCmdHandler mf_ultralight_command[] = { { .cmd = MF_ULTRALIGHT_CMD_READ_PAGE, @@ -402,6 +441,11 @@ static const MfUltralightListenerCmdHandler mf_ultralight_command[] = { .cmd_len_bits = 6 * 8, .callback = mf_ultralight_listener_increase_counter_handler, }, + { + .cmd = MF_ULTRALIGHT_CMD_SECTOR_SELECT, + .cmd_len_bits = 2 * 8, + .callback = mf_ultralight_sector_select_handler_p1, + }, { .cmd = MF_ULTRALIGHT_CMD_COMP_WRITE, .cmd_len_bits = 2 * 8, @@ -427,6 +471,7 @@ MfUltralightListener* mf_ultralight_listener_alloc( instance->data = data; mf_ultralight_listener_prepare_emulation(instance); mf_ultralight_composite_command_reset(instance); + instance->sector = 0; instance->tx_buffer = bit_buffer_alloc(MF_ULTRALIGHT_LISTENER_MAX_TX_BUFF_SIZE); instance->mfu_event.data = &instance->mfu_event_data; @@ -490,7 +535,9 @@ NfcCommand mf_ultralight_listener_run(NfcGenericEvent event, void* context) { if(mfu_command != MfUltralightCommandNotFound) break; } } - if(mfu_command != MfUltralightCommandProcessed) { + if(mfu_command == MfUltralightCommandProcessedSilent) { + command = NfcCommandSleep; + } else if(mfu_command != MfUltralightCommandProcessed) { instance->state = MfUltraligthListenerStateIdle; instance->auth_state = MfUltralightListenerAuthStateIdle; command = NfcCommandReset; @@ -505,6 +552,7 @@ NfcCommand mf_ultralight_listener_run(NfcGenericEvent event, void* context) { iso14443_3a_event->type == Iso14443_3aListenerEventTypeHalted) { // TODO generic state reset ? mf_ultralight_composite_command_reset(instance); + instance->sector = 0; instance->auth_state = MfUltralightListenerAuthStateIdle; command = NfcCommandReset; } diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h index ce6d0d8b9e08..ac390a800e29 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h @@ -20,6 +20,7 @@ typedef enum { typedef enum { MfUltralightCommandNotFound, MfUltralightCommandProcessed, + MfUltralightCommandProcessedSilent, MfUltralightCommandNotProcessedNAK, MfUltralightCommandNotProcessedSilent, } MfUltralightCommand; @@ -57,6 +58,7 @@ struct MfUltralightListener { MfUltralightListenerEvent mfu_event; MfUltralightListenerEventData mfu_event_data; NfcGenericCallback callback; + uint8_t sector; MfUltralightMirrorMode mirror; MfUltralightListenerCompositeCommandContext composite_cmd; void* context;