[FL-1424] NFC emulate CLI command (#514)
* nfc: move cli commands to separate file * nfc: add nfc_emulate CLI command * nfc: rework nfc emulate call from gui * nfc: deactivate nfc state machine when exiting worker Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									4ad5245969
								
							
						
					
					
						commit
						3a2121bbb8
					
				| @ -159,44 +159,6 @@ void nfc_free(Nfc* nfc) { | |||||||
|     free(nfc); |     free(nfc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_cli_detect(Cli* cli, string_t args, void* context) { |  | ||||||
|     // Check if nfc worker is not busy
 |  | ||||||
|     if(api_hal_nfc_is_busy()) { |  | ||||||
|         printf("Nfc is busy"); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     rfalNfcDevice* dev_list; |  | ||||||
|     uint8_t dev_cnt = 0; |  | ||||||
|     bool cmd_exit = false; |  | ||||||
|     api_hal_nfc_init(); |  | ||||||
|     printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n"); |  | ||||||
|     while(!cmd_exit) { |  | ||||||
|         cmd_exit |= cli_cmd_interrupt_received(cli); |  | ||||||
|         cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 100, true); |  | ||||||
|         if(dev_cnt > 0) { |  | ||||||
|             printf("Found %d devices\r\n", dev_cnt); |  | ||||||
|             for(uint8_t i = 0; i < dev_cnt; i++) { |  | ||||||
|                 printf("%d found: %s ", i, nfc_get_dev_type(dev_list[i].type)); |  | ||||||
|                 if(dev_list[i].type == RFAL_NFC_LISTEN_TYPE_NFCA) { |  | ||||||
|                     printf("type: %s, ", nfc_get_nfca_type(dev_list[i].dev.nfca.type)); |  | ||||||
|                 } |  | ||||||
|                 printf("UID length: %d, UID:", dev_list[i].nfcidLen); |  | ||||||
|                 for(uint8_t j = 0; j < dev_list[i].nfcidLen; j++) { |  | ||||||
|                     printf("%02X", dev_list[i].nfcid[j]); |  | ||||||
|                 } |  | ||||||
|                 printf("\r\n"); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         osDelay(50); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void nfc_cli_init() { |  | ||||||
|     Cli* cli = furi_record_open("cli"); |  | ||||||
|     cli_add_command(cli, "nfc_detect", nfc_cli_detect, NULL); |  | ||||||
|     furi_record_close("cli"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) { | void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) { | ||||||
|     NfcWorkerState state = nfc_worker_get_state(nfc->worker); |     NfcWorkerState state = nfc_worker_get_state(nfc->worker); | ||||||
|     if(state == NfcWorkerStateBroken) { |     if(state == NfcWorkerStateBroken) { | ||||||
|  | |||||||
							
								
								
									
										67
									
								
								applications/nfc/nfc_cli.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										67
									
								
								applications/nfc/nfc_cli.c
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,67 @@ | |||||||
|  | #include "nfc_cli.h" | ||||||
|  | #include "nfc_types.h" | ||||||
|  | #include <furi.h> | ||||||
|  | #include <api-hal.h> | ||||||
|  | 
 | ||||||
|  | void nfc_cli_init() { | ||||||
|  |     Cli* cli = furi_record_open("cli"); | ||||||
|  |     cli_add_command(cli, "nfc_detect", nfc_cli_detect, NULL); | ||||||
|  |     cli_add_command(cli, "nfc_emulate", nfc_cli_emulate, NULL); | ||||||
|  |     furi_record_close("cli"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_cli_detect(Cli* cli, string_t args, void* context) { | ||||||
|  |     // Check if nfc worker is not busy
 | ||||||
|  |     if(api_hal_nfc_is_busy()) { | ||||||
|  |         printf("Nfc is busy"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     rfalNfcDevice* dev_list; | ||||||
|  |     uint8_t dev_cnt = 0; | ||||||
|  |     bool cmd_exit = false; | ||||||
|  |     api_hal_nfc_init(); | ||||||
|  |     api_hal_nfc_exit_sleep(); | ||||||
|  |     printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n"); | ||||||
|  |     while(!cmd_exit) { | ||||||
|  |         cmd_exit |= cli_cmd_interrupt_received(cli); | ||||||
|  |         cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 100, true); | ||||||
|  |         if(dev_cnt > 0) { | ||||||
|  |             printf("Found %d devices\r\n", dev_cnt); | ||||||
|  |             for(uint8_t i = 0; i < dev_cnt; i++) { | ||||||
|  |                 printf("%d found: %s ", i + 1, nfc_get_dev_type(dev_list[i].type)); | ||||||
|  |                 if(dev_list[i].type == RFAL_NFC_LISTEN_TYPE_NFCA) { | ||||||
|  |                     printf("type: %s, ", nfc_get_nfca_type(dev_list[i].dev.nfca.type)); | ||||||
|  |                 } | ||||||
|  |                 printf("UID length: %d, UID:", dev_list[i].nfcidLen); | ||||||
|  |                 for(uint8_t j = 0; j < dev_list[i].nfcidLen; j++) { | ||||||
|  |                     printf("%02X", dev_list[i].nfcid[j]); | ||||||
|  |                 } | ||||||
|  |                 printf("\r\n"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         osDelay(50); | ||||||
|  |     } | ||||||
|  |     api_hal_nfc_deactivate(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_cli_emulate(Cli* cli, string_t args, void* context) { | ||||||
|  |     // Check if nfc worker is not busy
 | ||||||
|  |     if(api_hal_nfc_is_busy()) { | ||||||
|  |         printf("Nfc is busy"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     api_hal_nfc_init(); | ||||||
|  |     api_hal_nfc_exit_sleep(); | ||||||
|  |     printf("Emulating NFC-A Type: T2T UID: CF72D440 SAK: 20 ATQA: 00/04\r\n"); | ||||||
|  |     printf("Press Ctrl+C to abort\r\n"); | ||||||
|  | 
 | ||||||
|  |     while(!cli_cmd_interrupt_received(cli)) { | ||||||
|  |         if(api_hal_nfc_listen(100)) { | ||||||
|  |             printf("Reader detected\r\n"); | ||||||
|  |             api_hal_nfc_deactivate(); | ||||||
|  |         } | ||||||
|  |         osDelay(50); | ||||||
|  |     } | ||||||
|  |     api_hal_nfc_deactivate(); | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								applications/nfc/nfc_cli.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								applications/nfc/nfc_cli.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <cli/cli.h> | ||||||
|  | 
 | ||||||
|  | void nfc_cli_init(); | ||||||
|  | 
 | ||||||
|  | void nfc_cli_detect(Cli* cli, string_t args, void* context); | ||||||
|  | 
 | ||||||
|  | void nfc_cli_emulate(Cli* cli, string_t args, void* context); | ||||||
| @ -145,9 +145,9 @@ void nfc_view_emulate_draw(Canvas* canvas, void* model) { | |||||||
|     canvas_draw_str(canvas, 0, 12, "Emulating NFC-A"); |     canvas_draw_str(canvas, 0, 12, "Emulating NFC-A"); | ||||||
|     canvas_set_font(canvas, FontSecondary); |     canvas_set_font(canvas, FontSecondary); | ||||||
|     canvas_draw_str(canvas, 2, 22, "Type: T2T"); |     canvas_draw_str(canvas, 2, 22, "Type: T2T"); | ||||||
|     canvas_draw_str(canvas, 2, 32, "UID length: 7"); |     canvas_draw_str(canvas, 2, 32, "UID length: 4"); | ||||||
|     canvas_draw_str(canvas, 2, 42, "UID: 00010203040506"); |     canvas_draw_str(canvas, 2, 42, "UID: CF72D440"); | ||||||
|     canvas_draw_str(canvas, 2, 52, "SAK: 00 ATQA: 44/00"); |     canvas_draw_str(canvas, 2, 52, "SAK: 20 ATQA: 00/04"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_view_field_draw(Canvas* canvas, void* model) { | void nfc_view_field_draw(Canvas* canvas, void* model) { | ||||||
|  | |||||||
| @ -59,6 +59,7 @@ void nfc_worker_task(void* context) { | |||||||
|     NfcWorker* nfc_worker = context; |     NfcWorker* nfc_worker = context; | ||||||
| 
 | 
 | ||||||
|     api_hal_power_insomnia_enter(); |     api_hal_power_insomnia_enter(); | ||||||
|  |     api_hal_nfc_exit_sleep(); | ||||||
| 
 | 
 | ||||||
|     if(nfc_worker->state == NfcWorkerStatePoll) { |     if(nfc_worker->state == NfcWorkerStatePoll) { | ||||||
|         nfc_worker_poll(nfc_worker); |         nfc_worker_poll(nfc_worker); | ||||||
| @ -71,6 +72,7 @@ void nfc_worker_task(void* context) { | |||||||
|     } else if(nfc_worker->state == NfcWorkerStateField) { |     } else if(nfc_worker->state == NfcWorkerStateField) { | ||||||
|         nfc_worker_field(nfc_worker); |         nfc_worker_field(nfc_worker); | ||||||
|     } |     } | ||||||
|  |     api_hal_nfc_deactivate(); | ||||||
|     nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); |     nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); | ||||||
|     api_hal_power_insomnia_exit(); |     api_hal_power_insomnia_exit(); | ||||||
|     osThreadExit(); |     osThreadExit(); | ||||||
| @ -209,7 +211,6 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { | |||||||
|         } |         } | ||||||
|         osDelay(20); |         osDelay(20); | ||||||
|     } |     } | ||||||
|     api_hal_nfc_deactivate(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_worker_emulate_emv(NfcWorker* nfc_worker) { | void nfc_worker_emulate_emv(NfcWorker* nfc_worker) { | ||||||
| @ -305,104 +306,14 @@ void nfc_worker_poll(NfcWorker* nfc_worker) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_worker_state_callback(rfalNfcState st) { |  | ||||||
|     (void)st; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ReturnCode nfc_worker_trx( |  | ||||||
|     uint8_t* txBuf, |  | ||||||
|     uint16_t txBufSize, |  | ||||||
|     uint8_t** rxData, |  | ||||||
|     uint16_t** rcvLen, |  | ||||||
|     uint32_t fwt) { |  | ||||||
|     ReturnCode err; |  | ||||||
| 
 |  | ||||||
|     err = rfalNfcDataExchangeStart(txBuf, txBufSize, rxData, rcvLen, fwt); |  | ||||||
|     if(err == ERR_NONE) { |  | ||||||
|         do { |  | ||||||
|             rfalNfcWorker(); |  | ||||||
|             err = rfalNfcDataExchangeGetStatus(); |  | ||||||
|         } while(err == ERR_BUSY); |  | ||||||
|     } |  | ||||||
|     return err; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void nfc_worker_exchange(NfcWorker* nfc_worker, rfalNfcDevice* nfc_device) { |  | ||||||
|     ReturnCode err = ERR_NONE; |  | ||||||
|     uint8_t* rxData; |  | ||||||
|     uint16_t* rcvLen; |  | ||||||
|     uint8_t txBuf[100]; |  | ||||||
|     uint16_t txLen; |  | ||||||
| 
 |  | ||||||
|     do { |  | ||||||
|         rfalNfcWorker(); |  | ||||||
|         switch(rfalNfcGetState()) { |  | ||||||
|         case RFAL_NFC_STATE_ACTIVATED: |  | ||||||
|             err = nfc_worker_trx(NULL, 0, &rxData, &rcvLen, 0); |  | ||||||
|             break; |  | ||||||
|         case RFAL_NFC_STATE_DATAEXCHANGE: |  | ||||||
|         case RFAL_NFC_STATE_DATAEXCHANGE_DONE: |  | ||||||
|             // Not supported
 |  | ||||||
|             txBuf[0] = ((char)0x68); |  | ||||||
|             txBuf[1] = ((char)0x00); |  | ||||||
|             txLen = 2; |  | ||||||
|             err = nfc_worker_trx(txBuf, txLen, &rxData, &rcvLen, RFAL_FWT_NONE); |  | ||||||
|             break; |  | ||||||
|         case RFAL_NFC_STATE_START_DISCOVERY: |  | ||||||
|             return; |  | ||||||
|         case RFAL_NFC_STATE_LISTEN_SLEEP: |  | ||||||
|         default: |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } while((err == ERR_NONE) || (err == ERR_SLEEP_REQ)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void nfc_worker_emulate(NfcWorker* nfc_worker) { | void nfc_worker_emulate(NfcWorker* nfc_worker) { | ||||||
|     rfalNfcDiscoverParam params; |  | ||||||
|     params.compMode = RFAL_COMPLIANCE_MODE_NFC; |  | ||||||
|     params.techs2Find = RFAL_NFC_LISTEN_TECH_A; |  | ||||||
|     params.totalDuration = 1000U; |  | ||||||
|     params.devLimit = 1; |  | ||||||
|     params.wakeupEnabled = false; |  | ||||||
|     params.wakeupConfigDefault = true; |  | ||||||
|     params.nfcfBR = RFAL_BR_212; |  | ||||||
|     params.ap2pBR = RFAL_BR_424; |  | ||||||
|     params.maxBR = RFAL_BR_KEEP; |  | ||||||
|     params.GBLen = RFAL_NFCDEP_GB_MAX_LEN; |  | ||||||
|     params.notifyCb = nfc_worker_state_callback; |  | ||||||
| 
 |  | ||||||
|     params.lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_07; |  | ||||||
|     params.lmConfigPA.nfcid[0] = 0x00; |  | ||||||
|     params.lmConfigPA.nfcid[1] = 0x01; |  | ||||||
|     params.lmConfigPA.nfcid[2] = 0x02; |  | ||||||
|     params.lmConfigPA.nfcid[3] = 0x03; |  | ||||||
|     params.lmConfigPA.nfcid[4] = 0x04; |  | ||||||
|     params.lmConfigPA.nfcid[5] = 0x05; |  | ||||||
|     params.lmConfigPA.nfcid[6] = 0x06; |  | ||||||
|     params.lmConfigPA.SENS_RES[0] = 0x44; |  | ||||||
|     params.lmConfigPA.SENS_RES[1] = 0x00; |  | ||||||
|     params.lmConfigPA.SEL_RES = 0x00; |  | ||||||
|     api_hal_nfc_exit_sleep(); |  | ||||||
| 
 |  | ||||||
|     ReturnCode ret; |  | ||||||
|     ret = rfalNfcDiscover(¶ms); |  | ||||||
|     if(ret != ERR_NONE) { |  | ||||||
|         asm("bkpt 1"); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     rfalNfcDevice* nfc_device; |  | ||||||
|     while(nfc_worker->state == NfcWorkerStateEmulate) { |     while(nfc_worker->state == NfcWorkerStateEmulate) { | ||||||
|         rfalNfcWorker(); |         if(api_hal_nfc_listen(100)) { | ||||||
|         if(rfalNfcIsDevActivated(rfalNfcGetState())) { |             FURI_LOG_I(NFC_WORKER_TAG, "Reader detected"); | ||||||
|             rfalNfcGetActiveDevice(&nfc_device); |             api_hal_nfc_deactivate(); | ||||||
|             nfc_worker_exchange(nfc_worker, nfc_device); |  | ||||||
|         } |         } | ||||||
|         osDelay(10); |         osDelay(5); | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     rfalNfcDeactivate(false); |  | ||||||
|     api_hal_nfc_start_sleep(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_worker_field(NfcWorker* nfc_worker) { | void nfc_worker_field(NfcWorker* nfc_worker) { | ||||||
|  | |||||||
| @ -89,7 +89,6 @@ bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t cyc | |||||||
| 
 | 
 | ||||||
| bool api_hal_nfc_listen(uint32_t timeout) { | bool api_hal_nfc_listen(uint32_t timeout) { | ||||||
|     api_hal_nfc_exit_sleep(); |     api_hal_nfc_exit_sleep(); | ||||||
|     rfalLowPowerModeStop(); |  | ||||||
| 
 | 
 | ||||||
|     rfalNfcState state = rfalNfcGetState(); |     rfalNfcState state = rfalNfcGetState(); | ||||||
|     if(state == RFAL_NFC_STATE_NOTINIT) { |     if(state == RFAL_NFC_STATE_NOTINIT) { | ||||||
| @ -130,6 +129,7 @@ bool api_hal_nfc_listen(uint32_t timeout) { | |||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         if(state == RFAL_NFC_STATE_LISTEN_ACTIVATION) { |         if(state == RFAL_NFC_STATE_LISTEN_ACTIVATION) { | ||||||
|  |             start = DWT->CYCCNT; | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         taskYIELD(); |         taskYIELD(); | ||||||
|  | |||||||
| @ -89,7 +89,6 @@ bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t cyc | |||||||
| 
 | 
 | ||||||
| bool api_hal_nfc_listen(uint32_t timeout) { | bool api_hal_nfc_listen(uint32_t timeout) { | ||||||
|     api_hal_nfc_exit_sleep(); |     api_hal_nfc_exit_sleep(); | ||||||
|     rfalLowPowerModeStop(); |  | ||||||
| 
 | 
 | ||||||
|     rfalNfcState state = rfalNfcGetState(); |     rfalNfcState state = rfalNfcGetState(); | ||||||
|     if(state == RFAL_NFC_STATE_NOTINIT) { |     if(state == RFAL_NFC_STATE_NOTINIT) { | ||||||
| @ -130,6 +129,7 @@ bool api_hal_nfc_listen(uint32_t timeout) { | |||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         if(state == RFAL_NFC_STATE_LISTEN_ACTIVATION) { |         if(state == RFAL_NFC_STATE_LISTEN_ACTIVATION) { | ||||||
|  |             start = DWT->CYCCNT; | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         taskYIELD(); |         taskYIELD(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich