diff --git a/applications/debug/unit_tests/nfc/nfc_transport.c b/applications/debug/unit_tests/nfc/nfc_transport.c index fab6693db873..e9084ca20b93 100644 --- a/applications/debug/unit_tests/nfc/nfc_transport.c +++ b/applications/debug/unit_tests/nfc/nfc_transport.c @@ -1,6 +1,7 @@ #ifdef APP_UNIT_TESTS #include +#include #include #include @@ -246,13 +247,13 @@ static void nfc_worker_listener_pass_col_res(Nfc* instance, uint8_t* rx_data, ui if((rx_data[0] == 0x93) && (rx_data[1] == 0x70)) { bit_buffer_set_size_bytes(tx_buffer, 1); bit_buffer_set_byte(tx_buffer, 0, instance->col_res_data.sel_resp[0].sak); - iso14443_3a_append_crc(tx_buffer); + iso14443_crc_append(Iso14443CrcTypeA, tx_buffer); nfc_listener_tx(instance, tx_buffer); processed = true; } else if((rx_data[0] == 0x95) && (rx_data[1] == 0x70)) { bit_buffer_set_size_bytes(tx_buffer, 1); bit_buffer_set_byte(tx_buffer, 0, instance->col_res_data.sel_resp[1].sak); - iso14443_3a_append_crc(tx_buffer); + iso14443_crc_append(Iso14443CrcTypeA, tx_buffer); nfc_listener_tx(instance, tx_buffer); instance->col_res_status = Iso14443_3aColResStatusDone; NfcEvent event = {.type = NfcEventTypeListenerActivated}; diff --git a/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.c b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.c new file mode 100644 index 000000000000..b2b332aa450a --- /dev/null +++ b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.c @@ -0,0 +1,112 @@ +#include "iso14443_3b.h" +#include "iso14443_3b_render.h" + +#include + +#include "nfc/nfc_app_i.h" + +#include "../nfc_protocol_support_gui_common.h" + +static void nfc_scene_info_on_enter_iso14443_3b(NfcApp* instance) { + const NfcDevice* device = instance->nfc_device; + const Iso14443_3bData* data = nfc_device_get_data(device, NfcProtocolIso14443_3b); + + FuriString* temp_str = furi_string_alloc(); + furi_string_cat_printf( + temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull)); + nfc_render_iso14443_3b_info(data, NfcProtocolFormatTypeFull, temp_str); + + widget_add_text_scroll_element( + instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str)); + + furi_string_free(temp_str); +} + +static NfcCommand + nfc_scene_read_poller_callback_iso14443_3b(NfcGenericEvent event, void* context) { + furi_assert(event.protocol == NfcProtocolIso14443_3b); + + NfcApp* instance = context; + const Iso14443_3bPollerEvent* iso14443_3b_event = event.data; + + if(iso14443_3b_event->type == Iso14443_3bPollerEventTypeReady) { + nfc_device_set_data( + instance->nfc_device, NfcProtocolIso14443_3b, nfc_poller_get_data(instance->poller)); + view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess); + return NfcCommandStop; + } + + return NfcCommandContinue; +} + +static void nfc_scene_read_on_enter_iso14443_3b(NfcApp* instance) { + nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_iso14443_3b, instance); +} + +static void nfc_scene_read_success_on_enter_iso14443_3b(NfcApp* instance) { + const NfcDevice* device = instance->nfc_device; + const Iso14443_3bData* data = nfc_device_get_data(device, NfcProtocolIso14443_3b); + + FuriString* temp_str = furi_string_alloc(); + furi_string_cat_printf( + temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull)); + nfc_render_iso14443_3b_info(data, NfcProtocolFormatTypeShort, temp_str); + + widget_add_text_scroll_element( + instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + + furi_string_free(temp_str); +} + +static bool nfc_scene_info_on_event_iso14443_3b(NfcApp* instance, uint32_t event) { + if(event == GuiButtonTypeRight) { + scene_manager_next_scene(instance->scene_manager, NfcSceneNotImplemented); + return true; + } + + return false; +} + +static bool nfc_scene_saved_menu_on_event_iso14443_3b(NfcApp* instance, uint32_t event) { + if(event == SubmenuIndexCommonEdit) { + scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid); + return true; + } + + return false; +} + +const NfcProtocolSupportBase nfc_protocol_support_iso14443_3b = { + .features = NfcProtocolFeatureNone, // TODO: Implement better UID editing, + + .scene_info = + { + .on_enter = nfc_scene_info_on_enter_iso14443_3b, + .on_event = nfc_scene_info_on_event_iso14443_3b, + }, + .scene_read = + { + .on_enter = nfc_scene_read_on_enter_iso14443_3b, + .on_event = NULL, + }, + .scene_read_menu = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, + .scene_read_success = + { + .on_enter = nfc_scene_read_success_on_enter_iso14443_3b, + .on_event = NULL, + }, + .scene_saved_menu = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_scene_saved_menu_on_event_iso14443_3b, + }, + .scene_emulate = + { + .on_enter = NULL, + .on_event = NULL, + }, +}; diff --git a/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.h b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.h new file mode 100644 index 000000000000..bf3caa0c0e31 --- /dev/null +++ b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.h @@ -0,0 +1,5 @@ +#pragma once + +#include "../nfc_protocol_support_base.h" + +extern const NfcProtocolSupportBase nfc_protocol_support_iso14443_3b; diff --git a/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b_render.c b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b_render.c new file mode 100644 index 000000000000..c4098d61c25a --- /dev/null +++ b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b_render.c @@ -0,0 +1,28 @@ +#include "iso14443_3b_render.h" + +void nfc_render_iso14443_3b_info( + const Iso14443_3bData* data, + NfcProtocolFormatType format_type, + FuriString* str) { + if(format_type == NfcProtocolFormatTypeFull) { + const char iso_type = FURI_BIT(data->protocol_info[1], 0) ? '4' : '3'; + furi_string_cat_printf(str, "ISO 14443-%c (NFC-B)\n", iso_type); + } + + furi_string_cat_printf(str, "UID:"); + + for(size_t i = 0; i < ISO14443_3B_UID_SIZE; i++) { + furi_string_cat_printf(str, " %02X", data->uid[i]); + } + + if(format_type == NfcProtocolFormatTypeFull) { + furi_string_cat_printf(str, "\nApp. data:"); + for(size_t i = 0; i < ISO14443_3B_APP_DATA_SIZE; ++i) { + furi_string_cat_printf(str, " %02X", data->app_data[i]); + } + furi_string_cat_printf(str, "\nProtocol info:"); + for(size_t i = 0; i < ISO14443_3B_PROTOCOL_INFO_SIZE; ++i) { + furi_string_cat_printf(str, " %02X", data->protocol_info[i]); + } + } +} diff --git a/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b_render.h b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b_render.h new file mode 100644 index 000000000000..ee50f6acf5a8 --- /dev/null +++ b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b_render.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +#include "../nfc_protocol_support_render_common.h" + +void nfc_render_iso14443_3b_info( + const Iso14443_3bData* data, + NfcProtocolFormatType format_type, + FuriString* str); diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.c b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.c index 92a4cd561f65..9771dbe87500 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.c +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.c @@ -1,6 +1,7 @@ #include "nfc_protocol_support_defs.h" #include "iso14443_3a/iso14443_3a.h" +#include "iso14443_3b/iso14443_3b.h" #include "iso14443_4a/iso14443_4a.h" #include "mf_ultralight/mf_ultralight.h" #include "mf_classic/mf_classic.h" @@ -8,6 +9,7 @@ const NfcProtocolSupportBase* nfc_protocol_support[NfcProtocolNum] = { [NfcProtocolIso14443_3a] = &nfc_protocol_support_iso14443_3a, + [NfcProtocolIso14443_3b] = &nfc_protocol_support_iso14443_3b, [NfcProtocolIso14443_4a] = &nfc_protocol_support_iso14443_4a, [NfcProtocolMfUltralight] = &nfc_protocol_support_mf_ultralight, [NfcProtocolMfClassic] = &nfc_protocol_support_mf_classic, diff --git a/documentation/file_formats/NfcFileFormats.md b/documentation/file_formats/NfcFileFormats.md index f3b77c55a99b..f752cdb901b8 100644 --- a/documentation/file_formats/NfcFileFormats.md +++ b/documentation/file_formats/NfcFileFormats.md @@ -6,7 +6,7 @@ Filetype: Flipper NFC device Version: 4 - # Device type can be ISO14443-3A, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire + # Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire Device type: ISO14443-4A # UID is common for all formats UID: 04 48 6A 32 33 58 80 @@ -28,7 +28,7 @@ Version differences: Filetype: Flipper NFC device Version: 4 - # Device type can be ISO14443-3A, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire + # Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire Device type: ISO14443-3A # UID is common for all formats UID: 34 19 6D 41 14 56 E6 @@ -44,13 +44,33 @@ UID must be either 4 or 7 bytes long. ATQA is 2 bytes long. SAK is 1 byte long. Version differences: None, there are no versions yet. +## ISO14443-3B + + Filetype: Flipper NFC device + Version: 4 + # Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire + Device type: ISO14443-3B + # UID is common for all formats + UID: 30 1D B3 28 + # ISO14443-3B specific data + Application data: 00 12 34 FF + Protocol info: 11 81 E1 + +### Description + +This file format is used to store the UID, Application data and Protocol info of a ISO14443-3B device. +UID must be 4 bytes long. Application data is 4 bytes long. Protocol info is 3 bytes long. + +Version differences: +None, there are no versions yet. + ## ISO14443-4A ### Example Filetype: Flipper NFC device Version: 4 - # Device type can be ISO14443-3A, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire + # Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire Device type: ISO14443-4A # UID is common for all formats UID: 04 48 6A 32 33 58 80 @@ -74,7 +94,7 @@ None, there are no versions yet. Filetype: Flipper NFC device Version: 4 - # Device type can be ISO14443-3A, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire + # Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire Device type: NTAG/Ultralight # UID is common for all formats UID: 04 85 90 54 12 98 23 @@ -130,7 +150,7 @@ Version differences: Filetype: Flipper NFC device Version: 4 - # Device type can be ISO14443-3A, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire + # Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire Device type: Mifare Classic # UID is common for all formats UID: BA E2 7C 9D @@ -195,7 +215,7 @@ Example: Filetype: Flipper NFC device Version: 4 - # Device type can be ISO14443-3A, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire + # Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, NTAG/Ultralight, Mifare Classic, Mifare DESFire Device type: Mifare DESFire # UID is common for all formats UID: 04 2F 19 0A CD 66 80 diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 5f8b00464275..ac14d1f45744 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -151,6 +151,7 @@ Header,+,lib/music_worker/music_worker.h,, Header,+,lib/nanopb/pb.h,, Header,+,lib/nanopb/pb_decode.h,, Header,+,lib/nanopb/pb_encode.h,, +Header,+,lib/nfc/helpers/iso14443_crc.h,, Header,+,lib/nfc/helpers/nfc_util.h,, Header,+,lib/nfc/nfc.h,, Header,+,lib/nfc/nfc_device.h,, @@ -161,6 +162,8 @@ Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a.h,, Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.h,, Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_poller.h,, Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_sync_api.h,, +Header,+,lib/nfc/protocols/iso14443_3b/iso14443_3b.h,, +Header,+,lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.h,, Header,+,lib/nfc/protocols/iso14443_4a/iso14443_4a.h,, Header,+,lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h,, Header,+,lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h,, @@ -1835,8 +1838,6 @@ Function,-,islower_l,int,"int, locale_t" Function,-,isnan,int,double Function,-,isnanf,int,float Function,+,iso14443_3a_alloc,Iso14443_3aData*, -Function,+,iso14443_3a_append_crc,void,BitBuffer* -Function,+,iso14443_3a_check_crc,_Bool,const BitBuffer* Function,+,iso14443_3a_copy,void,"Iso14443_3aData*, const Iso14443_3aData*" Function,+,iso14443_3a_free,void,Iso14443_3aData* Function,+,iso14443_3a_get_base_data,const Iso14443_3aData*,const Iso14443_3aData* @@ -1848,8 +1849,20 @@ Function,+,iso14443_3a_load,_Bool,"Iso14443_3aData*, FlipperFormat*, uint32_t" Function,+,iso14443_3a_poller_read,Iso14443_3aError,"Nfc*, Iso14443_3aData*" Function,+,iso14443_3a_reset,void,Iso14443_3aData* Function,+,iso14443_3a_save,_Bool,"const Iso14443_3aData*, FlipperFormat*" -Function,+,iso14443_3a_trim_crc,void,BitBuffer* +Function,+,iso14443_3a_set_uid,_Bool,"Iso14443_3aData*, const uint8_t*, size_t" Function,+,iso14443_3a_verify,_Bool,"Iso14443_3aData*, const FuriString*" +Function,+,iso14443_3b_alloc,Iso14443_3bData*, +Function,+,iso14443_3b_copy,void,"Iso14443_3bData*, const Iso14443_3bData*" +Function,+,iso14443_3b_free,void,Iso14443_3bData* +Function,+,iso14443_3b_get_base_data,const Iso14443_3bData*,const Iso14443_3bData* +Function,+,iso14443_3b_get_device_name,const char*,"const Iso14443_3bData*, NfcDeviceNameType" +Function,+,iso14443_3b_get_uid,const uint8_t*,"const Iso14443_3bData*, size_t*" +Function,+,iso14443_3b_is_equal,_Bool,"const Iso14443_3bData*, const Iso14443_3bData*" +Function,+,iso14443_3b_load,_Bool,"Iso14443_3bData*, FlipperFormat*, uint32_t" +Function,+,iso14443_3b_reset,void,Iso14443_3bData* +Function,+,iso14443_3b_save,_Bool,"const Iso14443_3bData*, FlipperFormat*" +Function,+,iso14443_3b_set_uid,_Bool,"Iso14443_3bData*, const uint8_t*, size_t" +Function,+,iso14443_3b_verify,_Bool,"Iso14443_3bData*, const FuriString*" Function,+,iso14443_4a_alloc,Iso14443_4aData*, Function,+,iso14443_4a_copy,void,"Iso14443_4aData*, const Iso14443_4aData*" Function,+,iso14443_4a_free,void,Iso14443_4aData* @@ -1861,7 +1874,11 @@ Function,+,iso14443_4a_is_equal,_Bool,"const Iso14443_4aData*, const Iso14443_4a Function,+,iso14443_4a_load,_Bool,"Iso14443_4aData*, FlipperFormat*, uint32_t" Function,+,iso14443_4a_reset,void,Iso14443_4aData* Function,+,iso14443_4a_save,_Bool,"const Iso14443_4aData*, FlipperFormat*" +Function,+,iso14443_4a_set_uid,_Bool,"Iso14443_4aData*, const uint8_t*, size_t" Function,+,iso14443_4a_verify,_Bool,"Iso14443_4aData*, const FuriString*" +Function,+,iso14443_crc_append,void,"Iso14443CrcType, BitBuffer*" +Function,+,iso14443_crc_check,_Bool,"Iso14443CrcType, const BitBuffer*" +Function,+,iso14443_crc_trim,void,BitBuffer* Function,-,isprint,int,int Function,-,isprint_l,int,"int, locale_t" Function,-,ispunct,int,int @@ -2075,6 +2092,7 @@ Function,+,mf_classic_save,_Bool,"const MfClassicData*, FlipperFormat*" Function,+,mf_classic_set_block_read,void,"MfClassicData*, uint8_t, MfClassicBlock*" Function,+,mf_classic_set_key_found,void,"MfClassicData*, uint8_t, MfClassicKeyType, uint64_t" Function,+,mf_classic_set_key_not_found,void,"MfClassicData*, uint8_t, MfClassicKeyType" +Function,+,mf_classic_set_uid,_Bool,"MfClassicData*, const uint8_t*, size_t" Function,+,mf_classic_value_to_block,void,"int32_t, uint8_t, MfClassicBlock*" Function,+,mf_classic_verify,_Bool,"MfClassicData*, const FuriString*" Function,+,mf_desfire_alloc,MfDesfireData*, @@ -2090,6 +2108,7 @@ Function,+,mf_desfire_is_equal,_Bool,"const MfDesfireData*, const MfDesfireData* Function,+,mf_desfire_load,_Bool,"MfDesfireData*, FlipperFormat*, uint32_t" Function,+,mf_desfire_reset,void,MfDesfireData* Function,+,mf_desfire_save,_Bool,"const MfDesfireData*, FlipperFormat*" +Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t" Function,+,mf_desfire_verify,_Bool,"MfDesfireData*, const FuriString*" Function,+,mf_ultralight_alloc,MfUltralightData*, Function,+,mf_ultralight_copy,void,"MfUltralightData*, const MfUltralightData*" @@ -2116,6 +2135,7 @@ Function,+,mf_ultralight_poller_read_version,MfUltralightError,"Nfc*, MfUltralig Function,+,mf_ultralight_poller_write_page,MfUltralightError,"Nfc*, uint16_t, MfUltralightPage*" Function,+,mf_ultralight_reset,void,MfUltralightData* Function,+,mf_ultralight_save,_Bool,"const MfUltralightData*, FlipperFormat*" +Function,+,mf_ultralight_set_uid,_Bool,"MfUltralightData*, const uint8_t*, size_t" Function,+,mf_ultralight_verify,_Bool,"MfUltralightData*, const FuriString*" Function,-,mkdtemp,char*,char* Function,-,mkostemp,int,"char*, int" @@ -2170,6 +2190,7 @@ Function,+,nfc_device_reset,void,NfcDevice* Function,+,nfc_device_save,_Bool,"NfcDevice*, const char*" Function,+,nfc_device_set_data,void,"NfcDevice*, NfcProtocol, const NfcDeviceData*" Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*" +Function,+,nfc_device_set_uid,_Bool,"NfcDevice*, const uint8_t*, size_t" Function,-,nfc_free,void,Nfc* Function,-,nfc_iso14443_3a_listener_tx_custom_parity,NfcError,"Nfc*, const BitBuffer*" Function,-,nfc_iso14443_3a_sdd_frame,NfcError,"Nfc*, const BitBuffer*, BitBuffer*, uint32_t" @@ -3507,6 +3528,7 @@ Variable,+,message_sound_off,const NotificationMessage, Variable,+,message_vibro_off,const NotificationMessage, Variable,+,message_vibro_on,const NotificationMessage, Variable,-,nfc_device_iso14443_3a,const NfcDeviceBase, +Variable,+,nfc_device_iso14443_3b,const NfcDeviceBase, Variable,-,nfc_device_iso14443_4a,const NfcDeviceBase, Variable,-,nfc_device_mf_classic,const NfcDeviceBase, Variable,-,nfc_device_mf_desfire,const NfcDeviceBase, diff --git a/firmware/targets/f7/furi_hal/f_hal_nfc.c b/firmware/targets/f7/furi_hal/f_hal_nfc.c index 70e33bf83376..139edd270722 100644 --- a/firmware/targets/f7/furi_hal/f_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/f_hal_nfc.c @@ -299,71 +299,169 @@ FHalNfcError f_hal_nfc_low_power_mode_stop() { } static void f_hal_nfc_configure_poller_common(FuriHalSpiBusHandle* handle) { - st25r3916_change_reg_bits( - handle, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am, ST25R3916_REG_MODE_tr_am_am); - st25r3916_change_reg_bits( - handle, - ST25R3916_REG_TX_DRIVER, - ST25R3916_REG_TX_DRIVER_am_mod_mask, - ST25R3916_REG_TX_DRIVER_am_mod_12percent); + // Disable wake up + st25r3916_clear_reg_bits(handle, ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + // Enable correlator st25r3916_change_reg_bits( handle, - ST25R3916_REG_AUX_MOD, - (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), - 0x00); + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator); + st25r3916_change_reg_bits(handle, ST25R3916_REG_ANT_TUNE_A, 0xff, 0x82); st25r3916_change_reg_bits(handle, ST25R3916_REG_ANT_TUNE_B, 0xFF, 0x82); - st25r3916_change_reg_bits(handle, ST25R3916_REG_OVERSHOOT_CONF1, 0xff, 0x00); - st25r3916_change_reg_bits(handle, ST25R3916_REG_OVERSHOOT_CONF2, 0xff, 0x00); - st25r3916_change_reg_bits(handle, ST25R3916_REG_UNDERSHOOT_CONF1, 0xff, 0x00); - st25r3916_change_reg_bits(handle, ST25R3916_REG_UNDERSHOOT_CONF2, 0xff, 0x00); + + st25r3916_write_reg(handle, ST25R3916_REG_OVERSHOOT_CONF1, 0x00); + st25r3916_write_reg(handle, ST25R3916_REG_OVERSHOOT_CONF2, 0x00); + st25r3916_write_reg(handle, ST25R3916_REG_UNDERSHOOT_CONF1, 0x00); + st25r3916_write_reg(handle, ST25R3916_REG_UNDERSHOOT_CONF2, 0x00); } +// TODO: Refactor this function to be more modular and readable FHalNfcError f_hal_nfc_set_mode(FHalNfcMode mode, FHalNfcBitrate bitrate) { FHalNfcError error = FHalNfcErrorNone; FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; - if(mode == FHalNfcModeIso14443_3aPoller) { + if(mode == FHalNfcModeIso14443_3aPoller || mode == FHalNfcModeIso14443_3aListener) { + if(mode == FHalNfcModeIso14443_3aPoller) { + // Poller configuration + f_hal_nfc_configure_poller_common(handle); + // Enable ISO14443A mode, OOK modulation + st25r3916_change_reg_bits( + handle, + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_om_mask | ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_om_iso14443a | ST25R3916_REG_MODE_tr_am_ook); + + // Overshoot protection - is this necessary here? + st25r3916_change_reg_bits(handle, ST25R3916_REG_OVERSHOOT_CONF1, 0xff, 0x40); + st25r3916_change_reg_bits(handle, ST25R3916_REG_OVERSHOOT_CONF2, 0xff, 0x03); + st25r3916_change_reg_bits(handle, ST25R3916_REG_UNDERSHOOT_CONF1, 0xff, 0x40); + st25r3916_change_reg_bits(handle, ST25R3916_REG_UNDERSHOOT_CONF2, 0xff, 0x03); + + } else { + // Listener configuration + f_hal_nfca_listener_init(); + st25r3916_write_reg( + handle, + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en | + ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); + st25r3916_write_reg( + handle, ST25R3916_REG_MODE, ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om0); + st25r3916_write_reg( + handle, + ST25R3916_REG_PASSIVE_TARGET, + ST25R3916_REG_PASSIVE_TARGET_fdel_2 | ST25R3916_REG_PASSIVE_TARGET_fdel_0 | + ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p | + ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r); + + st25r3916_write_reg(handle, ST25R3916_REG_MASK_RX_TIMER, 0x02); + } + + if(bitrate == FHalNfcBitrate106) { + // Bitrate-dependent NFC-A settings + + // 1st stage zero = 600kHz, 3rd stage zero = 200 kHz + st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF1, ST25R3916_REG_RX_CONF1_z600k); + // AGC enabled, ratio 3:1, squelch after TX + st25r3916_write_reg( + handle, + ST25R3916_REG_RX_CONF2, + ST25R3916_REG_RX_CONF2_agc6_3 | ST25R3916_REG_RX_CONF2_agc_m | + ST25R3916_REG_RX_CONF2_agc_en | ST25R3916_REG_RX_CONF2_sqm_dyn); + // HF operation, full gain on AM and PM channels + st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF3, 0x00); + // No gain reduction on AM and PM channels + st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF4, 0x00); + // Correlator config + st25r3916_write_reg( + handle, + ST25R3916_REG_CORR_CONF1, + ST25R3916_REG_CORR_CONF1_corr_s0 | ST25R3916_REG_CORR_CONF1_corr_s4 | + ST25R3916_REG_CORR_CONF1_corr_s6); + // Sleep mode disable, 424kHz mode off + st25r3916_write_reg(handle, ST25R3916_REG_CORR_CONF2, 0x00); + } + + } else if(mode == FHalNfcModeIso14443_3bPoller /* TODO: Listener support */) { f_hal_nfc_configure_poller_common(handle); - // Disable wake up - st25r3916_clear_reg_bits(handle, ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); - // Enable ISO14443A mode - st25r3916_write_reg(handle, ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_iso14443a); + // Enable ISO14443B mode, AM modulation st25r3916_change_reg_bits( handle, - ST25R3916_REG_AUX, - ST25R3916_REG_AUX_dis_corr, - ST25R3916_REG_AUX_dis_corr_correlator); - st25r3916_change_reg_bits(handle, ST25R3916_REG_OVERSHOOT_CONF1, 0xff, 0x40); - st25r3916_change_reg_bits(handle, ST25R3916_REG_OVERSHOOT_CONF2, 0xff, 0x03); - st25r3916_change_reg_bits(handle, ST25R3916_REG_UNDERSHOOT_CONF1, 0xff, 0x40); - st25r3916_change_reg_bits(handle, ST25R3916_REG_UNDERSHOOT_CONF2, 0xff, 0x03); - } else if(mode == FHalNfcModeIso14443_3aListener) { - f_hal_nfca_listener_init(); - st25r3916_write_reg( - handle, - ST25R3916_REG_OP_CONTROL, - ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en | - ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); - st25r3916_write_reg( - handle, ST25R3916_REG_MODE, ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om0); - st25r3916_write_reg( + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_om_mask | ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_om_iso14443b | ST25R3916_REG_MODE_tr_am_am); + + // 10% ASK modulation + st25r3916_change_reg_bits( handle, - ST25R3916_REG_PASSIVE_TARGET, - ST25R3916_REG_PASSIVE_TARGET_fdel_2 | ST25R3916_REG_PASSIVE_TARGET_fdel_0 | - ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p | - ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r); + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_am_mod_mask, + ST25R3916_REG_TX_DRIVER_am_mod_10percent); - st25r3916_write_reg(handle, ST25R3916_REG_MASK_RX_TIMER, 0x02); - } + // Use regulator AM, resistive AM disabled + st25r3916_clear_reg_bits( + handle, + ST25R3916_REG_AUX_MOD, + ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am); - if(bitrate == FHalNfcBitrate106) { - st25r3916_change_reg_bits(handle, ST25R3916_REG_RX_CONF1, 0xff, 0x08); - st25r3916_change_reg_bits(handle, ST25R3916_REG_RX_CONF2, 0xff, 0x2d); - st25r3916_change_reg_bits(handle, ST25R3916_REG_RX_CONF3, 0xff, 0x00); - st25r3916_change_reg_bits(handle, ST25R3916_REG_RX_CONF4, 0xff, 0x00); - st25r3916_change_reg_bits(handle, ST25R3916_REG_CORR_CONF1, 0xff, 0x51); - st25r3916_change_reg_bits(handle, ST25R3916_REG_CORR_CONF2, 0xff, 0x00); + // EGT = 0 etu + // SOF = 10 etu LOW + 2 etu HIGH + // EOF = 10 etu + st25r3916_change_reg_bits( + handle, + ST25R3916_REG_ISO14443B_1, + ST25R3916_REG_ISO14443B_1_egt_mask | ST25R3916_REG_ISO14443B_1_sof_mask | + ST25R3916_REG_ISO14443B_1_eof, + (0U << ST25R3916_REG_ISO14443B_1_egt_shift) | ST25R3916_REG_ISO14443B_1_sof_0_10etu | + ST25R3916_REG_ISO14443B_1_sof_1_2etu | ST25R3916_REG_ISO14443B_1_eof_10etu); + + // TR1 = 80 / fs + // B' mode off (no_sof & no_eof = 0) + st25r3916_change_reg_bits( + handle, + ST25R3916_REG_ISO14443B_2, + ST25R3916_REG_ISO14443B_2_tr1_mask | ST25R3916_REG_ISO14443B_2_no_sof | + ST25R3916_REG_ISO14443B_2_no_eof, + ST25R3916_REG_ISO14443B_2_tr1_80fs80fs); + + if(bitrate == FHalNfcBitrate106) { + // Bitrate-dependent NFC-B settings + + // 1st stage zero = 60kHz, 3rd stage zero = 200 kHz + st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF1, ST25R3916_REG_RX_CONF1_h200); + + // Enable AGC + // AGC Ratio 6 + // AGC algorithm with RESET (recommended for ISO14443-B) + // AGC operation during complete receive period + // Squelch ratio 6/3 (recommended for ISO14443-B) + // Squelch automatic activation on TX end + st25r3916_write_reg( + handle, + ST25R3916_REG_RX_CONF2, + ST25R3916_REG_RX_CONF2_agc6_3 | ST25R3916_REG_RX_CONF2_agc_alg | + ST25R3916_REG_RX_CONF2_agc_m | ST25R3916_REG_RX_CONF2_agc_en | + ST25R3916_REG_RX_CONF2_pulz_61 | ST25R3916_REG_RX_CONF2_sqm_dyn); + + // HF operation, full gain on AM and PM channels + st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF3, 0x00); + // No gain reduction on AM and PM channels + st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF4, 0x00); + + // Subcarrier end detector enabled + // Subcarrier end detection level = 66% + // BPSK start 33 pilot pulses + // AM & PM summation before digitizing on + st25r3916_write_reg( + handle, + ST25R3916_REG_CORR_CONF1, + ST25R3916_REG_CORR_CONF1_corr_s0 | ST25R3916_REG_CORR_CONF1_corr_s1 | + ST25R3916_REG_CORR_CONF1_corr_s3 | ST25R3916_REG_CORR_CONF1_corr_s4); + // Sleep mode disable, 424kHz mode off + st25r3916_write_reg(handle, ST25R3916_REG_CORR_CONF2, 0x00); + } } return error; diff --git a/firmware/targets/furi_hal_include/f_hal_nfc.h b/firmware/targets/furi_hal_include/f_hal_nfc.h index 9dccf1365319..72563b9d9d6a 100644 --- a/firmware/targets/furi_hal_include/f_hal_nfc.h +++ b/firmware/targets/furi_hal_include/f_hal_nfc.h @@ -44,8 +44,8 @@ typedef enum { FHalNfcModeIso14443_3aPoller, FHalNfcModeIso14443_3aListener, - FHalNfcModeNfcbPoller, - FHalNfcModeNfcbListener, + FHalNfcModeIso14443_3bPoller, + FHalNfcModeIso14443_3bListener, FHalNfcModeNfcfPoller, FHalNfcModeNfcfListener, diff --git a/lib/nfc/SConscript b/lib/nfc/SConscript index fb9d1d3cc5ff..4702c7b96f08 100644 --- a/lib/nfc/SConscript +++ b/lib/nfc/SConscript @@ -13,12 +13,14 @@ env.Append( File("nfc_scanner.h"), # Protocols File("protocols/iso14443_3a/iso14443_3a.h"), + File("protocols/iso14443_3b/iso14443_3b.h"), File("protocols/iso14443_4a/iso14443_4a.h"), File("protocols/mf_ultralight/mf_ultralight.h"), File("protocols/mf_classic/mf_classic.h"), File("protocols/mf_desfire/mf_desfire.h"), # Pollers File("protocols/iso14443_3a/iso14443_3a_poller.h"), + File("protocols/iso14443_3b/iso14443_3b_poller.h"), File("protocols/iso14443_4a/iso14443_4a_poller.h"), File("protocols/mf_ultralight/mf_ultralight_poller.h"), File("protocols/mf_classic/mf_classic_poller.h"), @@ -34,6 +36,7 @@ env.Append( File("protocols/mf_classic/mf_classic_poller_sync_api.h"), # Misc File("helpers/nfc_util.h"), + File("helpers/iso14443_crc.h"), ], ) diff --git a/lib/nfc/helpers/bit_buffer.c b/lib/nfc/helpers/bit_buffer.c index c9c6bd5c980a..566393e784ed 100644 --- a/lib/nfc/helpers/bit_buffer.c +++ b/lib/nfc/helpers/bit_buffer.c @@ -41,6 +41,9 @@ void bit_buffer_reset(BitBuffer* buf) { void bit_buffer_copy(BitBuffer* buf, const BitBuffer* other) { furi_assert(buf); furi_assert(other); + + if(buf == other) return; + furi_assert(buf->capacity_bytes * BITS_IN_BYTE >= other->size_bits); memcpy(buf->data, other->data, bit_buffer_get_size_bytes(other)); diff --git a/lib/nfc/helpers/iso14443_crc.c b/lib/nfc/helpers/iso14443_crc.c new file mode 100644 index 000000000000..72fedb9e7e49 --- /dev/null +++ b/lib/nfc/helpers/iso14443_crc.c @@ -0,0 +1,59 @@ +#include "iso14443_crc.h" + +#include + +#define ISO14443_3A_CRC_INIT (0x6363U) +#define ISO14443_3B_CRC_INIT (0xFFFFU) + +static uint16_t + iso14443_crc_calculate(Iso14443CrcType type, const uint8_t* data, size_t data_size) { + furi_assert(data); + + uint16_t crc; + + if(type == Iso14443CrcTypeA) { + crc = ISO14443_3A_CRC_INIT; + } else if(type == Iso14443CrcTypeB) { + crc = ISO14443_3B_CRC_INIT; + } else { + furi_crash("Wrong ISO14443 CRC type"); + } + + for(size_t i = 0; i < data_size; i++) { + uint8_t byte = data[i]; + byte ^= (uint8_t)(crc & 0xff); + byte ^= byte << 4; + crc = (crc >> 8) ^ (((uint16_t)byte) << 8) ^ (((uint16_t)byte) << 3) ^ (byte >> 4); + } + + return type == Iso14443CrcTypeA ? crc : ~crc; +} + +void iso14443_crc_append(Iso14443CrcType type, BitBuffer* buf) { + const uint8_t* data = bit_buffer_get_data(buf); + const size_t data_size = bit_buffer_get_size_bytes(buf); + + const uint16_t crc = iso14443_crc_calculate(type, data, data_size); + bit_buffer_append_bytes(buf, (const uint8_t*)&crc, ISO14443_CRC_SIZE); +} + +bool iso14443_crc_check(Iso14443CrcType type, const BitBuffer* buf) { + const size_t data_size = bit_buffer_get_size_bytes(buf); + if(data_size <= ISO14443_CRC_SIZE) return false; + + uint16_t crc_received; + bit_buffer_write_bytes_mid( + buf, &crc_received, data_size - ISO14443_CRC_SIZE, ISO14443_CRC_SIZE); + + const uint8_t* data = bit_buffer_get_data(buf); + const uint16_t crc_calc = iso14443_crc_calculate(type, data, data_size - ISO14443_CRC_SIZE); + + return (crc_calc == crc_received); +} + +void iso14443_crc_trim(BitBuffer* buf) { + const size_t data_size = bit_buffer_get_size_bytes(buf); + furi_assert(data_size > ISO14443_CRC_SIZE); + + bit_buffer_set_size_bytes(buf, data_size - ISO14443_CRC_SIZE); +} diff --git a/lib/nfc/helpers/iso14443_crc.h b/lib/nfc/helpers/iso14443_crc.h new file mode 100644 index 000000000000..c9ad5397fc3e --- /dev/null +++ b/lib/nfc/helpers/iso14443_crc.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include "bit_buffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ISO14443_CRC_SIZE sizeof(uint16_t) + +typedef enum { + Iso14443CrcTypeA, + Iso14443CrcTypeB, +} Iso14443CrcType; + +void iso14443_crc_append(Iso14443CrcType type, BitBuffer* buf); + +bool iso14443_crc_check(Iso14443CrcType type, const BitBuffer* buf); + +void iso14443_crc_trim(BitBuffer* buf); + +#ifdef __cplusplus +} +#endif diff --git a/lib/nfc/nfc.c b/lib/nfc/nfc.c index 1090b412083c..1c4c0d955b1f 100644 --- a/lib/nfc/nfc.c +++ b/lib/nfc/nfc.c @@ -256,6 +256,9 @@ void nfc_config(Nfc* instance, NfcMode mode) { f_hal_nfc_low_power_mode_stop(); f_hal_nfc_set_mode(FHalNfcModeIso14443_3aListener, FHalNfcBitrate106); instance->config_state = NfcConfigurationStateDone; + } else if(mode == NfcModeIso14443_3bPoller) { + f_hal_nfc_set_mode(FHalNfcModeIso14443_3bPoller, FHalNfcBitrate106); + instance->config_state = NfcConfigurationStateDone; } } diff --git a/lib/nfc/nfc.h b/lib/nfc/nfc.h index 797e512ae0d0..bcb7066f3232 100644 --- a/lib/nfc/nfc.h +++ b/lib/nfc/nfc.h @@ -42,8 +42,8 @@ typedef enum { NfcModeIdle, NfcModeIso14443_3aPoller, NfcModeIso14443_3aListener, - NfcModeNfcbPoller, - NfcModeNfcbListener, + NfcModeIso14443_3bPoller, + NfcModeIso14443_3bListener, NfcModeNfcfPoller, NfcModeNfcfListener, NfcModeNfcvPoller, diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index c7fb3c94d197..62aeb6ab48f0 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -12,6 +12,8 @@ #define NFC_DEVICE_UID_KEY "UID" #define NFC_DEVICE_TYPE_KEY "Device type" +#define NFC_DEVICE_UID_MAX_LEN (10U) + struct NfcDevice { NfcProtocol protocol; NfcDeviceData* protocol_data; @@ -104,6 +106,13 @@ const uint8_t* nfc_device_get_uid(const NfcDevice* instance, size_t* uid_len) { return nfc_devices[instance->protocol]->get_uid(instance->protocol_data, uid_len); } +bool nfc_device_set_uid(NfcDevice* instance, const uint8_t* uid, size_t uid_len) { + furi_assert(instance); + furi_assert(instance->protocol < NfcProtocolNum); + + return nfc_devices[instance->protocol]->set_uid(instance->protocol_data, uid, uid_len); +} + void nfc_device_set_data( NfcDevice* instance, NfcProtocol protocol, @@ -221,6 +230,26 @@ bool nfc_device_save(NfcDevice* instance, const char* path) { return saved; } +static bool nfc_device_load_uid( + FlipperFormat* ff, + uint8_t* uid, + uint32_t* uid_len, + const uint32_t uid_maxlen) { + bool loaded = false; + + do { + uint32_t uid_len_current; + if(!flipper_format_get_value_count(ff, NFC_DEVICE_UID_KEY, &uid_len_current)) break; + if(uid_len_current > uid_maxlen) break; + if(!flipper_format_read_hex(ff, NFC_DEVICE_UID_KEY, uid, uid_len_current)) break; + + *uid_len = uid_len_current; + loaded = true; + } while(false); + + return loaded; +} + static bool nfc_device_load_unified(NfcDevice* instance, FlipperFormat* ff, uint32_t version) { bool loaded = false; @@ -246,17 +275,22 @@ static bool nfc_device_load_unified(NfcDevice* instance, FlipperFormat* ff, uint instance->protocol_data = nfc_devices[protocol]->alloc(); // Load UID - // TODO: move the respective code from ISO14443-3A to here + uint8_t uid[NFC_DEVICE_UID_MAX_LEN]; + uint32_t uid_len; + + if(!nfc_device_load_uid(ff, uid, &uid_len, NFC_DEVICE_UID_MAX_LEN)) break; + if(!nfc_device_set_uid(instance, uid, uid_len)) break; // Load data - if(!nfc_devices[protocol]->load(instance->protocol_data, ff, version)) { - nfc_device_clear(instance); - break; - } + if(!nfc_devices[protocol]->load(instance->protocol_data, ff, version)) break; loaded = true; } while(false); + if(!loaded) { + nfc_device_clear(instance); + } + furi_string_free(temp_str); return loaded; } @@ -277,11 +311,16 @@ static bool nfc_device_load_legacy(NfcDevice* instance, FlipperFormat* ff, uint3 instance->protocol = protocol; instance->protocol_data = nfc_devices[protocol]->alloc(); + // Verify protocol if(nfc_devices[protocol]->verify(instance->protocol_data, temp_str)) { - if(nfc_devices[protocol]->load(instance->protocol_data, ff, version)) { - loaded = true; - break; - } + uint8_t uid[NFC_DEVICE_UID_MAX_LEN]; + uint32_t uid_len; + + // Load data + loaded = nfc_device_load_uid(ff, uid, &uid_len, NFC_DEVICE_UID_MAX_LEN) && + nfc_device_set_uid(instance, uid, uid_len) && + nfc_devices[protocol]->load(instance->protocol_data, ff, version); + break; } nfc_device_clear(instance); diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h index 74ca73eaf6e4..8a37f3064997 100644 --- a/lib/nfc/nfc_device.h +++ b/lib/nfc/nfc_device.h @@ -35,6 +35,8 @@ const char* nfc_device_get_name(const NfcDevice* instance, NfcDeviceNameType nam const uint8_t* nfc_device_get_uid(const NfcDevice* instance, size_t* uid_len); +bool nfc_device_set_uid(NfcDevice* instance, const uint8_t* uid, size_t uid_len); + void nfc_device_set_data( NfcDevice* instance, NfcProtocol protocol, diff --git a/lib/nfc/protocols/iso14443_3a/iso14443_3a.c b/lib/nfc/protocols/iso14443_3a/iso14443_3a.c index 6ecc0d350644..98fcb6bf03b7 100644 --- a/lib/nfc/protocols/iso14443_3a/iso14443_3a.c +++ b/lib/nfc/protocols/iso14443_3a/iso14443_3a.c @@ -3,12 +3,10 @@ #include #include -#define ISO14443_3A_CRC_INIT (0x6363) #define ISO14443_3A_PROTOCOL_NAME_LEGACY "UID" #define ISO14443_3A_PROTOCOL_NAME "ISO14443-3A" -#define ISO14443_3A_DEVICE_NAME "Unknown ISO14443-3A Tag" +#define ISO14443_3A_DEVICE_NAME "ISO14443-3A (Unknown)" -#define ISO14443_3A_UID_KEY "UID" #define ISO14443_3A_ATQA_KEY "ATQA" #define ISO14443_3A_SAK_KEY "SAK" @@ -24,6 +22,7 @@ const NfcDeviceBase nfc_device_iso14443_3a = { .is_equal = (NfcDeviceEqual)iso14443_3a_is_equal, .get_name = (NfcDeviceGetName)iso14443_3a_get_device_name, .get_uid = (NfcDeviceGetUid)iso14443_3a_get_uid, + .set_uid = (NfcDeviceSetUid)iso14443_3a_set_uid, .get_base_data = (NfcDeviceGetBaseData)iso14443_3a_get_base_data, }; @@ -62,17 +61,6 @@ bool iso14443_3a_load(Iso14443_3aData* data, FlipperFormat* ff, uint32_t version bool parsed = false; do { - // TODO: Load UID in nfc_device.c - // if(version < NFC_UNIFIED_FORMAT_VERSION) { - uint32_t uid_len = 0; - if(!flipper_format_get_value_count(ff, ISO14443_3A_UID_KEY, &uid_len)) break; - if(!(uid_len == 4 || uid_len == 7)) break; - - data->uid_len = uid_len; - - if(!flipper_format_read_hex(ff, ISO14443_3A_UID_KEY, data->uid, data->uid_len)) break; - // } - // Common to all format versions if(!flipper_format_read_hex(ff, ISO14443_3A_ATQA_KEY, data->atqa, 2)) break; if(!flipper_format_read_hex(ff, ISO14443_3A_SAK_KEY, &data->sak, 1)) break; @@ -133,27 +121,24 @@ const uint8_t* iso14443_3a_get_uid(const Iso14443_3aData* data, size_t* uid_len) return data->uid; } -const Iso14443_3aData* iso14443_3a_get_base_data(const Iso14443_3aData* data) { - UNUSED(data); - furi_crash("No base data"); -} - -static uint16_t iso14443_3a_get_crc(const uint8_t* buff, uint16_t len) { - furi_assert(buff); - furi_assert(len); +bool iso14443_3a_set_uid(Iso14443_3aData* data, const uint8_t* uid, size_t uid_len) { + furi_assert(data); - uint16_t crc = ISO14443_3A_CRC_INIT; - uint8_t byte = 0; + const bool uid_valid = uid_len == ISO14443_3A_UID_4_BYTES || + uid_len == ISO14443_3A_UID_7_BYTES || + uid_len == ISO14443_3A_UID_10_BYTES; - for(uint8_t i = 0; i < len; i++) { - byte = buff[i]; - byte ^= (uint8_t)(crc & 0xff); - byte ^= byte << 4; - crc = (crc >> 8) ^ (((uint16_t)byte) << 8) ^ (((uint16_t)byte) << 3) ^ - (((uint16_t)byte) >> 4); + if(uid_valid) { + memcpy(data->uid, uid, uid_len); + data->uid_len = uid_len; } - return crc; + return uid_valid; +} + +const Iso14443_3aData* iso14443_3a_get_base_data(const Iso14443_3aData* data) { + UNUSED(data); + furi_crash("No base data"); } uint32_t iso14443_3a_get_cuid(const Iso14443_3aData* iso14443_3a_data) { @@ -168,42 +153,3 @@ uint32_t iso14443_3a_get_cuid(const Iso14443_3aData* iso14443_3a_data) { return cuid; } - -void iso14443_3a_append_crc(BitBuffer* buffer) { - furi_assert(buffer); - - const uint8_t* data = bit_buffer_get_data(buffer); - size_t bytes = bit_buffer_get_size_bytes(buffer); - - uint16_t crc = iso14443_3a_get_crc(data, bytes); - uint8_t crc_bytes[2] = {(uint8_t)crc, (uint8_t)(crc >> 8)}; - bit_buffer_append_bytes(buffer, crc_bytes, sizeof(crc_bytes)); -} - -bool iso14443_3a_check_crc(const BitBuffer* buf) { - furi_assert(buf); - - bool crc_ok = false; - do { - const uint8_t* data = bit_buffer_get_data(buf); - size_t bytes = bit_buffer_get_size_bytes(buf); - if(bytes < 3) break; - - uint16_t crc_calc = iso14443_3a_get_crc(data, bytes - 2); - uint8_t crc_start = bit_buffer_get_byte(buf, bytes - 2); - uint8_t crc_end = bit_buffer_get_byte(buf, bytes - 1); - uint16_t crc_received = (crc_end << 8) | crc_start; - crc_ok = (crc_calc == crc_received); - } while(false); - - return crc_ok; -} - -void iso14443_3a_trim_crc(BitBuffer* buf) { - furi_assert(buf); - - size_t bytes = bit_buffer_get_size_bytes(buf); - furi_assert(bytes > 2); - - bit_buffer_set_size_bytes(buf, bytes - 2); -} diff --git a/lib/nfc/protocols/iso14443_3a/iso14443_3a.h b/lib/nfc/protocols/iso14443_3a/iso14443_3a.h index 46b443acafc7..a899472f160e 100644 --- a/lib/nfc/protocols/iso14443_3a/iso14443_3a.h +++ b/lib/nfc/protocols/iso14443_3a/iso14443_3a.h @@ -7,7 +7,10 @@ extern "C" { #endif -#define ISO14443_3A_MAX_UID_SIZE (10U) +#define ISO14443_3A_UID_4_BYTES (4U) +#define ISO14443_3A_UID_7_BYTES (7U) +#define ISO14443_3A_UID_10_BYTES (10U) +#define ISO14443_3A_MAX_UID_SIZE ISO14443_3A_UID_10_BYTES #define ISO14443_3A_GUARD_TIME_US (5000) #define ISO14443_3A_FDT_POLL_FC (1620) @@ -81,16 +84,12 @@ const char* iso14443_3a_get_device_name(const Iso14443_3aData* data, NfcDeviceNa const uint8_t* iso14443_3a_get_uid(const Iso14443_3aData* data, size_t* uid_len); +bool iso14443_3a_set_uid(Iso14443_3aData* data, const uint8_t* uid, size_t uid_len); + const Iso14443_3aData* iso14443_3a_get_base_data(const Iso14443_3aData* data); uint32_t iso14443_3a_get_cuid(const Iso14443_3aData* iso14443_3a_data); -void iso14443_3a_append_crc(BitBuffer* buffer); - -bool iso14443_3a_check_crc(const BitBuffer* buf); - -void iso14443_3a_trim_crc(BitBuffer* buf); - #ifdef __cplusplus } #endif diff --git a/lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.c b/lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.c index 96da690cfde6..c6d14cc9187a 100644 --- a/lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.c +++ b/lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.c @@ -1,5 +1,7 @@ #include "iso14443_3a_listener_i.h" -#include "iso14443_3a_listener_defs.h" + +#include "nfc/protocols/nfc_listener_base.h" +#include "nfc/helpers/iso14443_crc.h" #include #include @@ -13,7 +15,7 @@ static bool iso14443_3a_listener_halt_received(BitBuffer* buf) { do { if(bit_buffer_get_size_bytes(buf) != 4) break; - if(!iso14443_3a_check_crc(buf)) break; + if(!iso14443_crc_check(Iso14443CrcTypeA, buf)) break; if(bit_buffer_get_byte(buf, 0) != 0x50) break; if(bit_buffer_get_byte(buf, 1) != 0x00) break; halt_cmd_received = true; @@ -101,10 +103,10 @@ NfcCommand iso14443_3a_listener_run(NfcGenericEvent event, void* context) { command = instance->callback(instance->generic_event, instance->context); } } else { - if(iso14443_3a_check_crc(nfc_event->data.buffer)) { + if(iso14443_crc_check(Iso14443CrcTypeA, nfc_event->data.buffer)) { instance->iso14443_3a_event.type = Iso14443_3aListenerEventTypeReceivedStandardFrame; - iso14443_3a_trim_crc(nfc_event->data.buffer); + iso14443_crc_trim(nfc_event->data.buffer); } else { instance->iso14443_3a_event.type = Iso14443_3aListenerEventTypeReceivedData; } diff --git a/lib/nfc/protocols/iso14443_3a/iso14443_3a_listener_i.c b/lib/nfc/protocols/iso14443_3a/iso14443_3a_listener_i.c index 4f5f702b6d56..76b3b341a9d4 100644 --- a/lib/nfc/protocols/iso14443_3a/iso14443_3a_listener_i.c +++ b/lib/nfc/protocols/iso14443_3a/iso14443_3a_listener_i.c @@ -1,5 +1,7 @@ #include "iso14443_3a_listener_i.h" +#include "nfc/helpers/iso14443_crc.h" + #define TAG "Iso14443_3aListener" static Iso14443_3aError iso14443_3a_listener_process_nfc_error(NfcError error) { @@ -66,7 +68,7 @@ Iso14443_3aError iso14443_3a_listener_send_standard_frame( Iso14443_3aError ret = Iso14443_3aErrorNone; do { bit_buffer_copy(instance->tx_buffer, tx_buffer); - iso14443_3a_append_crc(instance->tx_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_buffer); NfcError error = nfc_listener_tx(instance->nfc, instance->tx_buffer); if(error != NfcErrorNone) { @@ -77,4 +79,4 @@ Iso14443_3aError iso14443_3a_listener_send_standard_frame( } while(false); return ret; -} \ No newline at end of file +} diff --git a/lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.c b/lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.c index 90b9169a5866..a98894f3d019 100644 --- a/lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.c +++ b/lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.c @@ -2,6 +2,8 @@ #include +#include "nfc/helpers/iso14443_crc.h" + #define TAG "ISO14443_3A" static Iso14443_3aError iso14443_3a_poller_process_error(NfcError error) { @@ -39,7 +41,7 @@ static Iso14443_3aError iso14443_3a_poller_standard_frame_exchange( furi_assert(tx_bytes <= bit_buffer_get_capacity_bytes(instance->tx_buffer) - 2); bit_buffer_copy(instance->tx_buffer, tx_buffer); - iso14443_3a_append_crc(instance->tx_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_buffer); Iso14443_3aError ret = Iso14443_3aErrorNone; do { @@ -50,12 +52,12 @@ static Iso14443_3aError iso14443_3a_poller_standard_frame_exchange( } bit_buffer_copy(rx_buffer, instance->rx_buffer); - if(!iso14443_3a_check_crc(instance->rx_buffer)) { + if(!iso14443_crc_check(Iso14443CrcTypeA, instance->rx_buffer)) { ret = Iso14443_3aErrorWrongCrc; break; } - iso14443_3a_trim_crc(rx_buffer); + iso14443_crc_trim(rx_buffer); } while(false); return ret; diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b.c b/lib/nfc/protocols/iso14443_3b/iso14443_3b.c new file mode 100644 index 000000000000..2d46da056c3e --- /dev/null +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b.c @@ -0,0 +1,145 @@ +#include "iso14443_3b.h" + +#include + +#include +#include + +#define ISO14443_3B_PROTOCOL_NAME "ISO14443-3B" +#define ISO14443_3B_DEVICE_NAME "ISO14443-3B (Unknown)" + +#define ISO14443_3B_APP_DATA_KEY "Application data" +#define ISO14443_3B_PROTOCOL_INFO_KEY "Protocol info" + +const NfcDeviceBase nfc_device_iso14443_3b = { + .protocol_name = ISO14443_3B_PROTOCOL_NAME, + .alloc = (NfcDeviceAlloc)iso14443_3b_alloc, + .free = (NfcDeviceFree)iso14443_3b_free, + .reset = (NfcDeviceReset)iso14443_3b_reset, + .copy = (NfcDeviceCopy)iso14443_3b_copy, + .verify = (NfcDeviceVerify)iso14443_3b_verify, + .load = (NfcDeviceLoad)iso14443_3b_load, + .save = (NfcDeviceSave)iso14443_3b_save, + .is_equal = (NfcDeviceEqual)iso14443_3b_is_equal, + .get_name = (NfcDeviceGetName)iso14443_3b_get_device_name, + .get_uid = (NfcDeviceGetUid)iso14443_3b_get_uid, + .set_uid = (NfcDeviceSetUid)iso14443_3b_set_uid, + .get_base_data = (NfcDeviceGetBaseData)iso14443_3b_get_base_data, +}; + +Iso14443_3bData* iso14443_3b_alloc() { + Iso14443_3bData* data = malloc(sizeof(Iso14443_3bData)); + return data; +} + +void iso14443_3b_free(Iso14443_3bData* data) { + furi_assert(data); + + free(data); +} + +void iso14443_3b_reset(Iso14443_3bData* data) { + memset(data, 0, sizeof(Iso14443_3bData)); +} + +void iso14443_3b_copy(Iso14443_3bData* data, const Iso14443_3bData* other) { + furi_assert(data); + furi_assert(other); + + *data = *other; +} + +bool iso14443_3b_verify(Iso14443_3bData* data, const FuriString* device_type) { + UNUSED(data); + UNUSED(device_type); + // TODO: How to distinguish from old ISO14443-3/4a? + return false; +} + +bool iso14443_3b_load(Iso14443_3bData* data, FlipperFormat* ff, uint32_t version) { + furi_assert(data); + + bool parsed = false; + + do { + if(version < NFC_UNIFIED_FORMAT_VERSION) break; + + if(!flipper_format_read_hex( + ff, ISO14443_3B_APP_DATA_KEY, data->app_data, ISO14443_3B_APP_DATA_SIZE)) + break; + if(!flipper_format_read_hex( + ff, + ISO14443_3B_PROTOCOL_INFO_KEY, + data->protocol_info, + ISO14443_3B_PROTOCOL_INFO_SIZE)) + break; + + parsed = true; + } while(false); + + return parsed; +} + +bool iso14443_3b_save(const Iso14443_3bData* data, FlipperFormat* ff) { + furi_assert(data); + + bool saved = false; + + do { + if(!flipper_format_write_comment_cstr(ff, ISO14443_3B_PROTOCOL_NAME " specific data")) + break; + if(!flipper_format_write_hex( + ff, ISO14443_3B_APP_DATA_KEY, data->app_data, ISO14443_3B_APP_DATA_SIZE)) + break; + if(!flipper_format_write_hex( + ff, + ISO14443_3B_PROTOCOL_INFO_KEY, + data->protocol_info, + ISO14443_3B_PROTOCOL_INFO_SIZE)) + break; + saved = true; + } while(false); + + return saved; +} + +bool iso14443_3b_is_equal(const Iso14443_3bData* data, const Iso14443_3bData* other) { + furi_assert(data); + furi_assert(other); + + return memcmp(data, other, sizeof(Iso14443_3bData)) == 0; +} + +const char* iso14443_3b_get_device_name(const Iso14443_3bData* data, NfcDeviceNameType name_type) { + UNUSED(data); + UNUSED(name_type); + + return ISO14443_3B_DEVICE_NAME; +} + +const uint8_t* iso14443_3b_get_uid(const Iso14443_3bData* data, size_t* uid_len) { + furi_assert(data); + + if(uid_len) { + *uid_len = ISO14443_3B_UID_SIZE; + } + + return data->uid; +} + +bool iso14443_3b_set_uid(Iso14443_3bData* data, const uint8_t* uid, size_t uid_len) { + furi_assert(data); + + const bool uid_valid = uid_len == ISO14443_3B_UID_SIZE; + + if(uid_valid) { + memcpy(data->uid, uid, uid_len); + } + + return uid_valid; +} + +const Iso14443_3bData* iso14443_3b_get_base_data(const Iso14443_3bData* data) { + UNUSED(data); + furi_crash("No base data"); +} diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b.h b/lib/nfc/protocols/iso14443_3b/iso14443_3b.h new file mode 100644 index 000000000000..f222abd9db2e --- /dev/null +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ISO14443_3B_UID_SIZE (4U) +#define ISO14443_3B_APP_DATA_SIZE (4U) +#define ISO14443_3B_PROTOCOL_INFO_SIZE (3U) + +#define ISO14443_3B_GUARD_TIME_US (5000U) +#define ISO14443_3B_FDT_POLL_FC (9000U) +#define ISO14443_3B_FDT_ATTRIB_FC (42000U) +#define ISO14443_3B_POLL_POLL_MIN_US (1280U) + +#define ISO14443_3B_REQB_ALL (1U << 3) + +#define ISO14443_3B_ATTRIB_FRAME_SIZE_32 (0x02) +#define ISO14443_3B_ATTRIB_FRAME_SIZE_40 (0x03) +#define ISO14443_3B_ATTRIB_FRAME_SIZE_48 (0x04) +#define ISO14443_3B_ATTRIB_FRAME_SIZE_64 (0x05) +#define ISO14443_3B_ATTRIB_FRAME_SIZE_96 (0x06) +#define ISO14443_3B_ATTRIB_FRAME_SIZE_128 (0x07) +#define ISO14443_3B_ATTRIB_FRAME_SIZE_256 (0x08) + +typedef enum { + Iso14443_3bErrorNone, + Iso14443_3bErrorNotPresent, + Iso14443_3bErrorColResFailed, + Iso14443_3bErrorBufferOverflow, + Iso14443_3bErrorCommunication, + Iso14443_3bErrorFieldOff, + Iso14443_3bErrorWrongCrc, + Iso14443_3bErrorTimeout, +} Iso14443_3bError; + +typedef struct { + uint8_t flag; + uint8_t uid[ISO14443_3B_UID_SIZE]; + uint8_t app_data[ISO14443_3B_APP_DATA_SIZE]; + uint8_t protocol_info[ISO14443_3B_PROTOCOL_INFO_SIZE]; +} Iso14443_3bAtqB; + +typedef struct { + uint8_t uid[ISO14443_3B_UID_SIZE]; + uint8_t app_data[ISO14443_3B_APP_DATA_SIZE]; + uint8_t protocol_info[ISO14443_3B_PROTOCOL_INFO_SIZE]; +} Iso14443_3bData; + +extern const NfcDeviceBase nfc_device_iso14443_3b; + +Iso14443_3bData* iso14443_3b_alloc(); + +void iso14443_3b_free(Iso14443_3bData* data); + +void iso14443_3b_reset(Iso14443_3bData* data); + +void iso14443_3b_copy(Iso14443_3bData* data, const Iso14443_3bData* other); + +bool iso14443_3b_verify(Iso14443_3bData* data, const FuriString* device_type); + +bool iso14443_3b_load(Iso14443_3bData* data, FlipperFormat* ff, uint32_t version); + +bool iso14443_3b_save(const Iso14443_3bData* data, FlipperFormat* ff); + +bool iso14443_3b_is_equal(const Iso14443_3bData* data, const Iso14443_3bData* other); + +const char* iso14443_3b_get_device_name(const Iso14443_3bData* data, NfcDeviceNameType name_type); + +const uint8_t* iso14443_3b_get_uid(const Iso14443_3bData* data, size_t* uid_len); + +bool iso14443_3b_set_uid(Iso14443_3bData* data, const uint8_t* uid, size_t uid_len); + +const Iso14443_3bData* iso14443_3b_get_base_data(const Iso14443_3bData* data); + +#ifdef __cplusplus +} +#endif diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.c b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.c new file mode 100644 index 000000000000..4a95197c2c34 --- /dev/null +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.c @@ -0,0 +1,122 @@ +#include "iso14443_3b_poller_i.h" + +#include + +#include + +#define TAG "ISO14443_3bPoller" + +const Iso14443_3bData* iso14443_3b_poller_get_data(Iso14443_3bPoller* instance) { + furi_assert(instance); + furi_assert(instance->data); + + return instance->data; +} + +static Iso14443_3bPoller* iso14443_3b_poller_alloc(Nfc* nfc) { + furi_assert(nfc); + + Iso14443_3bPoller* instance = malloc(sizeof(Iso14443_3bPoller)); + instance->nfc = nfc; + instance->tx_buffer = bit_buffer_alloc(ISO14443_3B_POLLER_MAX_BUFFER_SIZE); + instance->rx_buffer = bit_buffer_alloc(ISO14443_3B_POLLER_MAX_BUFFER_SIZE); + + nfc_config(instance->nfc, NfcModeIso14443_3bPoller); + nfc_set_guard_time_us(instance->nfc, ISO14443_3B_GUARD_TIME_US); + nfc_set_fdt_poll_fc(instance->nfc, ISO14443_3B_FDT_POLL_FC); + nfc_set_fdt_poll_poll_us(instance->nfc, ISO14443_3B_POLL_POLL_MIN_US); + instance->data = iso14443_3b_alloc(); + + instance->iso14443_3b_event.data = &instance->iso14443_3b_event_data; + instance->general_event.protocol = NfcProtocolIso14443_3b; + instance->general_event.data = &instance->iso14443_3b_event; + instance->general_event.instance = instance; + + return instance; +} + +static void iso14443_3b_poller_free(Iso14443_3bPoller* instance) { + furi_assert(instance); + + furi_assert(instance->tx_buffer); + furi_assert(instance->rx_buffer); + furi_assert(instance->data); + + bit_buffer_free(instance->tx_buffer); + bit_buffer_free(instance->rx_buffer); + iso14443_3b_free(instance->data); + free(instance); +} + +static void iso14443_3b_poller_set_callback( + Iso14443_3bPoller* instance, + NfcGenericCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + + instance->callback = callback; + instance->context = context; +} + +static NfcCommand iso14443_3b_poller_run(NfcGenericEvent event, void* context) { + furi_assert(context); + furi_assert(event.protocol == NfcProtocolInvalid); + furi_assert(event.data); + + Iso14443_3bPoller* instance = context; + NfcEvent* nfc_event = event.data; + NfcCommand command = NfcCommandContinue; + + if(nfc_event->type == NfcEventTypePollerReady) { + if(instance->state != Iso14443_3bPollerStateActivated) { + Iso14443_3bData data = {}; + Iso14443_3bError error = iso14443_3b_poller_async_activate(instance, &data); + if(error == Iso14443_3bErrorNone) { + instance->iso14443_3b_event.type = Iso14443_3bPollerEventTypeReady; + instance->iso14443_3b_event_data.error = error; + command = instance->callback(instance->general_event, instance->context); + } else { + instance->iso14443_3b_event.type = Iso14443_3bPollerEventTypeError; + instance->iso14443_3b_event_data.error = error; + command = instance->callback(instance->general_event, instance->context); + // Add delay to switch context + furi_delay_ms(100); + } + } else { + instance->iso14443_3b_event.type = Iso14443_3bPollerEventTypeReady; + instance->iso14443_3b_event_data.error = Iso14443_3bErrorNone; + command = instance->callback(instance->general_event, instance->context); + } + } + + return command; +} + +static bool iso14443_3b_poller_detect(NfcGenericEvent event, void* context) { + furi_assert(context); + furi_assert(event.data); + furi_assert(event.instance); + furi_assert(event.protocol = NfcProtocolInvalid); + + bool protocol_detected = false; + Iso14443_3bPoller* instance = context; + NfcEvent* nfc_event = event.data; + furi_assert(instance->state == Iso14443_3bPollerStateIdle); + + if(nfc_event->type == NfcEventTypePollerReady) { + Iso14443_3bError error = iso14443_3b_poller_async_activate(instance, NULL); + protocol_detected = (error == Iso14443_3bErrorNone); + } + + return protocol_detected; +} + +const NfcPollerBase nfc_poller_iso14443_3b = { + .alloc = (NfcPollerAlloc)iso14443_3b_poller_alloc, + .free = (NfcPollerFree)iso14443_3b_poller_free, + .set_callback = (NfcPollerSetCallback)iso14443_3b_poller_set_callback, + .run = (NfcPollerRun)iso14443_3b_poller_run, + .detect = (NfcPollerDetect)iso14443_3b_poller_detect, + .get_data = (NfcPollerGetData)iso14443_3b_poller_get_data, +}; diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.h b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.h new file mode 100644 index 000000000000..d25d9dbe9fef --- /dev/null +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.h @@ -0,0 +1,30 @@ +#pragma once + +#include "iso14443_3b.h" +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct Iso14443_3bPoller Iso14443_3bPoller; + +typedef enum { + Iso14443_3bPollerEventTypeError, + Iso14443_3bPollerEventTypeReady, +} Iso14443_3bPollerEventType; + +typedef struct { + Iso14443_3bError error; +} Iso14443_3bPollerEventData; + +typedef struct { + Iso14443_3bPollerEventType type; + Iso14443_3bPollerEventData* data; +} Iso14443_3bPollerEvent; + +#ifdef __cplusplus +} +#endif diff --git a/lib/nfc/protocols/nfcb/nfcb_poller_i.h b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_defs.h similarity index 63% rename from lib/nfc/protocols/nfcb/nfcb_poller_i.h rename to lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_defs.h index 0a51fc556e24..ba8e6cb18c06 100644 --- a/lib/nfc/protocols/nfcb/nfcb_poller_i.h +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_defs.h @@ -1,13 +1,12 @@ #pragma once -#include "nfcb_poller.h" #include #ifdef __cplusplus extern "C" { #endif -extern const NfcPollerBase nfcb_protocol_base; +extern const NfcPollerBase nfc_poller_iso14443_3b; #ifdef __cplusplus } diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.c b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.c new file mode 100644 index 000000000000..d0ce99578e12 --- /dev/null +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.c @@ -0,0 +1,188 @@ +#include "iso14443_3b_poller_i.h" + +#include + +#define TAG "Iso14443_3bPoller" + +static Iso14443_3bError iso14443_3b_poller_process_error(NfcError error) { + switch(error) { + case NfcErrorNone: + return Iso14443_3bErrorNone; + case NfcErrorTimeout: + return Iso14443_3bErrorTimeout; + default: + return Iso14443_3bErrorNotPresent; + } +} + +static Iso14443_3bError iso14443_3b_poller_prepare_trx(Iso14443_3bPoller* instance) { + furi_assert(instance); + + if(instance->state == Iso14443_3bPollerStateIdle) { + return iso14443_3b_poller_async_activate(instance, NULL); + } + + return Iso14443_3bErrorNone; +} + +static Iso14443_3bError iso14443_3b_poller_frame_exchange( + Iso14443_3bPoller* instance, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer, + uint32_t fwt) { + furi_assert(instance); + + const size_t tx_bytes = bit_buffer_get_size_bytes(tx_buffer); + furi_assert( + tx_bytes <= bit_buffer_get_capacity_bytes(instance->tx_buffer) - ISO14443_CRC_SIZE); + + bit_buffer_copy(instance->tx_buffer, tx_buffer); + iso14443_crc_append(Iso14443CrcTypeB, instance->tx_buffer); + + Iso14443_3bError ret = Iso14443_3bErrorNone; + + do { + NfcError error = nfc_trx(instance->nfc, instance->tx_buffer, instance->rx_buffer, fwt); + if(error != NfcErrorNone) { + ret = iso14443_3b_poller_process_error(error); + break; + } + + bit_buffer_copy(rx_buffer, instance->rx_buffer); + if(!iso14443_crc_check(Iso14443CrcTypeB, instance->rx_buffer)) { + ret = Iso14443_3bErrorWrongCrc; + break; + } + + iso14443_crc_trim(rx_buffer); + } while(false); + + return ret; +} + +Iso14443_3bError + iso14443_3b_poller_async_activate(Iso14443_3bPoller* instance, Iso14443_3bData* data) { + furi_assert(instance); + furi_assert(instance->nfc); + + iso14443_3b_reset(instance->data); + + Iso14443_3bError ret; + + do { + instance->state = Iso14443_3bPollerStateColResInProgress; + + bit_buffer_reset(instance->tx_buffer); + bit_buffer_reset(instance->rx_buffer); + + // Send REQB + bit_buffer_append_byte(instance->tx_buffer, 0x05); + bit_buffer_append_byte(instance->tx_buffer, 0x00); + bit_buffer_append_byte(instance->tx_buffer, 0x08); + + ret = iso14443_3b_poller_frame_exchange( + instance, instance->tx_buffer, instance->rx_buffer, ISO14443_3B_FDT_POLL_FC); + if(ret != Iso14443_3bErrorNone) { + instance->state = Iso14443_3bPollerStateColResFailed; + break; + } + + if(bit_buffer_get_size_bytes(instance->rx_buffer) != sizeof(Iso14443_3bAtqB)) { + FURI_LOG_D(TAG, "Unexpected REQB response"); + instance->state = Iso14443_3bPollerStateColResFailed; + ret = Iso14443_3bErrorCommunication; + break; + } + + instance->state = Iso14443_3bPollerStateActivationInProgress; + + const Iso14443_3bAtqB* atqb = + (const Iso14443_3bAtqB*)bit_buffer_get_data(instance->rx_buffer); + + memcpy(instance->data->uid, atqb->uid, ISO14443_3B_UID_SIZE); + memcpy(instance->data->app_data, atqb->app_data, ISO14443_3B_APP_DATA_SIZE); + memcpy(instance->data->protocol_info, atqb->protocol_info, ISO14443_3B_PROTOCOL_INFO_SIZE); + + bit_buffer_reset(instance->tx_buffer); + bit_buffer_reset(instance->rx_buffer); + + // Send ATTRIB + bit_buffer_append_byte(instance->tx_buffer, 0x1d); + bit_buffer_append_bytes(instance->tx_buffer, atqb->uid, ISO14443_3B_UID_SIZE); + bit_buffer_append_byte(instance->tx_buffer, 0x00); + bit_buffer_append_byte(instance->tx_buffer, ISO14443_3B_ATTRIB_FRAME_SIZE_256); + bit_buffer_append_byte(instance->tx_buffer, 0x01); + bit_buffer_append_byte(instance->tx_buffer, 0x00); + + ret = iso14443_3b_poller_frame_exchange( + instance, instance->tx_buffer, instance->rx_buffer, ISO14443_3B_FDT_ATTRIB_FC); + if(ret != Iso14443_3bErrorNone) { + instance->state = Iso14443_3bPollerStateActivationFailed; + break; + } + + if(bit_buffer_get_size_bytes(instance->rx_buffer) != 1 || + bit_buffer_get_byte(instance->rx_buffer, 0) != 0) { + FURI_LOG_D(TAG, "Unexpected ATTRIB response"); + instance->state = Iso14443_3bPollerStateActivationFailed; + ret = Iso14443_3bErrorCommunication; + break; + } + + instance->state = Iso14443_3bPollerStateActivated; + + if(data) { + iso14443_3b_copy(data, instance->data); + } + + } while(false); + + return ret; +} + +Iso14443_3bError iso14443_3b_poller_halt(Iso14443_3bPoller* instance) { + furi_assert(instance); + + bit_buffer_reset(instance->tx_buffer); + bit_buffer_reset(instance->rx_buffer); + + bit_buffer_append_byte(instance->tx_buffer, 0x50); + bit_buffer_append_bytes(instance->tx_buffer, instance->data->uid, ISO14443_3B_UID_SIZE); + + Iso14443_3bError ret; + + do { + ret = iso14443_3b_poller_frame_exchange( + instance, instance->tx_buffer, instance->rx_buffer, ISO14443_3B_FDT_POLL_FC); + if(ret != Iso14443_3bErrorNone) { + break; + } + + if(bit_buffer_get_size_bytes(instance->rx_buffer) != sizeof(uint8_t) || + bit_buffer_get_byte(instance->rx_buffer, 0) != 0) { + ret = Iso14443_3bErrorCommunication; + break; + } + + instance->state = Iso14443_3bPollerStateIdle; + } while(false); + + return ret; +} + +Iso14443_3bError iso14443_3b_poller_send_frame( + Iso14443_3bPoller* instance, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer, + uint32_t fwt) { + Iso14443_3bError ret; + + do { + ret = iso14443_3b_poller_prepare_trx(instance); + if(ret != Iso14443_3bErrorNone) break; + + ret = iso14443_3b_poller_frame_exchange(instance, tx_buffer, rx_buffer, fwt); + } while(false); + + return ret; +} diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.h b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.h new file mode 100644 index 000000000000..898378ac3604 --- /dev/null +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.h @@ -0,0 +1,51 @@ +#pragma once + +#include "iso14443_3b_poller.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ISO14443_3B_POLLER_MAX_BUFFER_SIZE (256U) + +typedef enum { + Iso14443_3bPollerStateIdle, + Iso14443_3bPollerStateColResInProgress, + Iso14443_3bPollerStateColResFailed, + Iso14443_3bPollerStateActivationInProgress, + Iso14443_3bPollerStateActivationFailed, + Iso14443_3bPollerStateActivated, +} Iso14443_3bPollerState; + +struct Iso14443_3bPoller { + Nfc* nfc; + Iso14443_3bPollerState state; + Iso14443_3bData* data; + BitBuffer* tx_buffer; + BitBuffer* rx_buffer; + + NfcGenericEvent general_event; + Iso14443_3bPollerEvent iso14443_3b_event; + Iso14443_3bPollerEventData iso14443_3b_event_data; + NfcGenericCallback callback; + void* context; +}; + +const Iso14443_3bData* iso14443_3b_poller_get_data(Iso14443_3bPoller* instance); + +Iso14443_3bError + iso14443_3b_poller_async_activate(Iso14443_3bPoller* instance, Iso14443_3bData* data); + +Iso14443_3bError iso14443_3b_poller_halt(Iso14443_3bPoller* instance); + +Iso14443_3bError iso14443_3b_poller_send_frame( + Iso14443_3bPoller* instance, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer, + uint32_t fwt); + +#ifdef __cplusplus +} +#endif diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a.c b/lib/nfc/protocols/iso14443_4a/iso14443_4a.c index 992682931daa..68632af101c2 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a.c +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a.c @@ -3,7 +3,7 @@ #include #define ISO14443_4A_PROTOCOL_NAME "ISO14443-4A" -#define ISO14443_4A_DEVICE_NAME "Unknown ISO14443-4A Tag" +#define ISO14443_4A_DEVICE_NAME "ISO14443-4A (Unknown)" #define ISO14443_4A_ATS_BIT (1U << 5) #define ISO14443_4A_ATS_KEY "ATS" @@ -20,6 +20,7 @@ const NfcDeviceBase nfc_device_iso14443_4a = { .is_equal = (NfcDeviceEqual)iso14443_4a_is_equal, .get_name = (NfcDeviceGetName)iso14443_4a_get_device_name, .get_uid = (NfcDeviceGetUid)iso14443_4a_get_uid, + .set_uid = (NfcDeviceSetUid)iso14443_4a_set_uid, .get_base_data = (NfcDeviceGetBaseData)iso14443_4a_get_base_data, }; @@ -125,6 +126,12 @@ const uint8_t* iso14443_4a_get_uid(const Iso14443_4aData* data, size_t* uid_len) return iso14443_3a_get_uid(data->iso14443_3a_data, uid_len); } +bool iso14443_4a_set_uid(Iso14443_4aData* data, const uint8_t* uid, size_t uid_len) { + furi_assert(data); + + return iso14443_3a_set_uid(data->iso14443_3a_data, uid, uid_len); +} + const Iso14443_3aData* iso14443_4a_get_base_data(const Iso14443_4aData* data) { furi_assert(data); diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a.h b/lib/nfc/protocols/iso14443_4a/iso14443_4a.h index 9b6feb29cc19..75da18ed1ea2 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a.h +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a.h @@ -44,6 +44,8 @@ const char* iso14443_4a_get_device_name(const Iso14443_4aData* data, NfcDeviceNa const uint8_t* iso14443_4a_get_uid(const Iso14443_4aData* data, size_t* uid_len); +bool iso14443_4a_set_uid(Iso14443_4aData* data, const uint8_t* uid, size_t uid_len); + const Iso14443_3aData* iso14443_4a_get_base_data(const Iso14443_4aData* data); // Getters & Tests diff --git a/lib/nfc/protocols/mf_classic/mf_classic.c b/lib/nfc/protocols/mf_classic/mf_classic.c index 1f5c6dc34929..71d3e5147d02 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic.c +++ b/lib/nfc/protocols/mf_classic/mf_classic.c @@ -52,6 +52,7 @@ const NfcDeviceBase nfc_device_mf_classic = { .is_equal = (NfcDeviceEqual)mf_classic_is_equal, .get_name = (NfcDeviceGetName)mf_classic_get_device_name, .get_uid = (NfcDeviceGetUid)mf_classic_get_uid, + .set_uid = (NfcDeviceSetUid)mf_classic_set_uid, .get_base_data = (NfcDeviceGetBaseData)mf_classic_get_base_data, }; @@ -342,6 +343,12 @@ const uint8_t* mf_classic_get_uid(const MfClassicData* data, size_t* uid_len) { return iso14443_3a_get_uid(data->iso14443_3a_data, uid_len); } +bool mf_classic_set_uid(MfClassicData* data, const uint8_t* uid, size_t uid_len) { + furi_assert(data); + + return iso14443_3a_set_uid(data->iso14443_3a_data, uid, uid_len); +} + const Iso14443_3aData* mf_classic_get_base_data(const MfClassicData* data) { furi_assert(data); diff --git a/lib/nfc/protocols/mf_classic/mf_classic.h b/lib/nfc/protocols/mf_classic/mf_classic.h index 0601042dfe53..312cb7ed3618 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic.h +++ b/lib/nfc/protocols/mf_classic/mf_classic.h @@ -157,6 +157,8 @@ const char* mf_classic_get_device_name(const MfClassicData* data, NfcDeviceNameT const uint8_t* mf_classic_get_uid(const MfClassicData* data, size_t* uid_len); +bool mf_classic_set_uid(MfClassicData* data, const uint8_t* uid, size_t uid_len); + const Iso14443_3aData* mf_classic_get_base_data(const MfClassicData* data); bool mf_classic_detect_protocol(Iso14443_3aData* data, MfClassicType* type); diff --git a/lib/nfc/protocols/mf_classic/mf_classic_listener.c b/lib/nfc/protocols/mf_classic/mf_classic_listener.c index 4ca586f56869..bce8d2656475 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_listener.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_listener.c @@ -1,6 +1,9 @@ #include "mf_classic_listener_i.h" -#include "mf_classic_listener_defs.h" -#include + +#include + +#include +#include #include #include @@ -214,7 +217,7 @@ static MfClassicListenerCommand bit_buffer_copy_bytes( instance->tx_plain_buffer, access_block.data, sizeof(MfClassicBlock)); - iso14443_3a_append_crc(instance->tx_plain_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_plain_buffer); crypto1_encrypt( instance->crypto, NULL, instance->tx_plain_buffer, instance->tx_encrypted_buffer); iso14443_3a_listener_tx_with_custom_parity( diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller_i.c b/lib/nfc/protocols/mf_classic/mf_classic_poller_i.c index 6bb6afd3648e..958565f6146d 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller_i.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller_i.c @@ -3,6 +3,8 @@ #include #include +#include + #define TAG "MfCLassicPoller" #define MF_CLASSIC_FWT_FC (60000) @@ -117,7 +119,7 @@ MfClassicError mf_classic_aync_halt(MfClassicPoller* instance) { do { uint8_t halt_cmd[2] = {MF_CLASSIC_CMD_HALT_MSB, MF_CLASSIC_CMD_HALT_LSB}; bit_buffer_copy_bytes(instance->tx_plain_buffer, halt_cmd, sizeof(halt_cmd)); - iso14443_3a_append_crc(instance->tx_plain_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_plain_buffer); crypto1_encrypt( instance->crypto, NULL, instance->tx_plain_buffer, instance->tx_encrypted_buffer); @@ -148,7 +150,7 @@ MfClassicError mf_classic_async_read_block( do { uint8_t read_block_cmd[2] = {MF_CLASSIC_CMD_READ_BLOCK, block_num}; bit_buffer_copy_bytes(instance->tx_plain_buffer, read_block_cmd, sizeof(read_block_cmd)); - iso14443_3a_append_crc(instance->tx_plain_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_plain_buffer); crypto1_encrypt( instance->crypto, NULL, instance->tx_plain_buffer, instance->tx_encrypted_buffer); @@ -171,13 +173,13 @@ MfClassicError mf_classic_async_read_block( crypto1_decrypt( instance->crypto, instance->rx_encrypted_buffer, instance->rx_plain_buffer); - if(!iso14443_3a_check_crc(instance->rx_plain_buffer)) { + if(!iso14443_crc_check(Iso14443CrcTypeA, instance->rx_plain_buffer)) { FURI_LOG_D(TAG, "CRC error"); ret = MfClassicErrorProtocol; break; } - iso14443_3a_trim_crc(instance->rx_plain_buffer); + iso14443_crc_trim(instance->rx_plain_buffer); bit_buffer_write_bytes(instance->rx_plain_buffer, data->data, sizeof(MfClassicBlock)); } while(false); @@ -194,7 +196,7 @@ MfClassicError mf_classic_async_write_block( do { uint8_t write_block_cmd[2] = {MF_CLASSIC_CMD_WRITE_BLOCK, block_num}; bit_buffer_copy_bytes(instance->tx_plain_buffer, write_block_cmd, sizeof(write_block_cmd)); - iso14443_3a_append_crc(instance->tx_plain_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_plain_buffer); crypto1_encrypt( instance->crypto, NULL, instance->tx_plain_buffer, instance->tx_encrypted_buffer); @@ -223,7 +225,7 @@ MfClassicError mf_classic_async_write_block( } bit_buffer_copy_bytes(instance->tx_plain_buffer, data->data, sizeof(MfClassicBlock)); - iso14443_3a_append_crc(instance->tx_plain_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_plain_buffer); crypto1_encrypt( instance->crypto, NULL, instance->tx_plain_buffer, instance->tx_encrypted_buffer); @@ -274,7 +276,7 @@ MfClassicError mf_classic_async_value_cmd( } uint8_t value_cmd[2] = {cmd_value, block_num}; bit_buffer_copy_bytes(instance->tx_plain_buffer, value_cmd, sizeof(value_cmd)); - iso14443_3a_append_crc(instance->tx_plain_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_plain_buffer); crypto1_encrypt( instance->crypto, NULL, instance->tx_plain_buffer, instance->tx_encrypted_buffer); @@ -305,7 +307,7 @@ MfClassicError mf_classic_async_value_cmd( uint8_t data_arr[4] = {}; memcpy(data_arr, &data, sizeof(int32_t)); bit_buffer_copy_bytes(instance->tx_plain_buffer, data_arr, sizeof(data_arr)); - iso14443_3a_append_crc(instance->tx_plain_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_plain_buffer); crypto1_encrypt( instance->crypto, NULL, instance->tx_plain_buffer, instance->tx_encrypted_buffer); @@ -334,7 +336,7 @@ MfClassicError mf_classic_async_value_transfer(MfClassicPoller* instance, uint8_ do { uint8_t transfer_cmd[2] = {MF_CLASSIC_CMD_VALUE_TRANSFER, block_num}; bit_buffer_copy_bytes(instance->tx_plain_buffer, transfer_cmd, sizeof(transfer_cmd)); - iso14443_3a_append_crc(instance->tx_plain_buffer); + iso14443_crc_append(Iso14443CrcTypeA, instance->tx_plain_buffer); crypto1_encrypt( instance->crypto, NULL, instance->tx_plain_buffer, instance->tx_encrypted_buffer); diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire.c b/lib/nfc/protocols/mf_desfire/mf_desfire.c index 0c5709c5b645..ec5c626bc355 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire.c +++ b/lib/nfc/protocols/mf_desfire/mf_desfire.c @@ -16,6 +16,7 @@ const NfcDeviceBase nfc_device_mf_desfire = { .is_equal = (NfcDeviceEqual)mf_desfire_is_equal, .get_name = (NfcDeviceGetName)mf_desfire_get_device_name, .get_uid = (NfcDeviceGetUid)mf_desfire_get_uid, + .set_uid = (NfcDeviceSetUid)mf_desfire_set_uid, .get_base_data = (NfcDeviceGetBaseData)mf_desfire_get_base_data, }; @@ -226,6 +227,12 @@ const uint8_t* mf_desfire_get_uid(const MfDesfireData* data, size_t* uid_len) { return iso14443_4a_get_uid(data->iso14443_4a_data, uid_len); } +bool mf_desfire_set_uid(MfDesfireData* data, const uint8_t* uid, size_t uid_len) { + furi_assert(data); + + return iso14443_4a_set_uid(data->iso14443_4a_data, uid, uid_len); +} + const Iso14443_4aData* mf_desfire_get_base_data(const MfDesfireData* data) { furi_assert(data); diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire.h b/lib/nfc/protocols/mf_desfire/mf_desfire.h index 977c05121458..ae804c151e3d 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire.h +++ b/lib/nfc/protocols/mf_desfire/mf_desfire.h @@ -171,6 +171,8 @@ const char* mf_desfire_get_device_name(const MfDesfireData* data, NfcDeviceNameT const uint8_t* mf_desfire_get_uid(const MfDesfireData* data, size_t* uid_len); +bool mf_desfire_set_uid(MfDesfireData* data, const uint8_t* uid, size_t uid_len); + const Iso14443_4aData* mf_desfire_get_base_data(const MfDesfireData* data); // Getters and tests diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c index 9138cc8fae8b..7f068dab7349 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c @@ -152,6 +152,7 @@ const NfcDeviceBase nfc_device_mf_ultralight = { .is_equal = (NfcDeviceEqual)mf_ultralight_is_equal, .get_name = (NfcDeviceGetName)mf_ultralight_get_device_name, .get_uid = (NfcDeviceGetUid)mf_ultralight_get_uid, + .set_uid = (NfcDeviceSetUid)mf_ultralight_set_uid, .get_base_data = (NfcDeviceGetBaseData)mf_ultralight_get_base_data, }; @@ -467,6 +468,12 @@ const uint8_t* mf_ultralight_get_uid(const MfUltralightData* data, size_t* uid_l return iso14443_3a_get_uid(data->iso14443_3a_data, uid_len); } +bool mf_ultralight_set_uid(MfUltralightData* data, const uint8_t* uid, size_t uid_len) { + furi_assert(data); + + return iso14443_3a_set_uid(data->iso14443_3a_data, uid, uid_len); +} + const Iso14443_3aData* mf_ultralight_get_base_data(const MfUltralightData* data) { furi_assert(data); diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h index 3df841043ed8..4fca4cda30ce 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h @@ -188,6 +188,8 @@ const char* const uint8_t* mf_ultralight_get_uid(const MfUltralightData* data, size_t* uid_len); +bool mf_ultralight_set_uid(MfUltralightData* data, const uint8_t* uid, size_t uid_len); + const Iso14443_3aData* mf_ultralight_get_base_data(const MfUltralightData* data); MfUltralightType mf_ultralight_get_type_by_version(MfUltralightVersion* version); diff --git a/lib/nfc/protocols/nfc_device_base_i.h b/lib/nfc/protocols/nfc_device_base_i.h index ee6569459bc5..d4212f693435 100644 --- a/lib/nfc/protocols/nfc_device_base_i.h +++ b/lib/nfc/protocols/nfc_device_base_i.h @@ -18,6 +18,7 @@ typedef bool (*NfcDeviceSave)(const NfcDeviceData* data, FlipperFormat* ff); typedef bool (*NfcDeviceEqual)(const NfcDeviceData* data, const NfcDeviceData* other); typedef const char* (*NfcDeviceGetName)(const NfcDeviceData* data, NfcDeviceNameType name_type); typedef const uint8_t* (*NfcDeviceGetUid)(const NfcDeviceData* data, size_t* uid_len); +typedef bool (*NfcDeviceSetUid)(NfcDeviceData* data, const uint8_t* uid, size_t uid_len); typedef const NfcDeviceData* (*NfcDeviceGetBaseData)(const NfcDeviceData* data); typedef struct { @@ -32,6 +33,7 @@ typedef struct { NfcDeviceEqual is_equal; NfcDeviceGetName get_name; NfcDeviceGetUid get_uid; + NfcDeviceSetUid set_uid; NfcDeviceGetBaseData get_base_data; } NfcDeviceBase; diff --git a/lib/nfc/protocols/nfc_device_defs.c b/lib/nfc/protocols/nfc_device_defs.c index 6095206aaff3..49b5031ddf49 100644 --- a/lib/nfc/protocols/nfc_device_defs.c +++ b/lib/nfc/protocols/nfc_device_defs.c @@ -3,6 +3,7 @@ #include "nfc_protocol.h" #include +#include #include #include #include @@ -10,6 +11,7 @@ const NfcDeviceBase* nfc_devices[NfcProtocolNum] = { [NfcProtocolIso14443_3a] = &nfc_device_iso14443_3a, + [NfcProtocolIso14443_3b] = &nfc_device_iso14443_3b, [NfcProtocolIso14443_4a] = &nfc_device_iso14443_4a, [NfcProtocolMfUltralight] = &nfc_device_mf_ultralight, [NfcProtocolMfClassic] = &nfc_device_mf_classic, diff --git a/lib/nfc/protocols/nfc_poller_defs.c b/lib/nfc/protocols/nfc_poller_defs.c index e54320e2bb7b..0c2603b90c4c 100644 --- a/lib/nfc/protocols/nfc_poller_defs.c +++ b/lib/nfc/protocols/nfc_poller_defs.c @@ -1,6 +1,7 @@ #include "nfc_poller_defs.h" #include +#include #include #include #include @@ -8,8 +9,10 @@ const NfcPollerBase* nfc_pollers_api[NfcProtocolNum] = { [NfcProtocolIso14443_3a] = &nfc_poller_iso14443_3a, + [NfcProtocolIso14443_3b] = &nfc_poller_iso14443_3b, [NfcProtocolIso14443_4a] = &nfc_poller_iso14443_4a, [NfcProtocolMfUltralight] = &mf_ultralight_poller, [NfcProtocolMfClassic] = &mf_classic_poller, [NfcProtocolMfDesfire] = &mf_desfire_poller, + /* Add new pollers here */ }; diff --git a/lib/nfc/protocols/nfc_protocol.c b/lib/nfc/protocols/nfc_protocol.c index 8bb96483fab2..a4ea0ba3fc72 100644 --- a/lib/nfc/protocols/nfc_protocol.c +++ b/lib/nfc/protocols/nfc_protocol.c @@ -9,13 +9,21 @@ typedef struct { } NfcProtocolTreeNode; /**************************** Protocol tree structure **************************** - * _________ start ___________________________ - * / | | \ - * _________ iso14443-3a _______ nfc-b nfc-f nfc-v - * / | \ - * iso14443-4a mf ultralight mf classic - * / \ - * mf desfire bank card + * + * (Start) + * | + * +------------------------+-----------+-------+ + * | | | | + * ISO14443-3A ISO14443-3B NFC-F NFC-V + * | + * +---------------+-------------+ + * | | | + * ISO14443-4A Mf Ultralight Mf Classic + * | + * +-----+-----+ + * | | + * Mf Desfire Bank Card + * */ static const NfcProtocol nfc_protocol_iso14443_3a_children_protocol[] = { @@ -34,6 +42,12 @@ static const NfcProtocolTreeNode nfc_protocol_nodes[NfcProtocolNum] = { .children_num = COUNT_OF(nfc_protocol_iso14443_3a_children_protocol), .children_protocol = nfc_protocol_iso14443_3a_children_protocol, }, + [NfcProtocolIso14443_3b] = + { + .parent_protocol = NfcProtocolInvalid, + .children_num = 0, + .children_protocol = NULL, + }, [NfcProtocolIso14443_4a] = { .parent_protocol = NfcProtocolIso14443_3a, diff --git a/lib/nfc/protocols/nfc_protocol.h b/lib/nfc/protocols/nfc_protocol.h index 32ab9dbb1ca4..62f74186ff24 100644 --- a/lib/nfc/protocols/nfc_protocol.h +++ b/lib/nfc/protocols/nfc_protocol.h @@ -8,6 +8,7 @@ extern "C" { typedef enum { NfcProtocolIso14443_3a, + NfcProtocolIso14443_3b, NfcProtocolIso14443_4a, NfcProtocolMfUltralight, NfcProtocolMfClassic, diff --git a/lib/nfc/protocols/nfcb/nfcb.h b/lib/nfc/protocols/nfcb/nfcb.h deleted file mode 100644 index d23d1a6fdb76..000000000000 --- a/lib/nfc/protocols/nfcb/nfcb.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#define NFCB_UID_MAX_SIZE (7) - -// TODO change values -#define NFCB_GUARD_TIME_US (5000) -#define NFCB_FDT_POLL_FC (1620) -#define NFCB_FDT_LISTEN_FC (1172) -#define NFCB_POLLER_MASK_RX_FS ((NFCB_FDT_LISTEN_FC) / 2) -#define NFCB_POLL_POLL_MIN_US (1100) - -typedef enum { - NfcbErrorNone, - NfcbErrorTimeout, -} NfcbError; - -typedef struct { - uint8_t uid[NFCB_UID_MAX_SIZE]; - uint16_t uid_len; -} NfcbData; - -#ifdef __cplusplus -} -#endif diff --git a/lib/nfc/protocols/nfcb/nfcb_poller.c b/lib/nfc/protocols/nfcb/nfcb_poller.c deleted file mode 100644 index 920dfc5abc5d..000000000000 --- a/lib/nfc/protocols/nfcb/nfcb_poller.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "nfcb_poller.h" - -#include - -#define NFCB_POLLER_BUFER_MAX_SIZE (512) - -typedef enum { - NfcbPollerStateIdle, - NfcbPollerColResInProgress, - NfcbPollerColResFailed, - NfcbPollerActivated, -} NfcbPollerState; - -struct NfcbPoller { - Nfc* nfc; - NfcbPollerState state; - NfcbData* data; - NfcbPollerEventCallback callback; - void* context; -}; - -NfcbPoller* nfcb_poller_alloc(Nfc* nfc) { - NfcbPoller* instance = malloc(sizeof(NfcbPoller)); - instance->nfc = nfc; - - return instance; -} - -void nfcb_poller_free(NfcbPoller* instance) { - furi_assert(instance); - - free(instance); -} - -static NfcCommand nfcb_poller_event_callback(NfcEvent event, void* context) { - furi_assert(context); - UNUSED(event); - - NfcbPoller* instance = context; - furi_assert(instance->callback); - - return NfcCommandContinue; -} - -NfcbError - nfcb_poller_start(NfcbPoller* instance, NfcbPollerEventCallback callback, void* context) { - furi_assert(instance); - - instance->callback = callback; - instance->context = context; - - nfc_start_poller(instance->nfc, nfcb_poller_event_callback, instance); - return NfcbErrorNone; -} - -NfcbError nfcb_poller_get_data(NfcbPoller* instance, NfcbData* data) { - furi_assert(instance); - furi_assert(instance->data); - - *data = *instance->data; - return NfcbErrorNone; -} - -NfcbError nfcb_poller_reset(NfcbPoller* instance) { - furi_assert(instance); - furi_assert(instance->nfc); - furi_assert(instance->data); - - nfc_stop(instance->nfc); - - instance->callback = NULL; - instance->context = NULL; - free(instance->data); - instance->data = NULL; - - return NfcbErrorNone; -} - -NfcbError nfcb_poller_config(NfcbPoller* instance) { - furi_assert(instance); - - // instance->data = malloc(sizeof(NfcbData)); - - nfc_config(instance->nfc, NfcModeNfcbPoller); - nfc_set_guard_time_us(instance->nfc, NFCB_GUARD_TIME_US); - nfc_set_fdt_poll_fc(instance->nfc, NFCB_FDT_POLL_FC); - nfc_set_fdt_poll_poll_us(instance->nfc, NFCB_POLL_POLL_MIN_US); - - return NfcbErrorNone; -} - -NfcbError nfcb_poller_activate(NfcbPoller* instance, NfcbData* data) { - furi_assert(instance); - furi_assert(data); - - return NfcbErrorTimeout; -} diff --git a/lib/nfc/protocols/nfcb/nfcb_poller.h b/lib/nfc/protocols/nfcb/nfcb_poller.h deleted file mode 100644 index cd71df783967..000000000000 --- a/lib/nfc/protocols/nfcb/nfcb_poller.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include -#include "nfcb.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct NfcbPoller NfcbPoller; - -typedef enum { - NfcbPollerEventTypeError, - NfcbPollerEventDetected, - NfcbPollerEventTypeReady, -} NfcbPollerEventType; - -typedef struct { - NfcbError error; -} NfcbPollerEventData; - -typedef struct { - NfcbPollerEventType type; - NfcbPollerEventData data; -} NfcbPollerEvent; - -typedef enum { - NfcbPollerCommandContinue = NfcCommandContinue, - NfcbPollerCommandReset = NfcCommandReset, - NfcbPollerCommandStop = NfcCommandStop, -} NfcbPollerCommand; - -typedef NfcbPollerCommand (*NfcbPollerEventCallback)(NfcbPollerEvent* event, void* context); - -NfcbPoller* nfcb_poller_alloc(Nfc* nfc); - -void nfcb_poller_free(NfcbPoller* instance); - -NfcbError nfcb_poller_start(NfcbPoller* instance, NfcbPollerEventCallback callback, void* context); - -NfcbError nfcb_poller_get_data(NfcbPoller* instance, NfcbData* data); - -NfcbError nfcb_poller_reset(NfcbPoller* instance); - -NfcbError nfcb_poller_config(NfcbPoller* instance); - -NfcbError nfcb_poller_activate(NfcbPoller* instance, NfcbData* data); - -#ifdef __cplusplus -} -#endif diff --git a/lib/nfc/protocols/nfcb/nfcb_poller_i.c b/lib/nfc/protocols/nfcb/nfcb_poller_i.c deleted file mode 100644 index 9bd10a6ccddd..000000000000 --- a/lib/nfc/protocols/nfcb/nfcb_poller_i.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "nfcb_poller_i.h" - -const NfcPollerBase nfcb_protocol_base = { - .alloc = NULL, - .free = NULL, -}; \ No newline at end of file