NFC magic cards support (#1966)
* nfc magic: introduce nfc app to work with magic cards * nfc: add nfc device functions to API * nfc magic: add bacis scenes * nfc magic: add wrong card and write confirm scenes * nfc magic: introduce magic lib * nfc magic: write magic lib * nfc magic: add write commands to magic lib * nfc magic: work on worker * furi_hal_nfc: add bits data exchage method to API * nfc magic: rework with new API * nfc magic: add check and wipe scenes * nfc magic: add icons, gui fixes * nfc: format python src Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									3bd74b7f01
								
							
						
					
					
						commit
						bf8fd71c00
					
				
							
								
								
									
										20
									
								
								applications/plugins/nfc_magic/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								applications/plugins/nfc_magic/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| App( | ||||
|     appid="nfc_magic", | ||||
|     name="Nfc Magic", | ||||
|     apptype=FlipperAppType.EXTERNAL, | ||||
|     entry_point="nfc_magic_app", | ||||
|     requires=[ | ||||
|         "storage", | ||||
|         "gui", | ||||
|     ], | ||||
|     stack_size=4 * 1024, | ||||
|     order=30, | ||||
|     fap_icon="../../../assets/icons/Archive/125_10px.png", | ||||
|     fap_category="Tools", | ||||
|     fap_private_libs=[ | ||||
|         Lib( | ||||
|             name="magic", | ||||
|         ), | ||||
|     ], | ||||
|     fap_icon_assets="assets", | ||||
| ) | ||||
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/nfc_magic/assets/DolphinCommon_56x48.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								applications/plugins/nfc_magic/assets/DolphinCommon_56x48.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/nfc_magic/assets/DolphinNice_96x59.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								applications/plugins/nfc_magic/assets/DolphinNice_96x59.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/nfc_magic/assets/Loading_24.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								applications/plugins/nfc_magic/assets/Loading_24.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/nfc_magic/assets/NFC_manual_60x50.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								applications/plugins/nfc_magic/assets/NFC_manual_60x50.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.7 KiB | 
							
								
								
									
										214
									
								
								applications/plugins/nfc_magic/lib/magic/magic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								applications/plugins/nfc_magic/lib/magic/magic.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,214 @@ | ||||
| #include "magic.h" | ||||
| 
 | ||||
| #include <furi_hal_nfc.h> | ||||
| 
 | ||||
| #define TAG "Magic" | ||||
| 
 | ||||
| #define MAGIC_CMD_WUPA (0x40) | ||||
| #define MAGIC_CMD_WIPE (0x41) | ||||
| #define MAGIC_CMD_READ (0x43) | ||||
| #define MAGIC_CMD_WRITE (0x43) | ||||
| 
 | ||||
| #define MAGIC_MIFARE_READ_CMD (0x30) | ||||
| #define MAGIC_MIFARE_WRITE_CMD (0xA0) | ||||
| 
 | ||||
| #define MAGIC_ACK (0x0A) | ||||
| 
 | ||||
| #define MAGIC_BUFFER_SIZE (32) | ||||
| 
 | ||||
| bool magic_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 { | ||||
|         // 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( | ||||
|             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); | ||||
| 
 | ||||
|     if(!magic_activated) { | ||||
|         furi_hal_nfc_ll_txrx_off(); | ||||
|         furi_hal_nfc_start_sleep(); | ||||
|     } | ||||
| 
 | ||||
|     return magic_activated; | ||||
| } | ||||
| 
 | ||||
| bool magic_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_WRITE; | ||||
|         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); | ||||
| 
 | ||||
|     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) { | ||||
|     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); | ||||
| 
 | ||||
|     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) { | ||||
|     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); | ||||
| 
 | ||||
|     if(!write_success) { | ||||
|         furi_hal_nfc_ll_txrx_off(); | ||||
|         furi_hal_nfc_start_sleep(); | ||||
|     } | ||||
| 
 | ||||
|     return write_success; | ||||
| } | ||||
| 
 | ||||
| bool magic_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; | ||||
| } | ||||
| 
 | ||||
| void magic_deactivate() { | ||||
|     furi_hal_nfc_ll_txrx_off(); | ||||
|     furi_hal_nfc_start_sleep(); | ||||
| } | ||||
							
								
								
									
										15
									
								
								applications/plugins/nfc_magic/lib/magic/magic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								applications/plugins/nfc_magic/lib/magic/magic.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| #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(); | ||||
							
								
								
									
										169
									
								
								applications/plugins/nfc_magic/nfc_magic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								applications/plugins/nfc_magic/nfc_magic.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | ||||
| #include "nfc_magic_i.h" | ||||
| 
 | ||||
| bool nfc_magic_custom_event_callback(void* context, uint32_t event) { | ||||
|     furi_assert(context); | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     return scene_manager_handle_custom_event(nfc_magic->scene_manager, event); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_back_event_callback(void* context) { | ||||
|     furi_assert(context); | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     return scene_manager_handle_back_event(nfc_magic->scene_manager); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_tick_event_callback(void* context) { | ||||
|     furi_assert(context); | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     scene_manager_handle_tick_event(nfc_magic->scene_manager); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_show_loading_popup(void* context, bool show) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); | ||||
| 
 | ||||
|     if(show) { | ||||
|         // Raise timer priority so that animations can play
 | ||||
|         vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); | ||||
|         view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewLoading); | ||||
|     } else { | ||||
|         // Restore default timer priority
 | ||||
|         vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| NfcMagic* nfc_magic_alloc() { | ||||
|     NfcMagic* nfc_magic = malloc(sizeof(NfcMagic)); | ||||
| 
 | ||||
|     nfc_magic->worker = nfc_magic_worker_alloc(); | ||||
|     nfc_magic->view_dispatcher = view_dispatcher_alloc(); | ||||
|     nfc_magic->scene_manager = scene_manager_alloc(&nfc_magic_scene_handlers, nfc_magic); | ||||
|     view_dispatcher_enable_queue(nfc_magic->view_dispatcher); | ||||
|     view_dispatcher_set_event_callback_context(nfc_magic->view_dispatcher, nfc_magic); | ||||
|     view_dispatcher_set_custom_event_callback( | ||||
|         nfc_magic->view_dispatcher, nfc_magic_custom_event_callback); | ||||
|     view_dispatcher_set_navigation_event_callback( | ||||
|         nfc_magic->view_dispatcher, nfc_magic_back_event_callback); | ||||
|     view_dispatcher_set_tick_event_callback( | ||||
|         nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100); | ||||
| 
 | ||||
|     // Nfc device
 | ||||
|     nfc_magic->nfc_dev = nfc_device_alloc(); | ||||
| 
 | ||||
|     // Open GUI record
 | ||||
|     nfc_magic->gui = furi_record_open(RECORD_GUI); | ||||
|     view_dispatcher_attach_to_gui( | ||||
|         nfc_magic->view_dispatcher, nfc_magic->gui, ViewDispatcherTypeFullscreen); | ||||
| 
 | ||||
|     // Open Notification record
 | ||||
|     nfc_magic->notifications = furi_record_open(RECORD_NOTIFICATION); | ||||
| 
 | ||||
|     // Submenu
 | ||||
|     nfc_magic->submenu = submenu_alloc(); | ||||
|     view_dispatcher_add_view( | ||||
|         nfc_magic->view_dispatcher, NfcMagicViewMenu, submenu_get_view(nfc_magic->submenu)); | ||||
| 
 | ||||
|     // Popup
 | ||||
|     nfc_magic->popup = popup_alloc(); | ||||
|     view_dispatcher_add_view( | ||||
|         nfc_magic->view_dispatcher, NfcMagicViewPopup, popup_get_view(nfc_magic->popup)); | ||||
| 
 | ||||
|     // Loading
 | ||||
|     nfc_magic->loading = loading_alloc(); | ||||
|     view_dispatcher_add_view( | ||||
|         nfc_magic->view_dispatcher, NfcMagicViewLoading, loading_get_view(nfc_magic->loading)); | ||||
| 
 | ||||
|     // Text Input
 | ||||
|     nfc_magic->text_input = text_input_alloc(); | ||||
|     view_dispatcher_add_view( | ||||
|         nfc_magic->view_dispatcher, | ||||
|         NfcMagicViewTextInput, | ||||
|         text_input_get_view(nfc_magic->text_input)); | ||||
| 
 | ||||
|     // Custom Widget
 | ||||
|     nfc_magic->widget = widget_alloc(); | ||||
|     view_dispatcher_add_view( | ||||
|         nfc_magic->view_dispatcher, NfcMagicViewWidget, widget_get_view(nfc_magic->widget)); | ||||
| 
 | ||||
|     return nfc_magic; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_free(NfcMagic* nfc_magic) { | ||||
|     furi_assert(nfc_magic); | ||||
| 
 | ||||
|     // Nfc device
 | ||||
|     nfc_device_free(nfc_magic->nfc_dev); | ||||
| 
 | ||||
|     // Submenu
 | ||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); | ||||
|     submenu_free(nfc_magic->submenu); | ||||
| 
 | ||||
|     // Popup
 | ||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); | ||||
|     popup_free(nfc_magic->popup); | ||||
| 
 | ||||
|     // Loading
 | ||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading); | ||||
|     loading_free(nfc_magic->loading); | ||||
| 
 | ||||
|     // TextInput
 | ||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput); | ||||
|     text_input_free(nfc_magic->text_input); | ||||
| 
 | ||||
|     // Custom Widget
 | ||||
|     view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||
|     widget_free(nfc_magic->widget); | ||||
| 
 | ||||
|     // Worker
 | ||||
|     nfc_magic_worker_stop(nfc_magic->worker); | ||||
|     nfc_magic_worker_free(nfc_magic->worker); | ||||
| 
 | ||||
|     // View Dispatcher
 | ||||
|     view_dispatcher_free(nfc_magic->view_dispatcher); | ||||
| 
 | ||||
|     // Scene Manager
 | ||||
|     scene_manager_free(nfc_magic->scene_manager); | ||||
| 
 | ||||
|     // GUI
 | ||||
|     furi_record_close(RECORD_GUI); | ||||
|     nfc_magic->gui = NULL; | ||||
| 
 | ||||
|     // Notifications
 | ||||
|     furi_record_close(RECORD_NOTIFICATION); | ||||
|     nfc_magic->notifications = NULL; | ||||
| 
 | ||||
|     free(nfc_magic); | ||||
| } | ||||
| 
 | ||||
| static const NotificationSequence nfc_magic_sequence_blink_start_blue = { | ||||
|     &message_blink_start_10, | ||||
|     &message_blink_set_color_blue, | ||||
|     &message_do_not_reset, | ||||
|     NULL, | ||||
| }; | ||||
| 
 | ||||
| static const NotificationSequence nfc_magic_sequence_blink_stop = { | ||||
|     &message_blink_stop, | ||||
|     NULL, | ||||
| }; | ||||
| 
 | ||||
| void nfc_magic_blink_start(NfcMagic* nfc_magic) { | ||||
|     notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_start_blue); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_blink_stop(NfcMagic* nfc_magic) { | ||||
|     notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_stop); | ||||
| } | ||||
| 
 | ||||
| int32_t nfc_magic_app(void* p) { | ||||
|     UNUSED(p); | ||||
|     NfcMagic* nfc_magic = nfc_magic_alloc(); | ||||
| 
 | ||||
|     scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneStart); | ||||
| 
 | ||||
|     view_dispatcher_run(nfc_magic->view_dispatcher); | ||||
| 
 | ||||
|     nfc_magic_free(nfc_magic); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										3
									
								
								applications/plugins/nfc_magic/nfc_magic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								applications/plugins/nfc_magic/nfc_magic.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| typedef struct NfcMagic NfcMagic; | ||||
							
								
								
									
										77
									
								
								applications/plugins/nfc_magic/nfc_magic_i.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								applications/plugins/nfc_magic/nfc_magic_i.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "nfc_magic.h" | ||||
| #include "nfc_magic_worker.h" | ||||
| 
 | ||||
| #include "lib/magic/magic.h" | ||||
| 
 | ||||
| #include <furi.h> | ||||
| #include <gui/gui.h> | ||||
| #include <gui/view_dispatcher.h> | ||||
| #include <gui/scene_manager.h> | ||||
| #include <notification/notification_messages.h> | ||||
| 
 | ||||
| #include <gui/modules/submenu.h> | ||||
| #include <gui/modules/popup.h> | ||||
| #include <gui/modules/loading.h> | ||||
| #include <gui/modules/text_input.h> | ||||
| #include <gui/modules/widget.h> | ||||
| 
 | ||||
| #include <input/input.h> | ||||
| 
 | ||||
| #include "scenes/nfc_magic_scene.h" | ||||
| 
 | ||||
| #include <storage/storage.h> | ||||
| #include <lib/toolbox/path.h> | ||||
| 
 | ||||
| #include <lib/nfc/nfc_device.h> | ||||
| #include "nfc_magic_icons.h" | ||||
| 
 | ||||
| enum NfcMagicCustomEvent { | ||||
|     // Reserve first 100 events for button types and indexes, starting from 0
 | ||||
|     NfcMagicCustomEventReserved = 100, | ||||
| 
 | ||||
|     NfcMagicCustomEventViewExit, | ||||
|     NfcMagicCustomEventWorkerExit, | ||||
|     NfcMagicCustomEventByteInputDone, | ||||
|     NfcMagicCustomEventTextInputDone, | ||||
| }; | ||||
| 
 | ||||
| struct NfcMagic { | ||||
|     NfcMagicWorker* worker; | ||||
|     ViewDispatcher* view_dispatcher; | ||||
|     Gui* gui; | ||||
|     NotificationApp* notifications; | ||||
|     SceneManager* scene_manager; | ||||
|     // NfcMagicDevice* dev;
 | ||||
|     NfcDevice* nfc_dev; | ||||
| 
 | ||||
|     FuriString* text_box_store; | ||||
| 
 | ||||
|     // Common Views
 | ||||
|     Submenu* submenu; | ||||
|     Popup* popup; | ||||
|     Loading* loading; | ||||
|     TextInput* text_input; | ||||
|     Widget* widget; | ||||
| }; | ||||
| 
 | ||||
| typedef enum { | ||||
|     NfcMagicViewMenu, | ||||
|     NfcMagicViewPopup, | ||||
|     NfcMagicViewLoading, | ||||
|     NfcMagicViewTextInput, | ||||
|     NfcMagicViewWidget, | ||||
| } NfcMagicView; | ||||
| 
 | ||||
| NfcMagic* nfc_magic_alloc(); | ||||
| 
 | ||||
| void nfc_magic_text_store_set(NfcMagic* nfc_magic, const char* text, ...); | ||||
| 
 | ||||
| void nfc_magic_text_store_clear(NfcMagic* nfc_magic); | ||||
| 
 | ||||
