diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c index 2519fb90c..b2e1a4e24 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c @@ -70,7 +70,15 @@ static NfcCommand iso14443_4a_listener_run(NfcGenericEvent event, void* context) instance->state = Iso14443_4aListenerStateActive; } } - } else { + } else if(bit_buffer_get_size_bytes(rx_buffer) > 1) { + // TODO: This is a rudimentary PCB implementation! + // Just ignores its meaning and saves it for sending blocks to reader, + // there is no handling of S, R, I blocks and their different flags. + // We have iso14443_4_layer helper but it is entirely designed for poller, + // will need large rework for listener, for now this works. + instance->pcb_prev = bit_buffer_get_byte(rx_buffer, 0); + bit_buffer_copy_right(rx_buffer, rx_buffer, 1); + instance->iso14443_4a_event.type = Iso14443_4aListenerEventTypeReceivedData; instance->iso14443_4a_event.data->buffer = rx_buffer; diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h index 04f0b197a..ff4bad7e4 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h @@ -25,6 +25,18 @@ typedef struct { Iso14443_4aListenerEventData* data; } Iso14443_4aListenerEvent; +/** + * @brief Transmit Iso14443_4a blocks in listener mode. + * + * Must ONLY be used inside the callback function. + * + * @param[in, out] instance pointer to the instance to be used in the transaction. + * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted. + * @return Iso14443_4aErrorNone on success, an error code on failure. + */ +Iso14443_4aError + iso14443_4a_listener_send_block(Iso14443_4aListener* instance, const BitBuffer* tx_buffer); + #ifdef __cplusplus } #endif diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener_i.c b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener_i.c index 8590c22ad..20ffa3542 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener_i.c +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener_i.c @@ -30,3 +30,20 @@ Iso14443_4aError instance->iso14443_3a_listener, instance->tx_buffer); return iso14443_4a_process_error(error); } + +Iso14443_4aError + iso14443_4a_listener_send_block(Iso14443_4aListener* instance, const BitBuffer* tx_buffer) { + bit_buffer_reset(instance->tx_buffer); + + // TODO: This is a rudimentary PCB implementation! + // Just sends back same PCB that was last received from reader, + // there is no handling of S, R, I blocks and their different flags. + // We have iso14443_4_layer helper but it is entirely designed for poller, + // will need large rework for listener, for now this works. + bit_buffer_append_byte(instance->tx_buffer, instance->pcb_prev); + bit_buffer_append(instance->tx_buffer, tx_buffer); + + const Iso14443_3aError error = iso14443_3a_listener_send_standard_frame( + instance->iso14443_3a_listener, instance->tx_buffer); + return iso14443_4a_process_error(error); +} diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener_i.h b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener_i.h index d4e884f6f..9588d6849 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener_i.h +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener_i.h @@ -17,6 +17,7 @@ typedef enum { struct Iso14443_4aListener { Iso14443_3aListener* iso14443_3a_listener; Iso14443_4aData* data; + uint8_t pcb_prev; Iso14443_4aListenerState state; BitBuffer* tx_buffer; diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index d20e5e12f..03df9a8c8 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -2163,6 +2163,7 @@ Function,+,iso14443_4a_get_fwt_fc_max,uint32_t,const Iso14443_4aData* Function,+,iso14443_4a_get_historical_bytes,const uint8_t*,"const Iso14443_4aData*, uint32_t*" Function,+,iso14443_4a_get_uid,const uint8_t*,"const Iso14443_4aData*, size_t*" Function,+,iso14443_4a_is_equal,_Bool,"const Iso14443_4aData*, const Iso14443_4aData*" +Function,+,iso14443_4a_listener_send_block,Iso14443_4aError,"Iso14443_4aListener*, const BitBuffer*" Function,+,iso14443_4a_load,_Bool,"Iso14443_4aData*, FlipperFormat*, uint32_t" Function,+,iso14443_4a_poller_halt,Iso14443_4aError,Iso14443_4aPoller* Function,+,iso14443_4a_poller_read_ats,Iso14443_4aError,"Iso14443_4aPoller*, Iso14443_4aAtsData*"