diff --git a/applications/main/nfc/api/mosgortrans/mosgortrans_util.c b/applications/main/nfc/api/mosgortrans/mosgortrans_util.c index ef1e18f8d..8844ee4af 100644 --- a/applications/main/nfc/api/mosgortrans/mosgortrans_util.c +++ b/applications/main/nfc/api/mosgortrans/mosgortrans_util.c @@ -505,7 +505,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* card_use_before_date_s.year); if(data_block.valid_from_date == 0 || data_block.valid_to_date == 0) { - furi_string_cat(result, "\e#No ticket\n"); + furi_string_cat(result, "\e#No ticket"); return true; } //remaining_trips @@ -625,7 +625,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* data_block.valid_from_date + data_block.valid_for_days, &card_valid_to_date_s, 1992); furi_string_cat_printf( result, - "Valid to: %02d.%02d.%04d\n", + "Valid to: %02d.%02d.%04d", card_valid_to_date_s.day, card_valid_to_date_s.month, card_valid_to_date_s.year); @@ -663,7 +663,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 2016); furi_string_cat_printf( result, - "Valid to: %02d.%02d.%04d\n", + "Valid to: %02d.%02d.%04d", card_valid_to_date_s.day, card_valid_to_date_s.month, card_valid_to_date_s.year); @@ -676,7 +676,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 2016); furi_string_cat_printf( result, - "Trip from: %02d.%02d.%04d %02d:%02d\n", + "\nTrip from: %02d.%02d.%04d %02d:%02d", card_start_trip_minutes_s.day, card_start_trip_minutes_s.month, card_start_trip_minutes_s.year, @@ -693,7 +693,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 2016); furi_string_cat_printf( result, - "Trip switch: %02d.%02d.%04d %02d:%02d\n", + "\nTrip switch: %02d.%02d.%04d %02d:%02d", card_start_switch_trip_minutes_s.day, card_start_switch_trip_minutes_s.month, card_start_switch_trip_minutes_s.year, @@ -703,10 +703,10 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* //transport FuriString* transport = furi_string_alloc(); parse_transport_type(&data_block, transport); - furi_string_cat_printf(result, "Transport: %s\n", furi_string_get_cstr(transport)); + furi_string_cat_printf(result, "\nTransport: %s", furi_string_get_cstr(transport)); //validator if(data_block.validator) { - furi_string_cat_printf(result, "Validator: %05d\n", data_block.validator); + furi_string_cat_printf(result, "\nValidator: %05d", data_block.validator); } furi_string_free(transport); break; @@ -740,9 +740,9 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* card_valid_to_date_s.month, card_valid_to_date_s.year); //remaining_trips - furi_string_cat_printf(result, "Trips left: %d\n", data_block.remaining_trips); + furi_string_cat_printf(result, "Trips left: %d", data_block.remaining_trips); //trip_from - if(data_block.start_trip_date) { + if(data_block.start_trip_date) { // TODO: (-nofl) unused DateTime card_start_trip_minutes_s = {0}; from_minutes_to_datetime( data_block.start_trip_date * 24 * 60 + data_block.start_trip_time, @@ -751,7 +751,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* } //validator if(data_block.validator) { - furi_string_cat_printf(result, "Validator: %05d", data_block.validator); + furi_string_cat_printf(result, "\nValidator: %05d", data_block.validator); } break; } @@ -785,12 +785,12 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* data_block.valid_from_date + data_block.valid_for_days, &card_valid_to_date_s, 1992); furi_string_cat_printf( result, - "Valid to: %02d.%02d.%04d\n", + "Valid to: %02d.%02d.%04d", card_valid_to_date_s.day, card_valid_to_date_s.month, card_valid_to_date_s.year); //trip_from - if(data_block.start_trip_date) { + if(data_block.start_trip_date) { // TODO: (-nofl) unused DateTime card_start_trip_minutes_s = {0}; from_minutes_to_datetime( data_block.start_trip_date * 24 * 60 + data_block.start_trip_time, @@ -798,7 +798,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 1992); } //trip_switch - if(data_block.passage_5_minutes) { + if(data_block.passage_5_minutes) { // TODO: (-nofl) unused DateTime card_start_switch_trip_minutes_s = {0}; from_minutes_to_datetime( data_block.start_trip_date * 24 * 60 + data_block.start_trip_time + @@ -808,7 +808,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* } //validator if(data_block.validator) { - furi_string_cat_printf(result, "Validator: %05d", data_block.validator); + furi_string_cat_printf(result, "\nValidator: %05d", data_block.validator); } break; } @@ -870,10 +870,10 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* furi_string_cat(transport, ""); break; } - furi_string_cat_printf(result, "Transport: %s\n", furi_string_get_cstr(transport)); + furi_string_cat_printf(result, "Transport: %s", furi_string_get_cstr(transport)); //validator if(data_block.validator) { - furi_string_cat_printf(result, "Validator: %05d", data_block.validator); + furi_string_cat_printf(result, "\nValidator: %05d", data_block.validator); } furi_string_free(transport); break; @@ -899,7 +899,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* from_days_to_datetime(data_block.valid_from_date, &card_valid_from_date_s, 1992); furi_string_cat_printf( result, - "Valid from: %02d.%02d.%04d\n", + "Valid from: %02d.%02d.%04d", card_valid_from_date_s.day, card_valid_from_date_s.month, card_valid_from_date_s.year); @@ -912,7 +912,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 1992); furi_string_cat_printf( result, - "Valid to: %02d.%02d.%04d\n", + "\nValid to: %02d.%02d.%04d", card_valid_to_date_s.day, card_valid_to_date_s.month, card_valid_to_date_s.year); @@ -924,7 +924,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 1992); furi_string_cat_printf( result, - "Valid to: %02d.%02d.%04d\n", + "\nValid to: %02d.%02d.%04d", card_valid_to_date_s.day, card_valid_to_date_s.month, card_valid_to_date_s.year); @@ -939,7 +939,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 1992); //-time furi_string_cat_printf( result, - "Trip from: %02d.%02d.%04d %02d:%02d\n", + "\nTrip from: %02d.%02d.%04d %02d:%02d", card_start_trip_minutes_s.day, card_start_trip_minutes_s.month, card_start_trip_minutes_s.year, @@ -956,7 +956,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 1992); furi_string_cat_printf( result, - "Trip switch: %02d.%02d.%04d %02d:%02d\n", + "\nTrip switch: %02d.%02d.%04d %02d:%02d", card_start_switch_trip_minutes_s.day, card_start_switch_trip_minutes_s.month, card_start_switch_trip_minutes_s.year, @@ -965,7 +965,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* } //transport FuriString* transport = furi_string_alloc(); - switch(data_block.transport_type) { + switch(data_block.transport_type) { // TODO: (-nofl) unused case 1: furi_string_cat(transport, "Metro"); break; @@ -981,7 +981,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* } //validator if(data_block.validator) { - furi_string_cat_printf(result, "Validator: %05d", data_block.validator); + furi_string_cat_printf(result, "\nValidator: %05d", data_block.validator); } furi_string_free(transport); break; @@ -1094,14 +1094,14 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* data_block.valid_from_date * 24 * 60 + data_block.valid_for_minutes - data_block.start_trip_neg_minutes, &card_start_trip_minutes_s, - 2016); + 2016); // TODO: (-nofl) unused //transport FuriString* transport = furi_string_alloc(); parse_transport_type(&data_block, transport); - furi_string_cat_printf(result, "Transport: %s\n", furi_string_get_cstr(transport)); + furi_string_cat_printf(result, "Transport: %s", furi_string_get_cstr(transport)); // validator if(data_block.validator) { - furi_string_cat_printf(result, "Validator: %05d", data_block.validator); + furi_string_cat_printf(result, "\nValidator: %05d", data_block.validator); } furi_string_free(transport); break; @@ -1121,7 +1121,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* card_use_before_date_s.month, card_use_before_date_s.year); //remaining_funds - furi_string_cat_printf(result, "Balance: %ld rub\n", data_block.remaining_funds / 100); + furi_string_cat_printf(result, "Balance: %ld rub", data_block.remaining_funds / 100); //start_trip_minutes if(data_block.start_trip_minutes) { DateTime card_start_trip_minutes_s = {0}; @@ -1129,7 +1129,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* data_block.start_trip_minutes, &card_start_trip_minutes_s, 2019); furi_string_cat_printf( result, - "Trip from: %02d.%02d.%04d %02d:%02d\n", + "\nTrip from: %02d.%02d.%04d %02d:%02d", card_start_trip_minutes_s.day, card_start_trip_minutes_s.month, card_start_trip_minutes_s.year, @@ -1145,7 +1145,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 2019); furi_string_cat_printf( result, - "(M) from: %02d.%02d.%04d %02d:%02d\n", + "\n(M) from: %02d.%02d.%04d %02d:%02d", card_start_m_trip_minutes_s.day, card_start_m_trip_minutes_s.month, card_start_m_trip_minutes_s.year, @@ -1160,7 +1160,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 2019); furi_string_cat_printf( result, - "Trip edit: %02d.%02d.%04d %02d:%02d\n", + "\nTrip edit: %02d.%02d.%04d %02d:%02d", card_start_change_trip_minutes_s.day, card_start_change_trip_minutes_s.month, card_start_change_trip_minutes_s.year, @@ -1170,7 +1170,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* //transport //validator if(data_block.validator) { - furi_string_cat_printf(result, "Validator: %05d", data_block.validator); + furi_string_cat_printf(result, "\nValidator: %05d", data_block.validator); } break; } @@ -1207,7 +1207,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 2019); furi_string_cat_printf( result, - "Valid to: %02d.%02d.%04d\n", + "Valid to: %02d.%02d.%04d", card_use_to_date_s.day, card_use_to_date_s.month, card_use_to_date_s.year); @@ -1221,7 +1221,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 2019); //-time furi_string_cat_printf( result, - "Trip from: %02d.%02d.%04d %02d:%02d\n", + "\nTrip from: %02d.%02d.%04d %02d:%02d", card_start_trip_minutes_s.day, card_start_trip_minutes_s.month, card_start_trip_minutes_s.year, @@ -1238,7 +1238,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* 2019); furi_string_cat_printf( result, - "(M) from: %02d.%02d.%04d %02d:%02d\n", + "\n(M) from: %02d.%02d.%04d %02d:%02d", card_start_trip_m_minutes_s.day, card_start_trip_m_minutes_s.month, card_start_trip_m_minutes_s.year, @@ -1248,7 +1248,7 @@ bool mosgortrans_parse_transport_block(const MfClassicBlock* block, FuriString* //transport //validator if(data_block.validator) { - furi_string_cat_printf(result, "Validator: %05d", data_block.validator); + furi_string_cat_printf(result, "\nValidator: %05d", data_block.validator); } break; } diff --git a/applications/main/nfc/plugins/supported_cards/plantain.c b/applications/main/nfc/plugins/supported_cards/plantain.c index b1d2a5164..11b60d6fa 100644 --- a/applications/main/nfc/plugins/supported_cards/plantain.c +++ b/applications/main/nfc/plugins/supported_cards/plantain.c @@ -59,6 +59,29 @@ static const MfClassicKeyPair plantain_4k_keys[] = { {.a = 0xb27addfb64b0, .b = 0x152fd0c420a7}, {.a = 0x7259fa0197c6, .b = 0x5583698df085}, }; +static const MfClassicKeyPair plantain_4k_keys_legacy[] = { + {.a = 0xffffffffffff, .b = 0xffffffffffff}, {.a = 0xffffffffffff, .b = 0xffffffffffff}, + {.a = 0xffffffffffff, .b = 0xffffffffffff}, {.a = 0xffffffffffff, .b = 0xffffffffffff}, + {.a = 0xe56ac127dd45, .b = 0x19fc84a3784b}, {.a = 0x77dabc9825e1, .b = 0x9764fec3154a}, + {.a = 0xffffffffffff, .b = 0xffffffffffff}, {.a = 0xffffffffffff, .b = 0xffffffffffff}, + {.a = 0x26973ea74321, .b = 0xd27058c6e2c7}, {.a = 0xeb0a8ff88ade, .b = 0x578a9ada41e3}, + {.a = 0xea0fd73cb149, .b = 0x29c35fa068fb}, {.a = 0xc76bf71a2509, .b = 0x9ba241db3f56}, + {.a = 0xacffffffffff, .b = 0x71f3a315ad26}, {.a = 0xffffffffffff, .b = 0xffffffffffff}, + {.a = 0xffffffffffff, .b = 0xffffffffffff}, {.a = 0xffffffffffff, .b = 0xffffffffffff}, + {.a = 0x72f96bdd3714, .b = 0x462225cd34cf}, {.a = 0x044ce1872bc3, .b = 0x8c90c70cff4a}, + {.a = 0xbc2d1791dec1, .b = 0xca96a487de0b}, {.a = 0x8791b2ccb5c4, .b = 0xc956c3b80da3}, + {.a = 0x8e26e45e7d65, .b = 0x8e65b3af7d22}, {.a = 0x0f318130ed18, .b = 0x0c420a20e056}, + {.a = 0x045ceca15535, .b = 0x31bec3d9e510}, {.a = 0x9d993c5d4ef4, .b = 0x86120e488abf}, + {.a = 0xc65d4eaa645b, .b = 0xb69d40d1a439}, {.a = 0x46d78e850a7e, .b = 0xa470f8130991}, + {.a = 0x42e9b54e51ab, .b = 0x0231b86df52e}, {.a = 0x0f01ceff2742, .b = 0x6fec74559ca7}, + {.a = 0xb81f2b0c2f66, .b = 0xa7e2d95f0003}, {.a = 0x9ea3387a63c1, .b = 0x437e59f57561}, + {.a = 0x0eb23cc8110b, .b = 0x04dc35277635}, {.a = 0xbc4580b7f20b, .b = 0xd0a4131fb290}, + {.a = 0x7a396f0d633d, .b = 0xad2bdc097023}, {.a = 0xa3faa6daff67, .b = 0x7600e889adf9}, + {.a = 0xfd8705e721b0, .b = 0x296fc317a513}, {.a = 0x22052b480d11, .b = 0xe19504c39461}, + {.a = 0xa7141147d430, .b = 0xff16014fefc7}, {.a = 0x8a8d88151a00, .b = 0x038b5f9b5a2a}, + {.a = 0xb27addfb64b0, .b = 0x152fd0c420a7}, {.a = 0x7259fa0197c6, .b = 0x5583698df085}, +}; + static bool plantain_get_card_config(PlantainCardConfig* config, MfClassicType type) { bool success = true; @@ -125,6 +148,21 @@ static bool plantain_read(Nfc* nfc, NfcDevice* device) { PlantainCardConfig cfg = {}; if(!plantain_get_card_config(&cfg, data->type)) break; + const uint8_t legacy_check_sec_num = 26; + const uint8_t legacy_check_block_num = + mf_classic_get_first_block_num_of_sector(legacy_check_sec_num); + + MfClassicKey key = {0}; + bit_lib_num_to_bytes_be( + plantain_4k_keys_legacy[legacy_check_sec_num].a, COUNT_OF(key.data), key.data); + + error = mf_classic_poller_sync_auth( + nfc, legacy_check_block_num, &key, MfClassicKeyTypeA, NULL); + if(error == MfClassicErrorNone) { + FURI_LOG_D(TAG, "Legacy keys detected"); + cfg.keys = plantain_4k_keys_legacy; + } + MfClassicDeviceKeys keys = {}; for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(cfg.keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/troika.c b/applications/main/nfc/plugins/supported_cards/troika.c index 1831246ee..94e72391f 100644 --- a/applications/main/nfc/plugins/supported_cards/troika.c +++ b/applications/main/nfc/plugins/supported_cards/troika.c @@ -211,11 +211,11 @@ static bool troika_parse(const NfcDevice* device, FuriString* parsed_data) { if(result2) { furi_string_cat_printf( - parsed_data, "\e#Ediniy\n%s\n", furi_string_get_cstr(ground_result)); + parsed_data, "\n\e#Ediniy\n%s\n", furi_string_get_cstr(ground_result)); } if(result3) { - furi_string_cat_printf(parsed_data, "\e#TAT\n%s\n", furi_string_get_cstr(tat_result)); + furi_string_cat_printf(parsed_data, "\n\e#TAT\n%s", furi_string_get_cstr(tat_result)); } furi_string_free(tat_result); diff --git a/applications/services/gui/icon_animation.c b/applications/services/gui/icon_animation.c index c33c2042d..f887b90ac 100644 --- a/applications/services/gui/icon_animation.c +++ b/applications/services/gui/icon_animation.c @@ -70,7 +70,7 @@ uint8_t icon_animation_get_height(const IconAnimation* instance) { void icon_animation_start(IconAnimation* instance) { furi_check(instance); - if(!instance->animating && instance->icon->frame_rate && instance->icon->frame_count > 1) { + if(!instance->animating) { instance->animating = true; furi_assert(instance->icon->frame_rate); furi_check( diff --git a/applications/services/gui/modules/menu.c b/applications/services/gui/modules/menu.c index 2b3d8dba5..da4a84cbd 100644 --- a/applications/services/gui/modules/menu.c +++ b/applications/services/gui/modules/menu.c @@ -73,13 +73,11 @@ static void menu_centered_icon( size_t y, size_t width, size_t height) { - if(item->icon) { - canvas_draw_icon_animation( - canvas, - x + (width - item->icon->icon->width) / 2, - y + (height - item->icon->icon->height) / 2, - item->icon); - } + canvas_draw_icon_animation( + canvas, + x + (width - item->icon->icon->width) / 2, + y + (height - item->icon->icon->height) / 2, + item->icon); } static size_t menu_scroll_counter(MenuModel* model, bool selected) { @@ -482,8 +480,8 @@ static void menu_enter(void* context) { menu->view, MenuModel * model, { - MenuItem* item = MenuItemArray_get(model->items, model->position); - if(item && item->icon) { + if(MenuItemArray_size(model->items)) { + MenuItem* item = MenuItemArray_get(model->items, model->position); icon_animation_start(item->icon); } model->scroll_counter = 0; @@ -498,8 +496,8 @@ static void menu_exit(void* context) { menu->view, MenuModel * model, { - MenuItem* item = MenuItemArray_get(model->items, model->position); - if(item && item->icon) { + if(MenuItemArray_size(model->items)) { + MenuItem* item = MenuItemArray_get(model->items, model->position); icon_animation_stop(item->icon); } }, @@ -603,14 +601,10 @@ void menu_set_selected_item(Menu* menu, uint32_t index) { model->scroll_counter = 0; MenuItem* item = MenuItemArray_get(model->items, model->position); - if(item && item->icon) { - icon_animation_stop(item->icon); - } + icon_animation_stop(item->icon); item = MenuItemArray_get(model->items, index); - if(item && item->icon) { - icon_animation_start(item->icon); - } + icon_animation_start(item->icon); model->position = index; } @@ -831,7 +825,7 @@ static void menu_process_ok(Menu* menu) { menu->view, MenuModel * model, { - if(model->position < MenuItemArray_size(model->items)) { + if(MenuItemArray_size(model->items)) { item = MenuItemArray_get(model->items, model->position); } }, diff --git a/applications/system/findmy/findmy_i.h b/applications/system/findmy/findmy_i.h index b4ffa5c50..1d1178d58 100644 --- a/applications/system/findmy/findmy_i.h +++ b/applications/system/findmy/findmy_i.h @@ -38,7 +38,6 @@ struct FindMy { uint8_t mac_buf[EXTRA_BEACON_MAC_ADDR_SIZE]; uint8_t packet_buf[EXTRA_BEACON_MAX_DATA_SIZE]; - uint8_t battery_level; FindMyState state; }; diff --git a/applications/system/findmy/findmy_state.c b/applications/system/findmy/findmy_state.c index b1b1e272a..8a60a312e 100644 --- a/applications/system/findmy/findmy_state.c +++ b/applications/system/findmy/findmy_state.c @@ -42,13 +42,6 @@ bool findmy_state_load(FindMyState* out_state) { } state.tag_type = tmp; - if(!flipper_format_read_uint32(file, "battery_level", &tmp, 1)) { - tmp = 0x00; // Default battery level set to Full - flipper_format_rewind(file); - } - FURI_LOG_I("findmy_load", "Saved Battery: %ld", tmp); - state.battery_level = tmp; - if(!flipper_format_read_hex(file, "mac", state.mac, sizeof(state.mac))) break; if(!flipper_format_read_hex( @@ -171,9 +164,6 @@ void findmy_state_save(FindMyState* state) { tmp = state->tag_type; if(!flipper_format_write_uint32(file, "tag_type", &tmp, 1)) break; - tmp = state->battery_level; - if(!flipper_format_write_uint32(file, "battery_level", &tmp, 1)) break; - if(!flipper_format_write_bool(file, "show_mac", &state->show_mac, 1)) break; if(!flipper_format_write_hex(file, "mac", state->mac, sizeof(state->mac))) break; diff --git a/applications/system/js_app/modules/js_widget.c b/applications/system/js_app/modules/js_widget.c index 830474d92..a27c55c1e 100644 --- a/applications/system/js_app/modules/js_widget.c +++ b/applications/system/js_app/modules/js_widget.c @@ -917,9 +917,8 @@ static void widget_remove_view(void* context) { ComponentArray_it(it, model->component); while(!ComponentArray_end_p(it)) { WidgetComponent* component = *ComponentArray_ref(it); - if(component->free) { + if(component && component->free) { component->free(component); - component->free = NULL; } ComponentArray_next(it); } @@ -1003,6 +1002,7 @@ static void js_widget_destroy(void* inst) { view_dispatcher_stop(widget->view_dispatcher); widget_deinit(widget); } + widget_remove_view(widget); free(widget); } diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.c b/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.c index 4caeb7bfd..697abd2f2 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.c +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.c @@ -7,6 +7,10 @@ #define TAG "Iso14443_4aPoller" #define ISO14443_4A_FSDI_256 (0x8U) +#define ISO14443_4A_FWT_MAX (4096UL << 14) +#define ISO14443_4A_WTXM_MASK (0x3FU) +#define ISO14443_4A_WTXM_MAX (0x3BU) +#define ISO14443_4A_SWTX (0xF2U) #define ISO14443_4A_SEND_BLOCK_MAX_ATTEMPTS (20) Iso14443_4aError iso14443_4a_poller_halt(Iso14443_4aPoller* instance) { @@ -75,9 +79,35 @@ Iso14443_4aError iso14443_4a_poller_send_block( if(iso14443_3a_error != Iso14443_3aErrorNone) { error = iso14443_4a_process_error(iso14443_3a_error); break; + } - } else if(!iso14443_4_layer_decode_block( - instance->iso14443_4_layer, rx_buffer, instance->rx_buffer)) { + if(bit_buffer_starts_with_byte(instance->rx_buffer, ISO14443_4A_SWTX)) { + do { + uint8_t wtxm = bit_buffer_get_byte(instance->rx_buffer, 1) & ISO14443_4A_WTXM_MASK; + if(wtxm > ISO14443_4A_WTXM_MAX) { + return Iso14443_4aErrorProtocol; + } + + bit_buffer_reset(instance->tx_buffer); + bit_buffer_copy_left(instance->tx_buffer, instance->rx_buffer, 1); + bit_buffer_append_byte(instance->tx_buffer, wtxm); + + iso14443_3a_error = iso14443_3a_poller_send_standard_frame( + instance->iso14443_3a_poller, + instance->tx_buffer, + instance->rx_buffer, + MAX(iso14443_4a_get_fwt_fc_max(instance->data) * wtxm, ISO14443_4A_FWT_MAX)); + + if(iso14443_3a_error != Iso14443_3aErrorNone) { + error = iso14443_4a_process_error(iso14443_3a_error); + return error; + } + + } while(bit_buffer_starts_with_byte(instance->rx_buffer, ISO14443_4A_SWTX)); + } + + if(!iso14443_4_layer_decode_block( + instance->iso14443_4_layer, rx_buffer, instance->rx_buffer)) { error = Iso14443_4aErrorProtocol; break; }