1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/drivers/include/mfrc522.h
2023-01-31 21:05:07 +01:00

879 lines
34 KiB
C

/*
* Copyright (C) 2021 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_mfrc522 MFRC522 RFID controller
* @ingroup drivers_actuators
* @brief Device driver for the NXP MFRC522 RFID controller
*
* With this driver MIFARE and NTAG tags/keys can be read and written contactless.
*
* Supported features:
* - Communication (Crypto1) with MIFARE Classic (1k, 4k, Mini)
* - Communication (Crypto1) with MIFARE Classic compatible PICCs
* - Firmware self check of MFRC522
* - Set the UID, write to sector 0, and unbrick Chinese UID changeable MIFARE cards
*
* Partially supported features:
* - Communication with MIFARE Ultralight
* - Other PICCs (Ntag216)
*
* Data sheet available here: https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf
*
* This driver is a port of a driver originally written for Arduino, you can find
* the original here: https://github.com/miguelbalboa/rfid (currently based on
* commit 0a568b45baf1852883630e90ea125786e88f5322)
*
* @{
*
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
* @file
*/
#ifndef MFRC522_H
#define MFRC522_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "stdbool.h"
#include "periph/spi.h"
#include "mfrc522_regs.h"
/**
* @brief Maximum size for uid byte array
*/
#define MFRC522_UID_MAX_SIZE 10
/**
* @brief The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK
*/
#define MFRC522_MF_ACK 0xA
/**
* @brief A Mifare Crypto1 key is 6 bytes
*/
#define MFRC522_MF_KEY_SIZE 6
/**
* @brief MFRC522 device initialization parameters
*/
typedef struct {
spi_t spi_dev; /**< SPI bus the controller is connected to */
spi_clk_t spi_clk; /**< SPI clock speed */
gpio_t sck_pin; /**< SCK pin */
gpio_t miso_pin; /**< MISO pin */
gpio_t mosi_pin; /**< MOSI pin */
gpio_t cs_pin; /**< Slave select pin */
gpio_t rst_pin; /**< Reset pin */
} mfrc522_params_t;
/**
* @brief MFRC522 device data structure type
*/
typedef struct {
mfrc522_params_t params; /**< Device initialization parameters */
} mfrc522_t;
/**
* @brief A struct used for passing the UID of a PICC
*/
typedef struct {
uint8_t size; /**< Number of bytes in the UID. 4, 7 or 10 */
uint8_t uid_byte[MFRC522_UID_MAX_SIZE]; /**< UID */
uint8_t sak; /**< The SAK (Select acknowledge) byte returned from
the PICC after successful selection */
} mfrc522_uid_t;
/**
* @brief A struct used for passing a MIFARE Crypto1 key
*/
typedef struct {
uint8_t key_byte[MFRC522_MF_KEY_SIZE]; /**< Crypto1 key bytes */
} mfrc522_mifare_key_t;
/**
* @brief PICC types
*/
typedef enum {
MFRC522_PICC_TYPE_ISO_14443_4, /**< PICC compliant with ISO/IEC 14443-4 */
MFRC522_PICC_TYPE_ISO_18092, /**< PICC compliant with ISO/IEC 18092 (NFC) */
MFRC522_PICC_TYPE_MIFARE_MINI, /**< MIFARE Classic protocol, 320 bytes */
MFRC522_PICC_TYPE_MIFARE_1K, /**< MIFARE Classic protocol, 1KB */
MFRC522_PICC_TYPE_MIFARE_4K, /**< MIFARE Classic protocol, 4KB */
MFRC522_PICC_TYPE_MIFARE_UL, /**< MIFARE Ultralight or Ultralight C */
MFRC522_PICC_TYPE_MIFARE_PLUS, /**< MIFARE Plus */
MFRC522_PICC_TYPE_MIFARE_DESFIRE, /**< MIFARE DESFire */
MFRC522_PICC_TYPE_TNP3XXX, /**< Only mentioned in NXP AN 10833 MIFARE
Type Identification Procedure */
MFRC522_PICC_TYPE_NOT_COMPLETE, /**< SAK indicates UID is not complete */
MFRC522_PICC_TYPE_UNKNOWN /**< unknown type */
} mfrc522_picc_type_t;
/**
* @brief Sets the bits given in mask in register reg
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] reg Register to write to
* @param[in] mask Bitmask with the bits to set
*/
void mfrc522_pcd_set_register_bitmask(mfrc522_t *dev, mfrc522_pcd_register_t reg, uint8_t mask);
/**
* @brief Clears the bits given in mask from register reg
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] reg Register to write to
* @param[in] mask Bitmask with the bits to clear
*/
void mfrc522_pcd_clear_register_bitmask(mfrc522_t *dev, mfrc522_pcd_register_t reg, uint8_t mask);
/**
* @brief Use the CRC coprocessor in the MFRC522 to calculate a CRC_A
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] data Data to transfer to the FIFO for CRC calculation
* @param[in] length Number of bytes to transfer
* @param[out] result Result buffer. Result is written to result[0..1], low
* byte first.
*
* @retval 0 on success
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_pcd_calculate_crc(mfrc522_t *dev, const uint8_t *data, uint8_t length, uint8_t *result);
/**
* @brief Initialization
*
* @param[out] dev Device descriptor of the MFRC522
* @param[in] params Parameters for device initialization
*
* @retval 0 Success
* @retval -EINVAL Invalid CS pin/line
* @retval -ENXIO Invalid device
*/
int mfrc522_pcd_init(mfrc522_t *dev, const mfrc522_params_t *params);
/**
* @brief Performs a soft reset on the MFRC522 chip and waits for it to be ready
* again
*
* @param[in] dev Device descriptor of the MFRC522
*/
void mfrc522_pcd_reset(mfrc522_t *dev);
/**
* @brief Turns the antenna on by enabling pins TX1 and TX2.
* After a reset these pins are disabled.
*
* @param[in] dev Device descriptor of the MFRC522
*/
void mfrc522_pcd_antenna_on(mfrc522_t *dev);
/**
* @brief Turns the antenna off by disabling pins TX1 and TX2
*
* @param[in] dev Device descriptor of the MFRC522
*/
void mfrc522_pcd_antenna_off(mfrc522_t *dev);
/**
* @brief Get the current MFRC522 receiver gain
*
* @param[in] dev Device descriptor of the MFRC522
*
* @return Receiver gain
*/
mfrc522_pcd_rx_gain_t mfrc522_pcd_get_antenna_gain(mfrc522_t *dev);
/**
* @brief Set the MFRC522 receiver gain
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] rx_gain Antenna gain
*/
void mfrc522_pcd_set_antenna_gain(mfrc522_t *dev, mfrc522_pcd_rx_gain_t rx_gain);
/**
* @brief Set the MFRC522 to soft power-down mode
*
* @note Only soft power down mode is available through software.
*
* @note Calling any other function that uses MFRC522_REG_COMMAND will disable
* soft power down mode! For more details about power control, refer to
* the datasheet - page 33 (8.6)
*
* @param[in] dev Device descriptor of the MFRC522
*/
void mfrc522_pcd_soft_power_down(mfrc522_t *dev);
/**
* @brief Set the MFRC522 to leave soft power-down mode
*
* @param[in] dev Device descriptor of the MFRC522
*/
void mfrc522_pcd_soft_power_up(mfrc522_t *dev);
/**
* @brief Executes MFRC522_CMD_TRANSCEIVE.
*
* @note CRC validation can only be done if back_data and back_len are specified
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] send_data Data to transfer to the FIFO
* @param[in] send_len Number of bytes to transfer to the FIFO
* @param[out] back_data Buffer if data should be read back after executing
* the command, otherwise NULL
* @param[inout] back_len Max number of bytes to write to *back_data.
* Returns number of bytes returned.
* @param[inout] valid_bits Number of valid bits in the last byte. 0 for 8
* valid bits
* @param[in] rx_align Defines the bit position in back_data[0] for the
* first bit received
* @param[in] check_crc If true, the last two bytes of the response are
* assumed to be a CRC_A that must be validated
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_pcd_transceive_data(mfrc522_t *dev,
const uint8_t *send_data, uint8_t send_len,
uint8_t *back_data, uint8_t *back_len,
uint8_t *valid_bits, uint8_t rx_align, bool check_crc);
/**
* @brief Transfers data to MFRC522's FIFO, executes a command, waits for
* completion and transfers data back from the FIFO
*
* @note CRC validation can only be done if back_data and back_len are specified
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] command The command to execute
* @param[in] wait_irq The bits in the ComIrqReg register that signals
* successful completion of the command
* @param[in] send_data Data to transfer to the FIFO
* @param[in] send_len Number of bytes to transfer to the FIFO
* @param[out] back_data Buffer if data should be read back after executing
* the command, otherwise NULL
* @param[inout] back_len Max number of bytes to write to *back_data.
* Returns number of bytes returned.
* @param[inout] valid_bits Number of valid bits in the last byte. 0 for 8
* valid bits.
* @param[in] rx_align Defines the bit position in back_data[0] for the
* first bit received
* @param[in] check_crc True => The last two bytes of the response is
* assumed to be a CRC_A that must be validated
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_pcd_communicate_with_picc(mfrc522_t *dev, mfrc522_pcd_command_t command,
uint8_t wait_irq,
const uint8_t *send_data, uint8_t send_len,
uint8_t *back_data, uint8_t *back_len,
uint8_t *valid_bits, uint8_t rx_align, bool check_crc);
/**
* @brief Transmits REQA, Type A. Invites PICCs in state IDLE to go to READY and
* prepare for anti-collision or selection. 7 bit frame.
*
* @note When two PICCs are in the field at the same time we often get
* -ETIMEDOUT - probably due do bad antenna design.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[out] buffer_atqa Buffer to store the ATQA in
* @param[inout] buffer_size Buffer size, at least two bytes. Also number of
* bytes returned on success.
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_picc_request_a(mfrc522_t *dev, uint8_t *buffer_atqa, uint8_t *buffer_size);
/**
* @brief Transmits WUPA, Type A. Invites PICCs in state IDLE and HALT to go to
* READY(*) and prepare for anti-collision or selection. 7 bit frame.
*
* @note When two PICCs are in the field at the same time we often get
* -ETIMEDOUT - probably due do bad antenna design.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[out] buffer_atqa Buffer to store the ATQA in
* @param[inout] buffer_size Buffer size, at least two bytes. Also number of
* bytes returned on success.
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_picc_wakeup_a(mfrc522_t *dev, uint8_t *buffer_atqa, uint8_t *buffer_size);
/**
* @brief Transmits REQA (Type A) or WUPA (Type A) commands
*
* @note When two PICCs are in the field at the same time we often get
* -ETIMEDOUT - probably due do bad antenna design.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] command Command to send - MFRC522_PICC_CMD_ISO_14443_REQA
* or MFRC522_PICC_CMD_ISO_14443_WUPA
* @param[out] buffer_atqa Buffer to store the ATQA in
* @param[inout] buffer_size Buffer size, at least two bytes. Also number of
* bytes returned on success.
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL if command was neither MFRC522_PICC_CMD_ISO_14443_REQA nor
* MFRC522_PICC_CMD_ISO_14443_WUPA
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_picc_reqa_or_wupa(mfrc522_t *dev, mfrc522_picc_command_t command,
uint8_t *buffer_atqa, uint8_t *buffer_size);
/**
* @brief Transmits SELECT/ANTICOLLISION commands to select a single PICC
*
* @note Before calling this function the PICCs must be placed in the READY(*)
* state by calling mfrc522_picc_request_a() or mfrc522_picc_wakeup_a().
* On success:
* - The chosen PICC is in state ACTIVE(*) and all other PICCs have
* returned to state IDLE/HALT. (Figure 7 of the ISO/IEC 14443-3 draft.)
* - The UID size and value of the chosen PICC is returned in *uid along
* with the SAK.
*
* A PICC UID consists of 4, 7 or 10 bytes.
* Only 4 bytes can be specified in a SELECT command, so for the longer UIDs two
* or three iterations are used:
*
* UID size Number of UID bytes Cascade levels Example of PICC
* ======== =================== ============== ===============
* single 4 1 MIFARE Classic
* double 7 2 MIFARE Ultralight
* triple 10 3 Not currently in use?
*
* @param[in] dev Device descriptor of the MFRC522
* @param[inout] uid Normally output, but can also be used to supply a
* known UID
* @param[in] valid_bits Number of known UID bits supplied in *uid.
* Normally 0. If set you must also supply uid->size.
*
* @retval 0 on success
* @retval -ECANCELED on internal error
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_picc_select(mfrc522_t *dev, mfrc522_uid_t *uid, uint8_t valid_bits);
/**
* @brief Instructs a PICC in state ACTIVE(*) to go to state HALT
*
* @param[in] dev Device descriptor of the MFRC522
*
* @retval 0 on success
* @retval -EIO on communication error
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_picc_halt_a(mfrc522_t *dev);
/**
* @brief Executes the MFRC522 MFAuthent command
*
* This command manages MIFARE authentication to enable a secure communication
* to any MIFARE Mini, MIFARE 1K and MIFARE 4K card. The authentication is
* described in the MFRC522 datasheet section 10.3.1.9 and
* http://www.nxp.com/documents/data_sheet/MF1S503x.pdf section 10.1. For use
* with MIFARE Classic PICCs. The PICC must be selected - i.e. in state
* ACTIVE(*) - before calling this function. Remember to call
* mfrc522_pcd_stop_crypto1() after communicating with the authenticated PICC -
* otherwise no new communications can start.
*
* All keys are set to FFFFFFFFFFFFh at chip delivery.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] command MFRC522_PICC_CMD_MF_AUTH_KEY_A or PICC_CMD_MF_AUTH_KEY_B
* @param[in] block_addr Block number. See numbering in the comments in the .h file.
* @param[in] key Crypteo1 key to use (6 bytes)
* @param[in] uid PICC's UID
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_pcd_authenticate(mfrc522_t *dev, mfrc522_picc_command_t command,
uint8_t block_addr, const mfrc522_mifare_key_t *key,
const mfrc522_uid_t *uid);
/**
* @brief Used to exit the PCD from its authenticated state
*
* @note Remember to call this function after communicating with an
* authenticated PICC - otherwise no new communications can start.
*
* @param[in] dev Device descriptor of the MFRC522
*/
void mfrc522_pcd_stop_crypto1(mfrc522_t *dev);
/**
* @brief Read 16 bytes (+ 2 bytes CRC_A) from the active PICC
*
* @note For MIFARE Classic the sector containing the block must be
* authenticated before calling this function.
*
* For MIFARE Ultralight only addresses 00h to 0Fh are decoded. The MF0ICU1
* returns a NAK for higher addresses. The MF0ICU1 responds to the READ command
* by sending 16 bytes starting from the page address defined by the command
* argument. For example; if block_addr is 03h then pages 03h, 04h, 05h, 06h are
* returned. A roll-back is implemented: If block_addr is 0Eh, then the contents
* of pages 0Eh, 0Fh, 00h and 01h are returned.
*
* The buffer must be at least 18 bytes because a CRC_A is also returned.
* Checks the CRC_A before returning.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] block_addr MIFARE Classic: The block (0-0xff) number.
* MIFARE Ultralight: The first page to return data from.
* @param[out] buffer Buffer to store the data in
* @param[inout] buffer_size Buffer size, at least 18 bytes. Also number of
* bytes returned on success.
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_read(mfrc522_t *dev, uint8_t block_addr, uint8_t *buffer, uint8_t *buffer_size);
/**
* @brief Write 16 bytes to the active PICC
*
* @note For MIFARE Classic the sector containing the block must be
* authenticated before calling this function.
*
* For MIFARE Ultralight the operation is called "COMPATIBILITY WRITE". Even
* though 16 bytes are transferred to the Ultralight PICC, only the least
* significant 4 bytes (bytes 0 to 3) are written to the specified address. It
* is recommended to set the remaining bytes 04h to 0Fh to all logic 0.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] block_addr MIFARE Classic: The block (0-0xff) number.
* MIFARE Ultralight: The page (2-15) to write to.
* @param[in] buffer The 16 bytes to write to the PICC
* @param[in] buffer_size Buffer size, must be at least 16 bytes. Exactly 16
* bytes are written.
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_write(mfrc522_t *dev, uint8_t block_addr,
const uint8_t *buffer, uint8_t buffer_size);
/**
* @brief Write a 4 byte page to the active MIFARE Ultralight PICC
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] page The page (2-15) to write to
* @param[in] buffer The 4 bytes to write to the PICC
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_ultralight_write(mfrc522_t *dev, uint8_t page, const uint8_t *buffer);
/**
* @brief Subtract the operand from the value of the addressed block, and store
* the result in the Transfer Buffer
*
* MIFARE Decrement subtracts the delta from the value of the addressed block,
* and stores the result in a volatile memory. For MIFARE Classic only. The
* sector containing the block must be authenticated before calling this
* function. Only for blocks in "value block" mode, ie with access bits
* [C1 C2 C3] = [110] or [001]. Use MIFARE_Transfer() to store the result in a
* block.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] block_addr Block (0-0xff) number
* @param[in] delta Number to be subtracted from the value of block block_addr
*
* @retval 0 on success
* @retval -ECANCELED on internal error
*/
int mfrc522_mifare_decrement(mfrc522_t *dev, uint8_t block_addr, int32_t delta);
/**
* @brief Add the operand to the value of the addressed block, and store the
* result in the Transfer Buffer
*
* MIFARE Increment adds the delta to the value of the addressed block, and
* stores the result in a volatile memory. For MIFARE Classic only. The sector
* containing the block must be authenticated before calling this function. Only
* for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
* Use MIFARE_Transfer() to store the result in a block.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] block_addr Block (0-0xff) number
* @param[in] delta Number to be added to the value of block block_addr
*
* @retval 0 on success
* @retval -ECANCELED on internal error
*/
int mfrc522_mifare_increment(mfrc522_t *dev, uint8_t block_addr, int32_t delta);
/**
* @brief Copies the value of the addressed block into the Transfer Buffer
*
* MIFARE Restore copies the value of the addressed block into a volatile memory.
* For MIFARE Classic only. The sector containing the block must be
* authenticated before calling this function. Only for blocks in "value block"
* mode, i.e. with access bits [C1 C2 C3] = [110] or [001]. Use
* mfrc522_mifare_transfer() to store the result in a block.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] block_addr Block (0-0xff) number
*
* @retval 0 on success
* @retval -ECANCELED on internal error
*/
int mfrc522_mifare_restore(mfrc522_t *dev, uint8_t block_addr);
/**
* @brief Write the value from the Transfer Buffer into destination block
*
* MIFARE Transfer writes the value stored in the volatile memory into one
* MIFARE Classic block. For MIFARE Classic only. The sector containing the
* block must be authenticated before calling this function. Only for blocks in
* "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] block_addr Block (0-0xff) number
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_transfer(mfrc522_t *dev, uint8_t block_addr);
/**
* @brief Helper routine to read the current value from a Value Block
*
* @note Only for MIFARE Classic and only for blocks in "value block" mode,
* that is with access bits [C1 C2 C3] = [110] or [001]. The sector
* containing the block must be authenticated before calling this function.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] block_addr Block (0x00-0xff) number
* @param[out] value Current value of the Value Block
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_get_value(mfrc522_t *dev, uint8_t block_addr, int32_t *value);
/**
* @brief Helper routine to write a specific value into a Value Block
*
* @note Only for MIFARE Classic and only for blocks in "value block" mode,
* that is with access bits [C1 C2 C3] = [110] or [001]. The sector
* containing the block must be authenticated before calling this function.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] block_addr Block (0x00-0xff) number
* @param[in] value New value of the Value Block
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_set_value(mfrc522_t *dev, uint8_t block_addr, int32_t value);
/**
* @brief Authenticate with a NTAG216
*
* @note Only for NTAG216
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] password Password (must have a size of exactly 4 bytes)
* @param[out] p_ack result (must have a size of exactly 2 bytes)
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_pcd_ntag216_auth(mfrc522_t *dev, const uint8_t *password, uint8_t p_ack[]);
/**
* @brief Wrapper for MIFARE protocol communication
*
* Adds CRC_A, executes the Transceive command and checks that the response is
* MFRC522_MF_ACK or a timeout.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] send_data Data to transfer to the FIFO. Do NOT include the CRC_A.
* @param[in] send_len Number of bytes in send_data
* @param[in] accept_timeout If true, then a timeout is also a success
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_pcd_mifare_transceive(mfrc522_t *dev,
const uint8_t *send_data, uint8_t send_len,
bool accept_timeout);
/**
* @brief Translates the SAK (Select Acknowledge) to a PICC type
*
* @param[in] sak The SAK byte returned from mfrc522_picc_select()
*
* @return PICC type
*/
mfrc522_picc_type_t mfrc522_picc_get_type(uint8_t sak);
/**
* @brief Returns the name for the PICC type.
*
* @param[in] picc_type PICC type enum
*
* @return PICC type name
*/
const char *mfrc522_picc_get_type_string(mfrc522_picc_type_t picc_type);
/**
* @brief Calculates the bit pattern needed for the specified access bits. In
* the [C1 C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1).
*
* @param[out] access_bit_buffer Pointer to byte 6, 7 and 8 in the sector
* trailer. Bytes [0..2] will be set.
* @param[in] g0 Access bits [C1 C2 C3] for block 0 (for
* sectors 0-31) or blocks 0-4 (for sectors 32-39)
* @param[in] g1 Access bits [C1 C2 C3] for block 1 (for
* sectors 0-31) or blocks 5-9 (for sectors 32-39)
* @param[in] g2 Access bits [C1 C2 C3] for block 2 (for
* sectors 0-31) or blocks 10-14 (for sectors 32-39)
* @param[in] g3 Access bits [C1 C2 C3] for the sector trailer,
* block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
*/
void mfrc522_mifare_set_access_bits(uint8_t *access_bit_buffer,
uint8_t g0, uint8_t g1, uint8_t g2, uint8_t g3);
/**
* @brief Performs the "magic sequence" needed to get Chinese UID changeable
* Mifare cards to allow writing to sector 0, where the card UID is stored.
*
* @note Note that you do not need to have selected the card through REQA or WUPA,
* this sequence works immediately when the card is in the reader vicinity.
* This means you can use this method even on "bricked" cards that your
* reader does not recognise anymore (see mfrc522_mifare_unbrick_uid_sector).
* Of course with non-bricked devices, you are free to select them before
* calling this function.
*
* @param[in] dev Device descriptor of the MFRC522
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_open_uid_backdoor(mfrc522_t *dev);
/**
* @brief Read entire block 0, including all manufacturer data, and overwrites
* that block with the new UID, a freshly calculated BCC, and the original
* manufacturer data.
*
* @note It assumes a default KEY A of 0xFFFFFFFFFFFF. Make
* sure to have selected the PICC before this function is called and that
* the UID of the PICC is changeable.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] uid PICC's UID
* @param[in] new_uid New UID to set on PICC
* @param[in] new_uid_size Size of new UID
*
* @retval 0 on success
* @retval -ECANCELED on internal error
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_set_uid(mfrc522_t *dev, mfrc522_uid_t *uid,
const uint8_t *new_uid, uint8_t new_uid_size);
/**
* @brief Reset entire sector 0 to zeroes, so the card can be read again by readers
*
* @param[in] dev Device descriptor of the MFRC522
*
* @retval 0 on success
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_mifare_unbrick_uid_sector(mfrc522_t *dev);
/**
* @brief Checks whether a new card could be detected
*
* @note Only "new" cards in state IDLE are invited. Sleeping cards in state
* HALT are ignored.
*
* @param[in] dev Device descriptor of the MFRC522
*
* @return true if new card was detected, false otherwise
*/
bool mfrc522_picc_is_new_card_present(mfrc522_t *dev);
/**
* @brief Simple wrapper around mfrc522_picc_select()
*
* @note Remember to call mfrc522_picc_is_new_card_present(),
* mfrc522_picc_request_a() or mfrc522_picc_wakeup_a() first.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] uid PICC's UID
*
* @retval 0 on success
* @retval -ECANCELED on internal error
* @retval -ECONNABORTED when a collision occurred
* @retval -EINVAL on invalid argument
* @retval -EIO on communication error
* @retval -ENOBUFS when a buffer is too small to receive data
* @retval -ETIMEDOUT on timeout
*/
int mfrc522_picc_read_card_serial(mfrc522_t *dev, mfrc522_uid_t *uid);
/**
* @brief Dump debug info about the connected PCD to stdout
*
* @param[in] dev Device descriptor of the MFRC522
*/
void mfrc522_pcd_dump_version_to_serial(mfrc522_t *dev);
/**
* @brief Dump debug info about the selected PICC to stdout
*
* @note On success the PICC is halted after dumping the data.
* For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] uid PICC's UID
*/
void mfrc522_picc_dump_to_serial(mfrc522_t *dev, mfrc522_uid_t *uid);
/**
* @brief Dump card info (UID, SAK, Type) about the selected PICC to stdout
*
* @param[in] uid PICC's UID
*/
void mfrc522_picc_dump_details_to_serial(mfrc522_uid_t *uid);
/**
* @brief Dump memory contents of a MIFARE Classic PICC to stdout
*
* @note On success the PICC is halted after dumping the data.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] uid PICC's UID
* @param[in] picc_type PICC type enum
* @param[in] key Key A used for all sectors.
*/
void mfrc522_picc_dump_mifare_classic_to_serial(mfrc522_t *dev, mfrc522_uid_t *uid,
mfrc522_picc_type_t picc_type,
mfrc522_mifare_key_t *key);
/**
* @brief Dump memory contents of a sector of a MIFARE Classic PICC to stdout
*
* Uses mfrc522_pcd_authenticate(), mfrc522_mifare_read() and
* mfrc522_pcd_stop_crypto1(). Always uses MFRC522_PICC_CMD_MF_AUTH_KEY_A
* because only Key A can always read the sector trailer access bits.
*
* @param[in] dev Device descriptor of the MFRC522
* @param[in] uid PICC's UID
* @param[in] key Key A for the sector.
* @param[in] sector The sector to dump, 0..39
*/
void mfrc522_picc_dump_mifare_classic_sector_to_serial(mfrc522_t *dev, mfrc522_uid_t *uid,
mfrc522_mifare_key_t *key, uint8_t sector);
/**
* @brief Dump memory contents of a MIFARE Ultralight PICC to stdout
*
* @param[in] dev Device descriptor of the MFRC522
*/
void mfrc522_picc_dump_mifare_ultralight_to_serial(mfrc522_t *dev);
/**
* @brief Perform a self-test of the MFRC522
*
* (See section 16.1.1)
*
* @param[in] dev Device descriptor of the MFRC522
*
* @return true if the test passed, false otherwise and if no firmware reference is available.
*/
bool mfrc522_pcd_perform_self_test(mfrc522_t *dev);
#ifdef __cplusplus
}
#endif
#endif /* MFRC522_H */
/** @} */