diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b36df350..62f5e25e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,9 @@ - Add older qFlipper install demos for windows and macos (by @DXVVAY & @grugnoymeme) - OFW: New layout for es-LA (by @IRecabarren) - OFW: Dolphin: Happy mode in Desktop settings (by @portasynthinca3) -- OFW: GUI: Add up and down button drawing functions to GUI elements (by @DerSkythe) +- GUI: + - OFW: Add up and down button drawing functions to GUI elements (by @DerSkythe) + - OFW: Added one new function for drawing mirrored xbm bitmaps (by @RebornedBrain) - OFW: RPC: Support 5V on GPIO control for ext. modules (by @gsurkov) - OFW: Toolbox: Proper integer parsing library `strint` (by @portasynthinca3) - OFW: Furi: Put errno into TCB (by @portasynthinca3) @@ -55,9 +57,10 @@ - NFC: - Added 6 new Mifare Classic keys from Bulgaria Hotel (#216 by @z3r0l1nk) - NDEF parser supports NTAG I2C Plus 1k and 2k chips too (by @RocketGod-git) - - OFW: Rename 'Detect Reader' to 'Extract MF Keys' (by @bettse) + - OFW/UL: Rename 'Detect Reader' to 'Extract MFC Keys' (by @bettse & @xMasterX) - OFW: Plantain parser improvements (by @assasinfil) - OFW: Moscow social card parser (by @assasinfil) + - OFW: Fixes and improvements to iso14443_4a listener and poller (by @RebornedBrain) - Sub-GHz: - UL: Frequency analyzer fixes and improvements (by @xMasterX): - Enforce int module (like in OFW) usage due to lack of required hardware on external boards (PathIsolate (+rf switch for multiple paths)) and incorrect usage and/or understanding the purpose of frequency analyzer app by users, it should be used only to get frequency of the remote placed around 1-10cm around flipper's left corner diff --git a/applications/drivers/subghz/cc1101_ext/cc1101_ext.c b/applications/drivers/subghz/cc1101_ext/cc1101_ext.c index f093b9f28..dae8819ab 100644 --- a/applications/drivers/subghz/cc1101_ext/cc1101_ext.c +++ b/applications/drivers/subghz/cc1101_ext/cc1101_ext.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -16,12 +15,12 @@ #include #include -#include +#include #define TAG "SubGhzDeviceCc1101Ext" -#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO (&gpio_ext_pb2) -#define SUBGHZ_DEVICE_CC1101_EXT_E07M20S_AMP_GPIO &gpio_ext_pc3 +#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO (&gpio_ext_pb2) +#define SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO &gpio_ext_pc3 #define SUBGHZ_DEVICE_CC1101_CONFIG_VER 1 @@ -94,9 +93,9 @@ typedef struct { const GpioPin* g0_pin; SubGhzDeviceCC1101ExtAsyncTx async_tx; SubGhzDeviceCC1101ExtAsyncRx async_rx; + bool amp_and_leds; bool extended_range; bool bypass_region; - bool power_amp; } SubGhzDeviceCC1101Ext; static SubGhzDeviceCC1101Ext* subghz_device_cc1101_ext = NULL; @@ -221,14 +220,14 @@ bool subghz_device_cc1101_ext_alloc(SubGhzDeviceConf* conf) { subghz_device_cc1101_ext->regulation = SubGhzDeviceCC1101ExtRegulationTxRx; subghz_device_cc1101_ext->async_mirror_pin = NULL; subghz_device_cc1101_ext->g0_pin = SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO; + subghz_device_cc1101_ext->amp_and_leds = false; subghz_device_cc1101_ext->extended_range = false; subghz_device_cc1101_ext->bypass_region = false; - subghz_device_cc1101_ext->power_amp = false; if(conf) { if(conf->ver == SUBGHZ_DEVICE_CC1101_CONFIG_VER) { + subghz_device_cc1101_ext->amp_and_leds = conf->amp_and_leds; subghz_device_cc1101_ext->extended_range = conf->extended_range; subghz_device_cc1101_ext->bypass_region = conf->bypass_region; - subghz_device_cc1101_ext->power_amp = conf->power_amp; } else { FURI_LOG_E(TAG, "Config version mismatch"); } @@ -248,10 +247,9 @@ bool subghz_device_cc1101_ext_alloc(SubGhzDeviceConf* conf) { } furi_hal_spi_bus_handle_init(subghz_device_cc1101_ext->spi_bus_handle); - if(subghz_device_cc1101_ext->power_amp) { - furi_hal_gpio_init_simple( - SUBGHZ_DEVICE_CC1101_EXT_E07M20S_AMP_GPIO, GpioModeOutputPushPull); - furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07M20S_AMP_GPIO, 0); + if(subghz_device_cc1101_ext->amp_and_leds) { + furi_hal_gpio_init_simple(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, GpioModeOutputPushPull); + furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0); } return subghz_device_cc1101_ext_check_init(); @@ -263,7 +261,8 @@ void subghz_device_cc1101_ext_free(void) { furi_hal_spi_bus_handle_deinit(subghz_device_cc1101_ext->spi_bus_handle); // resetting the CS pins to floating - if(momentum_settings.spi_nrf24_handle == SpiDefault || subghz_device_cc1101_ext->power_amp) { + if(momentum_settings.spi_nrf24_handle == SpiDefault || + subghz_device_cc1101_ext->amp_and_leds) { furi_hal_gpio_init_simple(&gpio_ext_pc3, GpioModeAnalog); } else if(momentum_settings.spi_nrf24_handle == SpiExtra) { furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeAnalog); @@ -442,6 +441,7 @@ void subghz_device_cc1101_ext_reset(void) { // Reset GDO2 (!TX/RX) to floating state cc1101_write_reg( subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHighImpedance); + furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); } @@ -455,8 +455,8 @@ void subghz_device_cc1101_ext_idle(void) { cc1101_write_reg( subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHighImpedance); furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); - if(subghz_device_cc1101_ext->power_amp) { - furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07M20S_AMP_GPIO, 0); + if(subghz_device_cc1101_ext->amp_and_leds) { + furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0); } } @@ -471,8 +471,8 @@ void subghz_device_cc1101_ext_rx(void) { subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); - if(subghz_device_cc1101_ext->power_amp) { - furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07M20S_AMP_GPIO, 0); + if(subghz_device_cc1101_ext->amp_and_leds) { + furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0); } } @@ -486,8 +486,8 @@ bool subghz_device_cc1101_ext_tx(void) { // Go GDO2 (!TX/RX) to low (TX state) cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHW); furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); - if(subghz_device_cc1101_ext->power_amp) { - furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07M20S_AMP_GPIO, 1); + if(subghz_device_cc1101_ext->amp_and_leds) { + furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 1); } return true; } diff --git a/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic.c b/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic.c index 4fece16be..5f3592c4b 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic.c +++ b/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic.c @@ -117,7 +117,7 @@ static void nfc_scene_read_menu_on_enter_mf_classic(NfcApp* instance) { if(!mf_classic_is_card_read(data)) { submenu_add_item( submenu, - "Extract MF Keys", + "Extract MFC Keys", SubmenuIndexDetectReader, nfc_protocol_support_common_submenu_callback, instance); @@ -155,7 +155,7 @@ static void nfc_scene_saved_menu_on_enter_mf_classic(NfcApp* instance) { if(!mf_classic_is_card_read(data)) { submenu_add_item( submenu, - "Extract MF Keys", + "Extract MFC Keys", SubmenuIndexDetectReader, nfc_protocol_support_common_submenu_callback, instance); diff --git a/applications/main/nfc/scenes/nfc_scene_start.c b/applications/main/nfc/scenes/nfc_scene_start.c index 9d6fc66eb..01cf35e41 100644 --- a/applications/main/nfc/scenes/nfc_scene_start.c +++ b/applications/main/nfc/scenes/nfc_scene_start.c @@ -30,7 +30,7 @@ void nfc_scene_start_on_enter(void* context) { submenu_add_item(submenu, "Read", SubmenuIndexRead, nfc_scene_start_submenu_callback, nfc); submenu_add_item( submenu, - "Extract MF Keys", + "Extract MFC Keys", SubmenuIndexDetectReader, nfc_scene_start_submenu_callback, nfc); diff --git a/applications/main/subghz/scenes/subghz_scene_radio_settings.c b/applications/main/subghz/scenes/subghz_scene_radio_settings.c index 56bc1ad7f..5031731eb 100644 --- a/applications/main/subghz/scenes/subghz_scene_radio_settings.c +++ b/applications/main/subghz/scenes/subghz_scene_radio_settings.c @@ -14,8 +14,8 @@ const uint32_t radio_device_value[RADIO_DEVICE_COUNT] = { SubGhzRadioDeviceTypeExternalCC1101, }; -#define TIMESTAMP_NAMES_COUNT 2 -const char* const timestamp_names_text[TIMESTAMP_NAMES_COUNT] = { +#define ON_OFF_COUNT 2 +const char* const on_off_text[ON_OFF_COUNT] = { "OFF", "ON", }; @@ -139,7 +139,7 @@ static void subghz_scene_receiver_config_set_protocol_file_names(VariableItem* i SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, timestamp_names_text[index]); + variable_item_set_current_value_text(item, on_off_text[index]); subghz->last_settings->protocol_file_names = (index == 1); subghz_last_settings_save(subghz->last_settings); @@ -183,12 +183,12 @@ void subghz_scene_radio_settings_on_enter(void* context) { item = variable_item_list_add( variable_item_list, "Protocol Names", - TIMESTAMP_NAMES_COUNT, + ON_OFF_COUNT, subghz_scene_receiver_config_set_protocol_file_names, subghz); value_index = subghz->last_settings->protocol_file_names; variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, timestamp_names_text[value_index]); + variable_item_set_current_value_text(item, on_off_text[value_index]); item = variable_item_list_add( variable_item_list, diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 327314a0f..bc74fbf1a 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -561,6 +561,19 @@ void canvas_draw_xbm( canvas_draw_u8g2_bitmap(&canvas->fb, x, y, width, height, bitmap, IconRotation0); } +void canvas_draw_xbm_mirrored( + Canvas* canvas, + int32_t x, + int32_t y, + size_t width, + size_t height, + const uint8_t* bitmap_data) { + furi_check(canvas); + x += canvas->offset_x; + y += canvas->offset_y; + canvas_draw_u8g2_bitmap(&canvas->fb, x, y, width, height, bitmap_data, IconRotation180); +} + void canvas_draw_glyph(Canvas* canvas, int32_t x, int32_t y, uint16_t ch) { furi_check(canvas); x += canvas->offset_x; diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index 8343be2ae..3f79c5695 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -296,6 +296,23 @@ void canvas_draw_xbm( size_t height, const uint8_t* bitmap); +/** Draw mirrored XBM bitmap + * + * @param canvas Canvas instance + * @param x x coordinate + * @param y y coordinate + * @param[in] width bitmap width + * @param[in] height bitmap height + * @param bitmap pointer to XBM bitmap data + */ +void canvas_draw_xbm_mirrored( + Canvas* canvas, + int32_t x, + int32_t y, + size_t width, + size_t height, + const uint8_t* bitmap_data); + /** Draw dot at x,y * * @param canvas Canvas instance diff --git a/lib/nfc/helpers/iso14443_4_layer.c b/lib/nfc/helpers/iso14443_4_layer.c index 933612df8..b3570fd7e 100644 --- a/lib/nfc/helpers/iso14443_4_layer.c +++ b/lib/nfc/helpers/iso14443_4_layer.c @@ -2,22 +2,50 @@ #include -#define ISO14443_4_BLOCK_PCB (1U << 1) -#define ISO14443_4_BLOCK_PCB_I (0U) -#define ISO14443_4_BLOCK_PCB_R (5U << 5) -#define ISO14443_4_BLOCK_PCB_S (3U << 6) - +// EMV Specific masks #define ISO14443_4_BLOCK_PCB_I_ (0U << 6) #define ISO14443_4_BLOCK_PCB_R_ (2U << 6) #define ISO14443_4_BLOCK_PCB_TYPE_MASK (3U << 6) +#define ISO14443_4_BLOCK_PCB_S_WTX (3U << 4) +#define ISO14443_4_BLOCK_PCB_S (3U << 6) +// -#define ISO14443_4_BLOCK_PCB_S_DESELECT (0U << 4) -#define ISO14443_4_BLOCK_PCB_S_WTX (3U << 4) -#define ISO14443_4_BLOCK_PCB_BLOCK_NUMBER (1U << 0) +#define ISO14443_4_BLOCK_PCB (1U << 1) +#define ISO14443_4_BLOCK_PCB_MASK (0x03) -#define ISO14443_4_BLOCK_PCB_NAD (1U << 2) -#define ISO14443_4_BLOCK_PCB_CID (1U << 3) -#define ISO14443_4_BLOCK_PCB_CHAINING (1U << 4) +#define ISO14443_4_BLOCK_PCB_I (0U) +#define ISO14443_4_BLOCK_PCB_I_NAD_OFFSET (2) +#define ISO14443_4_BLOCK_PCB_I_CID_OFFSET (3) +#define ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET (4) +#define ISO14443_4_BLOCK_PCB_I_NAD_MASK (1U << ISO14443_4_BLOCK_PCB_I_NAD_OFFSET) +#define ISO14443_4_BLOCK_PCB_I_CID_MASK (1U << ISO14443_4_BLOCK_PCB_I_CID_OFFSET) +#define ISO14443_4_BLOCK_PCB_I_CHAIN_MASK (1U << ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET) + +#define ISO14443_4_BLOCK_PCB_R_MASK (5U << 5) +#define ISO14443_4_BLOCK_PCB_R_NACK_OFFSET (4) +#define ISO14443_4_BLOCK_PCB_R_CID_OFFSET (3) +#define ISO14443_4_BLOCK_PCB_R_CID_MASK (1U << ISO14443_4_BLOCK_PCB_R_CID_OFFSET) +#define ISO14443_4_BLOCK_PCB_R_NACK_MASK (1U << ISO14443_4_BLOCK_PCB_R_NACK_OFFSET) + +#define ISO14443_4_BLOCK_PCB_S_MASK (3U << 6) +#define ISO14443_4_BLOCK_PCB_S_CID_OFFSET (3) +#define ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_OFFSET (4) +#define ISO14443_4_BLOCK_PCB_S_CID_MASK (1U << ISO14443_4_BLOCK_PCB_R_CID_OFFSET) +#define ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_MASK (3U << ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_OFFSET) + +#define ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, mask) (((pcb) & mask) == mask) + +#define ISO14443_4_BLOCK_PCB_IS_R_BLOCK(pcb) \ + ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_R_MASK) + +#define ISO14443_4_BLOCK_PCB_IS_S_BLOCK(pcb) \ + ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_S_MASK) + +#define ISO14443_4_BLOCK_PCB_IS_CHAIN_ACTIVE(pcb) \ + ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_I_CHAIN_MASK) + +#define ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE(pcb) \ + ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_R_NACK_MASK) struct Iso14443_4Layer { uint8_t pcb; @@ -43,9 +71,31 @@ void iso14443_4_layer_free(Iso14443_4Layer* instance) { void iso14443_4_layer_reset(Iso14443_4Layer* instance) { furi_assert(instance); + instance->pcb_prev = 0; instance->pcb = ISO14443_4_BLOCK_PCB_I | ISO14443_4_BLOCK_PCB; } +void iso14443_4_layer_set_i_block(Iso14443_4Layer* instance, bool chaining, bool CID_present) { + uint8_t block_pcb = instance->pcb & ISO14443_4_BLOCK_PCB_MASK; + instance->pcb = ISO14443_4_BLOCK_PCB_I | (chaining << ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET) | + (CID_present << ISO14443_4_BLOCK_PCB_I_CID_OFFSET) | block_pcb; +} + +void iso14443_4_layer_set_r_block(Iso14443_4Layer* instance, bool acknowledged, bool CID_present) { + furi_assert(instance); + uint8_t block_pcb = instance->pcb & ISO14443_4_BLOCK_PCB_MASK; + instance->pcb = ISO14443_4_BLOCK_PCB_R_MASK | + (!acknowledged << ISO14443_4_BLOCK_PCB_R_NACK_OFFSET) | + (CID_present << ISO14443_4_BLOCK_PCB_R_CID_OFFSET) | block_pcb; +} + +void iso14443_4_layer_set_s_block(Iso14443_4Layer* instance, bool deselect, bool CID_present) { + furi_assert(instance); + uint8_t des_wtx = !deselect ? (ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_MASK) : 0; + instance->pcb = ISO14443_4_BLOCK_PCB_S_MASK | des_wtx | + (CID_present << ISO14443_4_BLOCK_PCB_S_CID_OFFSET) | ISO14443_4_BLOCK_PCB; +} + void iso14443_4_layer_encode_block( Iso14443_4Layer* instance, const BitBuffer* input_data, @@ -58,6 +108,11 @@ void iso14443_4_layer_encode_block( iso14443_4_layer_update_pcb(instance); } +static inline uint8_t iso14443_4_layer_get_response_pcb(const BitBuffer* block_data) { + const uint8_t* data = bit_buffer_get_data(block_data); + return data[0]; +} + bool iso14443_4_layer_decode_block( Iso14443_4Layer* instance, BitBuffer* output_data, @@ -74,9 +129,26 @@ bool iso14443_4_layer_decode_block( return ret; do { - if(!bit_buffer_starts_with_byte(block_data, instance->pcb_prev)) break; - bit_buffer_copy_right(output_data, block_data, 1); - ret = true; + if(ISO14443_4_BLOCK_PCB_IS_R_BLOCK(instance->pcb_prev)) { + const uint8_t response_pcb = iso14443_4_layer_get_response_pcb(block_data); + ret = (ISO14443_4_BLOCK_PCB_IS_R_BLOCK(response_pcb)) && + (!ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE(response_pcb)); + instance->pcb &= ISO14443_4_BLOCK_PCB_MASK; + iso14443_4_layer_update_pcb(instance); + } else if(ISO14443_4_BLOCK_PCB_IS_CHAIN_ACTIVE(instance->pcb_prev)) { + const uint8_t response_pcb = iso14443_4_layer_get_response_pcb(block_data); + ret = (ISO14443_4_BLOCK_PCB_IS_R_BLOCK(response_pcb)) && + (!ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE(response_pcb)); + instance->pcb &= ~(ISO14443_4_BLOCK_PCB_I_CHAIN_MASK); + } else if(ISO14443_4_BLOCK_PCB_IS_S_BLOCK(instance->pcb_prev)) { + ret = bit_buffer_starts_with_byte(block_data, instance->pcb_prev); + if(bit_buffer_get_size_bytes(block_data) > 1) + bit_buffer_copy_right(output_data, block_data, 1); + } else { + if(!bit_buffer_starts_with_byte(block_data, instance->pcb_prev)) break; + bit_buffer_copy_right(output_data, block_data, 1); + ret = true; + } } while(false); return ret; diff --git a/lib/nfc/helpers/iso14443_4_layer.h b/lib/nfc/helpers/iso14443_4_layer.h index f4f8db520..9daf25775 100644 --- a/lib/nfc/helpers/iso14443_4_layer.h +++ b/lib/nfc/helpers/iso14443_4_layer.h @@ -15,6 +15,10 @@ void iso14443_4_layer_free(Iso14443_4Layer* instance); void iso14443_4_layer_reset(Iso14443_4Layer* instance); +void iso14443_4_layer_set_i_block(Iso14443_4Layer* instance, bool chaining, bool CID_present); +void iso14443_4_layer_set_r_block(Iso14443_4Layer* instance, bool acknowledged, bool CID_present); +void iso14443_4_layer_set_s_block(Iso14443_4Layer* instance, bool deselect, bool CID_present); + void iso14443_4_layer_encode_block( Iso14443_4Layer* instance, const BitBuffer* input_data, diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c index 95612bf54..32cc8f198 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.c @@ -84,6 +84,15 @@ static NfcCommand iso14443_4a_listener_run(NfcGenericEvent event, void* context) iso14443_3a_event->type == Iso14443_3aListenerEventTypeHalted || iso14443_3a_event->type == Iso14443_3aListenerEventTypeFieldOff) { instance->state = Iso14443_4aListenerStateIdle; + + instance->iso14443_4a_event.type = iso14443_3a_event->type == + Iso14443_3aListenerEventTypeHalted ? + Iso14443_4aListenerEventTypeHalted : + Iso14443_4aListenerEventTypeFieldOff; + + if(instance->callback) { + command = instance->callback(instance->generic_event, instance->context); + } command = NfcCommandContinue; } diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h index ba649847b..04f0b197a 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_listener.h @@ -12,6 +12,7 @@ typedef struct Iso14443_4aListener Iso14443_4aListener; typedef enum { Iso14443_4aListenerEventTypeHalted, + Iso14443_4aListenerEventTypeFieldOff, Iso14443_4aListenerEventTypeReceivedData, } Iso14443_4aListenerEventType; diff --git a/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h b/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h index 019beb2be..7b43d6ee8 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h @@ -61,6 +61,69 @@ Iso14443_4aError iso14443_4a_poller_send_block_pwt_ext( const BitBuffer* tx_buffer, BitBuffer* rx_buffer); +/** + * @brief Transmit and receive Iso14443_4a chained block in poller mode. Also it + * automatically modifies PCB packet byte with appropriate bits then resets them back + * + * Must ONLY be used inside the callback function. + * + * The rx_buffer will be filled with any data received as a response to data + * sent from tx_buffer. The fwt parameter is calculated during activation procedure. + * + * @param[in, out] instance pointer to the instance to be used in the transaction. + * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted. + * @param[out] rx_buffer pointer to the buffer to be filled with received data. + * @return Iso14443_4aErrorNone on success, an error code on failure. + */ +Iso14443_4aError iso14443_4a_poller_send_chain_block( + Iso14443_4aPoller* instance, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer); + +/** + * @brief Transmit Iso14443_4a R-block in poller mode. This block never contains + * data, but can contain CID and NAD, therefore in tx_buffer only two bytes can be added. + * The first one will represent CID, the second one will represent NAD. + * + * Must ONLY be used inside the callback function. + * + * The rx_buffer will be filled with R-block repsonse + * + * @param[in, out] instance pointer to the instance to be used in the transaction. + * @param[in] acknowledged Sets appropriate bit in PCB byte. True - ACK, false - NAK + * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted. + * @param[out] rx_buffer pointer to the buffer to be filled with received data. + * @return Iso14443_4aErrorNone on success, an error code on failure. + */ +Iso14443_4aError iso14443_4a_poller_send_receive_ready_block( + Iso14443_4aPoller* instance, + bool acknowledged, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer); + +/** + * @brief Transmit Iso14443_4a S-block in poller mode. S-block used to exchange control + * information between the card and the reader. Two different types of S-blocks + * are defined: + * - Waiting time extension containing a 1 byte long INF field and (deselect = false) + * - DESELECT containing no INF field (deselect = true) + * + * Must ONLY be used inside the callback function. + * + * The rx_buffer will be filled with R-block repsonse + * + * @param[in, out] instance pointer to the instance to be used in the transaction. + * @param[in] deselect Sets appropriate bit in PCB byte. + * @param[in] tx_buffer pointer to the buffer containing the data to be transmitted. + * @param[out] rx_buffer pointer to the buffer to be filled with received data. + * @return Iso14443_4aErrorNone on success, an error code on failure. + */ +Iso14443_4aError iso14443_4a_poller_send_supervisory_block( + Iso14443_4aPoller* instance, + bool deselect, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer); + /** * @brief Send HALT command to the card. * 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 02d78fba5..97b3171d5 100644 --- a/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.c +++ b/lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.c @@ -164,3 +164,34 @@ Iso14443_4aError iso14443_4a_poller_send_block_pwt_ext( return error; } + +Iso14443_4aError iso14443_4a_poller_send_chain_block( + Iso14443_4aPoller* instance, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer) { + iso14443_4_layer_set_i_block(instance->iso14443_4_layer, true, false); + Iso14443_4aError error = iso14443_4a_poller_send_block(instance, tx_buffer, rx_buffer); + return error; +} + +Iso14443_4aError iso14443_4a_poller_send_receive_ready_block( + Iso14443_4aPoller* instance, + bool acknowledged, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer) { + bool CID_present = bit_buffer_get_size_bytes(tx_buffer) != 0; + iso14443_4_layer_set_r_block(instance->iso14443_4_layer, acknowledged, CID_present); + Iso14443_4aError error = iso14443_4a_poller_send_block(instance, tx_buffer, rx_buffer); + return error; +} + +Iso14443_4aError iso14443_4a_poller_send_supervisory_block( + Iso14443_4aPoller* instance, + bool deselect, + const BitBuffer* tx_buffer, + BitBuffer* rx_buffer) { + bool CID_present = bit_buffer_get_size_bytes(tx_buffer) != 0; + iso14443_4_layer_set_s_block(instance->iso14443_4_layer, deselect, CID_present); + Iso14443_4aError error = iso14443_4a_poller_send_block(instance, tx_buffer, rx_buffer); + return error; +} diff --git a/lib/subghz/devices/devices.c b/lib/subghz/devices/devices.c index fc3917c86..845f2d962 100644 --- a/lib/subghz/devices/devices.c +++ b/lib/subghz/devices/devices.c @@ -37,7 +37,7 @@ bool subghz_devices_begin(const SubGhzDevice* device) { .ver = 1, .extended_range = furi_hal_subghz_get_extended_range(), .bypass_region = furi_hal_subghz_get_bypass_region(), - .power_amp = true, + .amp_and_leds = true, }; ret = device->interconnect->begin(&conf); diff --git a/lib/subghz/devices/types.h b/lib/subghz/devices/types.h index 6e05c93c2..3c34aaf0b 100644 --- a/lib/subghz/devices/types.h +++ b/lib/subghz/devices/types.h @@ -99,5 +99,5 @@ struct SubGhzDeviceConf { uint8_t ver; bool extended_range; bool bypass_region; - bool power_amp; + bool amp_and_leds; }; diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 47cff59e7..452d23f50 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -842,6 +842,7 @@ Function,+,canvas_draw_str,void,"Canvas*, int32_t, int32_t, const char*" Function,+,canvas_draw_str_aligned,void,"Canvas*, int32_t, int32_t, Align, Align, const char*" Function,+,canvas_draw_triangle,void,"Canvas*, int32_t, int32_t, size_t, size_t, CanvasDirection" Function,+,canvas_draw_xbm,void,"Canvas*, int32_t, int32_t, size_t, size_t, const uint8_t*" +Function,+,canvas_draw_xbm_mirrored,void,"Canvas*, int32_t, int32_t, size_t, size_t, const uint8_t*" Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font" Function,+,canvas_glyph_width,size_t,"Canvas*, uint16_t" Function,+,canvas_height,size_t,const Canvas* @@ -2200,6 +2201,9 @@ Function,+,iso14443_4a_poller_halt,Iso14443_4aError,Iso14443_4aPoller* Function,+,iso14443_4a_poller_read_ats,Iso14443_4aError,"Iso14443_4aPoller*, Iso14443_4aAtsData*" Function,+,iso14443_4a_poller_send_block,Iso14443_4aError,"Iso14443_4aPoller*, const BitBuffer*, BitBuffer*" Function,+,iso14443_4a_poller_send_block_pwt_ext,Iso14443_4aError,"Iso14443_4aPoller*, const BitBuffer*, BitBuffer*" +Function,+,iso14443_4a_poller_send_chain_block,Iso14443_4aError,"Iso14443_4aPoller*, const BitBuffer*, BitBuffer*" +Function,+,iso14443_4a_poller_send_receive_ready_block,Iso14443_4aError,"Iso14443_4aPoller*, _Bool, const BitBuffer*, BitBuffer*" +Function,+,iso14443_4a_poller_send_supervisory_block,Iso14443_4aError,"Iso14443_4aPoller*, _Bool, const BitBuffer*, BitBuffer*" 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"