Flipper Zero Firmware
Loading...
Searching...
No Matches
furi_hal_nfc.h File Reference

NFC HAL library. More...

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

Go to the source code of this file.

Macros

#define FURI_HAL_NFC_CARRIER_HZ   (13560000UL)
 NFC carrier frequency, in Hz.
 
#define FURI_HAL_NFC_EVENT_WAIT_FOREVER   (0xFFFFFFFFU)
 Special value indicating that waiting for an event shall never time out.
 

Enumerations

enum  FuriHalNfcEvent {
  FuriHalNfcEventOscOn = (1U << 0) , FuriHalNfcEventFieldOn = (1U << 1) , FuriHalNfcEventFieldOff = (1U << 2) , FuriHalNfcEventListenerActive = (1U << 3) ,
  FuriHalNfcEventTxStart = (1U << 4) , FuriHalNfcEventTxEnd = (1U << 5) , FuriHalNfcEventRxStart = (1U << 6) , FuriHalNfcEventRxEnd = (1U << 7) ,
  FuriHalNfcEventCollision = (1U << 8) , FuriHalNfcEventTimerFwtExpired = (1U << 9) , FuriHalNfcEventTimerBlockTxExpired = (1U << 10) , FuriHalNfcEventTimeout ,
  FuriHalNfcEventAbortRequest
}
 Enumeration of possible NFC HAL events. More...
 
enum  FuriHalNfcError {
  FuriHalNfcErrorNone , FuriHalNfcErrorBusy , FuriHalNfcErrorCommunication , FuriHalNfcErrorOscillator ,
  FuriHalNfcErrorCommunicationTimeout , FuriHalNfcErrorBufferOverflow , FuriHalNfcErrorIncompleteFrame , FuriHalNfcErrorDataFormat
}
 Enumeration of possible NFC HAL errors. More...
 
enum  FuriHalNfcMode { FuriHalNfcModePoller , FuriHalNfcModeListener , FuriHalNfcModeNum }
 Enumeration of possible NFC HAL operating modes. More...
 
enum  FuriHalNfcTech {
  FuriHalNfcTechIso14443a , FuriHalNfcTechIso14443b , FuriHalNfcTechIso15693 , FuriHalNfcTechFelica ,
  FuriHalNfcTechNum , FuriHalNfcTechInvalid
}
 Enumeration of supported NFC technologies. More...
 
enum  FuriHalNfcaShortFrame { FuriHalNfcaShortFrameAllReq , FuriHalNfcaShortFrameSensReq }
 Enumeration of ISO14443 (Type A) short frame types.
 

Functions

FuriHalNfcError furi_hal_nfc_init (void)
 Initialise the NFC HAL and associated hardware.
 
FuriHalNfcError furi_hal_nfc_is_hal_ready (void)
 Check whether the NFC HAL was properly initialised and is ready.
 
FuriHalNfcError furi_hal_nfc_acquire (void)
 Exclusively take over the NFC HAL and associated hardware.
 
FuriHalNfcError furi_hal_nfc_release (void)
 Release the exclusive lock and make the NFC HAL available for others.
 
FuriHalNfcError furi_hal_nfc_low_power_mode_start (void)
 Configure the NFC hardware to enter the low-power mode.
 
FuriHalNfcError furi_hal_nfc_low_power_mode_stop (void)
 Configure the NFC hardware to exit the low-power mode.
 
FuriHalNfcError furi_hal_nfc_set_mode (FuriHalNfcMode mode, FuriHalNfcTech tech)
 Configure the NFC HAL to work in a particular mode.
 
FuriHalNfcError furi_hal_nfc_reset_mode (void)
 Reset the NFC HAL to its default (unconfigured) state.
 
FuriHalNfcError furi_hal_nfc_field_detect_start (void)
 Enable field (carrier) detection by the NFC hardware.
 
FuriHalNfcError furi_hal_nfc_field_detect_stop (void)
 Disable field (carrier) detection by the NFC hardware.
 
