[FL-3640] NFC: Felica UID emulation (#3190)
* Added basic template of Felica listener * Raw nfc felica listener functions * Added functions to setup chip for felica listener * Cleanup function templates from unnecessary parts * Removed todo comment * Updated api versions * Adjusted chip config for felica * Set proper chip passive target mode for felica * Added felica function to unit tests * Update furi_hal_nfc_felica.c * Removed duplication Co-authored-by: gornekich <n.gorbadey@gmail.com>
This commit is contained in:
		
							parent
							
								
									4b3e8aba29
								
							
						
					
					
						commit
						1c3cbec661
					
				| @ -455,4 +455,19 @@ NfcError nfc_iso15693_listener_tx_sof(Nfc* instance) { | |||||||
|     return NfcErrorNone; |     return NfcErrorNone; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | NfcError nfc_felica_listener_set_sensf_res_data( | ||||||
|  |     Nfc* instance, | ||||||
|  |     const uint8_t* idm, | ||||||
|  |     const uint8_t idm_len, | ||||||
|  |     const uint8_t* pmm, | ||||||
|  |     const uint8_t pmm_len) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(idm); | ||||||
|  |     furi_assert(pmm); | ||||||
|  |     furi_assert(idm_len == 8); | ||||||
|  |     furi_assert(pmm_len == 8); | ||||||
|  | 
 | ||||||
|  |     return NfcErrorNone; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -67,8 +67,14 @@ static bool nfc_scene_saved_menu_on_event_felica(NfcApp* instance, uint32_t even | |||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void nfc_scene_emulate_on_enter_felica(NfcApp* instance) { | ||||||
|  |     const FelicaData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolFelica); | ||||||
|  |     instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolFelica, data); | ||||||
|  |     nfc_listener_start(instance->listener, NULL, NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const NfcProtocolSupportBase nfc_protocol_support_felica = { | const NfcProtocolSupportBase nfc_protocol_support_felica = { | ||||||
|     .features = NfcProtocolFeatureNone, |     .features = NfcProtocolFeatureEmulateUid, | ||||||
| 
 | 
 | ||||||
|     .scene_info = |     .scene_info = | ||||||
|         { |         { | ||||||
| @ -102,7 +108,7 @@ const NfcProtocolSupportBase nfc_protocol_support_felica = { | |||||||
|         }, |         }, | ||||||
|     .scene_emulate = |     .scene_emulate = | ||||||
|         { |         { | ||||||
|             .on_enter = nfc_protocol_support_common_on_enter_empty, |             .on_enter = nfc_scene_emulate_on_enter_felica, | ||||||
|             .on_event = nfc_protocol_support_common_on_event_empty, |             .on_event = nfc_protocol_support_common_on_event_empty, | ||||||
|         }, |         }, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -76,7 +76,7 @@ static const FuriHalNfcTech nfc_tech_table[NfcModeNum][NfcTechNum] = { | |||||||
|             [NfcTechIso14443a] = FuriHalNfcTechIso14443a, |             [NfcTechIso14443a] = FuriHalNfcTechIso14443a, | ||||||
|             [NfcTechIso14443b] = FuriHalNfcTechInvalid, |             [NfcTechIso14443b] = FuriHalNfcTechInvalid, | ||||||
|             [NfcTechIso15693] = FuriHalNfcTechIso15693, |             [NfcTechIso15693] = FuriHalNfcTechIso15693, | ||||||
|             [NfcTechFelica] = FuriHalNfcTechInvalid, |             [NfcTechFelica] = FuriHalNfcTechFelica, | ||||||
|         }, |         }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -646,4 +646,20 @@ NfcError nfc_iso15693_listener_tx_sof(Nfc* instance) { | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | NfcError nfc_felica_listener_set_sensf_res_data( | ||||||
|  |     Nfc* instance, | ||||||
|  |     const uint8_t* idm, | ||||||
|  |     const uint8_t idm_len, | ||||||
|  |     const uint8_t* pmm, | ||||||
|  |     const uint8_t pmm_len) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(idm); | ||||||
|  |     furi_assert(pmm); | ||||||
|  | 
 | ||||||
|  |     FuriHalNfcError error = | ||||||
|  |         furi_hal_nfc_felica_listener_set_sensf_res_data(idm, idm_len, pmm, pmm_len); | ||||||
|  |     instance->comm_state = NfcCommStateIdle; | ||||||
|  |     return nfc_process_hal_error(error); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif // APP_UNIT_TESTS
 | #endif // APP_UNIT_TESTS
 | ||||||
|  | |||||||
| @ -351,6 +351,25 @@ NfcError nfc_iso14443a_listener_set_col_res_data( | |||||||
|     uint8_t* atqa, |     uint8_t* atqa, | ||||||
|     uint8_t sak); |     uint8_t sak); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Set FeliCa collision resolution parameters in listener mode. | ||||||
|  |  *  | ||||||
|  |  * Configures the NFC hardware for automatic collision resolution. | ||||||
|  |  * | ||||||
|  |  * @param[in,out] instance pointer to the instance to be configured. | ||||||
|  |  * @param[in] idm pointer to a byte array containing the IDm. | ||||||
|  |  * @param[in] idm_len IDm length in bytes. | ||||||
|  |  * @param[in] pmm pointer to a byte array containing the PMm. | ||||||
|  |  * @param[in] pmm_len PMm length in bytes. | ||||||
|  |  * @returns NfcErrorNone on success, any other error code on failure. | ||||||
|  | */ | ||||||
|  | NfcError nfc_felica_listener_set_sensf_res_data( | ||||||
|  |     Nfc* instance, | ||||||
|  |     const uint8_t* idm, | ||||||
|  |     const uint8_t idm_len, | ||||||
|  |     const uint8_t* pmm, | ||||||
|  |     const uint8_t pmm_len); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Send ISO15693 Start of Frame pattern in listener mode |  * @brief Send ISO15693 Start of Frame pattern in listener mode | ||||||
|  * |  * | ||||||
|  | |||||||
| @ -14,6 +14,8 @@ extern "C" { | |||||||
| #define FELICA_FDT_POLL_FC (10000U) | #define FELICA_FDT_POLL_FC (10000U) | ||||||
| #define FELICA_POLL_POLL_MIN_US (1280U) | #define FELICA_POLL_POLL_MIN_US (1280U) | ||||||
| 
 | 
 | ||||||
|  | #define FELICA_FDT_LISTEN_FC (1172) | ||||||
|  | 
 | ||||||
| #define FELICA_SYSTEM_CODE_CODE (0xFFFFU) | #define FELICA_SYSTEM_CODE_CODE (0xFFFFU) | ||||||
| #define FELICA_TIME_SLOT_1 (0x00U) | #define FELICA_TIME_SLOT_1 (0x00U) | ||||||
| #define FELICA_TIME_SLOT_2 (0x01U) | #define FELICA_TIME_SLOT_2 (0x01U) | ||||||
|  | |||||||
							
								
								
									
										79
									
								
								lib/nfc/protocols/felica/felica_listener.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								lib/nfc/protocols/felica/felica_listener.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | |||||||
|  | #include "felica_listener_i.h" | ||||||
|  | 
 | ||||||
|  | #include "nfc/protocols/nfc_listener_base.h" | ||||||
|  | 
 | ||||||
|  | #define FELICA_LISTENER_MAX_BUFFER_SIZE (64) | ||||||
|  | #define TAG "Felica" | ||||||
|  | 
 | ||||||
|  | FelicaListener* felica_listener_alloc(Nfc* nfc, FelicaData* data) { | ||||||
|  |     furi_assert(nfc); | ||||||
|  |     furi_assert(data); | ||||||
|  | 
 | ||||||
|  |     FelicaListener* instance = malloc(sizeof(FelicaListener)); | ||||||
|  |     instance->nfc = nfc; | ||||||
|  |     instance->data = data; | ||||||
|  |     instance->tx_buffer = bit_buffer_alloc(FELICA_LISTENER_MAX_BUFFER_SIZE); | ||||||
|  |     instance->rx_buffer = bit_buffer_alloc(FELICA_LISTENER_MAX_BUFFER_SIZE); | ||||||
|  | 
 | ||||||
|  |     nfc_set_fdt_listen_fc(instance->nfc, FELICA_FDT_LISTEN_FC); | ||||||
|  | 
 | ||||||
|  |     nfc_config(instance->nfc, NfcModeListener, NfcTechFelica); | ||||||
|  |     nfc_felica_listener_set_sensf_res_data( | ||||||
|  |         nfc, data->idm.data, sizeof(data->idm), data->pmm.data, sizeof(data->pmm)); | ||||||
|  | 
 | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void felica_listener_free(FelicaListener* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(instance->tx_buffer); | ||||||
|  | 
 | ||||||
|  |     bit_buffer_free(instance->tx_buffer); | ||||||
|  |     bit_buffer_free(instance->rx_buffer); | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void felica_listener_set_callback( | ||||||
|  |     FelicaListener* listener, | ||||||
|  |     NfcGenericCallback callback, | ||||||
|  |     void* context) { | ||||||
|  |     UNUSED(listener); | ||||||
|  |     UNUSED(callback); | ||||||
|  |     UNUSED(context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const FelicaData* felica_listener_get_data(const FelicaListener* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(instance->data); | ||||||
|  | 
 | ||||||
|  |     return instance->data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | NfcCommand felica_listener_run(NfcGenericEvent event, void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     furi_assert(event.protocol == NfcProtocolInvalid); | ||||||
|  |     furi_assert(event.event_data); | ||||||
|  | 
 | ||||||
|  |     FelicaListener* instance = context; | ||||||
|  |     NfcEvent* nfc_event = event.event_data; | ||||||
|  |     NfcCommand command = NfcCommandContinue; | ||||||
|  | 
 | ||||||
|  |     if(nfc_event->type == NfcEventTypeListenerActivated) { | ||||||
|  |         instance->state = Felica_ListenerStateActivated; | ||||||
|  |         FURI_LOG_D(TAG, "Activated"); | ||||||
|  |     } else if(nfc_event->type == NfcEventTypeFieldOff) { | ||||||
|  |         instance->state = Felica_ListenerStateIdle; | ||||||
|  |         FURI_LOG_D(TAG, "Field Off"); | ||||||
|  |     } else if(nfc_event->type == NfcEventTypeRxEnd) { | ||||||
|  |         FURI_LOG_D(TAG, "Rx Done"); | ||||||
|  |     } | ||||||
|  |     return command; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const NfcListenerBase nfc_listener_felica = { | ||||||
|  |     .alloc = (NfcListenerAlloc)felica_listener_alloc, | ||||||
|  |     .free = (NfcListenerFree)felica_listener_free, | ||||||
|  |     .set_callback = (NfcListenerSetCallback)felica_listener_set_callback, | ||||||
|  |     .get_data = (NfcListenerGetData)felica_listener_get_data, | ||||||
|  |     .run = (NfcListenerRun)felica_listener_run, | ||||||
|  | }; | ||||||
							
								
								
									
										14
									
								
								lib/nfc/protocols/felica/felica_listener.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								lib/nfc/protocols/felica/felica_listener.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "felica.h" | ||||||
|  | #include <lib/nfc/nfc.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | typedef struct FelicaListener FelicaListener; | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										13
									
								
								lib/nfc/protocols/felica/felica_listener_defs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/nfc/protocols/felica/felica_listener_defs.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <nfc/protocols/nfc_listener_base.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | extern const NfcListenerBase nfc_listener_felica; | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										21
									
								
								lib/nfc/protocols/felica/felica_listener_i.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								lib/nfc/protocols/felica/felica_listener_i.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | #include "felica_listener.h" | ||||||
|  | 
 | ||||||
|  | #include <nfc/protocols/nfc_generic_event.h> | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     Felica_ListenerStateIdle, | ||||||
|  |     Felica_ListenerStateActivated, | ||||||
|  | } FelicaListenerState; | ||||||
|  | 
 | ||||||
|  | struct FelicaListener { | ||||||
|  |     Nfc* nfc; | ||||||
|  |     FelicaData* data; | ||||||
|  |     FelicaListenerState state; | ||||||
|  | 
 | ||||||
|  |     BitBuffer* tx_buffer; | ||||||
|  |     BitBuffer* rx_buffer; | ||||||
|  | 
 | ||||||
|  |     NfcGenericEvent generic_event; | ||||||
|  |     NfcGenericCallback callback; | ||||||
|  |     void* context; | ||||||
|  | }; | ||||||
| @ -6,6 +6,7 @@ | |||||||
| #include <nfc/protocols/mf_ultralight/mf_ultralight_listener_defs.h> | #include <nfc/protocols/mf_ultralight/mf_ultralight_listener_defs.h> | ||||||
| #include <nfc/protocols/mf_classic/mf_classic_listener_defs.h> | #include <nfc/protocols/mf_classic/mf_classic_listener_defs.h> | ||||||
| #include <nfc/protocols/slix/slix_listener_defs.h> | #include <nfc/protocols/slix/slix_listener_defs.h> | ||||||
|  | #include <nfc/protocols/felica/felica_listener_defs.h> | ||||||
| 
 | 
 | ||||||
| const NfcListenerBase* nfc_listeners_api[NfcProtocolNum] = { | const NfcListenerBase* nfc_listeners_api[NfcProtocolNum] = { | ||||||
|     [NfcProtocolIso14443_3a] = &nfc_listener_iso14443_3a, |     [NfcProtocolIso14443_3a] = &nfc_listener_iso14443_3a, | ||||||
| @ -18,4 +19,5 @@ const NfcListenerBase* nfc_listeners_api[NfcProtocolNum] = { | |||||||
|     [NfcProtocolMfDesfire] = NULL, |     [NfcProtocolMfDesfire] = NULL, | ||||||
|     [NfcProtocolSlix] = &nfc_listener_slix, |     [NfcProtocolSlix] = &nfc_listener_slix, | ||||||
|     [NfcProtocolSt25tb] = NULL, |     [NfcProtocolSt25tb] = NULL, | ||||||
|  |     [NfcProtocolFelica] = &nfc_listener_felica, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1287,6 +1287,7 @@ Function,+,furi_hal_nfc_abort,FuriHalNfcError, | |||||||
| Function,+,furi_hal_nfc_acquire,FuriHalNfcError, | Function,+,furi_hal_nfc_acquire,FuriHalNfcError, | ||||||
| Function,+,furi_hal_nfc_event_start,FuriHalNfcError, | Function,+,furi_hal_nfc_event_start,FuriHalNfcError, | ||||||
| Function,+,furi_hal_nfc_event_stop,FuriHalNfcError, | Function,+,furi_hal_nfc_event_stop,FuriHalNfcError, | ||||||
|  | Function,+,furi_hal_nfc_felica_listener_set_sensf_res_data,FuriHalNfcError,"const uint8_t*, const uint8_t, const uint8_t*, const uint8_t" | ||||||
| Function,+,furi_hal_nfc_field_detect_start,FuriHalNfcError, | Function,+,furi_hal_nfc_field_detect_start,FuriHalNfcError, | ||||||
| Function,+,furi_hal_nfc_field_detect_stop,FuriHalNfcError, | Function,+,furi_hal_nfc_field_detect_stop,FuriHalNfcError, | ||||||
| Function,+,furi_hal_nfc_field_is_present,_Bool, | Function,+,furi_hal_nfc_field_is_present,_Bool, | ||||||
| @ -2316,6 +2317,7 @@ Function,+,nfc_dict_get_next_key,_Bool,"NfcDict*, uint8_t*, size_t" | |||||||
| Function,+,nfc_dict_get_total_keys,uint32_t,NfcDict* | Function,+,nfc_dict_get_total_keys,uint32_t,NfcDict* | ||||||
| Function,+,nfc_dict_is_key_present,_Bool,"NfcDict*, const uint8_t*, size_t" | Function,+,nfc_dict_is_key_present,_Bool,"NfcDict*, const uint8_t*, size_t" | ||||||
| Function,+,nfc_dict_rewind,_Bool,NfcDict* | Function,+,nfc_dict_rewind,_Bool,NfcDict* | ||||||
|  | Function,+,nfc_felica_listener_set_sensf_res_data,NfcError,"Nfc*, const uint8_t*, const uint8_t, const uint8_t*, const uint8_t" | ||||||
| Function,+,nfc_free,void,Nfc* | Function,+,nfc_free,void,Nfc* | ||||||
| Function,+,nfc_iso14443a_listener_set_col_res_data,NfcError,"Nfc*, uint8_t*, uint8_t, uint8_t*, uint8_t" | Function,+,nfc_iso14443a_listener_set_col_res_data,NfcError,"Nfc*, uint8_t*, uint8_t, uint8_t*, uint8_t" | ||||||
| Function,+,nfc_iso14443a_listener_tx_custom_parity,NfcError,"Nfc*, const BitBuffer*" | Function,+,nfc_iso14443a_listener_tx_custom_parity,NfcError,"Nfc*, const BitBuffer*" | ||||||
|  | |||||||
| 
 | 
| @ -1,6 +1,9 @@ | |||||||
| #include "furi_hal_nfc_i.h" | #include "furi_hal_nfc_i.h" | ||||||
| #include "furi_hal_nfc_tech_i.h" | #include "furi_hal_nfc_tech_i.h" | ||||||
| 
 | 
 | ||||||
|  | // Prevent FDT timer from starting
 | ||||||
|  | #define FURI_HAL_NFC_FELICA_LISTENER_FDT_COMP_FC (INT32_MAX) | ||||||
|  | 
 | ||||||
| static FuriHalNfcError furi_hal_nfc_felica_poller_init(FuriHalSpiBusHandle* handle) { | static FuriHalNfcError furi_hal_nfc_felica_poller_init(FuriHalSpiBusHandle* handle) { | ||||||
|     // Enable Felica mode, AM modulation
 |     // Enable Felica mode, AM modulation
 | ||||||
|     st25r3916_change_reg_bits( |     st25r3916_change_reg_bits( | ||||||
| @ -50,6 +53,126 @@ static FuriHalNfcError furi_hal_nfc_felica_poller_deinit(FuriHalSpiBusHandle* ha | |||||||
|     return FuriHalNfcErrorNone; |     return FuriHalNfcErrorNone; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static FuriHalNfcError furi_hal_nfc_felica_listener_init(FuriHalSpiBusHandle* handle) { | ||||||
|  |     furi_assert(handle); | ||||||
|  |     st25r3916_write_reg( | ||||||
|  |         handle, | ||||||
|  |         ST25R3916_REG_OP_CONTROL, | ||||||
|  |         ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en | | ||||||
|  |             ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); | ||||||
|  | 
 | ||||||
|  |     // Enable Target Felica mode, AM modulation
 | ||||||
|  |     st25r3916_write_reg( | ||||||
|  |         handle, | ||||||
|  |         ST25R3916_REG_MODE, | ||||||
|  |         ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om2 | ST25R3916_REG_MODE_tr_am); | ||||||
|  | 
 | ||||||
|  |     st25r3916_change_reg_bits( | ||||||
|  |         handle, | ||||||
|  |         ST25R3916_REG_BIT_RATE, | ||||||
|  |         ST25R3916_REG_BIT_RATE_txrate_mask | ST25R3916_REG_BIT_RATE_rxrate_mask, | ||||||
|  |         ST25R3916_REG_BIT_RATE_txrate_212 | ST25R3916_REG_BIT_RATE_rxrate_212); | ||||||
|  | 
 | ||||||
|  |     // Receive configuration
 | ||||||
|  |     st25r3916_write_reg( | ||||||
|  |         handle, | ||||||
|  |         ST25R3916_REG_RX_CONF1, | ||||||
|  |         ST25R3916_REG_RX_CONF1_lp0 | ST25R3916_REG_RX_CONF1_hz_12_80khz); | ||||||
|  | 
 | ||||||
|  |     // AGC enabled, ratio 3:1, squelch after TX
 | ||||||
|  |     st25r3916_write_reg( | ||||||
|  |         handle, | ||||||
|  |         ST25R3916_REG_RX_CONF2, | ||||||
|  |         ST25R3916_REG_RX_CONF2_agc6_3 | ST25R3916_REG_RX_CONF2_agc_m | | ||||||
|  |             ST25R3916_REG_RX_CONF2_agc_en | ST25R3916_REG_RX_CONF2_sqm_dyn); | ||||||
|  |     // HF operation, full gain on AM and PM channels
 | ||||||
|  |     st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF3, 0x00); | ||||||
|  |     // No gain reduction on AM and PM channels
 | ||||||
|  |     st25r3916_write_reg(handle, ST25R3916_REG_RX_CONF4, 0x00); | ||||||
|  |     // 10% ASK modulation
 | ||||||
|  |     st25r3916_write_reg(handle, ST25R3916_REG_TX_DRIVER, ST25R3916_REG_TX_DRIVER_am_mod_10percent); | ||||||
|  | 
 | ||||||
|  |     // Correlator setup
 | ||||||
|  |     st25r3916_write_reg( | ||||||
|  |         handle, | ||||||
|  |         ST25R3916_REG_CORR_CONF1, | ||||||
|  |         ST25R3916_REG_CORR_CONF1_corr_s6 | ST25R3916_REG_CORR_CONF1_corr_s4 | | ||||||
|  |             ST25R3916_REG_CORR_CONF1_corr_s2); | ||||||
|  | 
 | ||||||
|  |     // Sleep mode disable, 424kHz mode off
 | ||||||
|  |     st25r3916_write_reg(handle, ST25R3916_REG_CORR_CONF2, 0x00); | ||||||
|  | 
 | ||||||
|  |     st25r3916_write_reg(handle, ST25R3916_REG_MASK_RX_TIMER, 0x02); | ||||||
|  | 
 | ||||||
|  |     st25r3916_direct_cmd(handle, ST25R3916_CMD_STOP); | ||||||
|  |     uint32_t interrupts = | ||||||
|  |         (ST25R3916_IRQ_MASK_FWL | ST25R3916_IRQ_MASK_TXE | ST25R3916_IRQ_MASK_RXS | | ||||||
|  |          ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_CRC | | ||||||
|  |          ST25R3916_IRQ_MASK_ERR1 | ST25R3916_IRQ_MASK_ERR2 | ST25R3916_IRQ_MASK_NRE | | ||||||
|  |          ST25R3916_IRQ_MASK_EON | ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_WU_A_X | | ||||||
|  |          ST25R3916_IRQ_MASK_WU_A); | ||||||
|  |     // Clear interrupts
 | ||||||
|  |     st25r3916_get_irq(handle); | ||||||
|  | 
 | ||||||
|  |     st25r3916_write_reg( | ||||||
|  |         handle, | ||||||
|  |         ST25R3916_REG_PASSIVE_TARGET, | ||||||
|  |         ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a | ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p | | ||||||
|  |             ST25R3916_REG_PASSIVE_TARGET_fdel_1); | ||||||
|  |     // Enable interrupts
 | ||||||
|  |     st25r3916_mask_irq(handle, ~interrupts); | ||||||
|  |     st25r3916_direct_cmd(handle, ST25R3916_CMD_GOTO_SENSE); | ||||||
|  | 
 | ||||||
|  |     return FuriHalNfcErrorNone; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static FuriHalNfcError furi_hal_nfc_felica_listener_deinit(FuriHalSpiBusHandle* handle) { | ||||||
|  |     UNUSED(handle); | ||||||
|  |     return FuriHalNfcErrorNone; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static FuriHalNfcEvent furi_hal_nfc_felica_listener_wait_event(uint32_t timeout_ms) { | ||||||
|  |     UNUSED(timeout_ms); | ||||||
|  |     FuriHalNfcEvent event = furi_hal_nfc_wait_event_common(timeout_ms); | ||||||
|  | 
 | ||||||
|  |     return event; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalNfcError furi_hal_nfc_felica_listener_tx( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     const uint8_t* tx_data, | ||||||
|  |     size_t tx_bits) { | ||||||
|  |     UNUSED(handle); | ||||||
|  |     UNUSED(tx_data); | ||||||
|  |     UNUSED(tx_bits); | ||||||
|  |     return FuriHalNfcErrorNone; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalNfcError furi_hal_nfc_felica_listener_sleep(FuriHalSpiBusHandle* handle) { | ||||||
|  |     UNUSED(handle); | ||||||
|  |     return FuriHalNfcErrorNone; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalNfcError furi_hal_nfc_felica_listener_idle(FuriHalSpiBusHandle* handle) { | ||||||
|  |     UNUSED(handle); | ||||||
|  |     return FuriHalNfcErrorNone; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalNfcError furi_hal_nfc_felica_listener_set_sensf_res_data( | ||||||
|  |     const uint8_t* idm, | ||||||
|  |     const uint8_t idm_len, | ||||||
|  |     const uint8_t* pmm, | ||||||
|  |     const uint8_t pmm_len) { | ||||||
|  |     FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; | ||||||
|  |     // Write PT Memory
 | ||||||
|  |     uint8_t pt_memory[19] = {}; | ||||||
|  |     pt_memory[2] = 0x01; | ||||||
|  |     memcpy(pt_memory + 3, idm, idm_len); | ||||||
|  |     memcpy(pt_memory + 3 + idm_len, pmm, pmm_len); | ||||||
|  |     st25r3916_write_ptf_mem(handle, pt_memory, sizeof(pt_memory)); | ||||||
|  |     return FuriHalNfcErrorNone; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const FuriHalNfcTechBase furi_hal_nfc_felica = { | const FuriHalNfcTechBase furi_hal_nfc_felica = { | ||||||
|     .poller = |     .poller = | ||||||
|         { |         { | ||||||
| @ -65,5 +188,18 @@ const FuriHalNfcTechBase furi_hal_nfc_felica = { | |||||||
|             .rx = furi_hal_nfc_common_fifo_rx, |             .rx = furi_hal_nfc_common_fifo_rx, | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|     .listener = {}, |     .listener = | ||||||
|  |         { | ||||||
|  |             .compensation = | ||||||
|  |                 { | ||||||
|  |                     .fdt = FURI_HAL_NFC_FELICA_LISTENER_FDT_COMP_FC, | ||||||
|  |                 }, | ||||||
|  |             .init = furi_hal_nfc_felica_listener_init, | ||||||
|  |             .deinit = furi_hal_nfc_felica_listener_deinit, | ||||||
|  |             .wait_event = furi_hal_nfc_felica_listener_wait_event, | ||||||
|  |             .tx = furi_hal_nfc_felica_listener_tx, | ||||||
|  |             .rx = furi_hal_nfc_common_fifo_rx, | ||||||
|  |             .sleep = furi_hal_nfc_felica_listener_sleep, | ||||||
|  |             .idle = furi_hal_nfc_felica_listener_idle, | ||||||
|  |         }, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -452,6 +452,23 @@ FuriHalNfcError furi_hal_nfc_iso14443a_listener_tx_custom_parity( | |||||||
| */ | */ | ||||||
| FuriHalNfcError furi_hal_nfc_iso15693_listener_tx_sof(); | FuriHalNfcError furi_hal_nfc_iso15693_listener_tx_sof(); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Set FeliCa collision resolution parameters in listener mode. | ||||||
|  |  *  | ||||||
|  |  * Configures the NFC hardware for automatic collision resolution. | ||||||
|  |  * | ||||||
|  |  * @param[in] idm pointer to a byte array containing the IDm. | ||||||
|  |  * @param[in] idm_len IDm length in bytes. | ||||||
|  |  * @param[in] pmm pointer to a byte array containing the PMm. | ||||||
|  |  * @param[in] pmm_len PMm length in bytes. | ||||||
|  |  * @returns NfcErrorNone on success, any other error code on failure. | ||||||
|  | */ | ||||||
|  | FuriHalNfcError furi_hal_nfc_felica_listener_set_sensf_res_data( | ||||||
|  |     const uint8_t* idm, | ||||||
|  |     const uint8_t idm_len, | ||||||
|  |     const uint8_t* pmm, | ||||||
|  |     const uint8_t pmm_len); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 RebornedBrain
						RebornedBrain