| void nfc_magic_blink_start(NfcMagic* nfc_magic); | ||||
| 
 | ||||
| void nfc_magic_blink_stop(NfcMagic* nfc_magic); | ||||
| 
 | ||||
| void nfc_magic_show_loading_popup(void* context, bool show); | ||||
							
								
								
									
										174
									
								
								applications/plugins/nfc_magic/nfc_magic_worker.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								applications/plugins/nfc_magic/nfc_magic_worker.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,174 @@ | ||||
| #include "nfc_magic_worker_i.h" | ||||
| 
 | ||||
| #include "lib/magic/magic.h" | ||||
| 
 | ||||
| #define TAG "NfcMagicWorker" | ||||
| 
 | ||||
| static void | ||||
|     nfc_magic_worker_change_state(NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state) { | ||||
|     furi_assert(nfc_magic_worker); | ||||
| 
 | ||||
|     nfc_magic_worker->state = state; | ||||
| } | ||||
| 
 | ||||
| NfcMagicWorker* nfc_magic_worker_alloc() { | ||||
|     NfcMagicWorker* nfc_magic_worker = malloc(sizeof(NfcMagicWorker)); | ||||
| 
 | ||||
|     // Worker thread attributes
 | ||||
|     nfc_magic_worker->thread = furi_thread_alloc(); | ||||
|     furi_thread_set_name(nfc_magic_worker->thread, "NfcMagicWorker"); | ||||
|     furi_thread_set_stack_size(nfc_magic_worker->thread, 8192); | ||||
|     furi_thread_set_callback(nfc_magic_worker->thread, nfc_magic_worker_task); | ||||
|     furi_thread_set_context(nfc_magic_worker->thread, nfc_magic_worker); | ||||
| 
 | ||||
|     nfc_magic_worker->callback = NULL; | ||||
|     nfc_magic_worker->context = NULL; | ||||
| 
 | ||||
|     nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady); | ||||
| 
 | ||||
|     return nfc_magic_worker; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker) { | ||||
|     furi_assert(nfc_magic_worker); | ||||
| 
 | ||||
|     furi_thread_free(nfc_magic_worker->thread); | ||||
|     free(nfc_magic_worker); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) { | ||||
|     furi_assert(nfc_magic_worker); | ||||
| 
 | ||||
|     nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateStop); | ||||
|     furi_thread_join(nfc_magic_worker->thread); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_worker_start( | ||||
|     NfcMagicWorker* nfc_magic_worker, | ||||
|     NfcMagicWorkerState state, | ||||
|     NfcDeviceData* dev_data, | ||||
|     NfcMagicWorkerCallback callback, | ||||
|     void* context) { | ||||
|     furi_assert(nfc_magic_worker); | ||||
|     furi_assert(dev_data); | ||||
| 
 | ||||
|     nfc_magic_worker->callback = callback; | ||||
|     nfc_magic_worker->context = context; | ||||
|     nfc_magic_worker->dev_data = dev_data; | ||||
|     nfc_magic_worker_change_state(nfc_magic_worker, state); | ||||
|     furi_thread_start(nfc_magic_worker->thread); | ||||
| } | ||||
| 
 | ||||
| int32_t nfc_magic_worker_task(void* context) { | ||||
|     NfcMagicWorker* nfc_magic_worker = context; | ||||
| 
 | ||||
|     if(nfc_magic_worker->state == NfcMagicWorkerStateCheck) { | ||||
|         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 == NfcMagicWorkerStateWipe) { | ||||
|         nfc_magic_worker_wipe(nfc_magic_worker); | ||||
|     } | ||||
| 
 | ||||
|     nfc_magic_worker_change_state(nfc_magic_worker, NfcMagicWorkerStateReady); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) { | ||||
|     bool card_found_notified = false; | ||||
|     FuriHalNfcDevData nfc_data = {}; | ||||
|     MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_data; | ||||
| 
 | ||||
|     while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { | ||||
|         if(furi_hal_nfc_detect(&nfc_data, 200)) { | ||||
|             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, "Not Magic card"); | ||||
|                 nfc_magic_worker->callback( | ||||
|                     NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); | ||||
|                 break; | ||||
|             } | ||||
|             if(!magic_data_access_cmd()) { | ||||
|                 FURI_LOG_E(TAG, "Not Magic card"); | ||||
|                 nfc_magic_worker->callback( | ||||
|                     NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); | ||||
|                 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])) { | ||||
|                     FURI_LOG_E(TAG, "Failed to write %d block", i); | ||||
|                     nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             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; | ||||
|             } | ||||
|         } | ||||
|         furi_delay_ms(300); | ||||
|     } | ||||
|     magic_deactivate(); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { | ||||
|     bool card_found_notified = false; | ||||
| 
 | ||||
|     while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) { | ||||
|         if(magic_wupa()) { | ||||
|             if(!card_found_notified) { | ||||
|                 nfc_magic_worker->callback( | ||||
|                     NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); | ||||
|                 card_found_notified = true; | ||||
|             } | ||||
| 
 | ||||
|             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; | ||||
|             } | ||||
|         } | ||||
|         furi_delay_ms(300); | ||||
|     } | ||||
|     magic_deactivate(); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { | ||||
|     MfClassicBlock block; | ||||
|     memset(&block, 0, sizeof(MfClassicBlock)); | ||||
|     block.value[0] = 0x01; | ||||
|     block.value[1] = 0x02; | ||||
|     block.value[2] = 0x03; | ||||
|     block.value[3] = 0x04; | ||||
|     block.value[4] = 0x04; | ||||
|     block.value[5] = 0x08; | ||||
|     block.value[6] = 0x04; | ||||
| 
 | ||||
|     while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { | ||||
|         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; | ||||
|         nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||
|         magic_deactivate(); | ||||
|         break; | ||||
|     } | ||||
|     magic_deactivate(); | ||||
| } | ||||
							
								
								
									
										38
									
								
								applications/plugins/nfc_magic/nfc_magic_worker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								applications/plugins/nfc_magic/nfc_magic_worker.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <lib/nfc/nfc_device.h> | ||||
| 
 | ||||
| typedef struct NfcMagicWorker NfcMagicWorker; | ||||
| 
 | ||||
| typedef enum { | ||||
|     NfcMagicWorkerStateReady, | ||||
| 
 | ||||
|     NfcMagicWorkerStateCheck, | ||||
|     NfcMagicWorkerStateWrite, | ||||
|     NfcMagicWorkerStateWipe, | ||||
| 
 | ||||
|     NfcMagicWorkerStateStop, | ||||
| } NfcMagicWorkerState; | ||||
| 
 | ||||
| typedef enum { | ||||
|     NfcMagicWorkerEventSuccess, | ||||
|     NfcMagicWorkerEventFail, | ||||
|     NfcMagicWorkerEventCardDetected, | ||||
|     NfcMagicWorkerEventNoCardDetected, | ||||
|     NfcMagicWorkerEventWrongCard, | ||||
| } NfcMagicWorkerEvent; | ||||
| 
 | ||||
| typedef bool (*NfcMagicWorkerCallback)(NfcMagicWorkerEvent event, void* context); | ||||
| 
 | ||||
| NfcMagicWorker* nfc_magic_worker_alloc(); | ||||
| 
 | ||||
| void nfc_magic_worker_free(NfcMagicWorker* nfc_magic_worker); | ||||
| 
 | ||||
| void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker); | ||||
| 
 | ||||
| void nfc_magic_worker_start( | ||||
|     NfcMagicWorker* nfc_magic_worker, | ||||
|     NfcMagicWorkerState state, | ||||
|     NfcDeviceData* dev_data, | ||||
|     NfcMagicWorkerCallback callback, | ||||
|     void* context); | ||||
							
								
								
									
										24
									
								
								applications/plugins/nfc_magic/nfc_magic_worker_i.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								applications/plugins/nfc_magic/nfc_magic_worker_i.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <furi.h> | ||||
| 
 | ||||
| #include "nfc_magic_worker.h" | ||||
| 
 | ||||
| struct NfcMagicWorker { | ||||
|     FuriThread* thread; | ||||
| 
 | ||||
|     NfcDeviceData* dev_data; | ||||
| 
 | ||||
|     NfcMagicWorkerCallback callback; | ||||
|     void* context; | ||||
| 
 | ||||
|     NfcMagicWorkerState state; | ||||
| }; | ||||
| 
 | ||||
| int32_t nfc_magic_worker_task(void* context); | ||||
| 
 | ||||
| void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker); | ||||
| 
 | ||||
| void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker); | ||||
| 
 | ||||
| void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker); | ||||
							
								
								
									
										30
									
								
								applications/plugins/nfc_magic/scenes/nfc_magic_scene.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								applications/plugins/nfc_magic/scenes/nfc_magic_scene.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| #include "nfc_magic_scene.h" | ||||
| 
 | ||||
| // Generate scene on_enter handlers array
 | ||||
| #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, | ||||
| void (*const nfc_magic_on_enter_handlers[])(void*) = { | ||||
| #include "nfc_magic_scene_config.h" | ||||
| }; | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Generate scene on_event handlers array
 | ||||
| #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, | ||||
| bool (*const nfc_magic_on_event_handlers[])(void* context, SceneManagerEvent event) = { | ||||
| #include "nfc_magic_scene_config.h" | ||||
| }; | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Generate scene on_exit handlers array
 | ||||
| #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, | ||||
| void (*const nfc_magic_on_exit_handlers[])(void* context) = { | ||||
| #include "nfc_magic_scene_config.h" | ||||
| }; | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Initialize scene handlers configuration structure
 | ||||
| const SceneManagerHandlers nfc_magic_scene_handlers = { | ||||
|     .on_enter_handlers = nfc_magic_on_enter_handlers, | ||||
|     .on_event_handlers = nfc_magic_on_event_handlers, | ||||
|     .on_exit_handlers = nfc_magic_on_exit_handlers, | ||||
|     .scene_num = NfcMagicSceneNum, | ||||
| }; | ||||
							
								
								
									
										29
									
								
								applications/plugins/nfc_magic/scenes/nfc_magic_scene.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								applications/plugins/nfc_magic/scenes/nfc_magic_scene.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <gui/scene_manager.h> | ||||
| 
 | ||||
| // Generate scene id and total number
 | ||||
| #define ADD_SCENE(prefix, name, id) NfcMagicScene##id, | ||||
| typedef enum { | ||||
| #include "nfc_magic_scene_config.h" | ||||
|     NfcMagicSceneNum, | ||||
| } NfcMagicScene; | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| extern const SceneManagerHandlers nfc_magic_scene_handlers; | ||||
| 
 | ||||
| // Generate scene on_enter handlers declaration
 | ||||
| #define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); | ||||
| #include "nfc_magic_scene_config.h" | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Generate scene on_event handlers declaration
 | ||||
| #define ADD_SCENE(prefix, name, id) \ | ||||
|     bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); | ||||
| #include "nfc_magic_scene_config.h" | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Generate scene on_exit handlers declaration
 | ||||
| #define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); | ||||
| #include "nfc_magic_scene_config.h" | ||||
| #undef ADD_SCENE | ||||
| @ -0,0 +1,87 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| enum { | ||||
|     NfcMagicSceneCheckStateCardSearch, | ||||
|     NfcMagicSceneCheckStateCardFound, | ||||
| }; | ||||
| 
 | ||||
| bool nfc_magic_check_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_check_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, NfcMagicSceneCheck); | ||||
| 
 | ||||
|     if(state == NfcMagicSceneCheckStateCardSearch) { | ||||
|         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); | ||||
|     } else { | ||||
|         popup_set_icon(popup, 12, 23, &I_Loading_24); | ||||
|         popup_set_header(popup, "Checking\nDon't move...", 52, 32, AlignLeft, AlignCenter); | ||||
|     } | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_check_on_enter(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     scene_manager_set_scene_state( | ||||
|         nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch); | ||||
|     nfc_magic_scene_check_setup_view(nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     nfc_magic_worker_start( | ||||
|         nfc_magic->worker, | ||||
|         NfcMagicWorkerStateCheck, | ||||
|         &nfc_magic->nfc_dev->dev_data, | ||||
|         nfc_magic_check_worker_callback, | ||||
|         nfc_magic); | ||||
|     nfc_magic_blink_start(nfc_magic); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_check_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == NfcMagicWorkerEventSuccess) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneMagicInfo); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventWrongCard) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventCardDetected) { | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardFound); | ||||
|             nfc_magic_scene_check_setup_view(nfc_magic); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventNoCardDetected) { | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch); | ||||
|             nfc_magic_scene_check_setup_view(nfc_magic); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_check_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     nfc_magic_worker_stop(nfc_magic->worker); | ||||
|     scene_manager_set_scene_state( | ||||
|         nfc_magic->scene_manager, NfcMagicSceneCheck, NfcMagicSceneCheckStateCardSearch); | ||||
|     // Clear view
 | ||||
|     popup_reset(nfc_magic->popup); | ||||
| 
 | ||||
