[FL-2864] NFC update detect reader (#1820)
* nfc: update detect reader view * nfc: make detect reader more interractive * nfc: update icons * nfc: fix detect reader gui * nfc: fix gui, fix worker events * nfc: fix notifications * nfc: add nfc_worker NULL assert Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									69b9c54b2f
								
							
						
					
					
						commit
						5de2c32c81
					
				| @ -1,6 +1,15 @@ | ||||
| #include "../nfc_i.h" | ||||
| #include <dolphin/dolphin.h> | ||||
| 
 | ||||
| #define NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX (10U) | ||||
| 
 | ||||
| static const NotificationSequence sequence_detect_reader = { | ||||
|     &message_green_255, | ||||
|     &message_blue_255, | ||||
|     &message_do_not_reset, | ||||
|     NULL, | ||||
| }; | ||||
| 
 | ||||
| bool nfc_detect_reader_worker_callback(NfcWorkerEvent event, void* context) { | ||||
|     UNUSED(event); | ||||
|     furi_assert(context); | ||||
| @ -20,21 +29,26 @@ void nfc_scene_detect_reader_on_enter(void* context) { | ||||
|     DOLPHIN_DEED(DolphinDeedNfcEmulate); | ||||
| 
 | ||||
|     detect_reader_set_callback(nfc->detect_reader, nfc_scene_detect_reader_callback, nfc); | ||||
|     detect_reader_set_nonces_max(nfc->detect_reader, NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX); | ||||
| 
 | ||||
|     // Store number of collected nonces in scene state
 | ||||
|     scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDetectReader, 0); | ||||
|     notification_message(nfc->notifications, &sequence_detect_reader); | ||||
| 
 | ||||
|     nfc_worker_start( | ||||
|         nfc->worker, | ||||
|         NfcWorkerStateAnalyzeReader, | ||||
|         &nfc->dev->dev_data, | ||||
|         nfc_detect_reader_worker_callback, | ||||
|         nfc); | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDetectReader); | ||||
| 
 | ||||
|     nfc_blink_read_start(nfc); | ||||
| } | ||||
| 
 | ||||
| bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { | ||||
|     Nfc* nfc = context; | ||||
|     bool consumed = false; | ||||
|     uint32_t nonces_collected = | ||||
|         scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDetectReader); | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == NfcCustomEventViewExit) { | ||||
| @ -42,8 +56,29 @@ bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyNoncesInfo); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcWorkerEventDetectReaderMfkeyCollected) { | ||||
|             detect_reader_inc_nonce_cnt(nfc->detect_reader); | ||||
|             nonces_collected += 2; | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc->scene_manager, NfcSceneDetectReader, nonces_collected); | ||||
|             detect_reader_set_nonces_collected(nfc->detect_reader, nonces_collected); | ||||
|             if(nonces_collected >= NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { | ||||
|                 detect_reader_set_state(nfc->detect_reader, DetectReaderStateDone); | ||||
|                 nfc_blink_stop(nfc); | ||||
|                 notification_message(nfc->notifications, &sequence_single_vibro); | ||||
|                 notification_message(nfc->notifications, &sequence_set_green_255); | ||||
|                 nfc_worker_stop(nfc->worker); | ||||
|             } | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcWorkerEventDetectReaderDetected) { | ||||
|             if(nonces_collected < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { | ||||
|                 notification_message(nfc->notifications, &sequence_blink_start_cyan); | ||||
|                 detect_reader_set_state(nfc->detect_reader, DetectReaderStateReaderDetected); | ||||
|             } | ||||
|         } else if(event.event == NfcWorkerEventDetectReaderLost) { | ||||
|             if(nonces_collected < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { | ||||
|                 nfc_blink_stop(nfc); | ||||
|                 notification_message(nfc->notifications, &sequence_detect_reader); | ||||
|                 detect_reader_set_state(nfc->detect_reader, DetectReaderStateReaderLost); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -59,5 +94,7 @@ void nfc_scene_detect_reader_on_exit(void* context) { | ||||
|     // Clear view
 | ||||
|     detect_reader_reset(nfc->detect_reader); | ||||
| 
 | ||||
|     // Stop notifications
 | ||||
|     nfc_blink_stop(nfc); | ||||
|     notification_message(nfc->notifications, &sequence_reset_green); | ||||
| } | ||||
|  | ||||
| @ -16,14 +16,14 @@ void nfc_scene_mfkey_nonces_info_on_enter(void* context) { | ||||
| 
 | ||||
|     uint16_t nonces_saved = mfkey32_get_auth_sectors(temp_str); | ||||
|     widget_add_text_scroll_element(nfc->widget, 0, 22, 128, 42, furi_string_get_cstr(temp_str)); | ||||
|     furi_string_printf(temp_str, "Nonces saved %d", nonces_saved); | ||||
|     furi_string_printf(temp_str, "Nonce pairs saved: %d", nonces_saved); | ||||
|     widget_add_string_element( | ||||
|         nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(temp_str)); | ||||
|     widget_add_string_element( | ||||
|         nfc->widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Authenticated sectors:"); | ||||
| 
 | ||||
|     widget_add_button_element( | ||||
|         nfc->widget, GuiButtonTypeRight, "Next", nfc_scene_mfkey_nonces_info_callback, nfc); | ||||
|         nfc->widget, GuiButtonTypeCenter, "OK", nfc_scene_mfkey_nonces_info_callback, nfc); | ||||
| 
 | ||||
|     furi_string_free(temp_str); | ||||
| 
 | ||||
| @ -35,7 +35,7 @@ bool nfc_scene_mfkey_nonces_info_on_event(void* context, SceneManagerEvent event | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == GuiButtonTypeRight) { | ||||
|         if(event.event == GuiButtonTypeCenter) { | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyComplete); | ||||
|             consumed = true; | ||||
|         } | ||||
|  | ||||
| @ -10,29 +10,50 @@ struct DetectReader { | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint16_t nonces; | ||||
|     uint16_t nonces_max; | ||||
|     DetectReaderState state; | ||||
| } DetectReaderViewModel; | ||||
| 
 | ||||
| static void detect_reader_draw_callback(Canvas* canvas, void* model) { | ||||
|     DetectReaderViewModel* m = model; | ||||
|     char text[32] = {}; | ||||
| 
 | ||||
|     snprintf(text, sizeof(text), "Tap the reader several times"); | ||||
|     canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Tap the reader several times"); | ||||
|     // Draw header and icon
 | ||||
|     canvas_draw_icon(canvas, 0, 16, &I_Modern_reader_18x34); | ||||
|     if(m->state == DetectReaderStateStart) { | ||||
|         snprintf(text, sizeof(text), "Touch the reader"); | ||||
|         canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39); | ||||
|     } else if(m->state == DetectReaderStateReaderDetected) { | ||||
|         snprintf(text, sizeof(text), "Move the Flipper away"); | ||||
|         canvas_draw_icon(canvas, 24, 25, &I_Release_arrow_18x15); | ||||
|     } else if(m->state == DetectReaderStateReaderLost) { | ||||
|         snprintf(text, sizeof(text), "Touch the reader again"); | ||||
|         canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39); | ||||
|     } | ||||
| 
 | ||||
|     if(m->nonces == 0) { | ||||
|     canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, text); | ||||
| 
 | ||||
|     // Draw collected nonces
 | ||||
|     if(m->state == DetectReaderStateStart) { | ||||
|         canvas_set_font(canvas, FontPrimary); | ||||
|         canvas_draw_str_aligned(canvas, 52, 22, AlignLeft, AlignTop, "Emulating..."); | ||||
|         canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Emulating..."); | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
|         canvas_draw_str_aligned(canvas, 52, 35, AlignLeft, AlignTop, "MIFARE Classic"); | ||||
|         canvas_draw_icon(canvas, 0, 13, &I_Tap_reader_36x38); | ||||
|         canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, "MIFARE MFkey32"); | ||||
|     } else { | ||||
|         canvas_set_font(canvas, FontPrimary); | ||||
|         canvas_draw_str_aligned(canvas, 54, 22, AlignLeft, AlignTop, "Collecting..."); | ||||
|         if(m->state == DetectReaderStateDone) { | ||||
|             canvas_set_font(canvas, FontPrimary); | ||||
|             canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Completed!"); | ||||
|         } else { | ||||
|             canvas_set_font(canvas, FontPrimary); | ||||
|             canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Collecting..."); | ||||
|         } | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
|         snprintf(text, sizeof(text), "Nonces: %d", m->nonces); | ||||
|         canvas_draw_str_aligned(canvas, 54, 35, AlignLeft, AlignTop, text); | ||||
|         elements_button_right(canvas, "Next"); | ||||
|         canvas_draw_icon(canvas, 6, 15, &I_ArrowC_1_36x36); | ||||
|         snprintf(text, sizeof(text), "Nonce pairs: %d/%d", m->nonces, m->nonces_max); | ||||
|         canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, text); | ||||
|     } | ||||
|     // Draw button
 | ||||
|     if(m->nonces > 0) { | ||||
|         elements_button_center(canvas, "Done"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -49,7 +70,7 @@ static bool detect_reader_input_callback(InputEvent* event, void* context) { | ||||
|         }); | ||||
| 
 | ||||
|     if(event->type == InputTypeShort) { | ||||
|         if(event->key == InputKeyRight) { | ||||
|         if(event->key == InputKeyOk) { | ||||
|             if(nonces > 0) { | ||||
|                 detect_reader->callback(detect_reader->context); | ||||
|                 consumed = true; | ||||
| @ -84,6 +105,8 @@ void detect_reader_reset(DetectReader* detect_reader) { | ||||
|     with_view_model( | ||||
|         detect_reader->view, (DetectReaderViewModel * model) { | ||||
|             model->nonces = 0; | ||||
|             model->nonces_max = 0; | ||||
|             model->state = DetectReaderStateStart; | ||||
|             return false; | ||||
|         }); | ||||
| } | ||||
| @ -105,11 +128,31 @@ void detect_reader_set_callback( | ||||
|     detect_reader->context = context; | ||||
| } | ||||
| 
 | ||||
| void detect_reader_inc_nonce_cnt(DetectReader* detect_reader) { | ||||
| void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max) { | ||||
|     furi_assert(detect_reader); | ||||
| 
 | ||||
|     with_view_model( | ||||
|         detect_reader->view, (DetectReaderViewModel * model) { | ||||
|             model->nonces++; | ||||
|             model->nonces_max = nonces_max; | ||||
|             return false; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected) { | ||||
|     furi_assert(detect_reader); | ||||
| 
 | ||||
|     with_view_model( | ||||
|         detect_reader->view, (DetectReaderViewModel * model) { | ||||
|             model->nonces = nonces_collected; | ||||
|             return false; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state) { | ||||
|     furi_assert(detect_reader); | ||||
|     with_view_model( | ||||
|         detect_reader->view, (DetectReaderViewModel * model) { | ||||
|             model->state = state; | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
|  | ||||
| @ -5,6 +5,13 @@ | ||||
| 
 | ||||
| typedef struct DetectReader DetectReader; | ||||
| 
 | ||||
| typedef enum { | ||||
|     DetectReaderStateStart, | ||||
|     DetectReaderStateReaderDetected, | ||||
|     DetectReaderStateReaderLost, | ||||
|     DetectReaderStateDone, | ||||
| } DetectReaderState; | ||||
| 
 | ||||
| typedef void (*DetectReaderDoneCallback)(void* context); | ||||
| 
 | ||||
| DetectReader* detect_reader_alloc(); | ||||
| @ -20,4 +27,8 @@ void detect_reader_set_callback( | ||||
|     DetectReaderDoneCallback callback, | ||||
|     void* context); | ||||
| 
 | ||||
| void detect_reader_inc_nonce_cnt(DetectReader* detect_reader); | ||||
| void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max); | ||||
| 
 | ||||
| void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected); | ||||
| 
 | ||||
| void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state); | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/NFC/Modern_reader_18x34.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/NFC/Modern_reader_18x34.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/NFC/Move_flipper_26x39.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/NFC/Move_flipper_26x39.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/NFC/Release_arrow_18x15.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/NFC/Release_arrow_18x15.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.5 KiB | 
| @ -2693,6 +2693,8 @@ Variable,+,I_Lock_7x8,const Icon, | ||||
| Variable,+,I_Lock_8x8,const Icon, | ||||
| Variable,+,I_MHz_25x11,const Icon, | ||||
| Variable,+,I_Medium_chip_22x21,const Icon, | ||||
| Variable,+,I_Modern_reader_18x34,const Icon, | ||||
| Variable,+,I_Move_flipper_26x39,const Icon, | ||||
| Variable,+,I_Mute_25x27,const Icon, | ||||
| Variable,+,I_Mute_hvr_25x27,const Icon, | ||||
| Variable,+,I_NFC_manual_60x50,const Icon, | ||||
| @ -2720,6 +2722,7 @@ Variable,+,I_RFIDDolphinReceive_97x61,const Icon, | ||||
| Variable,+,I_RFIDDolphinSend_97x61,const Icon, | ||||
| Variable,+,I_RFIDDolphinSuccess_108x57,const Icon, | ||||
| Variable,+,I_Reader_detect_43x40,const Icon, | ||||
| Variable,+,I_Release_arrow_18x15,const Icon, | ||||
| Variable,+,I_Restoring_38x32,const Icon, | ||||
| Variable,+,I_Right_mouse_icon_9x9,const Icon, | ||||
| Variable,+,I_SDQuestion_35x43,const Icon, | ||||
|  | ||||
| 
 | 
| @ -92,7 +92,7 @@ void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, | ||||
| 
 | ||||
| static bool mfkey32_write_params(Mfkey32* instance, Mfkey32Params* params) { | ||||
|     FuriString* str = furi_string_alloc_printf( | ||||
|         "Sector %d key %c cuid %08x nt0 %08x nr0 %08x ar0 %08x nt1 %08x nr1 %08x ar1 %08x\n", | ||||
|         "Sec %d key %c cuid %08x nt0 %08x nr0 %08x ar0 %08x nt1 %08x nr1 %08x ar1 %08x\n", | ||||
|         params->sector, | ||||
|         params->key == MfClassicKeyA ? 'A' : 'B', | ||||
|         params->cuid, | ||||
|  | ||||
| @ -647,7 +647,8 @@ static void nfc_worker_reader_analyzer_callback(ReaderAnalyzerEvent event, void* | ||||
|     furi_assert(context); | ||||
|     NfcWorker* nfc_worker = context; | ||||
| 
 | ||||
|     if(event == ReaderAnalyzerEventMfkeyCollected) { | ||||
|     if((nfc_worker->state == NfcWorkerStateAnalyzeReader) && | ||||
|        (event == ReaderAnalyzerEventMfkeyCollected)) { | ||||
|         if(nfc_worker->callback) { | ||||
|             nfc_worker->callback(NfcWorkerEventDetectReaderMfkeyCollected, nfc_worker->context); | ||||
|         } | ||||
| @ -655,6 +656,9 @@ static void nfc_worker_reader_analyzer_callback(ReaderAnalyzerEvent event, void* | ||||
| } | ||||
| 
 | ||||
| void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { | ||||
|     furi_assert(nfc_worker); | ||||
|     furi_assert(nfc_worker->callback); | ||||
| 
 | ||||
|     FuriHalNfcTxRxContext tx_rx = {}; | ||||
| 
 | ||||
|     ReaderAnalyzer* reader_analyzer = nfc_worker->reader_analyzer; | ||||
| @ -673,17 +677,32 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { | ||||
|     rfal_platform_spi_acquire(); | ||||
| 
 | ||||
|     FURI_LOG_D(TAG, "Start reader analyzer"); | ||||
| 
 | ||||
|     uint8_t reader_no_data_received_cnt = 0; | ||||
|     bool reader_no_data_notified = true; | ||||
| 
 | ||||
|     while(nfc_worker->state == NfcWorkerStateAnalyzeReader) { | ||||
|         furi_hal_nfc_stop_cmd(); | ||||
|         furi_delay_ms(5); | ||||
|         furi_hal_nfc_listen_start(nfc_data); | ||||
|         if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { | ||||
|             if(reader_no_data_notified) { | ||||
|                 nfc_worker->callback(NfcWorkerEventDetectReaderDetected, nfc_worker->context); | ||||
|             } | ||||
|             reader_no_data_received_cnt = 0; | ||||
|             reader_no_data_notified = false; | ||||
|             NfcProtocol protocol = | ||||
|                 reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8); | ||||
|             if(protocol == NfcDeviceProtocolMifareClassic) { | ||||
|                 mf_classic_emulator(&emulator, &tx_rx); | ||||
|             } | ||||
|         } else { | ||||
|             reader_no_data_received_cnt++; | ||||
|             if(!reader_no_data_notified && (reader_no_data_received_cnt > 5)) { | ||||
|                 nfc_worker->callback(NfcWorkerEventDetectReaderLost, nfc_worker->context); | ||||
|                 reader_no_data_received_cnt = 0; | ||||
|                 reader_no_data_notified = true; | ||||
|             } | ||||
|             FURI_LOG_D(TAG, "No data from reader"); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
| @ -56,6 +56,8 @@ typedef enum { | ||||
|     NfcWorkerEventFoundKeyB, | ||||
| 
 | ||||
|     // Detect Reader events
 | ||||
|     NfcWorkerEventDetectReaderDetected, | ||||
|     NfcWorkerEventDetectReaderLost, | ||||
|     NfcWorkerEventDetectReaderMfkeyCollected, | ||||
| 
 | ||||
|     // Mifare Ultralight events
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich