 917410a0a8
			
		
	
	
		917410a0a8
		
			
		
	
	
	
	
		
			
			* fbt: reworking targets & assets handling WIP * fbt: dist fixes * fbt: moved SD card resources to owning apps * unit_tests: moved resources to app folder * github: updated unit_tests paths * github: packaging fixes * unit_tests: fixes * fbt: assets: internal cleanup * fbt: reworked assets handling * github: unit_tests: reintroducing fixes * minor cleanup * fbt: naming changes to reflect private nature of scons tools * fbt: resources: fixed dist archive paths * docs: updated paths * docs: updated more paths * docs: included "resources" parameter in app manifest docs; updated assets readme * updated gitignore for assets * github: updated action versions * unit_tests: restored timeout; scripts: assets: logging changes * gh: don't upload desktop animations for unit test run Co-authored-by: あく <alleteam@gmail.com>
		
			
				
	
	
		
			458 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			458 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**
 | |
|  * @file furi_hal_nfc.h
 | |
|  * @brief NFC HAL library.
 | |
|  *
 | |
|  * This library contains functions and definitions needed for NFC hardware low-level access.
 | |
|  *
 | |
|  * Application developers should first consider using the NFC protocol stack or
 | |
|  * the NFC transport layer and see if the APIs provided there sufficient
 | |
|  * for the applicaton's intended purpose.
 | |
|  *
 | |
|  * @see nfc.h
 | |
|  * @see nfc_protocol.h
 | |
|  *
 | |
|  * If any of the above mentioned options is used, calling any of the functions provided by this
 | |
|  * library is hardly necessary, as it will be taken care of under the hood.
 | |
|  *
 | |
|  */
 | |
| #pragma once
 | |
| 
 | |
| #include <stdint.h>
 | |
| #include <stddef.h>
 | |
| #include <stdbool.h>
 | |
| 
 | |
| #ifdef __cplusplus
 | |
| extern "C" {
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * @brief NFC carrier frequency, in Hz.
 | |
|  */
 | |
| #define FURI_HAL_NFC_CARRIER_HZ (13560000UL)
 | |
| 
 | |
| /**
 | |
|  * @brief Special value indicating that waiting for an event shall never time out.
 | |
|  */
 | |
| #define FURI_HAL_NFC_EVENT_WAIT_FOREVER (0xFFFFFFFFU)
 | |
| 
 | |
| /**
 | |
|  * @brief Enumeration of possible NFC HAL events.
 | |
|  */
 | |
| typedef enum {
 | |
|     FuriHalNfcEventOscOn = (1U << 0), /**< Oscillator has been started. */
 | |
|     FuriHalNfcEventFieldOn = (1U << 1), /**< External field (carrier) has been detected. */
 | |
|     FuriHalNfcEventFieldOff = (1U << 2), /**< External field (carrier) has been lost. */
 | |
|     FuriHalNfcEventListenerActive = (1U << 3), /**< Reader has issued a wake-up command. */
 | |
|     FuriHalNfcEventTxStart = (1U << 4), /**< Transmission has started. */
 | |
|     FuriHalNfcEventTxEnd = (1U << 5), /**< Transmission has ended. */
 | |
|     FuriHalNfcEventRxStart = (1U << 6), /**< Reception has started. */
 | |
|     FuriHalNfcEventRxEnd = (1U << 7), /**< Reception has ended. */
 | |
|     FuriHalNfcEventCollision = (1U << 8), /**< A collision has occurred. */
 | |
|     FuriHalNfcEventTimerFwtExpired = (1U << 9), /**< Frame wait timer has expired. */
 | |
|     FuriHalNfcEventTimerBlockTxExpired = (1U << 10), /**< Transmission block timer has expired. */
 | |
|     FuriHalNfcEventTimeout =
 | |
|         (1U << 11), /**< No events have occurred in a specified time period. */
 | |
|     FuriHalNfcEventAbortRequest =
 | |
|         (1U << 12), /**< User has requested to abort current operation. */
 | |
| } FuriHalNfcEvent;
 | |
| 
 | |
| /**
 | |
|  * @brief Enumeration of possible NFC HAL errors.
 | |
|  */
 | |
| typedef enum {
 | |
|     FuriHalNfcErrorNone, /**< No error has occurred. */
 | |
|     FuriHalNfcErrorBusy, /**< The communication bus is busy. */
 | |
|     FuriHalNfcErrorCommunication, /**< NFC hardware did not respond or responded unexpectedly. */
 | |
|     FuriHalNfcErrorOscillator, /**< Oscillator failed to start. */
 | |
|     FuriHalNfcErrorCommunicationTimeout, /**< NFC hardware did not respond in time. */
 | |
|     FuriHalNfcErrorBufferOverflow, /**< Receive buffer was too small for the received data. */
 | |
|     FuriHalNfcErrorIncompleteFrame, /**< Not enough data was received to parse a valid frame. */
 | |
|     FuriHalNfcErrorDataFormat, /**< Cannot parse a frame due to unexpected/invalid data. */
 | |
| } FuriHalNfcError;
 | |
| 
 | |
| /**
 | |
|  * @brief Enumeration of possible NFC HAL operating modes.
 | |
|  */
 | |
| typedef enum {
 | |
|     FuriHalNfcModePoller, /**< Configure NFC HAL to operate as a poller. */
 | |
|     FuriHalNfcModeListener, /**< Configure NFC HAL to operate as a listener. */
 | |
| 
 | |
|     FuriHalNfcModeNum, /**< Special value equal to the operating modes count. Internal use. */
 | |
| } FuriHalNfcMode;
 | |
| 
 | |
| /**
 | |
|  * @brief Enumeration of supported NFC technologies.
 | |
|  */
 | |
| typedef enum {
 | |
|     FuriHalNfcTechIso14443a, /**< Configure NFC HAL to use the ISO14443 (type A) technology. */
 | |
|     FuriHalNfcTechIso14443b, /**< Configure NFC HAL to use the ISO14443 (type B) technology. */
 | |
|     FuriHalNfcTechIso15693, /**< Configure NFC HAL to use the ISO15693 technology. */
 | |
|     FuriHalNfcTechFelica, /**< Configure NFC HAL to use the FeliCa technology. */
 | |
| 
 | |
|     FuriHalNfcTechNum, /**< Special value equal to the supported technologies count. Internal use. */
 | |
|     FuriHalNfcTechInvalid, /**< Special value indicating the unconfigured state. Internal use. */
 | |
| } FuriHalNfcTech;
 | |
| 
 | |
| /**
 | |
|  * @brief Initialise the NFC HAL and associated hardware.
 | |
|  *
 | |
|  * This function is called automatically during the firmware initialisation,
 | |
|  * so there is no need to call it explicitly.
 | |
|  * 
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_init();
 | |
| 
 | |
| /**
 | |
|  * @brief Check whether the NFC HAL was properly initialised and is ready.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone if ready, any other error code if not ready.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_is_hal_ready();
 | |
| 
 | |
| /**
 | |
|  * @brief Exclusively take over the NFC HAL and associated hardware.
 | |
|  *
 | |
|  * This function needs to be called whenever an interaction with the NFC HAL
 | |
|  * is to take place (usually once upon the application start).
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_acquire();
 | |
| 
 | |
| /**
 | |
|  * @brief Release the exclusive lock and make the NFC HAL available for others.
 | |
|  *
 | |
|  * This function needs to be called when the user code is done working
 | |
|  * with the NFC HAL (usually once upon application exit). It must be called
 | |
|  * from the same thread that has called furi_hal_nfc_acquire().
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_release();
 | |
| 
 | |
| /**
 | |
|  * @brief Configure the NFC hardware to enter the low-power mode.
 | |
|  *
 | |
|  * This function must be called each time when the user code is done working
 | |
|  * with the NFC HAL for the time being (e.g. waiting on user input).
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_low_power_mode_start();
 | |
| 
 | |
| /**
 | |
|  * @brief Configure the NFC hardware to exit the low-power mode.
 | |
|  *
 | |
|  * This function must be called each time when the user code begins working
 | |
|  * with the NFC HAL, as the default state is low-power mode.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_low_power_mode_stop();
 | |
| 
 | |
| /**
 | |
|  * @brief Configure the NFC HAL to work in a particular mode.
 | |
|  *
 | |
|  * Not all technologies implement the listener operating mode.
 | |
|  *
 | |
|  * @param[in] mode required operating mode.
 | |
|  * @param[in] tech required technology configuration.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_set_mode(FuriHalNfcMode mode, FuriHalNfcTech tech);
 | |
| 
 | |
| /**
 | |
|  * @brief Reset the NFC HAL to its default (unconfigured) state.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_reset_mode();
 | |
| 
 | |
| /**
 | |
|  * @brief Enable field (carrier) detection by the NFC hardware.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_field_detect_start();
 | |
| 
 | |
| /**
 | |
|  * @brief Disable field (carrier) detection by the NFC hardware.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_field_detect_stop();
 | |
| 
 | |
| /**
 | |
|  * @brief Check if the reader field (carrier) was detected by the NFC hardware.
 | |
|  *
 | |
|  * @returns true if the field was detected, false otherwise.
 | |
|  */
 | |
| bool furi_hal_nfc_field_is_present();
 | |
| 
 | |
| /**
 | |
|  * @brief Enable field (carrier) generation by the NFC hardware.
 | |
|  *
 | |
|  * No carrier modulation will occur unless a transmission is explicitly started.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_poller_field_on();
 | |
| 
 | |
| /**
 | |
|  * @brief Wait for an NFC HAL event in poller mode.
 | |
|  *
 | |
|  * @param[in] timeout_ms time to wait (timeout) in milliseconds.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcEvent furi_hal_nfc_poller_wait_event(uint32_t timeout_ms);
 | |
| 
 | |
| /**
 | |
|  * @brief Wait for an NFC HAL event in listener mode.
 | |
|  * @param[in] timeout_ms time to wait (timeout) in milliseconds.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcEvent furi_hal_nfc_listener_wait_event(uint32_t timeout_ms);
 | |
| 
 | |
| /**
 | |
|  * @brief Transmit data in poller mode.
 | |
|  *
 | |
|  * @param[in] tx_data pointer to a byte array containing the data to be transmitted.
 | |
|  * @param[in] tx_bits transmit data size, in bits.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_poller_tx(const uint8_t* tx_data, size_t tx_bits);
 | |
| 
 | |
| /**
 | |
|  * @brief Receive data in poller mode.
 | |
|  *
 | |
|  * The receive buffer must be big enough to accomodate all of the expected data.
 | |
|  *
 | |
|  * @param rx_data[out] pointer to a byte array to be filled with received data.
 | |
|  * @param rx_data_size[in] maximum received data size, in bytes.
 | |
|  * @param rx_bits[out] pointer to the variable to hold received data size, in bits.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_poller_rx(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits);
 | |
| 
 | |
| /**
 | |
|  * @brief Transmit data in listener mode.
 | |
|  *
 | |
|  * @param[in] tx_data pointer to a byte array containing the data to be transmitted.
 | |
|  * @param[in] tx_bits transmit data size, in bits.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_listener_tx(const uint8_t* tx_data, size_t tx_bits);
 | |
| 
 | |
| /**
 | |
|  * @brief Receive data in listener mode.
 | |
|  *
 | |
|  * The receive buffer must be big enough to accomodate all of the expected data.
 | |
|  *
 | |
|  * @param rx_data[out] pointer to a byte array to be filled with received data.
 | |
|  * @param rx_data_size[in] maximum received data size, in bytes.
 | |
|  * @param rx_bits[out] pointer to the variable to hold received data size, in bits.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_listener_rx(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits);
 | |
| 
 | |
| /**
 | |
|  * @brief Go to sleep in listener mode.
 | |
|  *
 | |
|  * Puts the passive target logic into Sleep (Halt) state.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_listener_sleep();
 | |
| 
 | |
| /**
 | |
|  * @brief Go to idle in listener mode.
 | |
|  *
 | |
|  * Puts the passive target logic into Sense (Idle) state.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_listener_idle();
 | |
| 
 | |
| /**
 | |
|  * @brief Enable reception in listener mode.
 | |
|  *
 | |
|  * Starts hardware receivers and receive decoders.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_listener_enable_rx();
 | |
| 
 | |
| /**
 | |
|  * @brief Reset communication.
 | |
|  *
 | |
|  * Resets the communication state and stops all activities: transmission, reception, etc.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_trx_reset();
 | |
| 
 | |
| /**
 | |
|  * @brief Enable generation of NFC HAL events.
 | |
|  *
 | |
|  * @warning This function must be called from the same thread from which
 | |
|  * the the furi_hal_nfc_*_wait_event() calls will be made.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_event_start();
 | |
| 
 | |
| /**
 | |
|  * @brief Disable generation of NFC HAL events.
 | |
|  *
 | |
|  * Unlike furi_hal_nfc_event_start(), this function may be called from any thread.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_event_stop();
 | |
| 
 | |
| /**
 | |
|  * @brief Manually emit the FuriHalNfcEventAbortRequest event.
 | |
|  *
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
| */
 | |
| FuriHalNfcError furi_hal_nfc_abort();
 | |
| 
 | |
| /**
 | |
|  * @brief Start frame wait timeout timer.
 | |
|  *
 | |
|  * @param[in] time_fc time to wait, in carrier cycles.
 | |
|  */
 | |
| void furi_hal_nfc_timer_fwt_start(uint32_t time_fc);
 | |
| 
 | |
| /**
 | |
|  * @brief Stop frame wait timeout timer.
 | |
|  */
 | |
| void furi_hal_nfc_timer_fwt_stop();
 | |
| 
 | |
| /**
 | |
|  * @brief Start block transmit (frame delay) timer.
 | |
|  *
 | |
|  * @param[in] time_fc time to wait, in carrier cycles.
 | |
| */
 | |
| void furi_hal_nfc_timer_block_tx_start(uint32_t time_fc);
 | |
| 
 | |
| /**
 | |
|  * @brief Start block transmit (frame delay) timer.
 | |
|  *
 | |
|  * @param[in] time_us time to wait, in microseconds.
 | |
|  */
 | |
| void furi_hal_nfc_timer_block_tx_start_us(uint32_t time_us);
 | |
| 
 | |
| /**
 | |
|  * @brief Stop block transmit (frame delay) timer.
 | |
|  */
 | |
| void furi_hal_nfc_timer_block_tx_stop();
 | |
| 
 | |
| /**
 | |
|  * @brief Check whether block transmit (frame delay) timer is running.
 | |
|  *
 | |
|  * @returns true if timer is running, false otherwise.
 | |
|  */
 | |
| bool furi_hal_nfc_timer_block_tx_is_running();
 | |
| 
 | |
| /*
 | |
|  * Technology-specific functions.
 | |
|  *
 | |
|  * In a perfect world, this would not be necessary.
 | |
|  * However, the current implementation employs NFC hardware that partially implements
 | |
|  * certain protocols (e.g. ISO14443-3A), thus requiring methods to access such features.
 | |
|  */
 | |
| 
 | |
| /******************* Iso14443a specific API *******************/
 | |
| 
 | |
| /**
 | |
|  * @brief Enumeration of ISO14443 (Type A) short frame types.
 | |
|  */
 | |
| typedef enum {
 | |
|     FuriHalNfcaShortFrameAllReq,
 | |
|     FuriHalNfcaShortFrameSensReq,
 | |
| } FuriHalNfcaShortFrame;
 | |
| 
 | |
| /**
 | |
|  * @brief Transmit ISO14443 (Type A) short frame in poller mode.
 | |
|  *
 | |
|  * @param[in] frame short frame type to be transmitted.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_iso14443a_poller_trx_short_frame(FuriHalNfcaShortFrame frame);
 | |
| 
 | |
| /** Transmit ISO14443 (Type A) SDD frame in poller mode.
 | |
|  *
 | |
|  * @param[in] tx_data pointer to a byte array containing the data to be transmitted.
 | |
|  * @param[in] tx_bits transmit data size, in bits.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_iso14443a_tx_sdd_frame(const uint8_t* tx_data, size_t tx_bits);
 | |
| 
 | |
| /**
 | |
|  * Receive ISO14443 (Type A) SDD frame in poller mode.
 | |
|  *
 | |
|  * The receive buffer must be big enough to accomodate all of the expected data.
 | |
|  *
 | |
|  * @param rx_data[out] pointer to a byte array to be filled with received data.
 | |
|  * @param rx_data_size[in] maximum received data size, in bytes.
 | |
|  * @param rx_bits[out] pointer to the variable to hold received data size, in bits.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError
 | |
|     furi_hal_nfc_iso14443a_rx_sdd_frame(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits);
 | |
| 
 | |
| /**
 | |
|  * @brief Transmit ISO14443 (Type A) frame with custom parity bits in poller mode.
 | |
|  *
 | |
|  * Same as furi_hal_nfc_poller_tx(), but uses the parity bits provided
 | |
|  * by the user code instead of calculating them automatically.
 | |
|  *
 | |
|  * @param[in] tx_data pointer to a byte array containing the data to be transmitted.
 | |
|  * @param[in] tx_bits transmit data size, in bits.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError
 | |
|     furi_hal_nfc_iso14443a_poller_tx_custom_parity(const uint8_t* tx_data, size_t tx_bits);
 | |
| 
 | |
| /**
 | |
|  * @brief Set ISO14443 (Type A) collision resolution parameters in listener mode.
 | |
|  *
 | |
|  * Configures the NFC hardware for automatic collision resolution.
 | |
|  *
 | |
|  * @param[in] uid pointer to a byte array containing the UID.
 | |
|  * @param[in] uid_len UID length in bytes (must be supported by the protocol).
 | |
|  * @param[in] atqa ATQA byte value.
 | |
|  * @param[in] sak SAK byte value.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_iso14443a_listener_set_col_res_data(
 | |
|     uint8_t* uid,
 | |
|     uint8_t uid_len,
 | |
|     uint8_t* atqa,
 | |
|     uint8_t sak);
 | |
| 
 | |
| /**
 | |
|  * @brief Transmit ISO14443 (Type A) frame with custom parity bits in listener mode.
 | |
|  *
 | |
|  * @param[in] tx_data pointer to a byte array containing the data to be transmitted.
 | |
|  * @param[in] tx_parity pointer to a (bit-packed) byte array containing the parity to be transmitted.
 | |
|  * @param[in] tx_bits transmit data size, in bits.
 | |
|  * @returns FuriHalNfcErrorNone on success, any other error code on failure.
 | |
|  */
 | |
| FuriHalNfcError furi_hal_nfc_iso14443a_listener_tx_custom_parity(
 | |
|     const uint8_t* tx_data,
 | |
|     const uint8_t* tx_parity,
 | |
|     size_t tx_bits);
 | |
| 
 | |
| /** Send ISO15693 SOF in listener mode
 | |
|  *
 | |
|  * @return FuriHalNfcError
 | |
| */
 | |
| FuriHalNfcError furi_hal_nfc_iso15693_listener_tx_sof();
 | |
| 
 | |
| #ifdef __cplusplus
 | |
| }
 | |
| #endif
 |