|     nfc_magic_blink_stop(nfc_magic); | ||||
| } | ||||
| @ -0,0 +1,12 @@ | ||||
| ADD_SCENE(nfc_magic, start, Start) | ||||
| ADD_SCENE(nfc_magic, file_select, FileSelect) | ||||
| ADD_SCENE(nfc_magic, write_confirm, WriteConfirm) | ||||
| ADD_SCENE(nfc_magic, wrong_card, WrongCard) | ||||
| ADD_SCENE(nfc_magic, write, Write) | ||||
| ADD_SCENE(nfc_magic, write_fail, WriteFail) | ||||
| 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, wipe, Wipe) | ||||
| ADD_SCENE(nfc_magic, wipe_fail, WipeFail) | ||||
| @ -0,0 +1,34 @@ | ||||
| #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); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
|     if(nfc_file_select(nfc_magic->nfc_dev)) { | ||||
|         if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); | ||||
|         } else { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard); | ||||
|         } | ||||
|     } else { | ||||
|         scene_manager_previous_scene(nfc_magic->scene_manager); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event) { | ||||
|     UNUSED(context); | ||||
|     UNUSED(event); | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| @ -0,0 +1,45 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| void nfc_magic_scene_magic_info_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_magic_info_on_enter(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     Widget* widget = nfc_magic->widget; | ||||
| 
 | ||||
|     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_button_element( | ||||
|         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == GuiButtonTypeLeft) { | ||||
|             consumed = scene_manager_previous_scene(nfc_magic->scene_manager); | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_magic_info_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     widget_reset(nfc_magic->widget); | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| void nfc_magic_scene_not_magic_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_not_magic_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, 73, 17, &I_DolphinCommon_56x48);
 | ||||
|     widget_add_string_element( | ||||
|         widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card"); | ||||
|     widget_add_string_multiline_element( | ||||
|         widget, 4, 17, AlignLeft, AlignTop, FontSecondary, "Not a magic\ncard"); | ||||
|     widget_add_button_element( | ||||
|         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_not_magic_widget_callback, nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_not_magic_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == GuiButtonTypeLeft) { | ||||
|             consumed = scene_manager_previous_scene(nfc_magic->scene_manager); | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_not_magic_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     widget_reset(nfc_magic->widget); | ||||
| } | ||||
| @ -0,0 +1,61 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| enum SubmenuIndex { | ||||
|     SubmenuIndexCheck, | ||||
|     SubmenuIndexWriteGen1A, | ||||
|     SubmenuIndexWipe, | ||||
| }; | ||||
| 
 | ||||
| void nfc_magic_scene_start_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_start_on_enter(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     Submenu* submenu = nfc_magic->submenu; | ||||
|     submenu_add_item( | ||||
|         submenu, | ||||
|         "Check Magic Tag", | ||||
|         SubmenuIndexCheck, | ||||
|         nfc_magic_scene_start_submenu_callback, | ||||
|         nfc_magic); | ||||
|     submenu_add_item( | ||||
|         submenu, | ||||
|         "Write Gen1A", | ||||
|         SubmenuIndexWriteGen1A, | ||||
|         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)); | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == SubmenuIndexCheck) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); | ||||
|             consumed = true; | ||||
|         } else if(event.event == SubmenuIndexWriteGen1A) { | ||||
|             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, NfcMagicSceneStart, event.event); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_start_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     submenu_reset(nfc_magic->submenu); | ||||
| } | ||||
| @ -0,0 +1,42 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| void nfc_magic_scene_success_popup_callback(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, NfcMagicCustomEventViewExit); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_success_on_enter(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     notification_message(nfc_magic->notifications, &sequence_success); | ||||
| 
 | ||||
|     Popup* popup = nfc_magic->popup; | ||||
|     popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); | ||||
|     popup_set_header(popup, "Success!", 10, 20, AlignLeft, AlignBottom); | ||||
|     popup_set_timeout(popup, 1500); | ||||
|     popup_set_context(popup, nfc_magic); | ||||
|     popup_set_callback(popup, nfc_magic_scene_success_popup_callback); | ||||
|     popup_enable_timeout(popup); | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_success_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == NfcMagicCustomEventViewExit) { | ||||
|             consumed = scene_manager_search_and_switch_to_previous_scene( | ||||
|                 nfc_magic->scene_manager, NfcMagicSceneStart); | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_success_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     // Clear view
 | ||||
|     popup_reset(nfc_magic->popup); | ||||
| } | ||||
							
								
								
									
										90
									
								
								applications/plugins/nfc_magic/scenes/nfc_magic_scene_wipe.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								applications/plugins/nfc_magic/scenes/nfc_magic_scene_wipe.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| enum { | ||||
|     NfcMagicSceneWipeStateCardSearch, | ||||
|     NfcMagicSceneWipeStateCardFound, | ||||
| }; | ||||
| 
 | ||||
| bool nfc_magic_wipe_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_wipe_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, NfcMagicSceneWipe); | ||||
| 
 | ||||
|     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); | ||||
|     } else { | ||||
|         popup_set_icon(popup, 12, 23, &I_Loading_24); | ||||
|         popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter); | ||||
|     } | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_wipe_on_enter(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     scene_manager_set_scene_state( | ||||
|         nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch); | ||||
|     nfc_magic_scene_wipe_setup_view(nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     nfc_magic_worker_start( | ||||
|         nfc_magic->worker, | ||||
|         NfcMagicWorkerStateWipe, | ||||
|         &nfc_magic->nfc_dev->dev_data, | ||||
|         nfc_magic_wipe_worker_callback, | ||||
|         nfc_magic); | ||||
|     nfc_magic_blink_start(nfc_magic); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_wipe_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == NfcMagicWorkerEventSuccess) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventFail) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipeFail); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventWrongCard) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventCardDetected) { | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardFound); | ||||
|             nfc_magic_scene_wipe_setup_view(nfc_magic); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventNoCardDetected) { | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch); | ||||
|             nfc_magic_scene_wipe_setup_view(nfc_magic); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_wipe_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     nfc_magic_worker_stop(nfc_magic->worker); | ||||
|     scene_manager_set_scene_state( | ||||
|         nfc_magic->scene_manager, NfcMagicSceneWipe, NfcMagicSceneWipeStateCardSearch); | ||||
|     // Clear view
 | ||||
|     popup_reset(nfc_magic->popup); | ||||
| 
 | ||||
|     nfc_magic_blink_stop(nfc_magic); | ||||
| } | ||||
| @ -0,0 +1,41 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| void nfc_magic_scene_wipe_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_wipe_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, 73, 17, &I_DolphinCommon_56x48); | ||||
|     widget_add_string_element(widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Wipe failed"); | ||||
|     widget_add_button_element( | ||||
|         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wipe_fail_widget_callback, nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_wipe_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_previous_scene(nfc_magic->scene_manager); | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_wipe_fail_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     widget_reset(nfc_magic->widget); | ||||
| } | ||||
| @ -0,0 +1,90 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| enum { | ||||
|     NfcMagicSceneWriteStateCardSearch, | ||||
|     NfcMagicSceneWriteStateCardFound, | ||||
| }; | ||||
| 
 | ||||
| bool nfc_magic_write_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_write_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, NfcMagicSceneWrite); | ||||
| 
 | ||||
|     if(state == NfcMagicSceneWriteStateCardSearch) { | ||||
|         popup_set_text( | ||||
|             nfc_magic->popup, "Apply card to\nthe 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_write_on_enter(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     scene_manager_set_scene_state( | ||||
|         nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch); | ||||
|     nfc_magic_scene_write_setup_view(nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     nfc_magic_worker_start( | ||||
|         nfc_magic->worker, | ||||
|         NfcMagicWorkerStateWrite, | ||||
|         &nfc_magic->nfc_dev->dev_data, | ||||
|         nfc_magic_write_worker_callback, | ||||
|         nfc_magic); | ||||
|     nfc_magic_blink_start(nfc_magic); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_write_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == NfcMagicWorkerEventSuccess) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventFail) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteFail); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventWrongCard) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNotMagic); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventCardDetected) { | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardFound); | ||||
|             nfc_magic_scene_write_setup_view(nfc_magic); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcMagicWorkerEventNoCardDetected) { | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch); | ||||
|             nfc_magic_scene_write_setup_view(nfc_magic); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_write_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     nfc_magic_worker_stop(nfc_magic->worker); | ||||
|     scene_manager_set_scene_state( | ||||
|         nfc_magic->scene_manager, NfcMagicSceneWrite, NfcMagicSceneWriteStateCardSearch); | ||||
|     // Clear view
 | ||||
|     popup_reset(nfc_magic->popup); | ||||
| 
 | ||||
