diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c50fc825..5f94135d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### Added: - Apps: + - NFC: ISO 15693-3 NFC Writer (by @ch4istO) - Sub-GHz: ProtoPirate (by @RocketGod-git & @xMasterX & @zero-mega et al.) - Sub-GHz: - UL: Cardin S449 protocol full support (64bit keeloq) (with Add manually, and all button codes) (use FSK12K modulation to read the remote) (by @xMasterX & @zero-mega) @@ -31,6 +32,7 @@ - UL: Alutech AT-4N & Nice Flor S turbo speedup (by @Dmitry422) - UL: Sommer fm2 in Add manually now uses FM12K modulation (Sommer without fm2 tag uses FM476) (try this if regular option doesn't work for you) (by @xMasterX) - UL: Replaced Cars ignore option with Revers RB2 protocol ignore option (by @xMasterX) +- Archive: Support opening and pinning ProtoPirate files from Archive (#510 by @LeeroysHub) ### Fixed: - Sub-GHz: @@ -38,7 +40,11 @@ - UL: Possible Sommer timings fix (by @xMasterX) - UL: Various fixes (by @xMasterX) - UL: Nice Flor S remove extra uint64 variable (by @xMasterX) -- UL: NFC: Fix LED not blinking at SLIX unlock (by @xMasterX) +- NFC: + - Fix sending 32+ byte ISO 15693-3 commands (by @WillyJL) + - Fixes to `READ_MULTI` and `GET_BLOCK_SECURITY` commands in ISO 15693-3 emulation (#501 by @WillyJL & aaronjamt) + - UL: Fix LED not blinking at SLIX unlock (by @xMasterX) +- UL: UI: Some small changes (by @xMasterX) ### Removed: - Sub-GHz: diff --git a/applications/external b/applications/external index d52c118c8..e9230bc08 160000 --- a/applications/external +++ b/applications/external @@ -1 +1 @@ -Subproject commit d52c118c825dd86c41c02943b34ae4529e4d3605 +Subproject commit e9230bc089ae26094a9cba4614815c36532fc964 diff --git a/applications/main/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h index ba3510ca1..3a6d13e81 100644 --- a/applications/main/archive/helpers/archive_browser.h +++ b/applications/main/archive/helpers/archive_browser.h @@ -45,6 +45,7 @@ static const char* const known_ext[] = { [ArchiveFileTypeUpdateManifest] = ".fuf", [ArchiveFileTypeDiskImage] = ".img", [ArchiveFileTypeFolder] = "?", + [ArchiveFileTypeProtoPirate] = ".psf", [ArchiveFileTypeUnknown] = "*", [ArchiveFileTypeAppOrJs] = ".fap|.js", [ArchiveFileTypeSetting] = "?", diff --git a/applications/main/archive/helpers/archive_files.h b/applications/main/archive/helpers/archive_files.h index 65e3beb13..c3566b994 100644 --- a/applications/main/archive/helpers/archive_files.h +++ b/applications/main/archive/helpers/archive_files.h @@ -31,6 +31,7 @@ typedef enum { ArchiveFileTypeDiskImage, ArchiveFileTypeFolder, ArchiveFileTypeSetting, + ArchiveFileTypeProtoPirate, ArchiveFileTypeUnknown, ArchiveFileTypeAppOrJs, ArchiveFileTypeLoading, diff --git a/applications/main/archive/scenes/archive_scene_browser.c b/applications/main/archive/scenes/archive_scene_browser.c index d7a8c3c40..0082737b8 100644 --- a/applications/main/archive/scenes/archive_scene_browser.c +++ b/applications/main/archive/scenes/archive_scene_browser.c @@ -29,6 +29,8 @@ const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) { return EXT_PATH("apps/Sub-Ghz/subghz_playlist.fap"); case ArchiveFileTypeSubghzRemote: return EXT_PATH("apps/Sub-Ghz/subghz_remote.fap"); + case ArchiveFileTypeProtoPirate: + return EXT_PATH("apps/Sub-Ghz/proto_pirate.fap"); case ArchiveFileTypeInfraredRemote: return EXT_PATH("apps/Infrared/ir_remote.fap"); case ArchiveFileTypeBadUsb: diff --git a/applications/main/archive/views/archive_browser_view.c b/applications/main/archive/views/archive_browser_view.c index 961d6ee4f..b454dbc30 100644 --- a/applications/main/archive/views/archive_browser_view.c +++ b/applications/main/archive/views/archive_browser_view.c @@ -48,6 +48,7 @@ static const Icon* ArchiveItemIcons[] = { [ArchiveFileTypeSearch] = &I_search_10px, [ArchiveFileTypeUpdateManifest] = &I_update_10px, [ArchiveFileTypeDiskImage] = &I_floppydisk_10px, + [ArchiveFileTypeProtoPirate] = &I_protopirate_10px, [ArchiveFileTypeFolder] = &I_dir_10px, [ArchiveFileTypeUnknown] = &I_unknown_10px, [ArchiveFileTypeLoading] = &I_loading_10px, diff --git a/applications/main/nfc/helpers/protocol_support/felica/felica.c b/applications/main/nfc/helpers/protocol_support/felica/felica.c index 26dc86d41..0c98e7ffc 100644 --- a/applications/main/nfc/helpers/protocol_support/felica/felica.c +++ b/applications/main/nfc/helpers/protocol_support/felica/felica.c @@ -105,9 +105,7 @@ static void nfc_scene_read_success_on_enter_felica(NfcApp* instance) { if(data->workflow_type == FelicaLite) { bool all_unlocked = data->blocks_read == data->blocks_total; furi_string_cat_printf( - temp_str, - "\e#%s\n", - all_unlocked ? "All Blocks Are Unlocked" : "Some Blocks Are Locked"); + temp_str, "\e#%s\n", all_unlocked ? "All Blocks Unlocked" : "Some Blocks Locked"); nfc_render_felica_idm(data, NfcProtocolFormatTypeShort, temp_str); uint8_t* ck_data = instance->felica_auth->card_key.data; furi_string_cat_printf(temp_str, "Key:"); diff --git a/applications/main/nfc/scenes/nfc_scene_slix_unlock.c b/applications/main/nfc/scenes/nfc_scene_slix_unlock.c index f6e5a8f50..21305c58d 100644 --- a/applications/main/nfc/scenes/nfc_scene_slix_unlock.c +++ b/applications/main/nfc/scenes/nfc_scene_slix_unlock.c @@ -35,7 +35,7 @@ void nfc_scene_slix_unlock_on_enter(void* context) { instance->popup, "Hold card next\nto Flipper's back", 94, 27, AlignCenter, AlignTop); view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup); - notification_message(instance->notifications, &sequence_blink_start_cyan); + notification_message(instance->notifications, &sequence_blink_start_yellow); instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolSlix); nfc_poller_start(instance->poller, nfc_scene_slix_unlock_worker_callback, instance); diff --git a/assets/icons/Archive/protopirate_10px.png b/assets/icons/Archive/protopirate_10px.png new file mode 100644 index 000000000..ba5e7ccbc Binary files /dev/null and b/assets/icons/Archive/protopirate_10px.png differ diff --git a/documentation/SubGHzSupportedSystems.md b/documentation/SubGHzSupportedSystems.md index 647c25163..2351531e9 100644 --- a/documentation/SubGHzSupportedSystems.md +++ b/documentation/SubGHzSupportedSystems.md @@ -125,7 +125,7 @@ The following manufacturers have KeeLoq support in Unleashed firmware: - Nice Smilo - `433.92MHz` `AM650` (KeeLoq, 64 bits) (8bit serial part in Hop - simple learning) - Normstahl - `433.92MHz` `AM650` (KeeLoq, 64 bits) - Novoferm - `433.92MHz` `AM650` (KeeLoq, 64 bits) -- Sommer `434.42MHz, 868.80MHz` `FSK12K (or FSK476)` (KeeLoq, 64 bits) (normal learning) (TX03-868-4, Pearl, and maybe other models are supported (SOMloq2)) +- Sommer `434.42MHz, 868.80MHz` `FSK12K (or FSK476)` (KeeLoq, 64 bits) (normal learning) (TX03-868-4, Pearl, and maybe other models are supported (SOMloq)) - Steelmate - `433.92MHz` `AM650` (KeeLoq, 64 bits) (12bit serial part in Hop - normal learning) - Stilmatic - `433.92MHz` `AM650` (KeeLoq, 64 bits) (normal learning) diff --git a/lib/digital_signal/presets/nfc/iso15693_signal.c b/lib/digital_signal/presets/nfc/iso15693_signal.c index 43066b5bf..560a393a0 100644 --- a/lib/digital_signal/presets/nfc/iso15693_signal.c +++ b/lib/digital_signal/presets/nfc/iso15693_signal.c @@ -2,8 +2,12 @@ #include +#include + #define BITS_IN_BYTE (8U) +#define ISO15693_SIGNAL_BUFFER_SIZE (ISO15693_3_LISTENER_BUFFER_SIZE * BITS_IN_BYTE + 2) + #define ISO15693_SIGNAL_COEFF_HI (1U) #define ISO15693_SIGNAL_COEFF_LO (4U) @@ -151,7 +155,7 @@ Iso15693Signal* iso15693_signal_alloc(const GpioPin* pin) { Iso15693Signal* instance = malloc(sizeof(Iso15693Signal)); - instance->tx_sequence = digital_sequence_alloc(BITS_IN_BYTE * 255 + 2, pin); + instance->tx_sequence = digital_sequence_alloc(ISO15693_SIGNAL_BUFFER_SIZE, pin); for(uint32_t i = 0; i < Iso15693SignalDataRateNum; ++i) { iso15693_signal_bank_fill(instance, i); diff --git a/lib/nfc/protocols/iso15693_3/iso15693_3_listener.c b/lib/nfc/protocols/iso15693_3/iso15693_3_listener.c index 151e4ae4a..2d1d053c3 100644 --- a/lib/nfc/protocols/iso15693_3/iso15693_3_listener.c +++ b/lib/nfc/protocols/iso15693_3/iso15693_3_listener.c @@ -8,8 +8,6 @@ #define TAG "Iso15693_3Listener" -#define ISO15693_3_LISTENER_BUFFER_SIZE (256U) - Iso15693_3Listener* iso15693_3_listener_alloc(Nfc* nfc, Iso15693_3Data* data) { furi_assert(nfc); diff --git a/lib/nfc/protocols/iso15693_3/iso15693_3_listener_i.c b/lib/nfc/protocols/iso15693_3/iso15693_3_listener_i.c index 6132fbf47..1e0f65bfd 100644 --- a/lib/nfc/protocols/iso15693_3/iso15693_3_listener_i.c +++ b/lib/nfc/protocols/iso15693_3/iso15693_3_listener_i.c @@ -263,8 +263,9 @@ static Iso15693_3Error iso15693_3_listener_read_multi_blocks_handler( const uint32_t block_index_start = request->first_block_num; const uint32_t block_index_end = - MIN((block_index_start + request->block_count + 1), + MIN((block_index_start + request->block_count), ((uint32_t)instance->data->system_info.block_count - 1)); + const uint32_t block_count = block_index_end - block_index_start + 1; error = iso15693_3_listener_extension_handler( instance, @@ -273,8 +274,21 @@ static Iso15693_3Error iso15693_3_listener_read_multi_blocks_handler( (uint32_t)block_index_end); if(error != Iso15693_3ErrorNone) break; + const bool include_block_security = (flags & ISO15693_3_REQ_FLAG_T4_OPTION) != 0; + const uint8_t bytes_per_block = + (include_block_security ? 1 : 0) + instance->data->system_info.block_size; + const uint32_t response_data_max = + bit_buffer_get_capacity_bytes(instance->tx_buffer) - 1 - 2; // Flags and CRC + const uint32_t response_blocks_max = response_data_max / bytes_per_block; + if(block_count > response_blocks_max) { + // Tested on SLIX2, if asked for more blocks than supported at once there is no reply + // Let's do the same + error = Iso15693_3ErrorIgnore; + break; + } + for(uint32_t i = block_index_start; i <= block_index_end; ++i) { - if(flags & ISO15693_3_REQ_FLAG_T4_OPTION) { + if(include_block_security) { iso15693_3_append_block_security( instance->data, i, instance->tx_buffer); // Block security (optional) } @@ -341,7 +355,7 @@ static Iso15693_3Error iso15693_3_listener_write_multi_blocks_handler( if(error != Iso15693_3ErrorNone) break; - for(uint32_t i = block_index_start; i < block_count + request->first_block_num; ++i) { + for(uint32_t i = block_index_start; i <= block_index_end; ++i) { const uint8_t* block_data = &request->block_data[block_size * i]; iso15693_3_set_block_data(instance->data, i, block_data, block_size); } diff --git a/lib/nfc/protocols/iso15693_3/iso15693_3_listener_i.h b/lib/nfc/protocols/iso15693_3/iso15693_3_listener_i.h index a9e0822bf..24a2d1cf0 100644 --- a/lib/nfc/protocols/iso15693_3/iso15693_3_listener_i.h +++ b/lib/nfc/protocols/iso15693_3/iso15693_3_listener_i.h @@ -10,6 +10,18 @@ extern "C" { #endif +// Based on GET_BLOCKS_SECURITY, one of the commands with lengthier responses: +// - 1 byte flags +// - 1 byte security status * 256 max block count +// - 2 byte crc +// for a response size of 259 bytes. +// There is also READ_MULTI_BLOCKS which has no explicit limit on requested block count +// and ISO 15693-3 also does not specify a maximum overall response length, so this command could +// theoretically result in a 8195 byte response (1 byte flags + 32 byte block * 256 blocks + 2 byte crc); +// for practicality we use a sufficient buffer for a full GET_BLOCKS_SECURITY and +// limit READ_MULTI_BLOCKS to how many blocks we can fit into that buffer size. +#define ISO15693_3_LISTENER_BUFFER_SIZE (259U) + typedef enum { Iso15693_3ListenerStateReady, Iso15693_3ListenerStateSelected, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index f96af9256..2d8f342d3 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -4321,6 +4321,7 @@ Variable,+,I_power_text_24x5,const Icon, Variable,+,I_prev_19x20,const Icon, Variable,+,I_prev_hover_19x20,const Icon, Variable,+,I_prev_text_19x5,const Icon, +Variable,+,I_protopirate_10px,const Icon, Variable,-,I_qr_benchmark_25x25,const Icon, Variable,+,I_red_19x20,const Icon, Variable,+,I_red_hover_19x20,const Icon, diff --git a/targets/f7/furi_hal/furi_hal_nfc_iso15693.c b/targets/f7/furi_hal/furi_hal_nfc_iso15693.c index d35b160f4..1fafba6b2 100644 --- a/targets/f7/furi_hal/furi_hal_nfc_iso15693.c +++ b/targets/f7/furi_hal/furi_hal_nfc_iso15693.c @@ -8,6 +8,7 @@ #define FURI_HAL_NFC_ISO15693_MAX_FRAME_SIZE (1024U) #define FURI_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE (64) +#define FURI_HAL_NFC_ISO15693_BIT_LEN (4) #define FURI_HAL_NFC_ISO15693_RESP_SOF_SIZE (5) #define FURI_HAL_NFC_ISO15693_RESP_EOF_SIZE (5) @@ -34,9 +35,9 @@ typedef struct { typedef struct { // 4 bits per data bit on transmit - uint8_t fifo_buf[FURI_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE * 4]; + uint8_t fifo_buf[FURI_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE * FURI_HAL_NFC_ISO15693_BIT_LEN]; size_t fifo_buf_bits; - uint8_t frame_buf[FURI_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE * 2]; + uint8_t frame_buf[FURI_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE * FURI_HAL_NFC_ISO15693_BIT_LEN]; size_t frame_buf_bits; } FuriHalNfcIso15693Poller;