bool furi_hal_nfc_field_is_present (void)
 Check if the reader field (carrier) was detected by the NFC hardware.
 
FuriHalNfcError furi_hal_nfc_poller_field_on (void)
 Enable field (carrier) generation by the NFC hardware.
 
FuriHalNfcEvent furi_hal_nfc_poller_wait_event (uint32_t timeout_ms)
 Wait for an NFC HAL event in poller mode.
 
FuriHalNfcEvent furi_hal_nfc_listener_wait_event (uint32_t timeout_ms)
 Wait for an NFC HAL event in listener mode.
 
FuriHalNfcError furi_hal_nfc_poller_tx (const uint8_t *tx_data, size_t tx_bits)
 Transmit data in poller mode.
 
FuriHalNfcError furi_hal_nfc_poller_rx (uint8_t *rx_data, size_t rx_data_size, size_t *rx_bits)
 Receive data in poller mode.
 
FuriHalNfcError furi_hal_nfc_listener_tx (const uint8_t *tx_data, size_t tx_bits)
 Transmit data in listener mode.
 
FuriHalNfcError furi_hal_nfc_listener_rx (uint8_t *rx_data, size_t rx_data_size, size_t *rx_bits)
 Receive data in listener mode.
 
FuriHalNfcError furi_hal_nfc_listener_sleep (void)
 Go to sleep in listener mode.
 
FuriHalNfcError furi_hal_nfc_listener_idle (void)
 Go to idle in listener mode.
 
FuriHalNfcError furi_hal_nfc_listener_enable_rx (void)
 Enable reception in listener mode.
 
FuriHalNfcError furi_hal_nfc_trx_reset (void)
 Reset communication.
 
FuriHalNfcError furi_hal_nfc_event_start (void)
 Enable generation of NFC HAL events.
 
FuriHalNfcError furi_hal_nfc_event_stop (void)
 Disable generation of NFC HAL events.
 
FuriHalNfcError furi_hal_nfc_abort (void)
 Manually emit the FuriHalNfcEventAbortRequest event.
 
void furi_hal_nfc_timer_fwt_start (uint32_t time_fc)
 Start frame wait timeout timer.
 
void furi_hal_nfc_timer_fwt_stop (void)
 Stop frame wait timeout timer.
 
void furi_hal_nfc_timer_block_tx_start (uint32_t time_fc)
 Start block transmit (frame delay) timer.
 
void furi_hal_nfc_timer_block_tx_start_us (uint32_t time_us)
 Start block transmit (frame delay) timer.
 
void furi_hal_nfc_timer_block_tx_stop (void)
 Stop block transmit (frame delay) timer.
 
bool furi_hal_nfc_timer_block_tx_is_running (void)
 Check whether block transmit (frame delay) timer is running.
 
FuriHalNfcError furi_hal_nfc_iso14443a_poller_trx_short_frame (FuriHalNfcaShortFrame frame)
 Transmit ISO14443 (Type A) short frame in poller mode.
 
FuriHalNfcError furi_hal_nfc_iso14443a_tx_sdd_frame (const uint8_t *tx_data, size_t tx_bits)
 Transmit ISO14443 (Type A) SDD frame in poller mode.
 
FuriHalNfcError furi_hal_nfc_iso14443a_rx_sdd_frame (uint8_t *rx_data, size_t rx_data_size, size_t *rx_bits)
 Receive ISO14443 (Type A) SDD frame in poller mode.
 
FuriHalNfcError furi_hal_nfc_iso14443a_poller_tx_custom_parity (const uint8_t *tx_data, size_t tx_bits)
 Transmit ISO14443 (Type A) frame with custom parity bits in poller mode.
 
FuriHalNfcError furi_hal_nfc_iso14443a_listener_set_col_res_data (uint8_t *uid, uint8_t uid_len, uint8_t *atqa, uint8_t sak)
 Set ISO14443 (Type A) collision resolution parameters in listener mode.
 