|     nfc_magic_blink_stop(nfc_magic); | ||||
| } | ||||
| @ -0,0 +1,64 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| void nfc_magic_scene_write_confirm_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_write_confirm_on_enter(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     Widget* widget = nfc_magic->widget; | ||||
| 
 | ||||
|     widget_add_string_element(widget, 3, 0, AlignLeft, AlignTop, FontPrimary, "Risky operation"); | ||||
|     widget_add_text_box_element( | ||||
|         widget, | ||||
|         0, | ||||
|         13, | ||||
|         128, | ||||
|         54, | ||||
|         AlignLeft, | ||||
|         AlignTop, | ||||
|         "Writing to this card will change manufacturer block. On some cards it may not be rewritten", | ||||
|         false); | ||||
|     widget_add_button_element( | ||||
|         widget, | ||||
|         GuiButtonTypeCenter, | ||||
|         "Continue", | ||||
|         nfc_magic_scene_write_confirm_widget_callback, | ||||
|         nfc_magic); | ||||
|     widget_add_button_element( | ||||
|         widget, | ||||
|         GuiButtonTypeLeft, | ||||
|         "Back", | ||||
|         nfc_magic_scene_write_confirm_widget_callback, | ||||
|         nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_write_confirm_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == GuiButtonTypeLeft) { | ||||
|             consumed = scene_manager_previous_scene(nfc_magic->scene_manager); | ||||
|         } else if(event.event == GuiButtonTypeCenter) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrite); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_write_confirm_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     widget_reset(nfc_magic->widget); | ||||
| } | ||||
| @ -0,0 +1,58 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| void nfc_magic_scene_write_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_write_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, "Writing gone wrong!"); | ||||
|     widget_add_string_multiline_element( | ||||
|         widget, | ||||
|         7, | ||||
|         17, | ||||
|         AlignLeft, | ||||
|         AlignTop, | ||||
|         FontSecondary, | ||||
|         "Not all sectors\nwere written\ncorrectly."); | ||||
| 
 | ||||
|     widget_add_button_element( | ||||
|         widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_write_fail_widget_callback, nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_write_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_write_fail_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     widget_reset(nfc_magic->widget); | ||||
| } | ||||
| @ -0,0 +1,53 @@ | ||||
| #include "../nfc_magic_i.h" | ||||
| 
 | ||||
