 6a5d63803a
			
		
	
	
		6a5d63803a
		
			
		
	
	
	
	
		
			
			* New scenes for ultralight poller write mode * Added new button and transition logic for write operation For now write is only possible for NTAG21x cards with default password and no AUTHLIM set * Poller states extended * Enums and datatypes extended for new poller mode * Added mode field to poller instance datatype * New states for poller added in order to implement write mode * Added new event type for locked cards in order to simplify state flow * New logic for poller write commands * Scenes adjustments * Scenes renamed * New field added to poller instance * Now we write in 'page per call' mode * Now function takes callback return value into account * Callback will be called only in write mode * Event type added * Log adjusted and start page to write set * Logs added and check in now false at start, then it moves to true * Now mf_ultralight_poller_handler_request_write_data halts card in case of check failure and stops poller * All fail events now returns NfcCommandStop callback * In case of fail we move back properly * Remove garbage Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
		
			
				
	
	
		
			120 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "../nfc_app_i.h"
 | |
| 
 | |
| #include <nfc/protocols/mf_ultralight/mf_ultralight_poller.h>
 | |
| 
 | |
| enum {
 | |
|     NfcSceneMfUltralightWriteStateCardSearch,
 | |
|     NfcSceneMfUltralightWriteStateCardFound,
 | |
| };
 | |
| 
 | |
| NfcCommand nfc_scene_mf_ultralight_write_worker_callback(NfcGenericEvent event, void* context) {
 | |
|     furi_assert(context);
 | |
|     furi_assert(event.event_data);
 | |
|     furi_assert(event.protocol == NfcProtocolMfUltralight);
 | |
| 
 | |
|     NfcCommand command = NfcCommandContinue;
 | |
|     NfcApp* instance = context;
 | |
|     MfUltralightPollerEvent* mfu_event = event.event_data;
 | |
| 
 | |
|     if(mfu_event->type == MfUltralightPollerEventTypeRequestMode) {
 | |
|         mfu_event->data->poller_mode = MfUltralightPollerModeWrite;
 | |
|         view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
 | |
|     } else if(mfu_event->type == MfUltralightPollerEventTypeAuthRequest) {
 | |
|         mfu_event->data->auth_context.skip_auth = true;
 | |
|     } else if(mfu_event->type == MfUltralightPollerEventTypeRequestWriteData) {
 | |
|         mfu_event->data->write_data =
 | |
|             nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
 | |
|     } else if(mfu_event->type == MfUltralightPollerEventTypeCardMismatch) {
 | |
|         view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventWrongCard);
 | |
|         command = NfcCommandStop;
 | |
|     } else if(mfu_event->type == MfUltralightPollerEventTypeCardLocked) {
 | |
|         view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure);
 | |
|         command = NfcCommandStop;
 | |
|     } else if(mfu_event->type == MfUltralightPollerEventTypeWriteFail) {
 | |
|         command = NfcCommandStop;
 | |
|     } else if(mfu_event->type == MfUltralightPollerEventTypeWriteSuccess) {
 | |
|         view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
 | |
|         command = NfcCommandStop;
 | |
|     }
 | |
|     return command;
 | |
| }
 | |
| 
 | |
| static void nfc_scene_mf_ultralight_write_setup_view(NfcApp* instance) {
 | |
|     Popup* popup = instance->popup;
 | |
|     popup_reset(popup);
 | |
|     uint32_t state =
 | |
|         scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfUltralightWrite);
 | |
| 
 | |
|     if(state == NfcSceneMfUltralightWriteStateCardSearch) {
 | |
|         popup_set_text(
 | |
|             instance->popup, "Apply the initial\ncard only", 128, 32, AlignRight, AlignCenter);
 | |
|         popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
 | |
|     } else {
 | |
|         popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
 | |
|         popup_set_icon(popup, 12, 23, &A_Loading_24);
 | |
|     }
 | |
| 
 | |
|     view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
 | |
| }
 | |
| 
 | |
| void nfc_scene_mf_ultralight_write_on_enter(void* context) {
 | |
|     NfcApp* instance = context;
 | |
|     dolphin_deed(DolphinDeedNfcEmulate);
 | |
| 
 | |
|     scene_manager_set_scene_state(
 | |
|         instance->scene_manager,
 | |
|         NfcSceneMfUltralightWrite,
 | |
|         NfcSceneMfUltralightWriteStateCardSearch);
 | |
|     nfc_scene_mf_ultralight_write_setup_view(instance);
 | |
| 
 | |
|     // Setup and start worker
 | |
|     FURI_LOG_D("WMFU", "Card searching...");
 | |
|     instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfUltralight);
 | |
|     nfc_poller_start(instance->poller, nfc_scene_mf_ultralight_write_worker_callback, instance);
 | |
| 
 | |
|     nfc_blink_emulate_start(instance);
 | |
| }
 | |
| 
 | |
| bool nfc_scene_mf_ultralight_write_on_event(void* context, SceneManagerEvent event) {
 | |
|     NfcApp* instance = context;
 | |
|     bool consumed = false;
 | |
| 
 | |
|     if(event.type == SceneManagerEventTypeCustom) {
 | |
|         if(event.event == NfcCustomEventCardDetected) {
 | |
|             scene_manager_set_scene_state(
 | |
|                 instance->scene_manager,
 | |
|                 NfcSceneMfUltralightWrite,
 | |
|                 NfcSceneMfUltralightWriteStateCardFound);
 | |
|             nfc_scene_mf_ultralight_write_setup_view(instance);
 | |
|             consumed = true;
 | |
|         } else if(event.event == NfcCustomEventWrongCard) {
 | |
|             scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWrongCard);
 | |
|             consumed = true;
 | |
|         } else if(event.event == NfcCustomEventPollerSuccess) {
 | |
|             scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWriteSuccess);
 | |
|             consumed = true;
 | |
|         } else if(event.event == NfcCustomEventPollerFailure) {
 | |
|             scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWriteFail);
 | |
|             consumed = true;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return consumed;
 | |
| }
 | |
| 
 | |
| void nfc_scene_mf_ultralight_write_on_exit(void* context) {
 | |
|     NfcApp* instance = context;
 | |
| 
 | |
|     nfc_poller_stop(instance->poller);
 | |
|     nfc_poller_free(instance->poller);
 | |
| 
 | |
|     scene_manager_set_scene_state(
 | |
|         instance->scene_manager,
 | |
|         NfcSceneMfUltralightWrite,
 | |
|         NfcSceneMfUltralightWriteStateCardSearch);
 | |
|     // Clear view
 | |
|     popup_reset(instance->popup);
 | |
| 
 | |
|     nfc_blink_stop(instance);
 | |
| }
 |