FuriHalNfcError furi_hal_nfc_iso14443a_listener_tx_custom_parity (const uint8_t *tx_data, const uint8_t *tx_parity, size_t tx_bits)
 Transmit ISO14443 (Type A) frame with custom parity bits in listener mode.
 
FuriHalNfcError furi_hal_nfc_iso15693_listener_tx_sof (void)
 Send ISO15693 SOF in listener mode.
 
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, const uint16_t sys_code)
 Set FeliCa collision resolution parameters in listener mode.
 

Detailed Description

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 also
nfc.h
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.

Enumeration Type Documentation

◆ FuriHalNfcError

Enumeration of possible NFC HAL errors.

Enumerator
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.

◆ FuriHalNfcEvent

Enumeration of possible NFC HAL events.

Enumerator
FuriHalNfcEventOscOn 

Oscillator has been started.

FuriHalNfcEventFieldOn 

External field (carrier) has been detected.

FuriHalNfcEventFieldOff 

External field (carrier) has been lost.

FuriHalNfcEventListenerActive 

Reader has issued a wake-up command.

FuriHalNfcEventTxStart 

Transmission has started.

FuriHalNfcEventTxEnd 

Transmission has ended.

FuriHalNfcEventRxStart 

Reception has started.

FuriHalNfcEventRxEnd 

Reception has ended.

FuriHalNfcEventCollision 

A collision has occurred.

FuriHalNfcEventTimerFwtExpired 

Frame wait timer has expired.

FuriHalNfcEventTimerBlockTxExpired 

Transmission block timer has expired.

FuriHalNfcEventTimeout 

No events have occurred in a specified time period.

FuriHalNfcEventAbortRequest 

User has requested to abort current operation.

◆ FuriHalNfcMode

Enumeration of possible NFC HAL operating modes.

Enumerator
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.

◆ FuriHalNfcTech

Enumeration of supported NFC technologies.

Enumerator
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.

Function Documentation

◆ furi_hal_nfc_abort()

FuriHalNfcError furi_hal_nfc_abort ( void )

Manually emit the FuriHalNfcEventAbortRequest event.

Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_acquire()

FuriHalNfcError furi_hal_nfc_acquire ( void )

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.

◆ furi_hal_nfc_event_start()

FuriHalNfcError furi_hal_nfc_event_start ( void )

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.

◆ furi_hal_nfc_event_stop()

FuriHalNfcError furi_hal_nfc_event_stop ( void )

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.

◆ furi_hal_nfc_felica_listener_set_sensf_res_data()

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,
const uint16_t sys_code )

Set FeliCa collision resolution parameters in listener mode.

Configures the NFC hardware for automatic collision resolution.

Parameters
[in]idmpointer to a byte array containing the IDm.
[in]idm_lenIDm length in bytes.
[in]pmmpointer to a byte array containing the PMm.
[in]pmm_lenPMm length in bytes.
[in]sys_codeSystem code from SYS_C block
Returns
NfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_field_detect_start()

FuriHalNfcError furi_hal_nfc_field_detect_start ( void )

Enable field (carrier) detection by the NFC hardware.

Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_field_detect_stop()

FuriHalNfcError furi_hal_nfc_field_detect_stop ( void )

Disable field (carrier) detection by the NFC hardware.

Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_field_is_present()

bool furi_hal_nfc_field_is_present ( void )

Check if the reader field (carrier) was detected by the NFC hardware.

Returns
true if the field was detected, false otherwise.

◆ furi_hal_nfc_init()

FuriHalNfcError furi_hal_nfc_init ( void )

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.

◆ furi_hal_nfc_is_hal_ready()

FuriHalNfcError furi_hal_nfc_is_hal_ready ( void )

Check whether the NFC HAL was properly initialised and is ready.

Returns
FuriHalNfcErrorNone if ready, any other error code if not ready.