| void nfc_magic_scene_wrong_card_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_wrong_card_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, 73, 17, &I_DolphinCommon_56x48); | ||||
|     widget_add_string_element( | ||||
|         widget, 1, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card"); | ||||
|     widget_add_string_multiline_element( | ||||
|         widget, | ||||
|         1, | ||||
|         17, | ||||
|         AlignLeft, | ||||
|         AlignTop, | ||||
|         FontSecondary, | ||||
|         "Writing is supported\nonly for 4 bytes UID\nMifare CLassic 1k"); | ||||
|     widget_add_button_element( | ||||
|         widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); | ||||
| 
 | ||||
|     // Setup and start worker
 | ||||
|     view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool nfc_magic_scene_wrong_card_on_event(void* context, SceneManagerEvent event) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == GuiButtonTypeLeft) { | ||||
|             consumed = scene_manager_previous_scene(nfc_magic->scene_manager); | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_magic_scene_wrong_card_on_exit(void* context) { | ||||
|     NfcMagic* nfc_magic = context; | ||||
| 
 | ||||
|     widget_reset(nfc_magic->widget); | ||||
| } | ||||
| @ -148,6 +148,7 @@ Header,+,lib/libusb_stm32/inc/usbd_core.h,, | ||||
| Header,+,lib/mbedtls/include/mbedtls/des.h,, | ||||
| Header,+,lib/mbedtls/include/mbedtls/sha1.h,, | ||||
| Header,+,lib/micro-ecc/uECC.h,, | ||||
| Header,+,lib/nfc/nfc_device.h,, | ||||
| Header,+,lib/one_wire/ibutton/ibutton_worker.h,, | ||||
| Header,+,lib/one_wire/maxim_crc.h,, | ||||
| Header,+,lib/one_wire/one_wire_device.h,, | ||||
| @ -668,6 +669,14 @@ Function,-,coshl,long double,long double | ||||
| Function,-,cosl,long double,long double | ||||
| Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t" | ||||
| Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*" | ||||
| Function,-,crypto1_bit,uint8_t,"Crypto1*, uint8_t, int" | ||||
| Function,-,crypto1_byte,uint8_t,"Crypto1*, uint8_t, int" | ||||
| Function,-,crypto1_decrypt,void,"Crypto1*, uint8_t*, uint16_t, uint8_t*" | ||||
| Function,-,crypto1_encrypt,void,"Crypto1*, uint8_t*, uint8_t*, uint16_t, uint8_t*, uint8_t*" | ||||
| Function,-,crypto1_filter,uint32_t,uint32_t | ||||
| Function,-,crypto1_init,void,"Crypto1*, uint64_t" | ||||
| Function,-,crypto1_reset,void,Crypto1* | ||||
| Function,-,crypto1_word,uint32_t,"Crypto1*, uint32_t, int" | ||||
| Function,-,ctermid,char*,char* | ||||
| Function,-,ctime,char*,const time_t* | ||||
| Function,-,ctime_r,char*,"const time_t*, char*" | ||||
| @ -750,6 +759,8 @@ Function,+,elements_text_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, | ||||
| Function,+,empty_screen_alloc,EmptyScreen*, | ||||
| Function,+,empty_screen_free,void,EmptyScreen* | ||||
| Function,+,empty_screen_get_view,View*,EmptyScreen* | ||||
| Function,-,emv_card_emulation,_Bool,FuriHalNfcTxRxContext* | ||||
| Function,-,emv_read_bank_card,_Bool,"FuriHalNfcTxRxContext*, EmvApplication*" | ||||
| Function,-,erand48,double,unsigned short[3] | ||||
| Function,-,erf,double,double | ||||
| Function,-,erfc,double,double | ||||
| @ -1161,6 +1172,7 @@ Function,+,furi_hal_nfc_ll_set_fdt_poll,void,uint32_t | ||||
| Function,+,furi_hal_nfc_ll_set_guard_time,void,uint32_t | ||||
| Function,+,furi_hal_nfc_ll_set_mode,FuriHalNfcReturn,"FuriHalNfcMode, FuriHalNfcBitrate, FuriHalNfcBitrate" | ||||
| Function,+,furi_hal_nfc_ll_txrx,FuriHalNfcReturn,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" | ||||
| Function,+,furi_hal_nfc_ll_txrx_bits,FuriHalNfcReturn,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" | ||||
| Function,+,furi_hal_nfc_ll_txrx_off,void, | ||||
| Function,+,furi_hal_nfc_ll_txrx_on,void, | ||||
| Function,+,furi_hal_nfc_sleep,void, | ||||
| @ -1806,6 +1818,100 @@ Function,+,menu_free,void,Menu* | ||||
| Function,+,menu_get_view,View*,Menu* | ||||
| Function,+,menu_reset,void,Menu* | ||||
| Function,+,menu_set_selected_item,void,"Menu*, uint32_t" | ||||
| Function,-,mf_classic_auth_attempt,_Bool,"FuriHalNfcTxRxContext*, MfClassicAuthContext*, uint64_t" | ||||
| Function,-,mf_classic_auth_init_context,void,"MfClassicAuthContext*, uint8_t" | ||||
| Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey" | ||||
| Function,-,mf_classic_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t" | ||||
| Function,-,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*" | ||||
| Function,-,mf_classic_dict_add_key_str,_Bool,"MfClassicDict*, FuriString*" | ||||
| Function,-,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType | ||||
| Function,-,mf_classic_dict_check_presence,_Bool,MfClassicDictType | ||||
| Function,-,mf_classic_dict_delete_index,_Bool,"MfClassicDict*, uint32_t" | ||||
| Function,-,mf_classic_dict_find_index,_Bool,"MfClassicDict*, uint8_t*, uint32_t*" | ||||
| Function,-,mf_classic_dict_find_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t*" | ||||
| Function,-,mf_classic_dict_free,void,MfClassicDict* | ||||
| Function,-,mf_classic_dict_get_key_at_index,_Bool,"MfClassicDict*, uint64_t*, uint32_t" | ||||
| Function,-,mf_classic_dict_get_key_at_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t" | ||||
| Function,-,mf_classic_dict_get_next_key,_Bool,"MfClassicDict*, uint64_t*" | ||||
| Function,-,mf_classic_dict_get_next_key_str,_Bool,"MfClassicDict*, FuriString*" | ||||
| Function,-,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict* | ||||
| Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" | ||||
| Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*" | ||||
| Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict* | ||||
| Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*" | ||||
| Function,-,mf_classic_get_classic_type,MfClassicType,"int8_t, uint8_t, uint8_t" | ||||
| Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" | ||||
| Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t | ||||
| Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t | ||||
| Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t" | ||||
| Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType | ||||
| Function,-,mf_classic_get_type_str,const char*,MfClassicType | ||||
| Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction" | ||||
| Function,-,mf_classic_is_allowed_access_sector_trailer,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction" | ||||
| Function,-,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t" | ||||
| Function,-,mf_classic_is_card_read,_Bool,MfClassicData* | ||||
| Function,-,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey" | ||||
| Function,-,mf_classic_is_sector_data_read,_Bool,"MfClassicData*, uint8_t" | ||||
| Function,-,mf_classic_is_sector_read,_Bool,"MfClassicData*, uint8_t" | ||||
| Function,-,mf_classic_is_sector_trailer,_Bool,uint8_t | ||||
| Function,-,mf_classic_read_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicReader*, MfClassicData*" | ||||
| Function,-,mf_classic_read_sector,void,"FuriHalNfcTxRxContext*, MfClassicData*, uint8_t" | ||||
| Function,-,mf_classic_reader_add_sector,void,"MfClassicReader*, uint8_t, uint64_t, uint64_t" | ||||
| Function,-,mf_classic_set_block_read,void,"MfClassicData*, uint8_t, MfClassicBlock*" | ||||
| Function,-,mf_classic_set_key_found,void,"MfClassicData*, uint8_t, MfClassicKey, uint64_t" | ||||
| Function,-,mf_classic_set_key_not_found,void,"MfClassicData*, uint8_t, MfClassicKey" | ||||
| Function,-,mf_classic_set_sector_data_not_read,void,MfClassicData* | ||||
| Function,-,mf_classic_update_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicData*" | ||||
| Function,-,mf_classic_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t" | ||||
| Function,-,mf_classic_write_sector,_Bool,"FuriHalNfcTxRxContext*, MfClassicData*, MfClassicData*, uint8_t" | ||||
| Function,-,mf_df_cat_application,void,"MifareDesfireApplication*, FuriString*" | ||||
| Function,-,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*" | ||||
| Function,-,mf_df_cat_card_info,void,"MifareDesfireData*, FuriString*" | ||||
| Function,-,mf_df_cat_data,void,"MifareDesfireData*, FuriString*" | ||||
| Function,-,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*" | ||||
| Function,-,mf_df_cat_free_mem,void,"MifareDesfireFreeMemory*, FuriString*" | ||||
| Function,-,mf_df_cat_key_settings,void,"MifareDesfireKeySettings*, FuriString*" | ||||
| Function,-,mf_df_cat_version,void,"MifareDesfireVersion*, FuriString*" | ||||
| Function,-,mf_df_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t" | ||||
| Function,-,mf_df_clear,void,MifareDesfireData* | ||||
| Function,-,mf_df_parse_get_application_ids_response,_Bool,"uint8_t*, uint16_t, MifareDesfireApplication**" | ||||
| Function,-,mf_df_parse_get_file_ids_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile**" | ||||
| Function,-,mf_df_parse_get_file_settings_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile*" | ||||
| Function,-,mf_df_parse_get_free_memory_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFreeMemory*" | ||||
| Function,-,mf_df_parse_get_key_settings_response,_Bool,"uint8_t*, uint16_t, MifareDesfireKeySettings*" | ||||
| Function,-,mf_df_parse_get_key_version_response,_Bool,"uint8_t*, uint16_t, MifareDesfireKeyVersion*" | ||||
| Function,-,mf_df_parse_get_version_response,_Bool,"uint8_t*, uint16_t, MifareDesfireVersion*" | ||||
| Function,-,mf_df_parse_read_data_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile*" | ||||
| Function,-,mf_df_parse_select_application_response,_Bool,"uint8_t*, uint16_t" | ||||
| Function,-,mf_df_prepare_get_application_ids,uint16_t,uint8_t* | ||||
| Function,-,mf_df_prepare_get_file_ids,uint16_t,uint8_t* | ||||
| Function,-,mf_df_prepare_get_file_settings,uint16_t,"uint8_t*, uint8_t" | ||||
| Function,-,mf_df_prepare_get_free_memory,uint16_t,uint8_t* | ||||
| Function,-,mf_df_prepare_get_key_settings,uint16_t,uint8_t* | ||||
| Function,-,mf_df_prepare_get_key_version,uint16_t,"uint8_t*, uint8_t" | ||||
| Function,-,mf_df_prepare_get_value,uint16_t,"uint8_t*, uint8_t" | ||||
| Function,-,mf_df_prepare_get_version,uint16_t,uint8_t* | ||||
| Function,-,mf_df_prepare_read_data,uint16_t,"uint8_t*, uint8_t, uint32_t, uint32_t" | ||||
| Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uint32_t" | ||||
| Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]" | ||||
| Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*" | ||||
| Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t" | ||||
| Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*" | ||||
| Function,-,mf_ul_prepare_emulation_response,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*" | ||||
| Function,-,mf_ul_pwdgen_amiibo,uint32_t,FuriHalNfcDevData* | ||||
| Function,-,mf_ul_pwdgen_xiaomi,uint32_t,FuriHalNfcDevData* | ||||
| Function,-,mf_ul_read_card,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" | ||||
| Function,-,mf_ul_reset,void,MfUltralightData* | ||||
| Function,-,mf_ul_reset_emulation,void,"MfUltralightEmulator*, _Bool" | ||||
| Function,-,mf_ultralight_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint32_t, uint16_t*" | ||||
| Function,-,mf_ultralight_fast_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" | ||||
| Function,-,mf_ultralight_get_config_pages,MfUltralightConfigPages*,MfUltralightData* | ||||
| Function,-,mf_ultralight_read_counters,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" | ||||
| Function,-,mf_ultralight_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" | ||||
| Function,-,mf_ultralight_read_pages_direct,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint8_t*" | ||||
| Function,-,mf_ultralight_read_signature,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" | ||||
| Function,-,mf_ultralight_read_tearing_flags,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" | ||||
| Function,-,mf_ultralight_read_version,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" | ||||
| Function,-,mkdtemp,char*,char* | ||||
| Function,-,mkostemp,int,"char*, int" | ||||
| Function,-,mkostemps,int,"char*, int, int" | ||||
| @ -1829,6 +1935,19 @@ Function,-,nextafterl,long double,"long double, long double" | ||||
| Function,-,nexttoward,double,"double, long double" | ||||
| Function,-,nexttowardf,float,"float, long double" | ||||
| Function,-,nexttowardl,long double,"long double, long double" | ||||
| Function,+,nfc_device_alloc,NfcDevice*, | ||||
| Function,+,nfc_device_clear,void,NfcDevice* | ||||
| Function,+,nfc_device_data_clear,void,NfcDeviceData* | ||||
| Function,+,nfc_device_delete,_Bool,"NfcDevice*, _Bool" | ||||
| Function,+,nfc_device_free,void,NfcDevice* | ||||
| Function,+,nfc_device_load,_Bool,"NfcDevice*, const char*, _Bool" | ||||
| Function,+,nfc_device_load_key_cache,_Bool,NfcDevice* | ||||
| Function,+,nfc_device_restore,_Bool,"NfcDevice*, _Bool" | ||||
| Function,+,nfc_device_save,_Bool,"NfcDevice*, const char*" | ||||
| Function,+,nfc_device_save_shadow,_Bool,"NfcDevice*, const char*" | ||||
| Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*" | ||||
| Function,+,nfc_device_set_name,void,"NfcDevice*, const char*" | ||||
| Function,+,nfc_file_select,_Bool,NfcDevice* | ||||
| Function,-,nfca_append_crc16,void,"uint8_t*, uint16_t" | ||||
| Function,-,nfca_emulation_handler,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*" | ||||
| Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t" | ||||
| @ -1913,6 +2032,7 @@ Function,+,power_reboot,void,PowerBootMode | ||||
| Function,+,powf,float,"float, float" | ||||
| Function,-,powl,long double,"long double, long double" | ||||
| Function,-,printf,int,"const char*, ..." | ||||
| Function,-,prng_successor,uint32_t,"uint32_t, uint32_t" | ||||
| Function,+,protocol_dict_alloc,ProtocolDict*,"const ProtocolBase**, size_t" | ||||
| Function,+,protocol_dict_decoders_feed,ProtocolId,"ProtocolDict*, _Bool, uint32_t" | ||||
| Function,+,protocol_dict_decoders_feed_by_feature,ProtocolId,"ProtocolDict*, uint32_t, _Bool, uint32_t" | ||||
| @ -2129,6 +2249,7 @@ Function,-,rfalT1TPollerRall,ReturnCode,"const uint8_t*, uint8_t*, uint16_t, uin | ||||
| Function,-,rfalT1TPollerRid,ReturnCode,rfalT1TRidRes* | ||||
| Function,-,rfalT1TPollerWrite,ReturnCode,"const uint8_t*, uint8_t, uint8_t" | ||||
| Function,-,rfalTransceiveBitsBlockingTx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" | ||||
| Function,-,rfalTransceiveBitsBlockingTxRx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" | ||||
| Function,-,rfalTransceiveBlockingRx,ReturnCode, | ||||
| Function,-,rfalTransceiveBlockingTx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" | ||||
| Function,-,rfalTransceiveBlockingTxRx,ReturnCode,"uint8_t*, uint16_t, uint8_t*, uint16_t, uint16_t*, uint32_t, uint32_t" | ||||
|  | ||||
| 
 | 
