Files
Momentum-Firmware/lib/nfc/helpers/nxp_native_command.c
2025-03-22 11:36:34 +00:00

116 lines
5.2 KiB
C

#include "nxp_native_command.h"
#include <lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.h>
#define TAG "NxpNativeCommand"
Iso14443_4aError nxp_native_command_iso14443_4a_poller(
Iso14443_4aPoller* iso14443_4a_poller,
NxpNativeCommandStatus* status_code,
const BitBuffer* input_buffer,
BitBuffer* result_buffer,
NxpNativeCommandMode command_mode,
BitBuffer* tx_buffer,
BitBuffer* rx_buffer) {
furi_check(iso14443_4a_poller);
furi_check(tx_buffer);
furi_check(rx_buffer);
furi_check(input_buffer);
furi_check(result_buffer);
furi_check(command_mode < NxpNativeCommandModeMAX);
Iso14443_4aError error = Iso14443_4aErrorNone;
*status_code = NXP_NATIVE_COMMAND_STATUS_OPERATION_OK;
do {
bit_buffer_reset(tx_buffer);
if(command_mode == NxpNativeCommandModePlain) {
bit_buffer_append(tx_buffer, input_buffer);
} else if(command_mode == NxpNativeCommandModeIsoWrapped) {
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_CLA);
bit_buffer_append_byte(tx_buffer, bit_buffer_get_byte(input_buffer, 0));
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_P1);
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_P2);
if(bit_buffer_get_size_bytes(input_buffer) > 1) {
bit_buffer_append_byte(tx_buffer, bit_buffer_get_size_bytes(input_buffer) - 1);
bit_buffer_append_right(tx_buffer, input_buffer, 1);
}
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_LE);
}
bit_buffer_reset(rx_buffer);
error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
if(error != Iso14443_4aErrorNone) {
break;
}
bit_buffer_reset(tx_buffer);
if(command_mode == NxpNativeCommandModePlain) {
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_STATUS_ADDITIONAL_FRAME);
} else if(command_mode == NxpNativeCommandModeIsoWrapped) {
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_CLA);
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_STATUS_ADDITIONAL_FRAME);
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_P1);
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_P2);
bit_buffer_append_byte(tx_buffer, NXP_NATIVE_COMMAND_ISO_LE);
}
size_t response_len = bit_buffer_get_size_bytes(rx_buffer);
*status_code = NXP_NATIVE_COMMAND_STATUS_LENGTH_ERROR;
bit_buffer_reset(result_buffer);
if(command_mode == NxpNativeCommandModePlain && response_len >= sizeof(uint8_t)) {
*status_code = bit_buffer_get_byte(rx_buffer, 0);
if(response_len > sizeof(uint8_t)) {
bit_buffer_copy_right(result_buffer, rx_buffer, sizeof(uint8_t));
}
} else if(
command_mode == NxpNativeCommandModeIsoWrapped &&
response_len >= 2 * sizeof(uint8_t) &&
bit_buffer_get_byte(rx_buffer, response_len - 2) == NXP_NATIVE_COMMAND_ISO_SW1) {
*status_code = bit_buffer_get_byte(rx_buffer, response_len - 1);
if(response_len > 2 * sizeof(uint8_t)) {
bit_buffer_copy_left(result_buffer, rx_buffer, response_len - 2 * sizeof(uint8_t));
}
}
while(*status_code == NXP_NATIVE_COMMAND_STATUS_ADDITIONAL_FRAME) {
bit_buffer_reset(rx_buffer);
error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
if(error != Iso14443_4aErrorNone) {
break;
}
const size_t rx_size = bit_buffer_get_size_bytes(rx_buffer);
const size_t rx_capacity_remaining = bit_buffer_get_capacity_bytes(result_buffer) -
bit_buffer_get_size_bytes(result_buffer);
if(command_mode == NxpNativeCommandModePlain) {
*status_code = rx_size >= 1 ? bit_buffer_get_byte(rx_buffer, 0) :
NXP_NATIVE_COMMAND_STATUS_LENGTH_ERROR;
if(rx_size <= rx_capacity_remaining + 1) {
bit_buffer_append_right(result_buffer, rx_buffer, sizeof(uint8_t));
} else {
FURI_LOG_W(TAG, "RX buffer overflow: ignoring %zu bytes", rx_size - 1);
}
} else if(command_mode == NxpNativeCommandModeIsoWrapped) {
if(rx_size >= 2 &&
bit_buffer_get_byte(rx_buffer, rx_size - 2) == NXP_NATIVE_COMMAND_ISO_SW1) {
*status_code = bit_buffer_get_byte(rx_buffer, rx_size - 1);
} else {
*status_code = NXP_NATIVE_COMMAND_STATUS_LENGTH_ERROR;
}
if(rx_size <= rx_capacity_remaining + 2) {
bit_buffer_set_size_bytes(rx_buffer, rx_size - 2);
bit_buffer_append(result_buffer, rx_buffer);
} else {
FURI_LOG_W(TAG, "RX buffer overflow: ignoring %zu bytes", rx_size - 2);
}
}
}
} while(false);
return error;
}