◆ furi_hal_nfc_iso14443a_listener_set_col_res_data()

FuriHalNfcError furi_hal_nfc_iso14443a_listener_set_col_res_data ( uint8_t * uid,
uint8_t uid_len,
uint8_t * atqa,
uint8_t sak )

Set ISO14443 (Type A) collision resolution parameters in listener mode.

Configures the NFC hardware for automatic collision resolution.

Parameters
[in]uidpointer to a byte array containing the UID.
[in]uid_lenUID length in bytes (must be supported by the protocol).
[in]atqaATQA byte value.
[in]sakSAK byte value.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_iso14443a_listener_tx_custom_parity()

FuriHalNfcError furi_hal_nfc_iso14443a_listener_tx_custom_parity ( const uint8_t * tx_data,
const uint8_t * tx_parity,
size_t tx_bits )

Transmit ISO14443 (Type A) frame with custom parity bits in listener mode.

Parameters
[in]tx_datapointer to a byte array containing the data to be transmitted.
[in]tx_paritypointer to a (bit-packed) byte array containing the parity to be transmitted.
[in]tx_bitstransmit data size, in bits.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_iso14443a_poller_trx_short_frame()

FuriHalNfcError furi_hal_nfc_iso14443a_poller_trx_short_frame ( FuriHalNfcaShortFrame frame)

Transmit ISO14443 (Type A) short frame in poller mode.

Parameters
[in]frameshort frame type to be transmitted.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_iso14443a_poller_tx_custom_parity()

FuriHalNfcError furi_hal_nfc_iso14443a_poller_tx_custom_parity ( const uint8_t * tx_data,
size_t tx_bits )

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.

Parameters
[in]tx_datapointer to a byte array containing the data to be transmitted.
[in]tx_bitstransmit data size, in bits.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_iso14443a_rx_sdd_frame()

FuriHalNfcError furi_hal_nfc_iso14443a_rx_sdd_frame ( uint8_t * rx_data,
size_t rx_data_size,
size_t * rx_bits )

Receive ISO14443 (Type A) SDD frame in poller mode.

The receive buffer must be big enough to accomodate all of the expected data.

Parameters
[in]rx_datapointer to a byte array to be filled with received data.
[in]rx_data_sizemaximum received data size, in bytes.
[in]rx_bitspointer to the variable to hold received data size, in bits.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_iso14443a_tx_sdd_frame()

FuriHalNfcError furi_hal_nfc_iso14443a_tx_sdd_frame ( const uint8_t * tx_data,
size_t tx_bits )

Transmit ISO14443 (Type A) SDD frame in poller mode.

Parameters
[in]tx_datapointer to a byte array containing the data to be transmitted.
[in]tx_bitstransmit data size, in bits.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_iso15693_listener_tx_sof()

FuriHalNfcError furi_hal_nfc_iso15693_listener_tx_sof ( void )

Send ISO15693 SOF in listener mode.

Returns
FuriHalNfcError

◆ furi_hal_nfc_listener_enable_rx()

FuriHalNfcError furi_hal_nfc_listener_enable_rx ( void )

Enable reception in listener mode.

Starts hardware receivers and receive decoders.

Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_listener_idle()

FuriHalNfcError furi_hal_nfc_listener_idle ( void )

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.

◆ furi_hal_nfc_listener_rx()

FuriHalNfcError furi_hal_nfc_listener_rx ( uint8_t * rx_data,
size_t rx_data_size,
size_t * rx_bits )

Receive data in listener mode.

The receive buffer must be big enough to accomodate all of the expected data.

Parameters
[out]rx_datapointer to a byte array to be filled with received data.
[in]rx_data_sizemaximum received data size, in bytes.
[out]rx_bitspointer to the variable to hold received data size, in bits.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_listener_sleep()

FuriHalNfcError furi_hal_nfc_listener_sleep ( void )

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.

◆ furi_hal_nfc_listener_tx()

