diff --git a/lib/nfc/helpers/iso14443_4_layer.c b/lib/nfc/helpers/iso14443_4_layer.c index 3089ec59c..1b4dac1dd 100644 --- a/lib/nfc/helpers/iso14443_4_layer.c +++ b/lib/nfc/helpers/iso14443_4_layer.c @@ -59,9 +59,11 @@ struct Iso14443_4Layer { uint8_t nad; }; -static inline void iso14443_4_layer_update_pcb(Iso14443_4Layer* instance) { +static inline void iso14443_4_layer_update_pcb(Iso14443_4Layer* instance, bool toggle_num) { instance->pcb_prev = instance->pcb; - instance->pcb ^= (uint8_t)0x01; + if(toggle_num) { + instance->pcb ^= (uint8_t)0x01; + } } Iso14443_4Layer* iso14443_4_layer_alloc(void) { @@ -115,7 +117,7 @@ void iso14443_4_layer_encode_command( bit_buffer_append_byte(block_data, instance->pcb); bit_buffer_append(block_data, input_data); - iso14443_4_layer_update_pcb(instance); + iso14443_4_layer_update_pcb(instance, true); } static inline uint8_t iso14443_4_layer_get_response_pcb(const BitBuffer* block_data) { @@ -137,7 +139,7 @@ bool iso14443_4_layer_decode_response( ret = (ISO14443_4_BLOCK_PCB_IS_R_BLOCK(response_pcb)) && (!ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE(response_pcb)); instance->pcb &= ISO14443_4_BLOCK_PCB_MASK; - iso14443_4_layer_update_pcb(instance); + iso14443_4_layer_update_pcb(instance, true); } else if(ISO14443_4_BLOCK_PCB_IS_CHAIN_ACTIVE(instance->pcb_prev)) { const uint8_t response_pcb = iso14443_4_layer_get_response_pcb(block_data); ret = (ISO14443_4_BLOCK_PCB_IS_R_BLOCK(response_pcb)) && @@ -165,65 +167,69 @@ void iso14443_4_layer_set_nad_supported(Iso14443_4Layer* instance, bool nad) { instance->nad = nad ? 0 : ISO14443_4_LAYER_NAD_NOT_SUPPORTED; } -Iso14443_4LayerStatus iso14443_4_layer_decode_command( +Iso14443_4LayerResult iso14443_4_layer_decode_command( Iso14443_4Layer* instance, const BitBuffer* input_data, BitBuffer* block_data) { - uint8_t prologue_len = 0; - instance->pcb_prev = bit_buffer_get_byte(input_data, prologue_len++); + furi_assert(instance); - if(ISO14443_4_BLOCK_PCB_IS_I_BLOCK(instance->pcb_prev)) { - if(instance->pcb_prev & ISO14443_4_BLOCK_PCB_I_CID_MASK) { + uint8_t prologue_len = 0; + instance->pcb = bit_buffer_get_byte(input_data, prologue_len++); + + if(ISO14443_4_BLOCK_PCB_IS_I_BLOCK(instance->pcb)) { + if(instance->pcb & ISO14443_4_BLOCK_PCB_I_CID_MASK) { const uint8_t cid = bit_buffer_get_byte(input_data, prologue_len++) & ISO14443_4_BLOCK_CID_MASK; if(instance->cid == ISO14443_4_LAYER_CID_NOT_SUPPORTED || cid != instance->cid) { - return Iso14443_4LayerStatusIgnore; + return Iso14443_4LayerResultSkip; } } else if(instance->cid != ISO14443_4_LAYER_CID_NOT_SUPPORTED && instance->cid != 0) { - return Iso14443_4LayerStatusIgnore; + return Iso14443_4LayerResultSkip; } - if(instance->pcb_prev & ISO14443_4_BLOCK_PCB_I_NAD_MASK) { + if(instance->pcb & ISO14443_4_BLOCK_PCB_I_NAD_MASK) { if(instance->nad == ISO14443_4_LAYER_NAD_NOT_SUPPORTED) { - return Iso14443_4LayerStatusIgnore; + return Iso14443_4LayerResultSkip; } instance->nad = bit_buffer_get_byte(input_data, prologue_len++); // FIXME: unset NAD when chaining after first block } // FIXME: chaining bit_buffer_copy_right(block_data, input_data, prologue_len); - return Iso14443_4LayerStatusOk; + iso14443_4_layer_update_pcb(instance, false); + return Iso14443_4LayerResultData; - } else if(ISO14443_4_BLOCK_PCB_IS_S_BLOCK(instance->pcb_prev)) { - if(instance->pcb_prev & ISO14443_4_BLOCK_PCB_S_CID_MASK) { + } else if(ISO14443_4_BLOCK_PCB_IS_S_BLOCK(instance->pcb)) { + if(instance->pcb & ISO14443_4_BLOCK_PCB_S_CID_MASK) { const uint8_t cid = bit_buffer_get_byte(input_data, prologue_len++) & ISO14443_4_BLOCK_CID_MASK; if(instance->cid == ISO14443_4_LAYER_CID_NOT_SUPPORTED || cid != instance->cid) { - return Iso14443_4LayerStatusIgnore; + return Iso14443_4LayerResultSkip; } } else if(instance->cid != ISO14443_4_LAYER_CID_NOT_SUPPORTED && instance->cid != 0) { - return Iso14443_4LayerStatusIgnore; + return Iso14443_4LayerResultSkip; } - if((instance->pcb_prev & ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_MASK) == 0) { + if((instance->pcb & ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_MASK) == 0) { // DESELECT bit_buffer_copy(block_data, input_data); - return Iso14443_4LayerStatusSendAndHalt; + return Iso14443_4LayerResultSend | Iso14443_4LayerResultHalt; } else { // WTX ACK or wrong value - return Iso14443_4LayerStatusIgnore; + return Iso14443_4LayerResultSkip; } // FIXME: R blocks } - return Iso14443_4LayerStatusIgnore; + return Iso14443_4LayerResultSkip; } bool iso14443_4_layer_encode_response( Iso14443_4Layer* instance, const BitBuffer* input_data, BitBuffer* block_data) { + furi_assert(instance); + if(ISO14443_4_BLOCK_PCB_IS_I_BLOCK(instance->pcb_prev)) { - instance->pcb = instance->pcb_prev; - bit_buffer_append_byte(block_data, instance->pcb); + bit_buffer_append_byte(block_data, 0x00); if(instance->pcb_prev & ISO14443_4_BLOCK_PCB_I_CID_MASK) { bit_buffer_append_byte(block_data, instance->cid); } @@ -239,6 +245,7 @@ bool iso14443_4_layer_encode_response( instance->pcb &= ~ISO14443_4_BLOCK_PCB_I_CHAIN_MASK; bit_buffer_set_byte(block_data, 0, instance->pcb); bit_buffer_append(block_data, input_data); + iso14443_4_layer_update_pcb(instance, false); return true; // FIXME: R blocks diff --git a/lib/nfc/helpers/iso14443_4_layer.h b/lib/nfc/helpers/iso14443_4_layer.h index 344d3ccf5..6c5edf49e 100644 --- a/lib/nfc/helpers/iso14443_4_layer.h +++ b/lib/nfc/helpers/iso14443_4_layer.h @@ -33,12 +33,13 @@ bool iso14443_4_layer_decode_response( // Listener mode typedef enum { - Iso14443_4LayerStatusOk, - Iso14443_4LayerStatusIgnore, - Iso14443_4LayerStatusSendAndHalt, -} Iso14443_4LayerStatus; + Iso14443_4LayerResultSkip = (0), + Iso14443_4LayerResultData = (1 << 1), + Iso14443_4LayerResultSend = (1 << 2), + Iso14443_4LayerResultHalt = (1 << 3), +} Iso14443_4LayerResult; -Iso14443_4LayerStatus iso14443_4_layer_decode_command( +Iso14443_4LayerResult iso14443_4_layer_decode_command( Iso14443_4Layer* instance, const BitBuffer* input_data, BitBuffer* block_data); diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c index 1d216a460..189a23dd2 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c @@ -88,19 +88,21 @@ static NfcCommand iso14443_4a_listener_run(NfcGenericEvent event, void* context) } } } else { - Iso14443_4LayerStatus status = + Iso14443_4LayerResult status = iso14443_4_layer_decode_command(instance->iso14443_4_layer, rx_buffer, rx_buffer); - if(status == Iso14443_4LayerStatusSendAndHalt) { - if(iso14443_3a_listener_send_standard_frame( - instance->iso14443_3a_listener, rx_buffer) == Iso14443_3aErrorNone) { - iso14443_4a_listener_reset(instance); - if(instance->callback) { - instance->iso14443_4a_event.type = Iso14443_4aListenerEventTypeHalted; - instance->callback(instance->generic_event, instance->context); - } - command = NfcCommandSleep; + if(status & Iso14443_4LayerResultSend) { + iso14443_3a_listener_send_standard_frame( + instance->iso14443_3a_listener, rx_buffer); + } + if(status & Iso14443_4LayerResultHalt) { + iso14443_4a_listener_reset(instance); + if(instance->callback) { + instance->iso14443_4a_event.type = Iso14443_4aListenerEventTypeHalted; + instance->callback(instance->generic_event, instance->context); } - } else if(status == Iso14443_4LayerStatusOk) { + command = NfcCommandSleep; + } + if(status & Iso14443_4LayerResultData) { instance->iso14443_4a_event.type = Iso14443_4aListenerEventTypeReceivedData; instance->iso14443_4a_event.data->buffer = rx_buffer;