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> | ||||
| 
 | ||||
| @ -15,7 +15,7 @@ | ||||
| 
 | ||||
| #define MAGIC_BUFFER_SIZE (32) | ||||
| 
 | ||||
| bool magic_wupa() { | ||||
| bool magic_gen1_wupa() { | ||||
|     bool magic_activated = false; | ||||
|     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||
|     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||
| @ -23,19 +23,6 @@ bool magic_wupa() { | ||||
|     FuriHalNfcReturn ret = 0; | ||||
| 
 | ||||
|     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
 | ||||
|         tx_data[0] = MAGIC_CMD_WUPA; | ||||
|         ret = furi_hal_nfc_ll_txrx_bits( | ||||
| @ -53,15 +40,10 @@ bool magic_wupa() { | ||||
|         magic_activated = true; | ||||
|     } while(false); | ||||
| 
 | ||||
|     if(!magic_activated) { | ||||
|         furi_hal_nfc_ll_txrx_off(); | ||||
|         furi_hal_nfc_start_sleep(); | ||||
|     } | ||||
| 
 | ||||
|     return magic_activated; | ||||
| } | ||||
| 
 | ||||
| bool magic_data_access_cmd() { | ||||
| 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] = {}; | ||||
| @ -86,15 +68,10 @@ bool magic_data_access_cmd() { | ||||
|         write_cmd_success = true; | ||||
|     } while(false); | ||||
| 
 | ||||
|     if(!write_cmd_success) { | ||||
|         furi_hal_nfc_ll_txrx_off(); | ||||
|         furi_hal_nfc_start_sleep(); | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     bool read_success = false; | ||||
| @ -122,15 +99,10 @@ bool magic_read_block(uint8_t block_num, MfClassicBlock* data) { | ||||
|         read_success = true; | ||||
|     } while(false); | ||||
| 
 | ||||
|     if(!read_success) { | ||||
|         furi_hal_nfc_ll_txrx_off(); | ||||
|         furi_hal_nfc_start_sleep(); | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     bool write_success = false; | ||||
| @ -170,15 +142,10 @@ bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) { | ||||
|         write_success = true; | ||||
|     } while(false); | ||||
| 
 | ||||
|     if(!write_success) { | ||||
|         furi_hal_nfc_ll_txrx_off(); | ||||
|         furi_hal_nfc_start_sleep(); | ||||
|     } | ||||
| 
 | ||||
|     return write_success; | ||||
| } | ||||
| 
 | ||||
| bool magic_wipe() { | ||||
| bool magic_gen1_wipe() { | ||||
|     bool wipe_success = false; | ||||
|     uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; | ||||
|     uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; | ||||
| @ -206,8 +173,3 @@ bool magic_wipe() { | ||||
| 
 | ||||
|     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 device
 | ||||
|     nfc_magic->nfc_dev = nfc_device_alloc(); | ||||
|     furi_string_set(nfc_magic->nfc_dev->folder, NFC_APP_FOLDER); | ||||
|     nfc_magic->dev = malloc(sizeof(NfcMagicDevice)); | ||||
|     nfc_magic->source_dev = nfc_device_alloc(); | ||||
|     furi_string_set(nfc_magic->source_dev->folder, NFC_APP_FOLDER); | ||||
| 
 | ||||
|     // Open GUI record
 | ||||
|     nfc_magic->gui = furi_record_open(RECORD_GUI); | ||||
| @ -81,6 +82,13 @@ NfcMagic* nfc_magic_alloc() { | ||||
|         NfcMagicViewTextInput, | ||||
|         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
 | ||||
|     nfc_magic->widget = widget_alloc(); | ||||
|     view_dispatcher_add_view( | ||||
| @ -93,7 +101,8 @@ void nfc_magic_free(NfcMagic* nfc_magic) { | ||||
|     furi_assert(nfc_magic); | ||||
| 
 | ||||
|     // Nfc device
 | ||||
|     nfc_device_free(nfc_magic->nfc_dev); | ||||
|     free(nfc_magic->dev); | ||||
|     nfc_device_free(nfc_magic->source_dev); | ||||
| 
 | ||||
|     // Submenu
 | ||||
|     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); | ||||
|     loading_free(nfc_magic->loading); | ||||
| 
 | ||||
|     // TextInput
 | ||||
|     // Text Input
 | ||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput); | ||||
|     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
 | ||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||
|     widget_free(nfc_magic->widget); | ||||
| @ -164,6 +177,7 @@ int32_t nfc_magic_app(void* p) { | ||||
| 
 | ||||
|     view_dispatcher_run(nfc_magic->view_dispatcher); | ||||
| 
 | ||||
|     magic_deactivate(); | ||||
|     nfc_magic_free(nfc_magic); | ||||
| 
 | ||||
|     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 | ||||
| 
 | ||||
| typedef struct NfcMagicDevice NfcMagicDevice; | ||||
| 
 | ||||
| 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_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 <gui/gui.h> | ||||
| @ -15,6 +18,7 @@ | ||||
| #include <gui/modules/popup.h> | ||||
| #include <gui/modules/loading.h> | ||||
| #include <gui/modules/text_input.h> | ||||
| #include <gui/modules/byte_input.h> | ||||
| #include <gui/modules/widget.h> | ||||
| 
 | ||||
| #include <input/input.h> | ||||
| @ -39,14 +43,22 @@ enum NfcMagicCustomEvent { | ||||
|     NfcMagicCustomEventTextInputDone, | ||||
| }; | ||||
| 
 | ||||
| struct NfcMagicDevice { | ||||
|     MagicType type; | ||||
|     uint32_t cuid; | ||||
|     uint32_t password; | ||||
| }; | ||||
| 
 | ||||
| struct NfcMagic { | ||||
|     NfcMagicWorker* worker; | ||||
|     ViewDispatcher* view_dispatcher; | ||||
|     Gui* gui; | ||||
|     NotificationApp* notifications; | ||||
|     SceneManager* scene_manager; | ||||
|     // NfcMagicDevice* dev;
 | ||||
|     NfcDevice* nfc_dev; | ||||
|     struct NfcMagicDevice* dev; | ||||
|     NfcDevice* source_dev; | ||||
| 
 | ||||
|     uint32_t new_password; | ||||
| 
 | ||||
|     FuriString* text_box_store; | ||||
| 
 | ||||
| @ -55,6 +67,7 @@ struct NfcMagic { | ||||
|     Popup* popup; | ||||
|     Loading* loading; | ||||
|     TextInput* text_input; | ||||
|     ByteInput* byte_input; | ||||
|     Widget* widget; | ||||
| }; | ||||
| 
 | ||||
| @ -63,6 +76,7 @@ typedef enum { | ||||
|     NfcMagicViewPopup, | ||||
|     NfcMagicViewLoading, | ||||
|     NfcMagicViewTextInput, | ||||
|     NfcMagicViewByteInput, | ||||
|     NfcMagicViewWidget, | ||||
| } NfcMagicView; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										318
									
								
								applications/external/nfc_magic/nfc_magic_worker.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										318
									
								
								applications/external/nfc_magic/nfc_magic_worker.c
									
									
									
									
										vendored
									
									
								
							| @ -1,6 +1,9 @@ | ||||
| #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" | ||||
| 
 | ||||
| @ -43,15 +46,20 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) { | ||||
| void nfc_magic_worker_start( | ||||
|     NfcMagicWorker* nfc_magic_worker, | ||||
|     NfcMagicWorkerState state, | ||||
|     NfcMagicDevice* magic_dev, | ||||
|     NfcDeviceData* dev_data, | ||||
|     uint32_t new_password, | ||||
|     NfcMagicWorkerCallback callback, | ||||
|     void* context) { | ||||
|     furi_assert(nfc_magic_worker); | ||||
|     furi_assert(magic_dev); | ||||
|     furi_assert(dev_data); | ||||
| 
 | ||||
|     nfc_magic_worker->callback = callback; | ||||
|     nfc_magic_worker->context = context; | ||||
|     nfc_magic_worker->magic_dev = magic_dev; | ||||
|     nfc_magic_worker->dev_data = dev_data; | ||||
|     nfc_magic_worker->new_password = new_password; | ||||
|     nfc_magic_worker_change_state(nfc_magic_worker, state); | ||||
|     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); | ||||
|     } else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { | ||||
|         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) { | ||||
|         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) { | ||||
|     bool card_found_notified = false; | ||||
|     bool done = false; | ||||
|     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) { | ||||
|         do { | ||||
|             if(furi_hal_nfc_detect(&nfc_data, 200)) { | ||||
|                 if(nfc_data.cuid != magic_dev->cuid) break; | ||||
|                 if(!card_found_notified) { | ||||
|                     nfc_magic_worker->callback( | ||||
|                         NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||
|                     card_found_notified = true; | ||||
|                 } | ||||
|                 furi_hal_nfc_sleep(); | ||||
|             if(!magic_wupa()) { | ||||
|                 FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)"); | ||||
| 
 | ||||
|                 magic_activate(); | ||||
|                 if(magic_dev->type == MagicTypeClassicGen1) { | ||||
|                     if(dev_protocol != NfcDeviceProtocolMifareClassic) break; | ||||
|                     MfClassicData* mfc_data = &dev_data->mf_classic_data; | ||||
| 
 | ||||
|                     if(mfc_data->type != MfClassicType1k) break; | ||||
|                     if(!magic_gen1_wupa()) { | ||||
|                         FURI_LOG_E(TAG, "Not Magic card"); | ||||
|                         nfc_magic_worker->callback( | ||||
|                             NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); | ||||
|                         done = true; | ||||
|                         break; | ||||
|                     } | ||||
|             furi_hal_nfc_sleep(); | ||||
|         } | ||||
|         if(magic_wupa()) { | ||||
|             if(!magic_data_access_cmd()) { | ||||
|                 FURI_LOG_E(TAG, "No card response to data access command (not a magic card)"); | ||||
|                     if(!magic_gen1_data_access_cmd()) { | ||||
|                         FURI_LOG_E(TAG, "Not Magic card"); | ||||
|                         nfc_magic_worker->callback( | ||||
|                             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_write_blk(i, &src_data->block[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); | ||||
|                             nfc_magic_worker->callback( | ||||
|                                 NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||
|                             done = true; | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|             nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||
| 
 | ||||
|                     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; | ||||
|                 } | ||||
|             } | ||||
|         } while(false); | ||||
| 
 | ||||
|         if(done) break; | ||||
| 
 | ||||
|         if(card_found_notified) { | ||||
|             nfc_magic_worker->callback( | ||||
|                 NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); | ||||
|             card_found_notified = false; | ||||
|         } | ||||
|         } | ||||
| 
 | ||||
|         furi_delay_ms(300); | ||||
|     } | ||||
|     magic_deactivate(); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { | ||||
|     NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; | ||||
|     bool card_found_notified = false; | ||||
|     uint8_t gen4_config[MAGIC_GEN4_CONFIG_LEN]; | ||||
| 
 | ||||
|     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) { | ||||
|                 nfc_magic_worker->callback( | ||||
|                     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); | ||||
|             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) { | ||||
|                 nfc_magic_worker->callback( | ||||
|                     NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); | ||||
|                 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); | ||||
|     } | ||||
| @ -148,6 +388,10 @@ void nfc_magic_worker_check(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; | ||||
|     memset(&block, 0, sizeof(MfClassicBlock)); | ||||
|     block.value[0] = 0x01; | ||||
| @ -159,14 +403,48 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { | ||||
|     block.value[6] = 0x04; | ||||
| 
 | ||||
|     while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { | ||||
|         do { | ||||
|             magic_deactivate(); | ||||
|             furi_delay_ms(300); | ||||
|         if(!magic_wupa()) continue; | ||||
|         if(!magic_wipe()) continue; | ||||
|         if(!magic_data_access_cmd()) continue; | ||||
|         if(!magic_write_blk(0, &block)) continue; | ||||
|             if(!magic_activate()) break; | ||||
|             if(magic_dev->type == MagicTypeClassicGen1) { | ||||
|                 if(!magic_gen1_wupa()) break; | ||||
|                 if(!card_found_notified) { | ||||
|                     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); | ||||
|         break; | ||||
|             } 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(); | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <lib/nfc/nfc_device.h> | ||||
| #include "nfc_magic.h" | ||||
| 
 | ||||
| typedef struct NfcMagicWorker NfcMagicWorker; | ||||
| 
 | ||||
| @ -9,6 +10,7 @@ typedef enum { | ||||
| 
 | ||||
|     NfcMagicWorkerStateCheck, | ||||
|     NfcMagicWorkerStateWrite, | ||||
|     NfcMagicWorkerStateRekey, | ||||
|     NfcMagicWorkerStateWipe, | ||||
| 
 | ||||
|     NfcMagicWorkerStateStop, | ||||
| @ -33,6 +35,8 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker); | ||||
| void nfc_magic_worker_start( | ||||
|     NfcMagicWorker* nfc_magic_worker, | ||||
|     NfcMagicWorkerState state, | ||||
|     NfcMagicDevice* magic_dev, | ||||
|     NfcDeviceData* dev_data, | ||||
|     uint32_t new_password, | ||||
|     NfcMagicWorkerCallback callback, | ||||
|     void* context); | ||||
|  | ||||
| @ -3,11 +3,14 @@ | ||||
| #include <furi.h> | ||||
| 
 | ||||
| #include "nfc_magic_worker.h" | ||||
| #include "lib/magic/common.h" | ||||
| 
 | ||||
| struct NfcMagicWorker { | ||||
|     FuriThread* thread; | ||||
| 
 | ||||
|     NfcMagicDevice* magic_dev; | ||||
|     NfcDeviceData* dev_data; | ||||
|     uint32_t new_password; | ||||
| 
 | ||||
|     NfcMagicWorkerCallback callback; | ||||
|     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_rekey(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, | ||||
|         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); | ||||
|     nfc_magic_blink_start(nfc_magic); | ||||
|  | ||||
| @ -1,4 +1,8 @@ | ||||
| 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, write_confirm, WriteConfirm) | ||||
| 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, not_magic, NotMagic) | ||||
| 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_fail, WipeFail) | ||||
|  | ||||
| @ -1,22 +1,60 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| static bool nfc_magic_scene_file_select_is_file_suitable(NfcDevice* nfc_dev) { | ||||
|     return (nfc_dev->format == NfcDeviceSaveFormatMifareClassic) && | ||||
|            (nfc_dev->dev_data.mf_classic_data.type == MfClassicType1k) && | ||||
|            (nfc_dev->dev_data.nfc_data.uid_len == 4); | ||||
| static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagic* nfc_magic) { | ||||
|     NfcDevice* nfc_dev = nfc_magic->source_dev; | ||||
|     if(nfc_dev->format == NfcDeviceSaveFormatMifareClassic) { | ||||
|         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) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     // 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)) { | ||||
|         furi_string_set_str(nfc_magic->nfc_dev->load_path, NFC_APP_FOLDER); | ||||
|     if(!furi_string_size(nfc_magic->source_dev->load_path)) { | ||||
|         furi_string_set_str(nfc_magic->source_dev->load_path, NFC_APP_FOLDER); | ||||
|     } | ||||
| 
 | ||||
|     if(nfc_file_select(nfc_magic->nfc_dev)) { | ||||
|         if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) { | ||||
|     if(nfc_file_select(nfc_magic->source_dev)) { | ||||
|         if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic)) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); | ||||
|         } else { | ||||
|             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) { | ||||
|     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 "../lib/magic/types.h" | ||||
| 
 | ||||
| void nfc_magic_scene_magic_info_widget_callback( | ||||
|     GuiButtonType result, | ||||
| @ -13,14 +14,18 @@ void nfc_magic_scene_magic_info_widget_callback( | ||||
| void nfc_magic_scene_magic_info_on_enter(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     Widget* widget = nfc_magic->widget; | ||||
|     const char* card_type = nfc_magic_type(nfc_magic->dev->type); | ||||
| 
 | ||||
|     notification_message(nfc_magic->notifications, &sequence_success); | ||||
| 
 | ||||
|     widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48); | ||||
|     widget_add_string_element( | ||||
|         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, 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
 | ||||
|     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.event == GuiButtonTypeLeft) { | ||||
|             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; | ||||
|  | ||||
							
								
								
									
										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" | ||||
| enum SubmenuIndex { | ||||
|     SubmenuIndexCheck, | ||||
|     SubmenuIndexWriteGen1A, | ||||
|     SubmenuIndexWipe, | ||||
|     SubmenuIndexAuthenticateGen4, | ||||
| }; | ||||
| 
 | ||||
| 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); | ||||
|     submenu_add_item( | ||||
|         submenu, | ||||
|         "Write Gen1A", | ||||
|         SubmenuIndexWriteGen1A, | ||||
|         "Authenticate Gen4", | ||||
|         SubmenuIndexAuthenticateGen4, | ||||
|         nfc_magic_scene_start_submenu_callback, | ||||
|         nfc_magic); | ||||
|     submenu_add_item( | ||||
|         submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_start_submenu_callback, nfc_magic); | ||||
| 
 | ||||
|     submenu_set_selected_item( | ||||
|         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.event == SubmenuIndexCheck) { | ||||
|             nfc_magic->dev->password = MAGIC_GEN4_DEFAULT_PWD; | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck); | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); | ||||
|             consumed = true; | ||||
|         } else if(event.event == SubmenuIndexWriteGen1A) { | ||||
|             // Explicitly save state in each branch so that the
 | ||||
|             // 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; | ||||
|         } else if(event.event == SubmenuIndexAuthenticateGen4) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneKeyInput); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -22,7 +22,12 @@ static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) { | ||||
|     if(state == NfcMagicSceneWipeStateCardSearch) { | ||||
|         popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); | ||||
|         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 { | ||||
|         popup_set_icon(popup, 12, 23, &I_Loading_24); | ||||
|         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, | ||||
|         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); | ||||
|     nfc_magic_blink_start(nfc_magic); | ||||
|  | ||||
| @ -21,7 +21,12 @@ static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) { | ||||
| 
 | ||||
|     if(state == NfcMagicSceneWriteStateCardSearch) { | ||||
|         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); | ||||
|     } else { | ||||
|         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, | ||||
|         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); | ||||
|     nfc_magic_blink_start(nfc_magic); | ||||
|  | ||||
| @ -26,7 +26,7 @@ void nfc_magic_scene_wrong_card_on_enter(void* context) { | ||||
|         AlignLeft, | ||||
|         AlignTop, | ||||
|         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, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Avery
						Avery