FuriHalNfcError furi_hal_nfc_listener_tx ( const uint8_t * tx_data,
size_t tx_bits )

Transmit data in listener mode.

Parameters
[in]tx_datapointer to a byte array containing the data to be transmitted.
[in]tx_bitstransmit data size, in bits.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_listener_wait_event()

FuriHalNfcEvent furi_hal_nfc_listener_wait_event ( uint32_t timeout_ms)

Wait for an NFC HAL event in listener mode.

Parameters
[in]timeout_mstime to wait (timeout) in milliseconds.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_low_power_mode_start()

FuriHalNfcError furi_hal_nfc_low_power_mode_start ( void )

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.

◆ furi_hal_nfc_low_power_mode_stop()

FuriHalNfcError furi_hal_nfc_low_power_mode_stop ( void )

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.

◆ furi_hal_nfc_poller_field_on()

FuriHalNfcError furi_hal_nfc_poller_field_on ( void )

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.

◆ furi_hal_nfc_poller_rx()

FuriHalNfcError furi_hal_nfc_poller_rx ( uint8_t * rx_data,
size_t rx_data_size,
size_t * rx_bits )

Receive data in poller mode.

The receive buffer must be big enough to accomodate all of the expected data.

Parameters
[out]rx_datapointer to a byte array to be filled with received data.
[in]rx_data_sizemaximum received data size, in bytes.
[out]rx_bitspointer to the variable to hold received data size, in bits.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_poller_tx()

FuriHalNfcError furi_hal_nfc_poller_tx ( const uint8_t * tx_data,
size_t tx_bits )

Transmit data in poller mode.

Parameters
[in]tx_datapointer to a byte array containing the data to be transmitted.
[in]tx_bitstransmit data size, in bits.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_poller_wait_event()

FuriHalNfcEvent furi_hal_nfc_poller_wait_event ( uint32_t timeout_ms)

Wait for an NFC HAL event in poller mode.

Parameters
[in]timeout_mstime to wait (timeout) in milliseconds.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_release()

FuriHalNfcError furi_hal_nfc_release ( void )

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.

◆ furi_hal_nfc_reset_mode()

FuriHalNfcError furi_hal_nfc_reset_mode ( void )

Reset the NFC HAL to its default (unconfigured) state.

Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_set_mode()

FuriHalNfcError furi_hal_nfc_set_mode ( FuriHalNfcMode mode,
FuriHalNfcTech tech )

Configure the NFC HAL to work in a particular mode.

Not all technologies implement the listener operating mode.

Parameters
[in]moderequired operating mode.
[in]techrequired technology configuration.
Returns
FuriHalNfcErrorNone on success, any other error code on failure.

◆ furi_hal_nfc_timer_block_tx_is_running()

bool furi_hal_nfc_timer_block_tx_is_running ( void )

Check whether block transmit (frame delay) timer is running.

Returns
true if timer is running, false otherwise.

◆ furi_hal_nfc_timer_block_tx_start()

void furi_hal_nfc_timer_block_tx_start ( uint32_t time_fc)

Start block transmit (frame delay) timer.

Parameters
[in]time_fctime to wait, in carrier cycles.

◆ furi_hal_nfc_timer_block_tx_start_us()

void furi_hal_nfc_timer_block_tx_start_us ( uint32_t time_us)

Start block transmit (frame delay) timer.

Parameters
[in]time_ustime to wait, in microseconds.

◆ furi_hal_nfc_timer_fwt_start()

void furi_hal_nfc_timer_fwt_start ( uint32_t time_fc)

Start frame wait timeout timer.

Parameters
[in]time_fctime to wait, in carrier cycles.

◆ furi_hal_nfc_trx_reset()

FuriHalNfcError furi_hal_nfc_trx_reset ( void )

Reset communication.

Resets the communication state and stops all activities: transmission, reception, etc.

Returns
FuriHalNfcErrorNone on success, any other error code on failure.