NFC: Add support for Gen4 "ultimate card" in Magic app (#2238)
* NFC: gen4 gtu detect in magic app * NFC: more support for GTU card * NFC: Fix Gen1 in Magic * Allow double UIDs for MFClassic on GTU cards * NFC: Small magic app tweaks * nfc magic: notify card event on wiping * nfc magic: fix power consumption * nfc magic: disable i2c writing and fix wipe loop * NfcMagic: correct formatting in printf * NfcMagic: correct formatting in printf, proper version * nfc_magic: rework card found notification and gen4 wiping Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									77bb997b0b
								
							
						
					
					
						commit
						490447bbd4
					
				
							
								
								
									
										175
									
								
								applications/external/nfc_magic/lib/magic/classic_gen1.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								applications/external/nfc_magic/lib/magic/classic_gen1.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,175 @@ | |||||||
|  | #include "classic_gen1.h" | ||||||
|  | 
 | ||||||
|  | #include <furi_hal_nfc.h> | ||||||
|  | 
 | ||||||
|  | #define TAG "Magic" | ||||||
|  | 
 | ||||||
|  | #define MAGIC_CMD_WUPA (0x40) | ||||||
|  | #define MAGIC_CMD_WIPE (0x41) | ||||||
|  | #define MAGIC_CMD_ACCESS (0x43) | ||||||
|  | 
 | ||||||
|  | #define MAGIC_MIFARE_READ_CMD (0x30) | ||||||
|  | #define MAGIC_MIFARE_WRITE_CMD (0xA0) | ||||||
|  | 
 | ||||||
|  | #define MAGIC_ACK (0x0A) | ||||||
|  | 
 | ||||||
|  | #define MAGIC_BUFFER_SIZE (32) | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_wupa() { | ||||||
|  |     bool magic_activated = false; | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         // Start communication
 | ||||||
|  |         tx_data[0] = MAGIC_CMD_WUPA; | ||||||
|  |         ret = furi_hal_nfc_ll_txrx_bits( | ||||||
|  |             tx_data, | ||||||
|  |             7, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | | ||||||
|  |                 FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(20)); | ||||||
|  |         if(ret != FuriHalNfcReturnIncompleteByte) break; | ||||||
|  |         if(rx_len != 4) break; | ||||||
|  |         if(rx_data[0] != MAGIC_ACK) break; | ||||||
|  |         magic_activated = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return magic_activated; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_data_access_cmd() { | ||||||
|  |     bool write_cmd_success = false; | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         tx_data[0] = MAGIC_CMD_ACCESS; | ||||||
|  |         ret = furi_hal_nfc_ll_txrx_bits( | ||||||
|  |             tx_data, | ||||||
|  |             8, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | | ||||||
|  |                 FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(20)); | ||||||
|  |         if(ret != FuriHalNfcReturnIncompleteByte) break; | ||||||
|  |         if(rx_len != 4) break; | ||||||
|  |         if(rx_data[0] != MAGIC_ACK) break; | ||||||
|  | 
 | ||||||
|  |         write_cmd_success = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return write_cmd_success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) { | ||||||
|  |     furi_assert(data); | ||||||
|  | 
 | ||||||
|  |     bool read_success = false; | ||||||
|  | 
 | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         tx_data[0] = MAGIC_MIFARE_READ_CMD; | ||||||
|  |         tx_data[1] = block_num; | ||||||
|  |         ret = furi_hal_nfc_ll_txrx_bits( | ||||||
|  |             tx_data, | ||||||
|  |             2 * 8, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(20)); | ||||||
|  | 
 | ||||||
|  |         if(ret != FuriHalNfcReturnOk) break; | ||||||
|  |         if(rx_len != 16 * 8) break; | ||||||
|  |         memcpy(data->value, rx_data, sizeof(data->value)); | ||||||
|  |         read_success = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return read_success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) { | ||||||
|  |     furi_assert(data); | ||||||
|  | 
 | ||||||
|  |     bool write_success = false; | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         tx_data[0] = MAGIC_MIFARE_WRITE_CMD; | ||||||
|  |         tx_data[1] = block_num; | ||||||
|  |         ret = furi_hal_nfc_ll_txrx_bits( | ||||||
|  |             tx_data, | ||||||
|  |             2 * 8, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(20)); | ||||||
|  |         if(ret != FuriHalNfcReturnIncompleteByte) break; | ||||||
|  |         if(rx_len != 4) break; | ||||||
|  |         if(rx_data[0] != MAGIC_ACK) break; | ||||||
|  | 
 | ||||||
|  |         memcpy(tx_data, data->value, sizeof(data->value)); | ||||||
|  |         ret = furi_hal_nfc_ll_txrx_bits( | ||||||
|  |             tx_data, | ||||||
|  |             16 * 8, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(20)); | ||||||
|  |         if(ret != FuriHalNfcReturnIncompleteByte) break; | ||||||
|  |         if(rx_len != 4) break; | ||||||
|  |         if(rx_data[0] != MAGIC_ACK) break; | ||||||
|  | 
 | ||||||
|  |         write_success = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return write_success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_wipe() { | ||||||
|  |     bool wipe_success = false; | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         tx_data[0] = MAGIC_CMD_WIPE; | ||||||
|  |         ret = furi_hal_nfc_ll_txrx_bits( | ||||||
|  |             tx_data, | ||||||
|  |             8, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | | ||||||
|  |                 FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(2000)); | ||||||
|  | 
 | ||||||
|  |         if(ret != FuriHalNfcReturnIncompleteByte) break; | ||||||
|  |         if(rx_len != 4) break; | ||||||
|  |         if(rx_data[0] != MAGIC_ACK) break; | ||||||
|  | 
 | ||||||
|  |         wipe_success = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return wipe_success; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								applications/external/nfc_magic/lib/magic/classic_gen1.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								applications/external/nfc_magic/lib/magic/classic_gen1.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <lib/nfc/protocols/mifare_classic.h> | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_wupa(); | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data); | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_data_access_cmd(); | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data); | ||||||
|  | 
 | ||||||
|  | bool magic_gen1_wipe(); | ||||||
							
								
								
									
										33
									
								
								applications/external/nfc_magic/lib/magic/common.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								applications/external/nfc_magic/lib/magic/common.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | #include "common.h" | ||||||
|  | 
 | ||||||
|  | #include <furi_hal_nfc.h> | ||||||
|  | 
 | ||||||
|  | #define REQA (0x26) | ||||||
|  | #define CL1_PREFIX (0x93) | ||||||
|  | #define SELECT (0x70) | ||||||
|  | 
 | ||||||
|  | #define MAGIC_BUFFER_SIZE (32) | ||||||
|  | 
 | ||||||
|  | bool magic_activate() { | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     // Setup nfc poller
 | ||||||
|  |     furi_hal_nfc_exit_sleep(); | ||||||
|  |     furi_hal_nfc_ll_txrx_on(); | ||||||
|  |     furi_hal_nfc_ll_poll(); | ||||||
|  |     ret = furi_hal_nfc_ll_set_mode( | ||||||
|  |         FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106); | ||||||
|  |     if(ret != FuriHalNfcReturnOk) return false; | ||||||
|  | 
 | ||||||
|  |     furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); | ||||||
|  |     furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); | ||||||
|  |     furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); | ||||||
|  |     furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void magic_deactivate() { | ||||||
|  |     furi_hal_nfc_ll_txrx_off(); | ||||||
|  |     furi_hal_nfc_sleep(); | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								applications/external/nfc_magic/lib/magic/common.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								applications/external/nfc_magic/lib/magic/common.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     MagicTypeClassicGen1, | ||||||
|  |     MagicTypeClassicDirectWrite, | ||||||
|  |     MagicTypeClassicAPDU, | ||||||
|  |     MagicTypeUltralightGen1, | ||||||
|  |     MagicTypeUltralightDirectWrite, | ||||||
|  |     MagicTypeUltralightC_Gen1, | ||||||
|  |     MagicTypeUltralightC_DirectWrite, | ||||||
|  |     MagicTypeGen4, | ||||||
|  | } MagicType; | ||||||
|  | 
 | ||||||
|  | bool magic_activate(); | ||||||
|  | 
 | ||||||
|  | void magic_deactivate(); | ||||||
							
								
								
									
										199
									
								
								applications/external/nfc_magic/lib/magic/gen4.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								applications/external/nfc_magic/lib/magic/gen4.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,199 @@ | |||||||
|  | #include "gen4.h" | ||||||
|  | 
 | ||||||
|  | #include <furi_hal_nfc.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | 
 | ||||||
|  | #define TAG "Magic" | ||||||
|  | 
 | ||||||
|  | #define MAGIC_CMD_PREFIX (0xCF) | ||||||
|  | 
 | ||||||
|  | #define MAGIC_CMD_GET_CFG (0xC6) | ||||||
|  | #define MAGIC_CMD_WRITE (0xCD) | ||||||
|  | #define MAGIC_CMD_READ (0xCE) | ||||||
|  | #define MAGIC_CMD_SET_CFG (0xF0) | ||||||
|  | #define MAGIC_CMD_FUSE_CFG (0xF1) | ||||||
|  | #define MAGIC_CMD_SET_PWD (0xFE) | ||||||
|  | 
 | ||||||
|  | #define MAGIC_BUFFER_SIZE (40) | ||||||
|  | 
 | ||||||
|  | const uint8_t MAGIC_DEFAULT_CONFIG[] = { | ||||||
|  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x00, 0x08, 0x00 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint8_t MAGIC_DEFAULT_BLOCK0[] = { | ||||||
|  |     0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint8_t MAGIC_EMPTY_BLOCK[16] = { 0 }; | ||||||
|  | 
 | ||||||
|  | const uint8_t MAGIC_DEFAULT_SECTOR_TRAILER[] = { | ||||||
|  |     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static bool magic_gen4_is_block_num_trailer(uint8_t n) { | ||||||
|  |     n++; | ||||||
|  |     if (n < 32 * 4) { | ||||||
|  |         return (n % 4 == 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return (n % 16 == 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config) { | ||||||
|  |     bool is_valid_config_len = false; | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         // Start communication
 | ||||||
|  |         tx_data[0] = MAGIC_CMD_PREFIX; | ||||||
|  |         tx_data[1] = (uint8_t)(pwd >> 24); | ||||||
|  |         tx_data[2] = (uint8_t)(pwd >> 16); | ||||||
|  |         tx_data[3] = (uint8_t)(pwd >> 8); | ||||||
|  |         tx_data[4] = (uint8_t)pwd; | ||||||
|  |         tx_data[5] = MAGIC_CMD_GET_CFG; | ||||||
|  |         ret = furi_hal_nfc_ll_txrx( | ||||||
|  |             tx_data, | ||||||
|  |             6, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_TXRX_DEFAULT, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(20)); | ||||||
|  |         if(ret != FuriHalNfcReturnOk) break; | ||||||
|  |         if(rx_len != 30 && rx_len != 32) break; | ||||||
|  |         memcpy(config, rx_data, rx_len); | ||||||
|  |         is_valid_config_len = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return is_valid_config_len; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse) { | ||||||
|  |     bool write_success = false; | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         // Start communication
 | ||||||
|  |         tx_data[0] = MAGIC_CMD_PREFIX; | ||||||
|  |         tx_data[1] = (uint8_t)(pwd >> 24); | ||||||
|  |         tx_data[2] = (uint8_t)(pwd >> 16); | ||||||
|  |         tx_data[3] = (uint8_t)(pwd >> 8); | ||||||
|  |         tx_data[4] = (uint8_t)pwd; | ||||||
|  |         tx_data[5] = fuse ? MAGIC_CMD_FUSE_CFG : MAGIC_CMD_SET_CFG; | ||||||
|  |         memcpy(tx_data + 6, config, config_length); | ||||||
|  |         ret = furi_hal_nfc_ll_txrx( | ||||||
|  |             tx_data, | ||||||
|  |             6 + config_length, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_TXRX_DEFAULT, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(20)); | ||||||
|  |         if(ret != FuriHalNfcReturnOk) break; | ||||||
|  |         if(rx_len != 2) break; | ||||||
|  |         write_success = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return write_success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd) { | ||||||
|  |     bool change_success = false; | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         // Start communication
 | ||||||
|  |         tx_data[0] = MAGIC_CMD_PREFIX; | ||||||
|  |         tx_data[1] = (uint8_t)(old_pwd >> 24); | ||||||
|  |         tx_data[2] = (uint8_t)(old_pwd >> 16); | ||||||
|  |         tx_data[3] = (uint8_t)(old_pwd >> 8); | ||||||
|  |         tx_data[4] = (uint8_t)old_pwd; | ||||||
|  |         tx_data[5] = MAGIC_CMD_SET_PWD; | ||||||
|  |         tx_data[6] = (uint8_t)(new_pwd >> 24); | ||||||
|  |         tx_data[7] = (uint8_t)(new_pwd >> 16); | ||||||
|  |         tx_data[8] = (uint8_t)(new_pwd >> 8); | ||||||
|  |         tx_data[9] = (uint8_t)new_pwd; | ||||||
|  |         ret = furi_hal_nfc_ll_txrx( | ||||||
|  |             tx_data, | ||||||
|  |             10, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_TXRX_DEFAULT, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(20)); | ||||||
|  |         FURI_LOG_I(TAG, "ret %d, len %d", ret, rx_len); | ||||||
|  |         if(ret != FuriHalNfcReturnOk) break; | ||||||
|  |         if(rx_len != 2) break; | ||||||
|  |         change_success = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return change_success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data) { | ||||||
|  |     bool write_success = false; | ||||||
|  |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|  |     uint16_t rx_len = 0; | ||||||
|  |     FuriHalNfcReturn ret = 0; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         // Start communication
 | ||||||
|  |         tx_data[0] = MAGIC_CMD_PREFIX; | ||||||
|  |         tx_data[1] = (uint8_t)(pwd >> 24); | ||||||
|  |         tx_data[2] = (uint8_t)(pwd >> 16); | ||||||
|  |         tx_data[3] = (uint8_t)(pwd >> 8); | ||||||
|  |         tx_data[4] = (uint8_t)pwd; | ||||||
|  |         tx_data[5] = MAGIC_CMD_WRITE; | ||||||
|  |         tx_data[6] = block_num; | ||||||
|  |         memcpy(tx_data + 7, data, 16); | ||||||
|  |         ret = furi_hal_nfc_ll_txrx( | ||||||
|  |             tx_data, | ||||||
|  |             23, | ||||||
|  |             rx_data, | ||||||
|  |             sizeof(rx_data), | ||||||
|  |             &rx_len, | ||||||
|  |             FURI_HAL_NFC_TXRX_DEFAULT, | ||||||
|  |             furi_hal_nfc_ll_ms2fc(200)); | ||||||
|  |         if(ret != FuriHalNfcReturnOk) break; | ||||||
|  |         if(rx_len != 2) break; | ||||||
|  |         write_success = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return write_success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_wipe(uint32_t pwd) { | ||||||
|  |     if(!magic_gen4_set_cfg(pwd, MAGIC_DEFAULT_CONFIG, sizeof(MAGIC_DEFAULT_CONFIG), false)) { | ||||||
|  |         FURI_LOG_E(TAG, "Set config failed"); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |     if(!magic_gen4_write_blk(pwd, 0, MAGIC_DEFAULT_BLOCK0)) { | ||||||
|  |         FURI_LOG_E(TAG, "Block 0 write failed"); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |     for(size_t i = 1; i < 64; i++) { | ||||||
|  |         const uint8_t* block = magic_gen4_is_block_num_trailer(i) ? MAGIC_DEFAULT_SECTOR_TRAILER : MAGIC_EMPTY_BLOCK; | ||||||
|  |         if(!magic_gen4_write_blk(pwd, i, block)) { | ||||||
|  |             FURI_LOG_E(TAG, "Block %d write failed", i); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     for(size_t i = 65; i < 256; i++) { | ||||||
|  |         if(!magic_gen4_write_blk(pwd, i, MAGIC_EMPTY_BLOCK)) { | ||||||
|  |             FURI_LOG_E(TAG, "Block %d write failed", i); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								applications/external/nfc_magic/lib/magic/gen4.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								applications/external/nfc_magic/lib/magic/gen4.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <lib/nfc/protocols/mifare_classic.h> | ||||||
|  | 
 | ||||||
|  | #define MAGIC_GEN4_DEFAULT_PWD 0x00000000 | ||||||
|  | #define MAGIC_GEN4_CONFIG_LEN 32 | ||||||
|  | 
 | ||||||
|  | #define NFCID1_SINGLE_SIZE 4 | ||||||
|  | #define NFCID1_DOUBLE_SIZE 7 | ||||||
|  | #define NFCID1_TRIPLE_SIZE 10 | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     MagicGen4UIDLengthSingle = 0x00, | ||||||
|  |     MagicGen4UIDLengthDouble = 0x01, | ||||||
|  |     MagicGen4UIDLengthTriple = 0x02 | ||||||
|  | } MagicGen4UIDLength; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     MagicGen4UltralightModeUL_EV1 = 0x00, | ||||||
|  |     MagicGen4UltralightModeNTAG = 0x01, | ||||||
|  |     MagicGen4UltralightModeUL_C = 0x02, | ||||||
|  |     MagicGen4UltralightModeUL = 0x03 | ||||||
|  | } MagicGen4UltralightMode; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     // for writing original (shadow) data
 | ||||||
|  |     MagicGen4ShadowModePreWrite = 0x00, | ||||||
|  |     // written data can be read once before restored to original
 | ||||||
|  |     MagicGen4ShadowModeRestore = 0x01, | ||||||
|  |     // written data is discarded
 | ||||||
|  |     MagicGen4ShadowModeIgnore = 0x02, | ||||||
|  |     // apparently for UL?
 | ||||||
|  |     MagicGen4ShadowModeHighSpeedIgnore = 0x03 | ||||||
|  | } MagicGen4ShadowMode; | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config); | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse); | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd); | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_read_blk(uint32_t pwd, uint8_t block_num, uint8_t* data); | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data); | ||||||
|  | 
 | ||||||
|  | bool magic_gen4_wipe(uint32_t pwd); | ||||||
|  | 
 | ||||||
|  | void magic_gen4_deactivate(); | ||||||
| @ -1,4 +1,4 @@ | |||||||
| #include "magic.h" | #include "classic_gen1.h" | ||||||
| 
 | 
 | ||||||
| #include <furi_hal_nfc.h> | #include <furi_hal_nfc.h> | ||||||
| 
 | 
 | ||||||
| @ -15,7 +15,7 @@ | |||||||
| 
 | 
 | ||||||
| #define MAGIC_BUFFER_SIZE (32) | #define MAGIC_BUFFER_SIZE (32) | ||||||
| 
 | 
 | ||||||
| bool magic_wupa() { | bool magic_gen1_wupa() { | ||||||
|     bool magic_activated = false; |     bool magic_activated = false; | ||||||
|     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
| @ -23,19 +23,6 @@ bool magic_wupa() { | |||||||
|     FuriHalNfcReturn ret = 0; |     FuriHalNfcReturn ret = 0; | ||||||
| 
 | 
 | ||||||
|     do { |     do { | ||||||
|         // Setup nfc poller
 |  | ||||||
|         furi_hal_nfc_exit_sleep(); |  | ||||||
|         furi_hal_nfc_ll_txrx_on(); |  | ||||||
|         furi_hal_nfc_ll_poll(); |  | ||||||
|         ret = furi_hal_nfc_ll_set_mode( |  | ||||||
|             FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106); |  | ||||||
|         if(ret != FuriHalNfcReturnOk) break; |  | ||||||
| 
 |  | ||||||
|         furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); |  | ||||||
|         furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); |  | ||||||
|         furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); |  | ||||||
|         furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); |  | ||||||
| 
 |  | ||||||
|         // Start communication
 |         // Start communication
 | ||||||
|         tx_data[0] = MAGIC_CMD_WUPA; |         tx_data[0] = MAGIC_CMD_WUPA; | ||||||
|         ret = furi_hal_nfc_ll_txrx_bits( |         ret = furi_hal_nfc_ll_txrx_bits( | ||||||
| @ -53,15 +40,10 @@ bool magic_wupa() { | |||||||
|         magic_activated = true; |         magic_activated = true; | ||||||
|     } while(false); |     } while(false); | ||||||
| 
 | 
 | ||||||
|     if(!magic_activated) { |  | ||||||
|         furi_hal_nfc_ll_txrx_off(); |  | ||||||
|         furi_hal_nfc_start_sleep(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return magic_activated; |     return magic_activated; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool magic_data_access_cmd() { | bool magic_gen1_data_access_cmd() { | ||||||
|     bool write_cmd_success = false; |     bool write_cmd_success = false; | ||||||
|     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
| @ -86,15 +68,10 @@ bool magic_data_access_cmd() { | |||||||
|         write_cmd_success = true; |         write_cmd_success = true; | ||||||
|     } while(false); |     } while(false); | ||||||
| 
 | 
 | ||||||
|     if(!write_cmd_success) { |  | ||||||
|         furi_hal_nfc_ll_txrx_off(); |  | ||||||
|         furi_hal_nfc_start_sleep(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return write_cmd_success; |     return write_cmd_success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool magic_read_block(uint8_t block_num, MfClassicBlock* data) { | bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) { | ||||||
|     furi_assert(data); |     furi_assert(data); | ||||||
| 
 | 
 | ||||||
|     bool read_success = false; |     bool read_success = false; | ||||||
| @ -122,15 +99,10 @@ bool magic_read_block(uint8_t block_num, MfClassicBlock* data) { | |||||||
|         read_success = true; |         read_success = true; | ||||||
|     } while(false); |     } while(false); | ||||||
| 
 | 
 | ||||||
|     if(!read_success) { |  | ||||||
|         furi_hal_nfc_ll_txrx_off(); |  | ||||||
|         furi_hal_nfc_start_sleep(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return read_success; |     return read_success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) { | bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) { | ||||||
|     furi_assert(data); |     furi_assert(data); | ||||||
| 
 | 
 | ||||||
|     bool write_success = false; |     bool write_success = false; | ||||||
| @ -170,15 +142,10 @@ bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) { | |||||||
|         write_success = true; |         write_success = true; | ||||||
|     } while(false); |     } while(false); | ||||||
| 
 | 
 | ||||||
|     if(!write_success) { |  | ||||||
|         furi_hal_nfc_ll_txrx_off(); |  | ||||||
|         furi_hal_nfc_start_sleep(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return write_success; |     return write_success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool magic_wipe() { | bool magic_gen1_wipe() { | ||||||
|     bool wipe_success = false; |     bool wipe_success = false; | ||||||
|     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; |     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
|     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; |     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||||
| @ -205,9 +172,4 @@ bool magic_wipe() { | |||||||
|     } while(false); |     } while(false); | ||||||
| 
 | 
 | ||||||
|     return wipe_success; |     return wipe_success; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void magic_deactivate() { |  | ||||||
|     furi_hal_nfc_ll_txrx_off(); |  | ||||||
|     furi_hal_nfc_sleep(); |  | ||||||
| } |  | ||||||
| @ -1,15 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <lib/nfc/protocols/mifare_classic.h> |  | ||||||
| 
 |  | ||||||
| bool magic_wupa(); |  | ||||||
| 
 |  | ||||||
| bool magic_read_block(uint8_t block_num, MfClassicBlock* data); |  | ||||||
| 
 |  | ||||||
| bool magic_data_access_cmd(); |  | ||||||
| 
 |  | ||||||
| bool magic_write_blk(uint8_t block_num, MfClassicBlock* data); |  | ||||||
| 
 |  | ||||||
| bool magic_wipe(); |  | ||||||
| 
 |  | ||||||
| void magic_deactivate(); |  | ||||||
							
								
								
									
										23
									
								
								applications/external/nfc_magic/lib/magic/types.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								applications/external/nfc_magic/lib/magic/types.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | #include "types.h" | ||||||
|  | 
 | ||||||
|  | const char* nfc_magic_type(MagicType type) { | ||||||
|  |     if(type == MagicTypeClassicGen1) { | ||||||
|  |         return "Classic Gen 1A/B"; | ||||||
|  |     } else if(type == MagicTypeClassicDirectWrite) { | ||||||
|  |         return "Classic DirectWrite"; | ||||||
|  |     } else if(type == MagicTypeClassicAPDU) { | ||||||
|  |         return "Classic APDU"; | ||||||
|  |     } else if(type == MagicTypeUltralightGen1) { | ||||||
|  |         return "Ultralight Gen 1"; | ||||||
|  |     } else if(type == MagicTypeUltralightDirectWrite) { | ||||||
|  |         return "Ultralight DirectWrite"; | ||||||
|  |     } else if(type == MagicTypeUltralightC_Gen1) { | ||||||
|  |         return "Ultralight-C Gen 1"; | ||||||
|  |     } else if(type == MagicTypeUltralightC_DirectWrite) { | ||||||
|  |         return "Ultralight-C DirectWrite"; | ||||||
|  |     } else if(type == MagicTypeGen4) { | ||||||
|  |         return "Gen 4 GTU"; | ||||||
|  |     } else { | ||||||
|  |         return "Unknown"; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								applications/external/nfc_magic/lib/magic/types.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								applications/external/nfc_magic/lib/magic/types.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "common.h" | ||||||
|  | 
 | ||||||
|  | const char* nfc_magic_type(MagicType type); | ||||||
							
								
								
									
										22
									
								
								applications/external/nfc_magic/nfc_magic.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								applications/external/nfc_magic/nfc_magic.c
									
									
									
									
										vendored
									
									
								
							| @ -48,8 +48,9 @@ NfcMagic* nfc_magic_alloc() { | |||||||
|         nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100); |         nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100); | ||||||
| 
 | 
 | ||||||
|     // Nfc device
 |     // Nfc device
 | ||||||
|     nfc_magic->nfc_dev = nfc_device_alloc(); |     nfc_magic->dev = malloc(sizeof(NfcMagicDevice)); | ||||||
|     furi_string_set(nfc_magic->nfc_dev->folder, NFC_APP_FOLDER); |     nfc_magic->source_dev = nfc_device_alloc(); | ||||||
|  |     furi_string_set(nfc_magic->source_dev->folder, NFC_APP_FOLDER); | ||||||
| 
 | 
 | ||||||
|     // Open GUI record
 |     // Open GUI record
 | ||||||
|     nfc_magic->gui = furi_record_open(RECORD_GUI); |     nfc_magic->gui = furi_record_open(RECORD_GUI); | ||||||
| @ -81,6 +82,13 @@ NfcMagic* nfc_magic_alloc() { | |||||||
|         NfcMagicViewTextInput, |         NfcMagicViewTextInput, | ||||||
|         text_input_get_view(nfc_magic->text_input)); |         text_input_get_view(nfc_magic->text_input)); | ||||||
| 
 | 
 | ||||||
|  |     // Byte Input
 | ||||||
|  |     nfc_magic->byte_input = byte_input_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         nfc_magic->view_dispatcher, | ||||||
|  |         NfcMagicViewByteInput, | ||||||
|  |         byte_input_get_view(nfc_magic->byte_input)); | ||||||
|  | 
 | ||||||
|     // Custom Widget
 |     // Custom Widget
 | ||||||
|     nfc_magic->widget = widget_alloc(); |     nfc_magic->widget = widget_alloc(); | ||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
| @ -93,7 +101,8 @@ void nfc_magic_free(NfcMagic* nfc_magic) { | |||||||
|     furi_assert(nfc_magic); |     furi_assert(nfc_magic); | ||||||
| 
 | 
 | ||||||
|     // Nfc device
 |     // Nfc device
 | ||||||
|     nfc_device_free(nfc_magic->nfc_dev); |     free(nfc_magic->dev); | ||||||
|  |     nfc_device_free(nfc_magic->source_dev); | ||||||
| 
 | 
 | ||||||
|     // Submenu
 |     // Submenu
 | ||||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); |     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); | ||||||
| @ -107,10 +116,14 @@ void nfc_magic_free(NfcMagic* nfc_magic) { | |||||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading); |     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading); | ||||||
|     loading_free(nfc_magic->loading); |     loading_free(nfc_magic->loading); | ||||||
| 
 | 
 | ||||||
|     // TextInput
 |     // Text Input
 | ||||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput); |     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput); | ||||||
|     text_input_free(nfc_magic->text_input); |     text_input_free(nfc_magic->text_input); | ||||||
| 
 | 
 | ||||||
|  |     // Byte Input
 | ||||||
|  |     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); | ||||||
|  |     byte_input_free(nfc_magic->byte_input); | ||||||
|  | 
 | ||||||
|     // Custom Widget
 |     // Custom Widget
 | ||||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); |     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||||
|     widget_free(nfc_magic->widget); |     widget_free(nfc_magic->widget); | ||||||
| @ -164,6 +177,7 @@ int32_t nfc_magic_app(void* p) { | |||||||
| 
 | 
 | ||||||
|     view_dispatcher_run(nfc_magic->view_dispatcher); |     view_dispatcher_run(nfc_magic->view_dispatcher); | ||||||
| 
 | 
 | ||||||
|  |     magic_deactivate(); | ||||||
|     nfc_magic_free(nfc_magic); |     nfc_magic_free(nfc_magic); | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								applications/external/nfc_magic/nfc_magic.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								applications/external/nfc_magic/nfc_magic.h
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +1,5 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | typedef struct NfcMagicDevice NfcMagicDevice; | ||||||
|  | 
 | ||||||
| typedef struct NfcMagic NfcMagic; | typedef struct NfcMagic NfcMagic; | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								applications/external/nfc_magic/nfc_magic_i.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								applications/external/nfc_magic/nfc_magic_i.h
									
									
									
									
										vendored
									
									
								
							| @ -3,7 +3,10 @@ | |||||||
| #include "nfc_magic.h" | #include "nfc_magic.h" | ||||||
| #include "nfc_magic_worker.h" | #include "nfc_magic_worker.h" | ||||||
| 
 | 
 | ||||||
| #include "lib/magic/magic.h" | #include "lib/magic/common.h" | ||||||
|  | #include "lib/magic/types.h" | ||||||
|  | #include "lib/magic/classic_gen1.h" | ||||||
|  | #include "lib/magic/gen4.h" | ||||||
| 
 | 
 | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <gui/gui.h> | #include <gui/gui.h> | ||||||
| @ -15,6 +18,7 @@ | |||||||
| #include <gui/modules/popup.h> | #include <gui/modules/popup.h> | ||||||
| #include <gui/modules/loading.h> | #include <gui/modules/loading.h> | ||||||
| #include <gui/modules/text_input.h> | #include <gui/modules/text_input.h> | ||||||
|  | #include <gui/modules/byte_input.h> | ||||||
| #include <gui/modules/widget.h> | #include <gui/modules/widget.h> | ||||||
| 
 | 
 | ||||||
| #include <input/input.h> | #include <input/input.h> | ||||||
| @ -39,14 +43,22 @@ enum NfcMagicCustomEvent { | |||||||
|     NfcMagicCustomEventTextInputDone, |     NfcMagicCustomEventTextInputDone, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct NfcMagicDevice { | ||||||
|  |     MagicType type; | ||||||
|  |     uint32_t cuid; | ||||||
|  |     uint32_t password; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct NfcMagic { | struct NfcMagic { | ||||||
|     NfcMagicWorker* worker; |     NfcMagicWorker* worker; | ||||||
|     ViewDispatcher* view_dispatcher; |     ViewDispatcher* view_dispatcher; | ||||||
|     Gui* gui; |     Gui* gui; | ||||||
|     NotificationApp* notifications; |     NotificationApp* notifications; | ||||||
|     SceneManager* scene_manager; |     SceneManager* scene_manager; | ||||||
|     // NfcMagicDevice* dev;
 |     struct NfcMagicDevice* dev; | ||||||
|     NfcDevice* nfc_dev; |     NfcDevice* source_dev; | ||||||
|  | 
 | ||||||
|  |     uint32_t new_password; | ||||||
| 
 | 
 | ||||||
|     FuriString* text_box_store; |     FuriString* text_box_store; | ||||||
| 
 | 
 | ||||||
| @ -55,6 +67,7 @@ struct NfcMagic { | |||||||
|     Popup* popup; |     Popup* popup; | ||||||
|     Loading* loading; |     Loading* loading; | ||||||
|     TextInput* text_input; |     TextInput* text_input; | ||||||
|  |     ByteInput* byte_input; | ||||||
|     Widget* widget; |     Widget* widget; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -63,6 +76,7 @@ typedef enum { | |||||||
|     NfcMagicViewPopup, |     NfcMagicViewPopup, | ||||||
|     NfcMagicViewLoading, |     NfcMagicViewLoading, | ||||||
|     NfcMagicViewTextInput, |     NfcMagicViewTextInput, | ||||||
|  |     NfcMagicViewByteInput, | ||||||
|     NfcMagicViewWidget, |     NfcMagicViewWidget, | ||||||
| } NfcMagicView; | } NfcMagicView; | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										372
									
								
								applications/external/nfc_magic/nfc_magic_worker.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										372
									
								
								applications/external/nfc_magic/nfc_magic_worker.c
									
									
									
									
										vendored
									
									
								
							| @ -1,6 +1,9 @@ | |||||||
| #include "nfc_magic_worker_i.h" | #include "nfc_magic_worker_i.h" | ||||||
| 
 | 
 | ||||||
| #include "lib/magic/magic.h" | #include "nfc_magic_i.h" | ||||||
|  | #include "lib/magic/common.h" | ||||||
|  | #include "lib/magic/classic_gen1.h" | ||||||
|  | #include "lib/magic/gen4.h" | ||||||
| 
 | 
 | ||||||
| #define TAG "NfcMagicWorker" | #define TAG "NfcMagicWorker" | ||||||
| 
 | 
 | ||||||
| @ -43,15 +46,20 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) { | |||||||
| void nfc_magic_worker_start( | void nfc_magic_worker_start( | ||||||
|     NfcMagicWorker* nfc_magic_worker, |     NfcMagicWorker* nfc_magic_worker, | ||||||
|     NfcMagicWorkerState state, |     NfcMagicWorkerState state, | ||||||
|  |     NfcMagicDevice* magic_dev, | ||||||
|     NfcDeviceData* dev_data, |     NfcDeviceData* dev_data, | ||||||
|  |     uint32_t new_password, | ||||||
|     NfcMagicWorkerCallback callback, |     NfcMagicWorkerCallback callback, | ||||||
|     void* context) { |     void* context) { | ||||||
|     furi_assert(nfc_magic_worker); |     furi_assert(nfc_magic_worker); | ||||||
|  |     furi_assert(magic_dev); | ||||||
|     furi_assert(dev_data); |     furi_assert(dev_data); | ||||||
| 
 | 
 | ||||||
|     nfc_magic_worker->callback = callback; |     nfc_magic_worker->callback = callback; | ||||||
|     nfc_magic_worker->context = context; |     nfc_magic_worker->context = context; | ||||||
|  |     nfc_magic_worker->magic_dev = magic_dev; | ||||||
|     nfc_magic_worker->dev_data = dev_data; |     nfc_magic_worker->dev_data = dev_data; | ||||||
|  |     nfc_magic_worker->new_password = new_password; | ||||||
|     nfc_magic_worker_change_state(nfc_magic_worker, state); |     nfc_magic_worker_change_state(nfc_magic_worker, state); | ||||||
|     furi_thread_start(nfc_magic_worker->thread); |     furi_thread_start(nfc_magic_worker->thread); | ||||||
| } | } | ||||||
| @ -63,6 +71,8 @@ int32_t nfc_magic_worker_task(void* context) { | |||||||
|         nfc_magic_worker_check(nfc_magic_worker); |         nfc_magic_worker_check(nfc_magic_worker); | ||||||
|     } else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { |     } else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { | ||||||
|         nfc_magic_worker_write(nfc_magic_worker); |         nfc_magic_worker_write(nfc_magic_worker); | ||||||
|  |     } else if(nfc_magic_worker->state == NfcMagicWorkerStateRekey) { | ||||||
|  |         nfc_magic_worker_rekey(nfc_magic_worker); | ||||||
|     } else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { |     } else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { | ||||||
|         nfc_magic_worker_wipe(nfc_magic_worker); |         nfc_magic_worker_wipe(nfc_magic_worker); | ||||||
|     } |     } | ||||||
| @ -74,59 +84,245 @@ int32_t nfc_magic_worker_task(void* context) { | |||||||
| 
 | 
 | ||||||
| void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) { | void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) { | ||||||
|     bool card_found_notified = false; |     bool card_found_notified = false; | ||||||
|  |     bool done = false; | ||||||
|     FuriHalNfcDevData nfc_data = {}; |     FuriHalNfcDevData nfc_data = {}; | ||||||
|     MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_data; |     NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; | ||||||
|  |     NfcDeviceData* dev_data = nfc_magic_worker->dev_data; | ||||||
|  |     NfcProtocol dev_protocol = dev_data->protocol; | ||||||
| 
 | 
 | ||||||
|     while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { |     while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { | ||||||
|         if(furi_hal_nfc_detect(&nfc_data, 200)) { |         do { | ||||||
|             if(!card_found_notified) { |             if(furi_hal_nfc_detect(&nfc_data, 200)) { | ||||||
|                 nfc_magic_worker->callback( |                 if(nfc_data.cuid != magic_dev->cuid) break; | ||||||
|                     NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); |                 if(!card_found_notified) { | ||||||
|                 card_found_notified = true; |                     nfc_magic_worker->callback( | ||||||
|             } |                         NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||||
|             furi_hal_nfc_sleep(); |                     card_found_notified = true; | ||||||
|             if(!magic_wupa()) { |                 } | ||||||
|                 FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)"); |                 furi_hal_nfc_sleep(); | ||||||
|                 nfc_magic_worker->callback( | 
 | ||||||
|                     NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); |                 magic_activate(); | ||||||
|                 break; |                 if(magic_dev->type == MagicTypeClassicGen1) { | ||||||
|             } |                     if(dev_protocol != NfcDeviceProtocolMifareClassic) break; | ||||||
|             furi_hal_nfc_sleep(); |                     MfClassicData* mfc_data = &dev_data->mf_classic_data; | ||||||
|         } | 
 | ||||||
|         if(magic_wupa()) { |                     if(mfc_data->type != MfClassicType1k) break; | ||||||
|             if(!magic_data_access_cmd()) { |                     if(!magic_gen1_wupa()) { | ||||||
|                 FURI_LOG_E(TAG, "No card response to data access command (not a magic card)"); |                         FURI_LOG_E(TAG, "Not Magic card"); | ||||||
|                 nfc_magic_worker->callback( |                         nfc_magic_worker->callback( | ||||||
|                     NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); |                             NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); | ||||||
|                 break; |                         done = true; | ||||||
|             } |                         break; | ||||||
|             for(size_t i = 0; i < 64; i++) { |                     } | ||||||
|                 FURI_LOG_D(TAG, "Writing block %d", i); |                     if(!magic_gen1_data_access_cmd()) { | ||||||
|                 if(!magic_write_blk(i, &src_data->block[i])) { |                         FURI_LOG_E(TAG, "Not Magic card"); | ||||||
|                     FURI_LOG_E(TAG, "Failed to write %d block", i); |                         nfc_magic_worker->callback( | ||||||
|                     nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context); |                             NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); | ||||||
|  |                         done = true; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     for(size_t i = 0; i < 64; i++) { | ||||||
|  |                         FURI_LOG_D(TAG, "Writing block %d", i); | ||||||
|  |                         if(!magic_gen1_write_blk(i, &mfc_data->block[i])) { | ||||||
|  |                             FURI_LOG_E(TAG, "Failed to write %d block", i); | ||||||
|  |                             nfc_magic_worker->callback( | ||||||
|  |                                 NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||||
|  |                             done = true; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     nfc_magic_worker->callback( | ||||||
|  |                         NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||||
|  |                     done = true; | ||||||
|  |                     break; | ||||||
|  |                 } else if(magic_dev->type == MagicTypeGen4) { | ||||||
|  |                     uint8_t gen4_config[28]; | ||||||
|  |                     uint32_t password = magic_dev->password; | ||||||
|  | 
 | ||||||
|  |                     uint32_t cuid; | ||||||
|  |                     if(dev_protocol == NfcDeviceProtocolMifareClassic) { | ||||||
|  |                         gen4_config[0] = 0x00; | ||||||
|  |                         gen4_config[27] = 0x00; | ||||||
|  |                     } else if(dev_protocol == NfcDeviceProtocolMifareUl) { | ||||||
|  |                         MfUltralightData* mf_ul_data = &dev_data->mf_ul_data; | ||||||
|  |                         gen4_config[0] = 0x01; | ||||||
|  |                         switch(mf_ul_data->type) { | ||||||
|  |                         case MfUltralightTypeUL11: | ||||||
|  |                         case MfUltralightTypeUL21: | ||||||
|  |                         // UL-C?
 | ||||||
|  |                         // UL?
 | ||||||
|  |                         default: | ||||||
|  |                             gen4_config[27] = MagicGen4UltralightModeUL_EV1; | ||||||
|  |                             break; | ||||||
|  |                         case MfUltralightTypeNTAG203: | ||||||
|  |                         case MfUltralightTypeNTAG213: | ||||||
|  |                         case MfUltralightTypeNTAG215: | ||||||
|  |                         case MfUltralightTypeNTAG216: | ||||||
|  |                         case MfUltralightTypeNTAGI2C1K: | ||||||
|  |                         case MfUltralightTypeNTAGI2C2K: | ||||||
|  |                         case MfUltralightTypeNTAGI2CPlus1K: | ||||||
|  |                         case MfUltralightTypeNTAGI2CPlus2K: | ||||||
|  |                             gen4_config[27] = MagicGen4UltralightModeNTAG; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     if(dev_data->nfc_data.uid_len == 4) { | ||||||
|  |                         gen4_config[1] = MagicGen4UIDLengthSingle; | ||||||
|  |                     } else if(dev_data->nfc_data.uid_len == 7) { | ||||||
|  |                         gen4_config[1] = MagicGen4UIDLengthDouble; | ||||||
|  |                     } else { | ||||||
|  |                         FURI_LOG_E(TAG, "Unexpected UID length %d", dev_data->nfc_data.uid_len); | ||||||
|  |                         nfc_magic_worker->callback( | ||||||
|  |                             NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||||
|  |                         done = true; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     gen4_config[2] = (uint8_t)(password >> 24); | ||||||
|  |                     gen4_config[3] = (uint8_t)(password >> 16); | ||||||
|  |                     gen4_config[4] = (uint8_t)(password >> 8); | ||||||
|  |                     gen4_config[5] = (uint8_t)password; | ||||||
|  | 
 | ||||||
|  |                     if(dev_protocol == NfcDeviceProtocolMifareUl) { | ||||||
|  |                         gen4_config[6] = MagicGen4ShadowModeHighSpeedIgnore; | ||||||
|  |                     } else { | ||||||
|  |                         gen4_config[6] = MagicGen4ShadowModeIgnore; | ||||||
|  |                     } | ||||||
|  |                     gen4_config[7] = 0x00; | ||||||
|  |                     memset(gen4_config + 8, 0, 16); | ||||||
|  |                     gen4_config[24] = dev_data->nfc_data.atqa[0]; | ||||||
|  |                     gen4_config[25] = dev_data->nfc_data.atqa[1]; | ||||||
|  |                     gen4_config[26] = dev_data->nfc_data.sak; | ||||||
|  | 
 | ||||||
|  |                     furi_hal_nfc_activate_nfca(200, &cuid); | ||||||
|  |                     if(!magic_gen4_set_cfg(password, gen4_config, sizeof(gen4_config), false)) { | ||||||
|  |                         nfc_magic_worker->callback( | ||||||
|  |                             NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||||
|  |                         done = true; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     if(dev_protocol == NfcDeviceProtocolMifareClassic) { | ||||||
|  |                         MfClassicData* mfc_data = &dev_data->mf_classic_data; | ||||||
|  |                         size_t block_count = 64; | ||||||
|  |                         if(mfc_data->type == MfClassicType4k) block_count = 256; | ||||||
|  |                         for(size_t i = 0; i < block_count; i++) { | ||||||
|  |                             FURI_LOG_D(TAG, "Writing block %d", i); | ||||||
|  |                             if(!magic_gen4_write_blk(password, i, mfc_data->block[i].value)) { | ||||||
|  |                                 FURI_LOG_E(TAG, "Failed to write %d block", i); | ||||||
|  |                                 nfc_magic_worker->callback( | ||||||
|  |                                     NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||||
|  |                                 done = true; | ||||||
|  |                                 break; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } else if(dev_protocol == NfcDeviceProtocolMifareUl) { | ||||||
|  |                         MfUltralightData* mf_ul_data = &dev_data->mf_ul_data; | ||||||
|  |                         for(size_t i = 0; (i * 4) < mf_ul_data->data_read; i++) { | ||||||
|  |                             size_t data_offset = i * 4; | ||||||
|  |                             FURI_LOG_D( | ||||||
|  |                                 TAG, | ||||||
|  |                                 "Writing page %zu (%zu/%u)", | ||||||
|  |                                 i, | ||||||
|  |                                 data_offset, | ||||||
|  |                                 mf_ul_data->data_read); | ||||||
|  |                             uint8_t* block = mf_ul_data->data + data_offset; | ||||||
|  |                             if(!magic_gen4_write_blk(password, i, block)) { | ||||||
|  |                                 FURI_LOG_E(TAG, "Failed to write %zu page", i); | ||||||
|  |                                 nfc_magic_worker->callback( | ||||||
|  |                                     NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||||
|  |                                 done = true; | ||||||
|  |                                 break; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         uint8_t buffer[16] = {0}; | ||||||
|  | 
 | ||||||
|  |                         for(size_t i = 0; i < 8; i++) { | ||||||
|  |                             memcpy(buffer, &mf_ul_data->signature[i * 4], 4); //-V1086
 | ||||||
|  |                             if(!magic_gen4_write_blk(password, 0xF2 + i, buffer)) { | ||||||
|  |                                 FURI_LOG_E(TAG, "Failed to write signature block %d", i); | ||||||
|  |                                 nfc_magic_worker->callback( | ||||||
|  |                                     NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||||
|  |                                 done = true; | ||||||
|  |                                 break; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         buffer[0] = mf_ul_data->version.header; | ||||||
|  |                         buffer[1] = mf_ul_data->version.vendor_id; | ||||||
|  |                         buffer[2] = mf_ul_data->version.prod_type; | ||||||
|  |                         buffer[3] = mf_ul_data->version.prod_subtype; | ||||||
|  |                         if(!magic_gen4_write_blk(password, 0xFA, buffer)) { | ||||||
|  |                             FURI_LOG_E(TAG, "Failed to write version block 0"); | ||||||
|  |                             nfc_magic_worker->callback( | ||||||
|  |                                 NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||||
|  |                             done = true; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         buffer[0] = mf_ul_data->version.prod_ver_major; | ||||||
|  |                         buffer[1] = mf_ul_data->version.prod_ver_minor; | ||||||
|  |                         buffer[2] = mf_ul_data->version.storage_size; | ||||||
|  |                         buffer[3] = mf_ul_data->version.protocol_type; | ||||||
|  |                         if(!magic_gen4_write_blk(password, 0xFB, buffer)) { | ||||||
|  |                             FURI_LOG_E(TAG, "Failed to write version block 1"); | ||||||
|  |                             nfc_magic_worker->callback( | ||||||
|  |                                 NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||||
|  |                             done = true; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     nfc_magic_worker->callback( | ||||||
|  |                         NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||||
|  |                     done = true; | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); |         } while(false); | ||||||
|             break; | 
 | ||||||
|         } else { |         if(done) break; | ||||||
|             if(card_found_notified) { | 
 | ||||||
|                 nfc_magic_worker->callback( |         if(card_found_notified) { | ||||||
|                     NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); |             nfc_magic_worker->callback( | ||||||
|                 card_found_notified = false; |                 NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); | ||||||
|             } |             card_found_notified = false; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         furi_delay_ms(300); |         furi_delay_ms(300); | ||||||
|     } |     } | ||||||
|     magic_deactivate(); |     magic_deactivate(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { | void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { | ||||||
|  |     NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; | ||||||
|     bool card_found_notified = false; |     bool card_found_notified = false; | ||||||
|  |     uint8_t gen4_config[MAGIC_GEN4_CONFIG_LEN]; | ||||||
| 
 | 
 | ||||||
|     while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) { |     while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) { | ||||||
|         if(magic_wupa()) { |         magic_activate(); | ||||||
|  |         if(magic_gen1_wupa()) { | ||||||
|  |             magic_dev->type = MagicTypeClassicGen1; | ||||||
|  |             if(!card_found_notified) { | ||||||
|  |                 nfc_magic_worker->callback( | ||||||
|  |                     NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||||
|  |                 card_found_notified = true; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             furi_hal_nfc_activate_nfca(200, &magic_dev->cuid); | ||||||
|  |             nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         magic_deactivate(); | ||||||
|  |         furi_delay_ms(300); | ||||||
|  |         magic_activate(); | ||||||
|  | 
 | ||||||
|  |         furi_hal_nfc_activate_nfca(200, &magic_dev->cuid); | ||||||
|  |         if(magic_gen4_get_cfg(magic_dev->password, gen4_config)) { | ||||||
|  |             magic_dev->type = MagicTypeGen4; | ||||||
|             if(!card_found_notified) { |             if(!card_found_notified) { | ||||||
|                 nfc_magic_worker->callback( |                 nfc_magic_worker->callback( | ||||||
|                     NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); |                     NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||||
| @ -135,12 +331,56 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { | |||||||
| 
 | 
 | ||||||
|             nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); |             nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||||
|             break; |             break; | ||||||
|         } else { |         } | ||||||
|  | 
 | ||||||
|  |         if(card_found_notified) { | ||||||
|  |             nfc_magic_worker->callback( | ||||||
|  |                 NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); | ||||||
|  |             card_found_notified = false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         magic_deactivate(); | ||||||
|  |         furi_delay_ms(300); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     magic_deactivate(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker) { | ||||||
|  |     NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; | ||||||
|  |     bool card_found_notified = false; | ||||||
|  | 
 | ||||||
|  |     if(magic_dev->type != MagicTypeGen4) { | ||||||
|  |         nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     while(nfc_magic_worker->state == NfcMagicWorkerStateRekey) { | ||||||
|  |         magic_activate(); | ||||||
|  |         uint32_t cuid; | ||||||
|  |         furi_hal_nfc_activate_nfca(200, &cuid); | ||||||
|  |         if(cuid != magic_dev->cuid) { | ||||||
|             if(card_found_notified) { |             if(card_found_notified) { | ||||||
|                 nfc_magic_worker->callback( |                 nfc_magic_worker->callback( | ||||||
|                     NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); |                     NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); | ||||||
|                 card_found_notified = false; |                 card_found_notified = false; | ||||||
|             } |             } | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||||
|  |         card_found_notified = true; | ||||||
|  | 
 | ||||||
|  |         if(magic_gen4_set_pwd(magic_dev->password, nfc_magic_worker->new_password)) { | ||||||
|  |             magic_dev->password = nfc_magic_worker->new_password; | ||||||
|  |             nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(card_found_notified) { //-V547
 | ||||||
|  |             nfc_magic_worker->callback( | ||||||
|  |                 NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); | ||||||
|  |             card_found_notified = false; | ||||||
|         } |         } | ||||||
|         furi_delay_ms(300); |         furi_delay_ms(300); | ||||||
|     } |     } | ||||||
| @ -148,6 +388,10 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { | void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { | ||||||
|  |     NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; | ||||||
|  |     bool card_found_notified = false; | ||||||
|  |     bool card_wiped = false; | ||||||
|  | 
 | ||||||
|     MfClassicBlock block; |     MfClassicBlock block; | ||||||
|     memset(&block, 0, sizeof(MfClassicBlock)); |     memset(&block, 0, sizeof(MfClassicBlock)); | ||||||
|     block.value[0] = 0x01; |     block.value[0] = 0x01; | ||||||
| @ -159,14 +403,48 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { | |||||||
|     block.value[6] = 0x04; |     block.value[6] = 0x04; | ||||||
| 
 | 
 | ||||||
|     while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { |     while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { | ||||||
|         magic_deactivate(); |         do { | ||||||
|         furi_delay_ms(300); |             magic_deactivate(); | ||||||
|         if(!magic_wupa()) continue; |             furi_delay_ms(300); | ||||||
|         if(!magic_wipe()) continue; |             if(!magic_activate()) break; | ||||||
|         if(!magic_data_access_cmd()) continue; |             if(magic_dev->type == MagicTypeClassicGen1) { | ||||||
|         if(!magic_write_blk(0, &block)) continue; |                 if(!magic_gen1_wupa()) break; | ||||||
|         nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); |                 if(!card_found_notified) { | ||||||
|         break; |                     nfc_magic_worker->callback( | ||||||
|  |                         NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||||
|  |                     card_found_notified = true; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(!magic_gen1_wipe()) break; | ||||||
|  |                 if(!magic_gen1_data_access_cmd()) break; | ||||||
|  |                 if(!magic_gen1_write_blk(0, &block)) break; | ||||||
|  | 
 | ||||||
|  |                 card_wiped = true; | ||||||
|  |                 nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||||
|  |             } else if(magic_dev->type == MagicTypeGen4) { | ||||||
|  |                 uint32_t cuid; | ||||||
|  |                 if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; | ||||||
|  |                 if(cuid != magic_dev->cuid) break; | ||||||
|  |                 if(!card_found_notified) { | ||||||
|  |                     nfc_magic_worker->callback( | ||||||
|  |                         NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||||
|  |                     card_found_notified = true; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(!magic_gen4_wipe(magic_dev->password)) break; | ||||||
|  | 
 | ||||||
|  |                 card_wiped = true; | ||||||
|  |                 nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||||
|  |             } | ||||||
|  |         } while(false); | ||||||
|  | 
 | ||||||
|  |         if(card_wiped) break; | ||||||
|  | 
 | ||||||
|  |         if(card_found_notified) { | ||||||
|  |             nfc_magic_worker->callback( | ||||||
|  |                 NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); | ||||||
|  |             card_found_notified = false; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     magic_deactivate(); |     magic_deactivate(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <lib/nfc/nfc_device.h> | #include <lib/nfc/nfc_device.h> | ||||||
|  | #include "nfc_magic.h" | ||||||
| 
 | 
 | ||||||
| typedef struct NfcMagicWorker NfcMagicWorker; | typedef struct NfcMagicWorker NfcMagicWorker; | ||||||
| 
 | 
 | ||||||
| @ -9,6 +10,7 @@ typedef enum { | |||||||
| 
 | 
 | ||||||
|     NfcMagicWorkerStateCheck, |     NfcMagicWorkerStateCheck, | ||||||
|     NfcMagicWorkerStateWrite, |     NfcMagicWorkerStateWrite, | ||||||
|  |     NfcMagicWorkerStateRekey, | ||||||
|     NfcMagicWorkerStateWipe, |     NfcMagicWorkerStateWipe, | ||||||
| 
 | 
 | ||||||
|     NfcMagicWorkerStateStop, |     NfcMagicWorkerStateStop, | ||||||
| @ -33,6 +35,8 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker); | |||||||
| void nfc_magic_worker_start( | void nfc_magic_worker_start( | ||||||
|     NfcMagicWorker* nfc_magic_worker, |     NfcMagicWorker* nfc_magic_worker, | ||||||
|     NfcMagicWorkerState state, |     NfcMagicWorkerState state, | ||||||
|  |     NfcMagicDevice* magic_dev, | ||||||
|     NfcDeviceData* dev_data, |     NfcDeviceData* dev_data, | ||||||
|  |     uint32_t new_password, | ||||||
|     NfcMagicWorkerCallback callback, |     NfcMagicWorkerCallback callback, | ||||||
|     void* context); |     void* context); | ||||||
|  | |||||||
| @ -3,11 +3,14 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| 
 | 
 | ||||||
| #include "nfc_magic_worker.h" | #include "nfc_magic_worker.h" | ||||||
|  | #include "lib/magic/common.h" | ||||||
| 
 | 
 | ||||||
| struct NfcMagicWorker { | struct NfcMagicWorker { | ||||||
|     FuriThread* thread; |     FuriThread* thread; | ||||||
| 
 | 
 | ||||||
|  |     NfcMagicDevice* magic_dev; | ||||||
|     NfcDeviceData* dev_data; |     NfcDeviceData* dev_data; | ||||||
|  |     uint32_t new_password; | ||||||
| 
 | 
 | ||||||
|     NfcMagicWorkerCallback callback; |     NfcMagicWorkerCallback callback; | ||||||
|     void* context; |     void* context; | ||||||
| @ -21,4 +24,6 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker); | |||||||
| 
 | 
 | ||||||
| void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker); | void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker); | ||||||
| 
 | 
 | ||||||
|  | void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker); | ||||||
|  | 
 | ||||||
| void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker); | void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker); | ||||||
|  | |||||||
							
								
								
									
										50
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | #include "../nfc_magic_i.h" | ||||||
|  | enum SubmenuIndex { | ||||||
|  |     SubmenuIndexWrite, | ||||||
|  |     SubmenuIndexWipe, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_actions_submenu_callback(void* context, uint32_t index) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_actions_on_enter(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     Submenu* submenu = nfc_magic->submenu; | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, "Write", SubmenuIndexWrite, nfc_magic_scene_actions_submenu_callback, nfc_magic); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_actions_submenu_callback, nfc_magic); | ||||||
|  | 
 | ||||||
|  |     submenu_set_selected_item( | ||||||
|  |         submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions)); | ||||||
|  |     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool nfc_magic_scene_actions_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == SubmenuIndexWrite) { | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == SubmenuIndexWipe) { | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |         scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions, event.event); | ||||||
|  |     } else if(event.type == SceneManagerEventTypeBack) { | ||||||
|  |         consumed = scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |             nfc_magic->scene_manager, NfcMagicSceneStart); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_actions_on_exit(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     submenu_reset(nfc_magic->submenu); | ||||||
|  | } | ||||||
| @ -42,7 +42,9 @@ void nfc_magic_scene_check_on_enter(void* context) { | |||||||
|     nfc_magic_worker_start( |     nfc_magic_worker_start( | ||||||
|         nfc_magic->worker, |         nfc_magic->worker, | ||||||
|         NfcMagicWorkerStateCheck, |         NfcMagicWorkerStateCheck, | ||||||
|         &nfc_magic->nfc_dev->dev_data, |         nfc_magic->dev, | ||||||
|  |         &nfc_magic->source_dev->dev_data, | ||||||
|  |         nfc_magic->new_password, | ||||||
|         nfc_magic_check_worker_callback, |         nfc_magic_check_worker_callback, | ||||||
|         nfc_magic); |         nfc_magic); | ||||||
|     nfc_magic_blink_start(nfc_magic); |     nfc_magic_blink_start(nfc_magic); | ||||||
|  | |||||||
| @ -1,4 +1,8 @@ | |||||||
| ADD_SCENE(nfc_magic, start, Start) | ADD_SCENE(nfc_magic, start, Start) | ||||||
|  | ADD_SCENE(nfc_magic, key_input, KeyInput) | ||||||
|  | ADD_SCENE(nfc_magic, actions, Actions) | ||||||
|  | ADD_SCENE(nfc_magic, gen4_actions, Gen4Actions) | ||||||
|  | ADD_SCENE(nfc_magic, new_key_input, NewKeyInput) | ||||||
| ADD_SCENE(nfc_magic, file_select, FileSelect) | ADD_SCENE(nfc_magic, file_select, FileSelect) | ||||||
| ADD_SCENE(nfc_magic, write_confirm, WriteConfirm) | ADD_SCENE(nfc_magic, write_confirm, WriteConfirm) | ||||||
| ADD_SCENE(nfc_magic, wrong_card, WrongCard) | ADD_SCENE(nfc_magic, wrong_card, WrongCard) | ||||||
| @ -8,5 +12,7 @@ ADD_SCENE(nfc_magic, success, Success) | |||||||
| ADD_SCENE(nfc_magic, check, Check) | ADD_SCENE(nfc_magic, check, Check) | ||||||
| ADD_SCENE(nfc_magic, not_magic, NotMagic) | ADD_SCENE(nfc_magic, not_magic, NotMagic) | ||||||
| ADD_SCENE(nfc_magic, magic_info, MagicInfo) | ADD_SCENE(nfc_magic, magic_info, MagicInfo) | ||||||
|  | ADD_SCENE(nfc_magic, rekey, Rekey) | ||||||
|  | ADD_SCENE(nfc_magic, rekey_fail, RekeyFail) | ||||||
| ADD_SCENE(nfc_magic, wipe, Wipe) | ADD_SCENE(nfc_magic, wipe, Wipe) | ||||||
| ADD_SCENE(nfc_magic, wipe_fail, WipeFail) | ADD_SCENE(nfc_magic, wipe_fail, WipeFail) | ||||||
|  | |||||||
| @ -1,22 +1,60 @@ | |||||||
| #include "../nfc_magic_i.h" | #include "../nfc_magic_i.h" | ||||||
| 
 | 
 | ||||||
| static bool nfc_magic_scene_file_select_is_file_suitable(NfcDevice* nfc_dev) { | static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagic* nfc_magic) { | ||||||
|     return (nfc_dev->format == NfcDeviceSaveFormatMifareClassic) && |     NfcDevice* nfc_dev = nfc_magic->source_dev; | ||||||
|            (nfc_dev->dev_data.mf_classic_data.type == MfClassicType1k) && |     if(nfc_dev->format == NfcDeviceSaveFormatMifareClassic) { | ||||||
|            (nfc_dev->dev_data.nfc_data.uid_len == 4); |         switch(nfc_magic->dev->type) { | ||||||
|  |         case MagicTypeClassicGen1: | ||||||
|  |         case MagicTypeClassicDirectWrite: | ||||||
|  |         case MagicTypeClassicAPDU: | ||||||
|  |             if((nfc_dev->dev_data.mf_classic_data.type != MfClassicType1k) || | ||||||
|  |                (nfc_dev->dev_data.nfc_data.uid_len != 4)) { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  | 
 | ||||||
|  |         case MagicTypeGen4: | ||||||
|  |             return true; | ||||||
|  |         default: | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } else if( | ||||||
|  |         (nfc_dev->format == NfcDeviceSaveFormatMifareUl) && | ||||||
|  |         (nfc_dev->dev_data.nfc_data.uid_len == 7)) { | ||||||
|  |         switch(nfc_magic->dev->type) { | ||||||
|  |         case MagicTypeUltralightGen1: | ||||||
|  |         case MagicTypeUltralightDirectWrite: | ||||||
|  |         case MagicTypeUltralightC_Gen1: | ||||||
|  |         case MagicTypeUltralightC_DirectWrite: | ||||||
|  |         case MagicTypeGen4: | ||||||
|  |             switch(nfc_dev->dev_data.mf_ul_data.type) { | ||||||
|  |             case MfUltralightTypeNTAGI2C1K: | ||||||
|  |             case MfUltralightTypeNTAGI2C2K: | ||||||
|  |             case MfUltralightTypeNTAGI2CPlus1K: | ||||||
|  |             case MfUltralightTypeNTAGI2CPlus2K: | ||||||
|  |                 return false; | ||||||
|  |             default: | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |         default: | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_magic_scene_file_select_on_enter(void* context) { | void nfc_magic_scene_file_select_on_enter(void* context) { | ||||||
|     NfcMagic* nfc_magic = context; |     NfcMagic* nfc_magic = context; | ||||||
|     // Process file_select return
 |     // Process file_select return
 | ||||||
|     nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic); |     nfc_device_set_loading_callback( | ||||||
|  |         nfc_magic->source_dev, nfc_magic_show_loading_popup, nfc_magic); | ||||||
| 
 | 
 | ||||||
|     if(!furi_string_size(nfc_magic->nfc_dev->load_path)) { |     if(!furi_string_size(nfc_magic->source_dev->load_path)) { | ||||||
|         furi_string_set_str(nfc_magic->nfc_dev->load_path, NFC_APP_FOLDER); |         furi_string_set_str(nfc_magic->source_dev->load_path, NFC_APP_FOLDER); | ||||||
|     } |     } | ||||||
| 
 |     if(nfc_file_select(nfc_magic->source_dev)) { | ||||||
|     if(nfc_file_select(nfc_magic->nfc_dev)) { |         if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic)) { | ||||||
|         if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) { |  | ||||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); | ||||||
|         } else { |         } else { | ||||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard); |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard); | ||||||
| @ -34,5 +72,5 @@ bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event | |||||||
| 
 | 
 | ||||||
| void nfc_magic_scene_file_select_on_exit(void* context) { | void nfc_magic_scene_file_select_on_exit(void* context) { | ||||||
|     NfcMagic* nfc_magic = context; |     NfcMagic* nfc_magic = context; | ||||||
|     nfc_device_set_loading_callback(nfc_magic->nfc_dev, NULL, nfc_magic); |     nfc_device_set_loading_callback(nfc_magic->source_dev, NULL, nfc_magic); | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										70
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | |||||||
|  | #include "../nfc_magic_i.h" | ||||||
|  | enum SubmenuIndex { | ||||||
|  |     SubmenuIndexWrite, | ||||||
|  |     SubmenuIndexChangePassword, | ||||||
|  |     SubmenuIndexWipe, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_gen4_actions_submenu_callback(void* context, uint32_t index) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_gen4_actions_on_enter(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     Submenu* submenu = nfc_magic->submenu; | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Write", | ||||||
|  |         SubmenuIndexWrite, | ||||||
|  |         nfc_magic_scene_gen4_actions_submenu_callback, | ||||||
|  |         nfc_magic); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Change password", | ||||||
|  |         SubmenuIndexChangePassword, | ||||||
|  |         nfc_magic_scene_gen4_actions_submenu_callback, | ||||||
|  |         nfc_magic); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Wipe", | ||||||
|  |         SubmenuIndexWipe, | ||||||
|  |         nfc_magic_scene_gen4_actions_submenu_callback, | ||||||
|  |         nfc_magic); | ||||||
|  | 
 | ||||||
|  |     submenu_set_selected_item( | ||||||
|  |         submenu, | ||||||
|  |         scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneGen4Actions)); | ||||||
|  |     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool nfc_magic_scene_gen4_actions_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == SubmenuIndexWrite) { | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == SubmenuIndexChangePassword) { | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNewKeyInput); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == SubmenuIndexWipe) { | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |         scene_manager_set_scene_state( | ||||||
|  |             nfc_magic->scene_manager, NfcMagicSceneGen4Actions, event.event); | ||||||
|  |     } else if(event.type == SceneManagerEventTypeBack) { | ||||||
|  |         consumed = scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |             nfc_magic->scene_manager, NfcMagicSceneStart); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_gen4_actions_on_exit(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     submenu_reset(nfc_magic->submenu); | ||||||
|  | } | ||||||
							
								
								
									
										45
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | #include "../nfc_magic_i.h" | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_key_input_byte_input_callback(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_send_custom_event( | ||||||
|  |         nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_key_input_on_enter(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     // Setup view
 | ||||||
|  |     ByteInput* byte_input = nfc_magic->byte_input; | ||||||
|  |     byte_input_set_header_text(byte_input, "Enter the password in hex"); | ||||||
|  |     byte_input_set_result_callback( | ||||||
|  |         byte_input, | ||||||
|  |         nfc_magic_scene_key_input_byte_input_callback, | ||||||
|  |         NULL, | ||||||
|  |         nfc_magic, | ||||||
|  |         (uint8_t*)&nfc_magic->dev->password, | ||||||
|  |         4); | ||||||
|  |     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool nfc_magic_scene_key_input_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == NfcMagicCustomEventByteInputDone) { | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_key_input_on_exit(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     // Clear view
 | ||||||
|  |     byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0); | ||||||
|  |     byte_input_set_header_text(nfc_magic->byte_input, ""); | ||||||
|  | } | ||||||
| @ -1,4 +1,5 @@ | |||||||
| #include "../nfc_magic_i.h" | #include "../nfc_magic_i.h" | ||||||
|  | #include "../lib/magic/types.h" | ||||||
| 
 | 
 | ||||||
| void nfc_magic_scene_magic_info_widget_callback( | void nfc_magic_scene_magic_info_widget_callback( | ||||||
|     GuiButtonType result, |     GuiButtonType result, | ||||||
| @ -13,14 +14,18 @@ void nfc_magic_scene_magic_info_widget_callback( | |||||||
| void nfc_magic_scene_magic_info_on_enter(void* context) { | void nfc_magic_scene_magic_info_on_enter(void* context) { | ||||||
|     NfcMagic* nfc_magic = context; |     NfcMagic* nfc_magic = context; | ||||||
|     Widget* widget = nfc_magic->widget; |     Widget* widget = nfc_magic->widget; | ||||||
|  |     const char* card_type = nfc_magic_type(nfc_magic->dev->type); | ||||||
| 
 | 
 | ||||||
|     notification_message(nfc_magic->notifications, &sequence_success); |     notification_message(nfc_magic->notifications, &sequence_success); | ||||||
| 
 | 
 | ||||||
|     widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48); |     widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48); | ||||||
|     widget_add_string_element( |     widget_add_string_element( | ||||||
|         widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected"); |         widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected"); | ||||||
|  |     widget_add_string_element(widget, 3, 17, AlignLeft, AlignTop, FontSecondary, card_type); | ||||||
|     widget_add_button_element( |     widget_add_button_element( | ||||||
|         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic); |         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic); | ||||||
|  |     widget_add_button_element( | ||||||
|  |         widget, GuiButtonTypeRight, "More", nfc_magic_scene_magic_info_widget_callback, nfc_magic); | ||||||
| 
 | 
 | ||||||
|     // Setup and start worker
 |     // Setup and start worker
 | ||||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); |     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||||
| @ -33,6 +38,15 @@ bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event) | |||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == GuiButtonTypeLeft) { |         if(event.event == GuiButtonTypeLeft) { | ||||||
|             consumed = scene_manager_previous_scene(nfc_magic->scene_manager); |             consumed = scene_manager_previous_scene(nfc_magic->scene_manager); | ||||||
|  |         } else if(event.event == GuiButtonTypeRight) { | ||||||
|  |             MagicType type = nfc_magic->dev->type; | ||||||
|  |             if(type == MagicTypeGen4) { | ||||||
|  |                 scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneGen4Actions); | ||||||
|  |                 consumed = true; | ||||||
|  |             } else { | ||||||
|  |                 scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneActions); | ||||||
|  |                 consumed = true; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return consumed; |     return consumed; | ||||||
|  | |||||||
							
								
								
									
										45
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | #include "../nfc_magic_i.h" | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_new_key_input_byte_input_callback(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_send_custom_event( | ||||||
|  |         nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_new_key_input_on_enter(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     // Setup view
 | ||||||
|  |     ByteInput* byte_input = nfc_magic->byte_input; | ||||||
|  |     byte_input_set_header_text(byte_input, "Enter the password in hex"); | ||||||
|  |     byte_input_set_result_callback( | ||||||
|  |         byte_input, | ||||||
|  |         nfc_magic_scene_new_key_input_byte_input_callback, | ||||||
|  |         NULL, | ||||||
|  |         nfc_magic, | ||||||
|  |         (uint8_t*)&nfc_magic->new_password, | ||||||
|  |         4); | ||||||
|  |     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool nfc_magic_scene_new_key_input_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == NfcMagicCustomEventByteInputDone) { | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekey); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_new_key_input_on_exit(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     // Clear view
 | ||||||
|  |     byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0); | ||||||
|  |     byte_input_set_header_text(nfc_magic->byte_input, ""); | ||||||
|  | } | ||||||
							
								
								
									
										95
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | |||||||
|  | #include "../nfc_magic_i.h" | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |     NfcMagicSceneRekeyStateCardSearch, | ||||||
|  |     NfcMagicSceneRekeyStateCardFound, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | bool nfc_magic_rekey_worker_callback(NfcMagicWorkerEvent event, void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  | 
 | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event); | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void nfc_magic_scene_rekey_setup_view(NfcMagic* nfc_magic) { | ||||||
|  |     Popup* popup = nfc_magic->popup; | ||||||
|  |     popup_reset(popup); | ||||||
|  |     uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneRekey); | ||||||
|  | 
 | ||||||
|  |     if(state == NfcMagicSceneRekeyStateCardSearch) { | ||||||
|  |         popup_set_text( | ||||||
|  |             nfc_magic->popup, | ||||||
|  |             "Apply the\nsame card\nto the back", | ||||||
|  |             128, | ||||||
|  |             32, | ||||||
|  |             AlignRight, | ||||||
|  |             AlignCenter); | ||||||
|  |         popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); | ||||||
|  |     } else { | ||||||
|  |         popup_set_icon(popup, 12, 23, &I_Loading_24); | ||||||
|  |         popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_rekey_on_enter(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     scene_manager_set_scene_state( | ||||||
|  |         nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); | ||||||
|  |     nfc_magic_scene_rekey_setup_view(nfc_magic); | ||||||
|  | 
 | ||||||
|  |     // Setup and start worker
 | ||||||
|  |     nfc_magic_worker_start( | ||||||
|  |         nfc_magic->worker, | ||||||
|  |         NfcMagicWorkerStateRekey, | ||||||
|  |         nfc_magic->dev, | ||||||
|  |         &nfc_magic->source_dev->dev_data, | ||||||
|  |         nfc_magic->new_password, | ||||||
|  |         nfc_magic_rekey_worker_callback, | ||||||
|  |         nfc_magic); | ||||||
|  |     nfc_magic_blink_start(nfc_magic); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool nfc_magic_scene_rekey_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == NfcMagicWorkerEventSuccess) { | ||||||
|  |             nfc_magic->dev->password = nfc_magic->new_password; | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == NfcMagicWorkerEventFail) { | ||||||
|  |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekeyFail); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == NfcMagicWorkerEventCardDetected) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardFound); | ||||||
|  |             nfc_magic_scene_rekey_setup_view(nfc_magic); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == NfcMagicWorkerEventNoCardDetected) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); | ||||||
|  |             nfc_magic_scene_rekey_setup_view(nfc_magic); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_rekey_on_exit(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     nfc_magic_worker_stop(nfc_magic->worker); | ||||||
|  |     scene_manager_set_scene_state( | ||||||
|  |         nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); | ||||||
|  |     // Clear view
 | ||||||
|  |     popup_reset(nfc_magic->popup); | ||||||
|  | 
 | ||||||
|  |     nfc_magic_blink_stop(nfc_magic); | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | #include "../nfc_magic_i.h" | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_rekey_fail_widget_callback( | ||||||
|  |     GuiButtonType result, | ||||||
|  |     InputType type, | ||||||
|  |     void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     if(type == InputTypeShort) { | ||||||
|  |         view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_rekey_fail_on_enter(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     Widget* widget = nfc_magic->widget; | ||||||
|  | 
 | ||||||
|  |     notification_message(nfc_magic->notifications, &sequence_error); | ||||||
|  | 
 | ||||||
|  |     widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48); | ||||||
|  |     widget_add_string_element( | ||||||
|  |         widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Can't change password!"); | ||||||
|  | 
 | ||||||
|  |     widget_add_button_element( | ||||||
|  |         widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_rekey_fail_widget_callback, nfc_magic); | ||||||
|  | 
 | ||||||
|  |     // Setup and start worker
 | ||||||
|  |     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool nfc_magic_scene_rekey_fail_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == GuiButtonTypeLeft) { | ||||||
|  |             consumed = scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |                 nfc_magic->scene_manager, NfcMagicSceneStart); | ||||||
|  |         } | ||||||
|  |     } else if(event.type == SceneManagerEventTypeBack) { | ||||||
|  |         consumed = scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |             nfc_magic->scene_manager, NfcMagicSceneStart); | ||||||
|  |     } | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_magic_scene_rekey_fail_on_exit(void* context) { | ||||||
|  |     NfcMagic* nfc_magic = context; | ||||||
|  | 
 | ||||||
|  |     widget_reset(nfc_magic->widget); | ||||||
|  | } | ||||||
| @ -1,8 +1,7 @@ | |||||||
| #include "../nfc_magic_i.h" | #include "../nfc_magic_i.h" | ||||||
| enum SubmenuIndex { | enum SubmenuIndex { | ||||||
|     SubmenuIndexCheck, |     SubmenuIndexCheck, | ||||||
|     SubmenuIndexWriteGen1A, |     SubmenuIndexAuthenticateGen4, | ||||||
|     SubmenuIndexWipe, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) { | void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) { | ||||||
| @ -22,12 +21,10 @@ void nfc_magic_scene_start_on_enter(void* context) { | |||||||
|         nfc_magic); |         nfc_magic); | ||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
|         submenu, |         submenu, | ||||||
|         "Write Gen1A", |         "Authenticate Gen4", | ||||||
|         SubmenuIndexWriteGen1A, |         SubmenuIndexAuthenticateGen4, | ||||||
|         nfc_magic_scene_start_submenu_callback, |         nfc_magic_scene_start_submenu_callback, | ||||||
|         nfc_magic); |         nfc_magic); | ||||||
|     submenu_add_item( |  | ||||||
|         submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_start_submenu_callback, nfc_magic); |  | ||||||
| 
 | 
 | ||||||
|     submenu_set_selected_item( |     submenu_set_selected_item( | ||||||
|         submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart)); |         submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart)); | ||||||
| @ -40,23 +37,13 @@ bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) { | |||||||
| 
 | 
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SubmenuIndexCheck) { |         if(event.event == SubmenuIndexCheck) { | ||||||
|  |             nfc_magic->dev->password = MAGIC_GEN4_DEFAULT_PWD; | ||||||
|             scene_manager_set_scene_state( |             scene_manager_set_scene_state( | ||||||
|                 nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck); |                 nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck); | ||||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); | ||||||
|             consumed = true; |             consumed = true; | ||||||
|         } else if(event.event == SubmenuIndexWriteGen1A) { |         } else if(event.event == SubmenuIndexAuthenticateGen4) { | ||||||
|             // Explicitly save state in each branch so that the
 |             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneKeyInput); | ||||||
|             // correct option is reselected if the user cancels
 |  | ||||||
|             // loading a file.
 |  | ||||||
|             scene_manager_set_scene_state( |  | ||||||
|                 nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWriteGen1A); |  | ||||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); |  | ||||||
|             consumed = true; |  | ||||||
|         } else if(event.event == SubmenuIndexWipe) { |  | ||||||
|             scene_manager_set_scene_state( |  | ||||||
|                 nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWipe); |  | ||||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); |  | ||||||
|             consumed = true; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -22,7 +22,12 @@ static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) { | |||||||
|     if(state == NfcMagicSceneWipeStateCardSearch) { |     if(state == NfcMagicSceneWipeStateCardSearch) { | ||||||
|         popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); |         popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); | ||||||
|         popup_set_text( |         popup_set_text( | ||||||
|             nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter); |             nfc_magic->popup, | ||||||
|  |             "Apply the\nsame card\nto the back", | ||||||
|  |             128, | ||||||
|  |             32, | ||||||
|  |             AlignRight, | ||||||
|  |             AlignCenter); | ||||||
|     } else { |     } else { | ||||||
|         popup_set_icon(popup, 12, 23, &I_Loading_24); |         popup_set_icon(popup, 12, 23, &I_Loading_24); | ||||||
|         popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter); |         popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter); | ||||||
| @ -42,7 +47,9 @@ void nfc_magic_scene_wipe_on_enter(void* context) { | |||||||
|     nfc_magic_worker_start( |     nfc_magic_worker_start( | ||||||
|         nfc_magic->worker, |         nfc_magic->worker, | ||||||
|         NfcMagicWorkerStateWipe, |         NfcMagicWorkerStateWipe, | ||||||
|         &nfc_magic->nfc_dev->dev_data, |         nfc_magic->dev, | ||||||
|  |         &nfc_magic->source_dev->dev_data, | ||||||
|  |         nfc_magic->new_password, | ||||||
|         nfc_magic_wipe_worker_callback, |         nfc_magic_wipe_worker_callback, | ||||||
|         nfc_magic); |         nfc_magic); | ||||||
|     nfc_magic_blink_start(nfc_magic); |     nfc_magic_blink_start(nfc_magic); | ||||||
|  | |||||||
| @ -21,7 +21,12 @@ static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) { | |||||||
| 
 | 
 | ||||||
|     if(state == NfcMagicSceneWriteStateCardSearch) { |     if(state == NfcMagicSceneWriteStateCardSearch) { | ||||||
|         popup_set_text( |         popup_set_text( | ||||||
|             nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter); |             nfc_magic->popup, | ||||||
|  |             "Apply the\nsame card\nto the back", | ||||||
|  |             128, | ||||||
|  |             32, | ||||||
|  |             AlignRight, | ||||||
|  |             AlignCenter); | ||||||
|         popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); |         popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); | ||||||
|     } else { |     } else { | ||||||
|         popup_set_icon(popup, 12, 23, &I_Loading_24); |         popup_set_icon(popup, 12, 23, &I_Loading_24); | ||||||
| @ -42,7 +47,9 @@ void nfc_magic_scene_write_on_enter(void* context) { | |||||||
|     nfc_magic_worker_start( |     nfc_magic_worker_start( | ||||||
|         nfc_magic->worker, |         nfc_magic->worker, | ||||||
|         NfcMagicWorkerStateWrite, |         NfcMagicWorkerStateWrite, | ||||||
|         &nfc_magic->nfc_dev->dev_data, |         nfc_magic->dev, | ||||||
|  |         &nfc_magic->source_dev->dev_data, | ||||||
|  |         nfc_magic->new_password, | ||||||
|         nfc_magic_write_worker_callback, |         nfc_magic_write_worker_callback, | ||||||
|         nfc_magic); |         nfc_magic); | ||||||
|     nfc_magic_blink_start(nfc_magic); |     nfc_magic_blink_start(nfc_magic); | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ void nfc_magic_scene_wrong_card_on_enter(void* context) { | |||||||
|         AlignLeft, |         AlignLeft, | ||||||
|         AlignTop, |         AlignTop, | ||||||
|         FontSecondary, |         FontSecondary, | ||||||
|         "Writing is supported\nonly for 4 bytes UID\nMifare Classic 1k"); |         "Writing this file is\nnot supported for\nthis magic card."); | ||||||
|     widget_add_button_element( |     widget_add_button_element( | ||||||
|         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); |         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Avery
						Avery