From 8faf1a8a1b54009c328cc221710cdeafd2fba7e5 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Tue, 19 Mar 2024 17:34:27 -0700 Subject: [PATCH 1/8] 14a error handling --- seader_worker.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/seader_worker.c b/seader_worker.c index 7630742..cbd38ee 100644 --- a/seader_worker.c +++ b/seader_worker.c @@ -286,6 +286,22 @@ NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void } else if(seader_worker->stage == SeaderPollerEventTypeComplete) { ret = NfcCommandStop; } + } else if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeError) { + Iso14443_4aPollerEventData* data = iso14443_4a_event->data; + Iso14443_4aError error = data->error; + FURI_LOG_W(TAG, "Iso14443_4aError %i", error); + // I was hoping to catch MFC here, but it seems to be treated the same (None) as no card being present. + switch(error) { + case Iso14443_4aErrorNone: + break; + case Iso14443_4aErrorNotPresent: + break; + case Iso14443_4aErrorProtocol: + ret = NfcCommandStop; + break; + case Iso14443_4aErrorTimeout: + break; + } } return ret; From 30f45563cdeb4f8b9b96c6c0d1edd87fb98013be Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Tue, 19 Mar 2024 19:30:12 -0700 Subject: [PATCH 2/8] Revert "double size of rx buffer" This reverts commit 996e90b5fc02328d32ae53960a28e4fdf7a15a9d. --- seader_bridge.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seader_bridge.h b/seader_bridge.h index 0600576..c621deb 100644 --- a/seader_bridge.h +++ b/seader_bridge.h @@ -9,7 +9,7 @@ #include #include -#define SEADER_UART_RX_BUF_SIZE (256) +#define SEADER_UART_RX_BUF_SIZE (128) typedef struct { uint8_t uart_ch; From 460ace1be38cff1412be38329b41899737a7777c Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Tue, 19 Mar 2024 18:31:02 -0700 Subject: [PATCH 3/8] MFC support --- sam_api.c | 84 +++++++++++++++++++++++++++---- scenes/seader_scene_config.h | 1 + scenes/seader_scene_read_mfc.c | 61 ++++++++++++++++++++++ scenes/seader_scene_sam_present.c | 12 +++++ seader_i.h | 4 +- seader_worker.c | 31 ++++++++++++ seader_worker.h | 3 +- 7 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 scenes/seader_scene_read_mfc.c diff --git a/sam_api.c b/sam_api.c index f1ad999..4d05e41 100644 --- a/sam_api.c +++ b/sam_api.c @@ -728,6 +728,56 @@ void seader_iso14443a_transmit( bit_buffer_free(rx_buffer); } +/* Assumes this is called in the context of the NFC API callback */ +#define MF_CLASSIC_FWT_FC (60000) +void seader_mfc_transmit( + Seader* seader, + MfClassicPoller* mfc_poller, + uint8_t* buffer, + size_t len, + uint16_t timeout, + uint8_t format[3]) { + UNUSED(timeout); + + furi_assert(seader); + furi_assert(buffer); + furi_assert(mfc_poller); + SeaderWorker* seader_worker = seader->worker; + SeaderUartBridge* seader_uart = seader_worker->uart; + + BitBuffer* tx_buffer = bit_buffer_alloc(len); + BitBuffer* rx_buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE); + + do { + bit_buffer_append_bytes(tx_buffer, buffer, len); + if(format[0] == 0x00 && format[1] == 0xC0 && format[2] == 0x00) { + //iso14443_3a_poller_standard_frame_exchange + } 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)) { + /* + Iso14443_3aPoller* iso14443_3a_poller = (MfClassicPoller)mfc_poller->iso14443_3a_poller; + Iso14443_3aError error = iso14443_3a_poller_txrx_custom_parity(iso14443_3a_poller,tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); + if(error == Iso14443_3aErrorWrongCrc) { + if(bit_buffer_get_size_bytes(rx_buffer) != sizeof(MfClassicNt)) { + FURI_LOG_W(TAG, "iso14443_3a_poller_txrx_custom_parity error %d", error); + seader_worker->stage = SeaderPollerEventTypeFail; + } + } + */ + } + + seader_send_nfc_rx( + seader_uart, + (uint8_t*)bit_buffer_get_data(rx_buffer), + bit_buffer_get_size_bytes(rx_buffer)); + + } while(false); + bit_buffer_free(tx_buffer); + bit_buffer_free(rx_buffer); +} + void seader_parse_nfc_command_transmit( Seader* seader, NFCSend_t* nfcSend, @@ -757,13 +807,23 @@ void seader_parse_nfc_command_transmit( seader_iso15693_transmit( seader, spc->picopass_poller, nfcSend->data.buf, nfcSend->data.size); } else if(frameProtocol == FrameProtocol_nfc) { - seader_iso14443a_transmit( - seader, - spc->iso14443_4a_poller, - nfcSend->data.buf, - nfcSend->data.size, - (uint16_t)timeOut, - nfcSend->format->buf); + if(spc->iso14443_4a_poller) { + seader_iso14443a_transmit( + seader, + spc->iso14443_4a_poller, + nfcSend->data.buf, + nfcSend->data.size, + (uint16_t)timeOut, + nfcSend->format->buf); + } else if(spc->mfc_poller) { + seader_mfc_transmit( + seader, + spc->mfc_poller, + nfcSend->data.buf, + nfcSend->data.size, + (uint16_t)timeOut, + nfcSend->format->buf); + } } else { FURI_LOG_W(TAG, "unknown frame protocol %lx", frameProtocol); } @@ -911,18 +971,22 @@ NfcCommand seader_worker_card_detect( OCTET_STRING_t atqa_string = {.buf = atqa, .size = 2}; uint8_t protocol_bytes[] = {0x00, 0x00}; - if(sak == 0 && atqa == NULL) { + if(sak == 0 && atqa == NULL) { // picopass protocol_bytes[1] = FrameProtocol_iclass; OCTET_STRING_fromBuf( &cardDetails->protocol, (const char*)protocol_bytes, sizeof(protocol_bytes)); memcpy(credential->diversifier, uid, uid_len); credential->diversifier_len = uid_len; credential->isDesfire = false; - } else { + } else if(atqa == 0) { // MFC + protocol_bytes[1] = FrameProtocol_nfc; + OCTET_STRING_fromBuf( + &cardDetails->protocol, (const char*)protocol_bytes, sizeof(protocol_bytes)); + cardDetails->sak = &sak_string; + } else { // type 4 protocol_bytes[1] = FrameProtocol_nfc; OCTET_STRING_fromBuf( &cardDetails->protocol, (const char*)protocol_bytes, sizeof(protocol_bytes)); - cardDetails->sak = &sak_string; cardDetails->atqa = &atqa_string; credential->isDesfire = seader_mf_df_check_card_type(atqa[0], atqa[1], sak); diff --git a/scenes/seader_scene_config.h b/scenes/seader_scene_config.h index 86443dc..0abac9d 100644 --- a/scenes/seader_scene_config.h +++ b/scenes/seader_scene_config.h @@ -16,3 +16,4 @@ ADD_SCENE(seader, credential_info, CredentialInfo) ADD_SCENE(seader, sam_info, SamInfo) ADD_SCENE(seader, virtual_credential, VirtualCredential) ADD_SCENE(seader, formats, Formats) +ADD_SCENE(seader, read_mfc, ReadMfc) diff --git a/scenes/seader_scene_read_mfc.c b/scenes/seader_scene_read_mfc.c new file mode 100644 index 0000000..faeafc7 --- /dev/null +++ b/scenes/seader_scene_read_mfc.c @@ -0,0 +1,61 @@ +#include "../seader_i.h" +#include + +void seader_scene_read_mfc_on_enter(void* context) { + Seader* seader = context; + dolphin_deed(DolphinDeedNfcRead); + + // Setup view + Popup* popup = seader->popup; + popup_set_header(popup, "Detecting\nMFC\ncard", 68, 30, AlignLeft, AlignTop); + popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); + + // Start worker + view_dispatcher_switch_to_view(seader->view_dispatcher, SeaderViewPopup); + + seader->poller = nfc_poller_alloc(seader->nfc, NfcProtocolMfClassic); + + seader->worker->stage = SeaderPollerEventTypeCardDetect; + seader_credential_clear(seader->credential); + seader->credential->type = SeaderCredentialTypeMifareClassic; + nfc_poller_start(seader->poller, seader_worker_poller_callback_mfc, seader); + + seader_blink_start(seader); +} + +bool seader_scene_read_mfc_on_event(void* context, SceneManagerEvent event) { + Seader* seader = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SeaderCustomEventWorkerExit) { + seader->credential->type = SeaderCredentialTypeMifareClassic; + scene_manager_next_scene(seader->scene_manager, SeaderSceneReadCardSuccess); + consumed = true; + } else if(event.event == SeaderCustomEventPollerSuccess) { + seader->credential->type = SeaderCredentialTypeMifareClassic; + scene_manager_next_scene(seader->scene_manager, SeaderSceneReadCardSuccess); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_search_and_switch_to_previous_scene( + seader->scene_manager, SeaderSceneSamPresent); + consumed = true; + } + + return consumed; +} + +void seader_scene_read_mfc_on_exit(void* context) { + Seader* seader = context; + + if(seader->poller) { + nfc_poller_stop(seader->poller); + nfc_poller_free(seader->poller); + } + + // Clear view + popup_reset(seader->popup); + + seader_blink_stop(seader); +} diff --git a/scenes/seader_scene_sam_present.c b/scenes/seader_scene_sam_present.c index 4f299a7..f65fc07 100644 --- a/scenes/seader_scene_sam_present.c +++ b/scenes/seader_scene_sam_present.c @@ -2,6 +2,7 @@ enum SubmenuIndex { SubmenuIndexReadPicopass, SubmenuIndexRead14a, + SubmenuIndexReadMfc, SubmenuIndexSaved, SubmenuIndexSamInfo, SubmenuIndexFwVersion, @@ -33,6 +34,12 @@ void seader_scene_sam_present_on_update(void* context) { SubmenuIndexRead14a, seader_scene_sam_present_submenu_callback, seader); + submenu_add_item( + submenu, + "Read MFC", + SubmenuIndexReadMfc, + seader_scene_sam_present_submenu_callback, + seader); submenu_add_item( submenu, "Saved", SubmenuIndexSaved, seader_scene_sam_present_submenu_callback, seader); @@ -75,6 +82,11 @@ bool seader_scene_sam_present_on_event(void* context, SceneManagerEvent event) { seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexRead14a); scene_manager_next_scene(seader->scene_manager, SeaderSceneRead14a); consumed = true; + } else if(event.event == SubmenuIndexReadMfc) { + scene_manager_set_scene_state( + seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexReadMfc); + scene_manager_next_scene(seader->scene_manager, SeaderSceneReadMfc); + consumed = true; } else if(event.event == SubmenuIndexSamInfo) { scene_manager_set_scene_state( seader->scene_manager, SeaderSceneSamPresent, SubmenuIndexSamInfo); diff --git a/seader_i.h b/seader_i.h index 2cd5b80..dc3b038 100644 --- a/seader_i.h +++ b/seader_i.h @@ -24,10 +24,7 @@ #include #include -#include - #include - #include #include @@ -124,6 +121,7 @@ struct Seader { struct SeaderPollerContainer { Iso14443_4aPoller* iso14443_4a_poller; + MfClassicPoller* mfc_poller; PicopassPoller* picopass_poller; }; diff --git a/seader_worker.c b/seader_worker.c index cbd38ee..b6f5811 100644 --- a/seader_worker.c +++ b/seader_worker.c @@ -307,6 +307,37 @@ NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void return ret; } +NfcCommand seader_worker_poller_callback_mfc(NfcGenericEvent event, void* context) { + furi_assert(event.protocol == NfcProtocolMfClassic); + NfcCommand ret = NfcCommandContinue; + + Seader* seader = context; + SeaderWorker* seader_worker = seader->worker; + + MfClassicPollerEvent* mfc_event = event.event_data; + SeaderPollerContainer spc = {.mfc_poller = event.instance}; + + if(mfc_event->type == MfClassicPollerEventTypeSuccess) { + if(seader_worker->stage == SeaderPollerEventTypeCardDetect) { + const MfClassicData* mfc_data = nfc_poller_get_data(seader->poller); + uint8_t sak = iso14443_3a_get_sak(mfc_data->iso14443_3a_data); + size_t uid_len = 0; + const uint8_t* uid = mf_classic_get_uid(mfc_data, &uid_len); + seader_worker_card_detect(seader, sak, NULL, uid, uid_len, NULL, 0); + furi_thread_set_current_priority(FuriThreadPriorityLowest); + seader_worker->stage = SeaderPollerEventTypeConversation; + } else if(seader_worker->stage == SeaderPollerEventTypeConversation) { + seader_worker_poller_conversation(seader, &spc); + } else if(seader_worker->stage == SeaderPollerEventTypeComplete) { + ret = NfcCommandStop; + } + } else if(mfc_event->type == MfClassicPollerEventTypeFail) { + ret = NfcCommandStop; + } + + return ret; +} + NfcCommand seader_worker_poller_callback_picopass(PicopassPollerEvent event, void* context) { furi_assert(context); NfcCommand ret = NfcCommandContinue; diff --git a/seader_worker.h b/seader_worker.h index 0194a76..2bc3e97 100644 --- a/seader_worker.h +++ b/seader_worker.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "sam_api.h" #include "seader_credential.h" @@ -65,5 +66,5 @@ bool seader_worker_process_sam_message(Seader* seader, CCID_Message* message); void seader_worker_send_version(Seader* seader); NfcCommand seader_worker_poller_callback_iso14443_4a(NfcGenericEvent event, void* context); - +NfcCommand seader_worker_poller_callback_mfc(NfcGenericEvent event, void* context); NfcCommand seader_worker_poller_callback_picopass(PicopassPollerEvent event, void* context); From ce15b26a40eae75f1e94b1ff83fd7b03f75abca8 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Sun, 21 Apr 2024 17:51:26 -0700 Subject: [PATCH 4/8] reduce stack size --- application.fam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application.fam b/application.fam index 588798e..759b4dc 100644 --- a/application.fam +++ b/application.fam @@ -9,7 +9,7 @@ App( requires=[ "gui", "storage", "nfc", ], - stack_size=7 * 1024, + stack_size=5 * 1024, order=20, sources=[ "*.c", From 60440dd5c4a03026355b0241a4fc05d2c739e5b9 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Sun, 21 Apr 2024 17:57:15 -0700 Subject: [PATCH 5/8] gets a couple messages in --- sam_api.c | 21 ++++++++++----------- scenes/seader_scene_read_mfc.c | 4 ++++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/sam_api.c b/sam_api.c index 4d05e41..8986baf 100644 --- a/sam_api.c +++ b/sam_api.c @@ -751,22 +751,21 @@ void seader_mfc_transmit( do { bit_buffer_append_bytes(tx_buffer, buffer, len); if(format[0] == 0x00 && format[1] == 0xC0 && format[2] == 0x00) { - //iso14443_3a_poller_standard_frame_exchange + // MfClassicError error = mf_classic_poller_send_standard_frame(mfc_poller,tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); + MfClassicError error = + mf_classic_poller_send_frame(mfc_poller, tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); + if(error != MfClassicErrorNone) { + FURI_LOG_W(TAG, "mf_classic_poller_send_standard_frame error %d", error); + seader_worker->stage = SeaderPollerEventTypeFail; + break; + } } 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)) { - /* - Iso14443_3aPoller* iso14443_3a_poller = (MfClassicPoller)mfc_poller->iso14443_3a_poller; - Iso14443_3aError error = iso14443_3a_poller_txrx_custom_parity(iso14443_3a_poller,tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); - if(error == Iso14443_3aErrorWrongCrc) { - if(bit_buffer_get_size_bytes(rx_buffer) != sizeof(MfClassicNt)) { - FURI_LOG_W(TAG, "iso14443_3a_poller_txrx_custom_parity error %d", error); - seader_worker->stage = SeaderPollerEventTypeFail; - } - } - */ + FURI_LOG_W(TAG, "TODO"); } + FURI_LOG_W(TAG, "mf_classic_poller_send_standard_frame success"); seader_send_nfc_rx( seader_uart, diff --git a/scenes/seader_scene_read_mfc.c b/scenes/seader_scene_read_mfc.c index faeafc7..bc4e855 100644 --- a/scenes/seader_scene_read_mfc.c +++ b/scenes/seader_scene_read_mfc.c @@ -1,6 +1,8 @@ #include "../seader_i.h" #include +#define TAG "SceneReadNfc" + void seader_scene_read_mfc_on_enter(void* context) { Seader* seader = context; dolphin_deed(DolphinDeedNfcRead); @@ -18,6 +20,8 @@ void seader_scene_read_mfc_on_enter(void* context) { seader->worker->stage = SeaderPollerEventTypeCardDetect; seader_credential_clear(seader->credential); seader->credential->type = SeaderCredentialTypeMifareClassic; + + FURI_LOG_W(TAG, "Start poller"); nfc_poller_start(seader->poller, seader_worker_poller_callback_mfc, seader); seader_blink_start(seader); From be81164ccc2e307e955e16545a23732a9af2cf50 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Sun, 21 Apr 2024 22:23:17 -0700 Subject: [PATCH 6/8] gets response for encrypted MFC --- sam_api.c | 52 ++++++++++++++++++++++++++++++++++++++++++++----- seader_worker.c | 2 ++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/sam_api.c b/sam_api.c index 8986baf..9ef0fae 100644 --- a/sam_api.c +++ b/sam_api.c @@ -1,6 +1,7 @@ #include "sam_api.h" #include +#include #define TAG "SAMAPI" @@ -749,13 +750,12 @@ void seader_mfc_transmit( BitBuffer* rx_buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE); do { - bit_buffer_append_bytes(tx_buffer, buffer, len); if(format[0] == 0x00 && format[1] == 0xC0 && format[2] == 0x00) { - // MfClassicError error = mf_classic_poller_send_standard_frame(mfc_poller,tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); + bit_buffer_append_bytes(tx_buffer, buffer, len); MfClassicError error = mf_classic_poller_send_frame(mfc_poller, tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); if(error != MfClassicErrorNone) { - FURI_LOG_W(TAG, "mf_classic_poller_send_standard_frame error %d", error); + FURI_LOG_W(TAG, "mf_classic_poller_send_frame error %d", error); seader_worker->stage = SeaderPollerEventTypeFail; break; } @@ -763,9 +763,51 @@ void seader_mfc_transmit( (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)) { - FURI_LOG_W(TAG, "TODO"); + //bit_buffer_copy_bytes_with_parity(tx_buffer, buffer, len * 8); + + uint8_t tx_parity = 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_parity, i, val); + } + + for(size_t i = 0; i < 8; i++) { + buffer[i] = (buffer[i] << i) | (buffer[i + 1] >> (8 - i)); + } + bit_buffer_append_bytes(tx_buffer, buffer, 8); + + for(size_t i = 0; i < 8; i++) { + bit_lib_reverse_bits(buffer + i, 0, 8); + bit_buffer_set_byte_with_parity( + tx_buffer, i, buffer[i], bit_lib_get_bit(&tx_parity, i)); + } + + MfClassicError error = mf_classic_poller_send_custom_parity_frame( + mfc_poller, tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); + if(error != MfClassicErrorNone) { + FURI_LOG_W(TAG, "mf_classic_poller_send_encrypted_frame error %d", error); + seader_worker->stage = SeaderPollerEventTypeFail; + break; + } + + /* + uint8_t b[SEADER_POLLER_MAX_BUFFER_SIZE]; + memset(b, 0, SEADER_POLLER_MAX_BUFFER_SIZE); + size_t bits_written = 0; + bit_buffer_write_bytes_with_parity(rx_buffer, b, SEADER_POLLER_MAX_BUFFER_SIZE, &bits_written); + + seader_send_nfc_rx(seader_uart, b, bits_written/8); + */ + } else { + FURI_LOG_W(TAG, "UNHANDLED FORMAT"); } - FURI_LOG_W(TAG, "mf_classic_poller_send_standard_frame success"); seader_send_nfc_rx( seader_uart, diff --git a/seader_worker.c b/seader_worker.c index b6f5811..66a5fdb 100644 --- a/seader_worker.c +++ b/seader_worker.c @@ -330,6 +330,8 @@ NfcCommand seader_worker_poller_callback_mfc(NfcGenericEvent event, void* contex seader_worker_poller_conversation(seader, &spc); } else if(seader_worker->stage == SeaderPollerEventTypeComplete) { ret = NfcCommandStop; + } else if(seader_worker->stage == SeaderPollerEventTypeFail) { + ret = NfcCommandStop; } } else if(mfc_event->type == MfClassicPollerEventTypeFail) { ret = NfcCommandStop; From 3f83d81288864f8dae47b73f775272bb2fbb208f Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Mon, 22 Apr 2024 10:01:09 -0700 Subject: [PATCH 7/8] returns at message --- sam_api.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/sam_api.c b/sam_api.c index 9ef0fae..bc22b4c 100644 --- a/sam_api.c +++ b/sam_api.c @@ -768,7 +768,7 @@ void seader_mfc_transmit( uint8_t tx_parity = 0; // Don't forget to swap the bits of buffer[8] - for(size_t i = 0; i < 8 + 1; i++) { + for(size_t i = 0; i < len; i++) { bit_lib_reverse_bits(buffer + i, 0, 8); } @@ -797,14 +797,59 @@ void seader_mfc_transmit( break; } - /* - uint8_t b[SEADER_POLLER_MAX_BUFFER_SIZE]; - memset(b, 0, SEADER_POLLER_MAX_BUFFER_SIZE); - size_t bits_written = 0; - bit_buffer_write_bytes_with_parity(rx_buffer, b, SEADER_POLLER_MAX_BUFFER_SIZE, &bits_written); + size_t length = bit_buffer_get_size_bytes(rx_buffer); + const uint8_t* rx_parity = bit_buffer_get_parity(rx_buffer); + + memset(display, 0, sizeof(display)); + for(uint8_t i = 0; i < length; i++) { + snprintf( + display + (i * 2), sizeof(display), "%02x", bit_buffer_get_byte(rx_buffer, i)); + } + FURI_LOG_D(TAG, "NFC Response %d: %s [%02x]", length, display, rx_parity[0]); + + uint8_t with_parity[SEADER_POLLER_MAX_BUFFER_SIZE]; + memset(with_parity, 0, sizeof(with_parity)); + + for(size_t i = 0; i < length; i++) { + uint8_t b = bit_buffer_get_byte(rx_buffer, i); + bit_lib_reverse_bits(&b, 0, 8); + bit_buffer_set_byte(rx_buffer, i, b); + } + + 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] = bit_buffer_get_byte(rx_buffer, i + soffset) >> i; + if(i > 0) { + with_parity[i + doffset] |= bit_buffer_get_byte(rx_buffer, i + soffset - 1) + << (9 - i); + } + + if(i > 0) { + bool val = bit_lib_get_bit(rx_parity, i - 1); + bit_lib_set_bit(with_parity + i, i - 1, val); + } + } + } + + for(size_t i = 0; i < length; i++) { + bit_lib_reverse_bits(with_parity + i, 0, 8); + } + + bit_buffer_copy_bytes(rx_buffer, with_parity, length); + + memset(display, 0, sizeof(display)); + for(uint8_t i = 0; i < length; i++) { + snprintf( + display + (i * 2), sizeof(display), "%02x", bit_buffer_get_byte(rx_buffer, i)); + } + FURI_LOG_D(TAG, "NFC Response %d: %s [%02x]", length, display, rx_parity[0]); - seader_send_nfc_rx(seader_uart, b, bits_written/8); - */ } else { FURI_LOG_W(TAG, "UNHANDLED FORMAT"); } From 70548acc54458048decf8d9d4bbaee5040beadc2 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Mon, 22 Apr 2024 10:17:07 -0700 Subject: [PATCH 8/8] reads MFC SE --- sam_api.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/sam_api.c b/sam_api.c index bc22b4c..84b669b 100644 --- a/sam_api.c +++ b/sam_api.c @@ -763,9 +763,15 @@ void seader_mfc_transmit( (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)) { - //bit_buffer_copy_bytes_with_parity(tx_buffer, buffer, len * 8); + memset(display, 0, sizeof(display)); + for(uint8_t i = 0; i < len; i++) { + snprintf(display + (i * 2), sizeof(display), "%02x", buffer[i]); + } + FURI_LOG_D(TAG, "NFC Send with parity %d: %s", len, display); + // Only handles message up to 8 data bytes uint8_t tx_parity = 0; + uint8_t len_without_parity = len - 1; // Don't forget to swap the bits of buffer[8] for(size_t i = 0; i < len; i++) { @@ -773,22 +779,34 @@ void seader_mfc_transmit( } // Pull out parity bits - for(size_t i = 0; i < 8; i++) { + for(size_t i = 0; i < len_without_parity; i++) { bool val = bit_lib_get_bit(buffer + i + 1, i); bit_lib_set_bit(&tx_parity, i, val); } - for(size_t i = 0; i < 8; i++) { + for(size_t i = 0; i < len_without_parity; i++) { buffer[i] = (buffer[i] << i) | (buffer[i + 1] >> (8 - i)); } - bit_buffer_append_bytes(tx_buffer, buffer, 8); + bit_buffer_append_bytes(tx_buffer, buffer, len_without_parity); - for(size_t i = 0; i < 8; i++) { + for(size_t i = 0; i < len_without_parity; i++) { bit_lib_reverse_bits(buffer + i, 0, 8); bit_buffer_set_byte_with_parity( tx_buffer, i, buffer[i], bit_lib_get_bit(&tx_parity, i)); } + memset(display, 0, sizeof(display)); + for(uint8_t i = 0; i < bit_buffer_get_size_bytes(tx_buffer); i++) { + snprintf( + display + (i * 2), sizeof(display), "%02x", bit_buffer_get_byte(tx_buffer, i)); + } + FURI_LOG_D( + TAG, + "NFC Send without parity %d: %s [%02x]", + bit_buffer_get_size_bytes(tx_buffer), + display, + tx_parity); + MfClassicError error = mf_classic_poller_send_custom_parity_frame( mfc_poller, tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); if(error != MfClassicErrorNone) { @@ -805,7 +823,8 @@ void seader_mfc_transmit( snprintf( display + (i * 2), sizeof(display), "%02x", bit_buffer_get_byte(rx_buffer, i)); } - FURI_LOG_D(TAG, "NFC Response %d: %s [%02x]", length, display, rx_parity[0]); + FURI_LOG_D( + TAG, "NFC Response without parity %d: %s [%02x]", length, display, rx_parity[0]); uint8_t with_parity[SEADER_POLLER_MAX_BUFFER_SIZE]; memset(with_parity, 0, sizeof(with_parity)); @@ -848,7 +867,8 @@ void seader_mfc_transmit( snprintf( display + (i * 2), sizeof(display), "%02x", bit_buffer_get_byte(rx_buffer, i)); } - FURI_LOG_D(TAG, "NFC Response %d: %s [%02x]", length, display, rx_parity[0]); + FURI_LOG_D( + TAG, "NFC Response with parity %d: %s [%02x]", length, display, rx_parity[0]); } else { FURI_LOG_W(TAG, "UNHANDLED FORMAT");