diff --git a/seader_worker.c b/seader_worker.c index 227fdb8..79ed1be 100644 --- a/seader_worker.c +++ b/seader_worker.c @@ -1,6 +1,8 @@ #include "seader_worker_i.h" #include +#include +#include #define TAG "SeaderWorker" @@ -230,8 +232,6 @@ bool seader_read_nfc(SeaderUartBridge* seader_uart) { } else if(seader_mf_classic_check_card_type( nfc_data.atqa[0], nfc_data.atqa[1], nfc_data.sak)) { FURI_LOG_D(TAG, "MFC"); - OCTET_STRING_t atqa = {.buf = nfc_data.atqa, .size = sizeof(nfc_data.atqa)}; - cardDetails->atqa = &atqa; seader_send_card_detected(seader_uart, cardDetails); rtn = true; } else if(nfc_data.interface == FuriHalNfcInterfaceIsoDep) { @@ -550,20 +550,100 @@ void seader_send_nfc_rx(SeaderUartBridge* seader_uart, uint8_t* buffer, size_t l ASN_STRUCT_FREE(asn_DEF_Response, response); } -bool seader_iso14443a_transmit(SeaderWorker* seader_worker, uint8_t* buffer, size_t len) { +bool seader_iso14443a_transmit( + SeaderWorker* seader_worker, + uint8_t* buffer, + size_t len, + uint16_t timeout, + uint8_t format[3]) { SeaderUartBridge* seader_uart = seader_worker->uart; FuriHalNfcTxRxContext tx_rx = {.tx_rx_type = FuriHalNfcTxRxTypeDefault}; + memcpy(&tx_rx.tx_data, buffer, len); tx_rx.tx_bits = len * 8; - if(furi_hal_nfc_tx_rx_full(&tx_rx)) { + if(format[0] == 0x00 && format[1] == 0xC0 && format[2] == 0x00) { + tx_rx.tx_rx_type = FuriHalNfcTxRxTypeRxNoCrc; + tx_rx.tx_bits -= 16; + } else if( + (format[0] == 0x00 && format[1] == 0x00 && format[2] == 0x40) || + (format[0] == 0x00 && format[1] == 0x00 && format[2] == 0x24) || + (format[0] == 0x00 && format[1] == 0x00 && format[2] == 0x44)) { + tx_rx.tx_rx_type = FuriHalNfcTxRxTypeRaw; + tx_rx.tx_bits -= 8; + tx_rx.tx_parity[0] = 0; + + // Don't forget to swap the bits of buffer[8] + for(size_t i = 0; i < 8 + 1; i++) { + bit_lib_reverse_bits(buffer + i, 0, 8); + } + + // Pull out parity bits + for(size_t i = 0; i < 8; i++) { + bool val = bit_lib_get_bit(buffer + i + 1, i); + bit_lib_set_bit(tx_rx.tx_parity, i, val); + } + + for(size_t i = 0; i < 8; i++) { + buffer[i] = (buffer[i] << i) | (buffer[i + 1] >> (8 - i)); + } + + for(size_t i = 0; i < 8; i++) { + bit_lib_reverse_bits(buffer + i, 0, 8); + tx_rx.tx_data[i] = buffer[i]; + } + } + + if(furi_hal_nfc_tx_rx(&tx_rx, timeout)) { furi_delay_ms(1); size_t length = tx_rx.rx_bits / 8; memset(display, 0, sizeof(display)); for(uint8_t i = 0; i < length; i++) { snprintf(display + (i * 2), sizeof(display), "%02x", tx_rx.rx_data[i]); } - // FURI_LOG_D(TAG, "NFC Response %d: %s", length, display); + FURI_LOG_D(TAG, "NFC Response %d: %s [%02x]", length, display, tx_rx.rx_parity[0]); + + if(tx_rx.tx_rx_type == FuriHalNfcTxRxTypeRaw) { + for(size_t i = 0; i < length; i++) { + bit_lib_reverse_bits(tx_rx.rx_data + i, 0, 8); + } + + uint8_t with_parity[FURI_HAL_NFC_DATA_BUFF_SIZE]; + memset(with_parity, 0, sizeof(with_parity)); + length = length + (length / 8) + 1; + + uint8_t parts = 1 + length / 9; + for(size_t p = 0; p < parts; p++) { + uint8_t doffset = p * 9; + uint8_t soffset = p * 8; + + for(size_t i = 0; i < 9; i++) { + with_parity[i + doffset] = tx_rx.rx_data[i + soffset] >> i; + if(i > 0) { + with_parity[i + doffset] |= tx_rx.rx_data[i + soffset - 1] << (9 - i); + } + + if(i > 0) { + bool val = bit_lib_get_bit(tx_rx.rx_parity, i - 1); + bit_lib_set_bit(with_parity + i, i - 1, val); + } + } + } + + memcpy(tx_rx.rx_data, with_parity, length); + + for(size_t i = 0; i < length; i++) { + bit_lib_reverse_bits(tx_rx.rx_data + i, 0, 8); + } + } + + memset(display, 0, sizeof(display)); + + for(uint8_t i = 0; i < length; i++) { + snprintf(display + (i * 2), sizeof(display), "%02x", tx_rx.rx_data[i]); + } + FURI_LOG_D(TAG, "NFC Response %d: %s [%02x]", length, display, tx_rx.rx_parity[0]); + seader_send_nfc_rx(seader_uart, tx_rx.rx_data, length); } else { FURI_LOG_W(TAG, "Bad exchange"); @@ -689,14 +769,17 @@ bool seader_parse_nfc_command_transmit(SeaderWorker* seader_worker, NFCSend_t* n nfcSend->data.size, display, protocolName); -#else - UNUSED(timeOut); #endif if(frameProtocol == FrameProtocol_iclass) { return seader_iso15693_transmit(seader_worker, nfcSend->data.buf, nfcSend->data.size); } else if(frameProtocol == FrameProtocol_nfc) { - return seader_iso14443a_transmit(seader_worker, nfcSend->data.buf, nfcSend->data.size); + return seader_iso14443a_transmit( + seader_worker, + nfcSend->data.buf, + nfcSend->data.size, + (uint16_t)timeOut, + nfcSend->format->buf); } return false; }