| @ -786,6 +786,17 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx( | ||||
|     return rfalTransceiveBlockingTxRx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt); | ||||
| } | ||||
| 
 | ||||
| FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits( | ||||
|     uint8_t* txBuf, | ||||
|     uint16_t txBufLen, | ||||
|     uint8_t* rxBuf, | ||||
|     uint16_t rxBufLen, | ||||
|     uint16_t* actLen, | ||||
|     uint32_t flags, | ||||
|     uint32_t fwt) { | ||||
|     return rfalTransceiveBitsBlockingTxRx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_nfc_ll_poll() { | ||||
|     rfalWorker(); | ||||
| } | ||||
| @ -398,6 +398,7 @@ void furi_hal_nfc_ll_txrx_on(); | ||||
| 
 | ||||
| void furi_hal_nfc_ll_txrx_off(); | ||||
| 
 | ||||
| // TODO rework all pollers with furi_hal_nfc_ll_txrx_bits
 | ||||
| FuriHalNfcReturn furi_hal_nfc_ll_txrx( | ||||
|     uint8_t* txBuf, | ||||
|     uint16_t txBufLen, | ||||
| @ -407,6 +408,15 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx( | ||||
|     uint32_t flags, | ||||
|     uint32_t fwt); | ||||
| 
 | ||||
| FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits( | ||||
|     uint8_t* txBuf, | ||||
|     uint16_t txBufLen, | ||||
|     uint8_t* rxBuf, | ||||
|     uint16_t rxBufLen, | ||||
|     uint16_t* actLen, | ||||
|     uint32_t flags, | ||||
|     uint32_t fwt); | ||||
| 
 | ||||
| void furi_hal_nfc_ll_poll(); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  | ||||
| @ -1496,6 +1496,15 @@ ReturnCode rfalTransceiveBlockingTxRx( | ||||
|     uint32_t flags, | ||||
|     uint32_t fwt); | ||||
| 
 | ||||
| ReturnCode rfalTransceiveBitsBlockingTxRx( | ||||
|     uint8_t* txBuf, | ||||
|     uint16_t txBufLen, | ||||
|     uint8_t* rxBuf, | ||||
|     uint16_t rxBufLen, | ||||
|     uint16_t* actLen, | ||||
|     uint32_t flags, | ||||
|     uint32_t fwt); | ||||
| 
 | ||||
| ReturnCode rfalTransceiveBitsBlockingTx( | ||||
|     uint8_t* txBuf, | ||||
|     uint16_t txBufLen, | ||||
|  | ||||
| @ -1607,6 +1607,23 @@ ReturnCode rfalTransceiveBlockingTxRx( | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| ReturnCode rfalTransceiveBitsBlockingTxRx( | ||||
|     uint8_t* txBuf, | ||||
|     uint16_t txBufLen, | ||||
|     uint8_t* rxBuf, | ||||
|     uint16_t rxBufLen, | ||||
|     uint16_t* actLen, | ||||
|     uint32_t flags, | ||||
|     uint32_t fwt) { | ||||
|     ReturnCode ret; | ||||
| 
 | ||||
|     EXIT_ON_ERR( | ||||
|         ret, rfalTransceiveBitsBlockingTx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt)); | ||||
|     ret = rfalTransceiveBlockingRx(); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| /*******************************************************************************/ | ||||
| static ReturnCode rfalRunTransceiveWorker(void) { | ||||
|     if(gRFAL.state == RFAL_STATE_TXRX) { | ||||
|  | ||||
| @ -4,6 +4,9 @@ env.Append( | ||||
|     CPPPATH=[ | ||||
|         "#/lib/nfc", | ||||
|     ], | ||||
|     SDK_HEADERS=[ | ||||
|         File("#/lib/nfc/nfc_device.h"), | ||||
|     ], | ||||
| ) | ||||
| 
 | ||||
| libenv = env.Clone(FW_LIB_NAME="nfc") | ||||
|  | ||||
| @ -12,6 +12,10 @@ | ||||
| #include <lib/nfc/protocols/mifare_classic.h> | ||||
| #include <lib/nfc/protocols/mifare_desfire.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #define NFC_DEV_NAME_MAX_LEN 22 | ||||
| #define NFC_READER_DATA_MAX_SIZE 64 | ||||
| #define NFC_DICT_KEY_BATCH_SIZE 50 | ||||
| @ -101,3 +105,7 @@ bool nfc_device_delete(NfcDevice* dev, bool use_load_path); | ||||
| bool nfc_device_restore(NfcDevice* dev, bool use_load_path); | ||||
| 
 | ||||
| void nfc_device_set_loading_callback(NfcDevice* dev, NfcLoadingCallback callback, void* context); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich