Add Gitea OTA firmware update, dual-slot partition layout, and Gitea Actions release workflow

This commit is contained in:
2026-09-12 10:49:39 +02:00
parent 8ac465229c
commit 1d954287a2
82 changed files with 7611 additions and 395 deletions

View File

@@ -0,0 +1,28 @@
#pragma once
#include "driver/i2c_master.h"
#include "driver/i2c_types.h"
#include "rc522_driver.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
i2c_master_bus_handle_t bus;
i2c_master_bus_config_t *bus_config; // Only required if `bus` is NULL
i2c_device_config_t dev_config;
/**
* GPIO number of the RC522 RST pin.
* Set to -1 if the RST pin is not connected.
*/
gpio_num_t rst_io_num;
} rc522_i2c_config_t;
esp_err_t rc522_i2c_create(const rc522_i2c_config_t *config, rc522_driver_handle_t *driver);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,32 @@
#pragma once
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include "rc522_driver.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RC522_SPI_WRITE (0)
#define RC522_SPI_READ (1)
typedef struct
{
spi_host_device_t host_id;
spi_bus_config_t *bus_config;
spi_device_interface_config_t dev_config;
spi_dma_chan_t dma_chan;
/**
* GPIO number of the RC522 RST pin.
* Set to -1 if the RST pin is not connected.
*/
gpio_num_t rst_io_num;
} rc522_spi_config_t;
esp_err_t rc522_spi_create(const rc522_spi_config_t *config, rc522_driver_handle_t *driver);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,193 @@
#pragma once
#include "rc522_types.h"
#include "rc522_picc.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RC522_ERR_MIFARE_BASE (RC522_ERR_BASE + 0xFF)
#define RC522_ERR_MIFARE_ACCESS_BITS_INTEGRITY_VIOLATION (RC522_ERR_MIFARE_BASE + 1)
#define RC522_ERR_MIFARE_VALUE_BLOCK_INTEGRITY_VIOLATION (RC522_ERR_MIFARE_BASE + 2)
#define RC522_ERR_MIFARE_NACK (RC522_ERR_MIFARE_BASE + 3)
#define RC522_ERR_MIFARE_AUTHENTICATION_FAILED (RC522_ERR_MIFARE_BASE + 4)
#define RC522_ERR_MIFARE_SECTOR_TRAILER_WRITE_NOT_ALLOWED (RC522_ERR_MIFARE_BASE + 5)
#define RC522_MIFARE_SECTOR_INDEX_MAX (39) // No MIFARE Classic has more than 40 sectors
#define RC522_MIFARE_BLOCK_SIZE (16)
#define RC522_MIFARE_ACK (0x0A) // The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK.
#define RC522_MIFARE_KEY_SIZE (6)
#define RC522_MIFARE_KEY_VALUE_DEFAULT 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
typedef struct
{
uint8_t number_of_sectors;
} rc522_mifare_desc_t;
typedef struct
{
uint8_t index; // Zero-based index of Sector
uint8_t number_of_blocks; // Total number of blocks inside of Sector
uint8_t block_0_address; // Zero-based index of the first Block inside of MIFARE memory
} rc522_mifare_sector_desc_t;
typedef enum
{
RC522_MIFARE_KEY_A = 0,
RC522_MIFARE_KEY_B,
} rc522_mifare_key_type_t;
typedef struct
{
rc522_mifare_key_type_t type;
uint8_t value[RC522_MIFARE_KEY_SIZE];
} rc522_mifare_key_t;
typedef enum
{
RC522_MIFARE_BLOCK_UNDEFINED = 0,
RC522_MIFARE_BLOCK_TRAILER,
RC522_MIFARE_BLOCK_DATA,
RC522_MIFARE_BLOCK_VALUE,
RC522_MIFARE_BLOCK_MANUFACTURER_DATA,
} rc522_mifare_block_type_t;
typedef struct
{
uint8_t c1 :1;
uint8_t c2 :1;
uint8_t c3 :1;
} rc522_mifare_access_bits_t;
typedef struct
{
rc522_mifare_access_bits_t access_bits[4]; // [3] = Trailer, [2] = Block 2, [1] = Block 1, [0] = Block 0
} rc522_mifare_sector_trailer_info_t;
typedef struct
{
int32_t value; // Value stored in the block
uint8_t addr; // Value block address (this is not the memory address)
} rc522_mifare_sector_value_block_info_t;
typedef struct
{
uint8_t address;
rc522_mifare_block_type_t type;
uint8_t bytes[RC522_MIFARE_BLOCK_SIZE];
union
{
rc522_mifare_sector_trailer_info_t trailer_info; // Valid only if type == RC522_MIFARE_BLOCK_TRAILER
rc522_mifare_sector_value_block_info_t value_info; // Valid only if type == RC522_MIFARE_BLOCK_VALUE
};
rc522_mifare_access_bits_t access_bits;
esp_err_t error; // e.g. acces bits or value block integrity violation
} rc522_mifare_sector_block_t;
// {{ MIFARE_Specific_Functions
/**
* @brief Authenticate a block read/write operations.
*
* After a successful authentication, communication between
* the PCD and the PICC is secured with MF1xxS20, MF1xxS70 or MF1xxS50 encryption.
*
* Once when read/write operations are authenticated for one block inside of a sector,
* read/write operations are authenticated for all blocks inside of that sector as well.
*
* @note After read/write operations are done, the PICC must be deauthenticated using @c rc522_mifare_deauth().
*
* @param rc522 RC522 handle
* @param picc PICC that is currently selected
* @param block_address Address of the block to authenticate
* @param key Key to authenticate with
*/
esp_err_t rc522_mifare_auth(
const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t block_address, const rc522_mifare_key_t *key);
/**
* @brief Read from a block at the given @c block_address on the PICC.
*
* @note The block must be authenticated before calling this function.
*
* @param rc522 RC522 handle
* @param picc PICC that is currently selected
* @param block_address Address of the block to read
* @param[out] out_buffer Buffer of exactly @c RC522_MIFARE_BLOCK_SIZE bytes to store the retrived data in
*/
esp_err_t rc522_mifare_read(const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t block_address,
uint8_t out_buffer[RC522_MIFARE_BLOCK_SIZE]);
/**
* @brief Write to a block at the given @c block_address on the PICC.
*
* @note The block must be authenticated before calling this function.
*
* @param rc522 RC522 handle
* @param picc PICC that is currently selected
* @param block_address Address of the block to write
* @param[in] buffer Buffer of exactly @c RC522_MIFARE_BLOCK_SIZE that contains the data to write
*/
esp_err_t rc522_mifare_write(const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t block_address,
const uint8_t buffer[RC522_MIFARE_BLOCK_SIZE]);
// }}
// {{ MIFARE_Utility_Functions
/**
* @brief Deauthenticates read/write operations and allows PCD to perform other commands
*
* @param rc522 RC522 handle
* @param picc PICC that is currently selected
*/
esp_err_t rc522_mifare_deauth(const rc522_handle_t rc522, const rc522_picc_t *picc);
/**
* @brief Authenticates read/write operations
*/
esp_err_t rc522_mifare_auth_sector(const rc522_handle_t rc522, const rc522_picc_t *picc,
const rc522_mifare_sector_desc_t *sector_desc, const rc522_mifare_key_t *key);
/**
* @brief Checks if the PICC is MIFARE Classic
*/
bool rc522_mifare_type_is_classic_compatible(rc522_picc_type_t type);
/**
* @brief Get MIFARE description (e.g number of sectors)
*/
esp_err_t rc522_mifare_get_desc(const rc522_picc_t *picc, rc522_mifare_desc_t *out_mifare_desc);
/**
* @brief Get MIFARE sector description (e.g number of blocks, block 0 address)
*/
esp_err_t rc522_mifare_get_sector_desc(uint8_t sector_index, rc522_mifare_sector_desc_t *out_sector_desc);
/**
* @brief Read and parse MIFARE sector trailer block
*/
esp_err_t rc522_mifare_read_sector_trailer_block(const rc522_handle_t rc522, const rc522_picc_t *picc,
const rc522_mifare_sector_desc_t *sector_desc, rc522_mifare_sector_block_t *out_trailer);
/**
* @brief Read and parse MIFARE sector (non-trailer) block
*/
esp_err_t rc522_mifare_read_sector_block(const rc522_handle_t rc522, const rc522_picc_t *picc,
const rc522_mifare_sector_desc_t *sector_desc, const rc522_mifare_sector_block_t *trailer, uint8_t block_offset,
rc522_mifare_sector_block_t *out_block);
esp_err_t rc522_mifare_get_number_of_sectors(rc522_picc_type_t type, uint8_t *out_result);
uint8_t rc522_mifare_get_sector_index_by_block_address(uint8_t block_address);
esp_err_t rc522_mifare_get_number_of_blocks_in_sector(uint8_t sector_index, uint8_t *out_result);
esp_err_t rc522_mifare_get_sector_block_0_address(uint8_t sector_index, uint8_t *out_result);
// }}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,377 @@
/** Functions to support interfacing with NXP tags
*
* This header defines functions for working with ISO14443-3 compliant NXP
* PICCs, primarily the Ultralight and NTAG families. These PICCs use
* predominately the same command set, with some small variations.
*
* For MIFARE Classic PICCs, see `include/picc/rc522_mifare.h`.
*
* Authentication:
* Ultralight {C,AES}: Key-based (3DES and AES respectively)
* Ultralight EV1, NTAG 21x: Password-based
*
* Some functions have been commented out; ideally these would be implemented
* at some stage to implement full support for these PICC functions, but I don't
* have any of the actual PICCs to properly test with.
*
* CMD/PICC | UL | UL C | UL EV1 | UL AES | UL Nano | NTAG21x |
* -------------|---------|---------|---------|---------|---------|---------|
* GET_VERSION | | | y | y | y | y |
* READ | y | y | y | y | y | y |
* FAST_READ | | | y | y | | y |
* WRITE | y | y | y | y | y | y |
* COMPAT_WRITE | y | y | y | | y | y |
* READ_CNT | | | 3 | 3 | | 1 |
* INCR_CNT | | | y | y | | |
* READ_SIG | | | 32 | 48 | 32 | 32 | (bytes)
* WRITE_SIG | | | | y | y | |
* LOCK_SIG | | | | y | y | |
* AUTHENTICATE | | 3DES | | AES | | |
* PWD_AUTH | | | y | | | y |
* VCSL | | | y | y | | |
*/
#pragma once
#include "rc522_picc.h"
#include "rc522_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RC522_ERR_NXP_BASE (RC522_ERR_BASE + 0XF0)
#define RC522_ERR_NXP_NACK (RC522_ERR_NXP_BASE + 1)
#define RC522_ERR_NXP_AUTHENTICATION_FAILED (RC522_ERR_NXP_BASE + 2)
#define RC522_ERR_NXP_PACK_MISMATCH (RC522_ERR_NXP_BASE + 3)
#define RC522_NXP_PWD_SIZE 4
#define RC522_NXP_PACK_SIZE 2
#define RC522_NXP_PAGE_SIZE 4
#define RC522_NXP_READ_SIZE (RC522_NXP_PAGE_SIZE * 4)
extern const uint8_t RC522_NXP_DEFAULT_PWD[RC522_NXP_PWD_SIZE];
extern const uint8_t RC522_NXP_DEFAULT_PACK[RC522_NXP_PACK_SIZE];
enum
{
/**
* Get PICC information.
*/
RC522_NXP_GET_VERSION = 0x60,
/**
* Read four pages from memory.
*/
RC522_NXP_READ = 0x30,
/**
* Read pages from START to END in memory.
*/
RC522_NXP_FAST_READ = 0x3A,
/**
* Write a page to memory.
*/
RC522_NXP_WRITE = 0xA2,
/**
* Write the first 4 bytes of 16 to a page in memory.
*/
RC522_NXP_COMPAT_WRITE = 0xA0,
/**
* Read an onboard counter.
*/
RC522_NXP_READ_CNT = 0x39,
/**
* Increment an onboard counter.
*/
RC522_NXP_INCR_CNT = 0xA5,
/**
* Read the originality signature.
*/
RC522_NXP_READ_SIG = 0x3C,
/**
* Write a new originality signature.
*/
RC522_NXP_WRITE_SIG = 0xA9,
/**
* Control access to the originality signature.
*/
RC522_NXP_LOCK_SIG = 0xAC,
/**
* Perform key-based authentication, stage 1.
*/
RC522_NXP_AUTHENTICATE = 0x1A,
/**
* Perform key-based authentication, stage 2.
*/
RC522_NXP_AUTHENTICATE_2 = 0xAF,
/**
* Perform password-based authentication.
*/
RC522_NXP_PWD_AUTH = 0x1B,
RC522_NXP_VCSL = 0x4B,
};
/**
* L3 GET_VERSION: product_type field
*/
typedef enum
{
RC522_NXP_PRODUCT_TYPE_UNKNOWN,
RC522_NXP_PRODUCT_TYPE_UL = 0x03,
RC522_NXP_PRODUCT_TYPE_NTAG = 0x04,
} rc522_nxp_product_type_t;
/**
* L3 GET_VERSION: major_version field
*/
typedef enum
{
RC522_NXP_MAJ_VER_UNKNOWN = 0,
RC522_NXP_MAJ_VER_NTAG21 = 0x01,
RC522_NXP_MAJ_VER_UL_EV1 = 0x01,
RC522_NXP_MAJ_VER_UL_NANO = 0x02,
RC522_NXP_MAJ_VER_UL_AES = 0x04,
} rc522_nxp_major_version_t;
/**
* L3 GET_VERSION result
*/
typedef struct
{
uint8_t header;
uint8_t vendor;
rc522_nxp_product_type_t product_type :8;
uint8_t product_subtype;
rc522_nxp_major_version_t major_version :8;
uint8_t minor_version;
uint8_t storage_size;
uint8_t protocol_type;
} rc522_nxp_picc_version_t;
/**
* L3 FAST_READ result
*
* Contains a buffer, the size of the buffer, and the amount of space occupied
* by the data after a read
*/
typedef struct
{
uint8_t *bytes;
uint8_t buffer_size;
uint8_t read_size;
} rc522_nxp_fast_read_data_t;
/**
* Variable-length protection signature
*
* UL EV1: 32 bytes
* UL AES: 48 bytes
* UL Nano: 32 bytes
* NTAG213/215/216: 32 bytes
*/
typedef struct
{
uint8_t *bytes;
uint8_t buffer_size;
uint8_t sig_size;
} rc522_nxp_sig_t;
/**
* @brief Determine the total memory size of an NXP PICC
*
* Given an NXP PICC type, returns the total size of the memory in pages. This
* is not equivalent to generic user memory.
*
* For invalid types, unknown types, or types without pages, returns 0.
*
* @sa rc522_nxp_get_user_page_count()
*/
uint8_t rc522_nxp_get_page_count(rc522_picc_type_t type);
/**
* @brief Determine the user memory size of an NXP PICC
*
* Given an NXP PICC type (RC522_PICC_TYPE_MIFARE_UL_* or RC522_PICC_TYPE_NTAG*),
* returns the total size of the user memory in pages. The user memory always
* starts at page 4.
*
* For invalid types, unknown types, or types without pages, returns 0.
*/
uint8_t rc522_nxp_get_user_page_count(rc522_picc_type_t type);
/**
* @brief Determine the start page of user memory for an NXP PICC
*
* Currently this is 0x04 for all PICCs. It's unlikely to change in future
* for compatibility reasons, but this function exists in case (and also
* as a reference).
*
* For invalid or unknown types, returns 0.
*/
uint8_t rc522_nxp_get_user_mem_start(rc522_picc_type_t type);
/**
* @brief Determine the final page of user memory for an NXP PICC
*
* Returns the address of the final page of user memory for a given PICC
* type. This is the last page that can be safely written to without changing
* the configuration of the PICC.
*
* For invalid or unknown types, returns 0.
*/
uint8_t rc522_nxp_get_user_mem_end(rc522_picc_type_t type);
/**
* @brief Determine the type of an NXP PICC
*
* The Ultralight and NTAG families both use SAK=0, and need further processing
* to identify. This function attempts to determine the PICC in use following
* the procedure in NXP Application Note 10833.
*/
esp_err_t rc522_nxp_get_type(const rc522_handle_t rc522, const rc522_picc_t *picc, rc522_picc_type_t *out_type);
/**
* @brief NXP Level 3 GET_VERSION
*
* If supported, returns information about the PICC, including manufacturer,
* product, and memory size.
*/
esp_err_t rc522_nxp_get_version(
const rc522_handle_t rc522, const rc522_picc_t *picc, rc522_nxp_picc_version_t *out_version);
/**
* @brief NXP Level 3 READ
*
* Reads 4 pages (16 bytes) from a given page address on the PICC.
*/
esp_err_t rc522_nxp_read(
const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t address, uint8_t out_buffer[RC522_NXP_PAGE_SIZE * 4]);
/**
* NXP Level 3 FAST_READ
*
* If supported, allows a variable number of pages to be read at once, instead
* of the fixed 4 in READ.
*
* @param start Page address to start reading from
* @param end Page address to end reading (inclusive)
* @param out_buffer Output buffer; should be at least (end-start+1) * 4 bytes
*
* Supported PICCs: UL EV1, UL AES, NTAG21x
*/
esp_err_t rc522_nxp_fast_read(const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t start, uint8_t end,
rc522_nxp_fast_read_data_t *out_buffer);
/**
* @brief NXP Level 3 WRITE
*
* Writes 4 bytes of data to a single page.
*/
esp_err_t rc522_nxp_write(
const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t address, const uint8_t buffer[RC522_NXP_PAGE_SIZE]);
/**
* @brief NXP Level 3 READ_CNT
*
* If supported, reads a counter from the PICC. Some PICCs have more than one
* counter; if so counter_no specifies the counter to address.
*
* Supported PICCs: UL EV1 (3), UL AES (3), NTAG21x (1)
*/
esp_err_t rc522_nxp_read_cnt(
const rc522_handle_t rc522, const rc522_picc_t *picc, uint8_t counter_no, uint32_t *out_count);
/**
* @brief NXP Level 3 INCR_CNT
*
* If supported, increments a counter on the PICC. If the PICC has more than one
* counter, counter_no specifies the counter to target.
*
* TODO
*/
// esp_err_t rc522_nxp_incr_cnt(const rc522_handle_t rc522, const rc522_picc_t *picc,
// uint8_t counter_no);
/**
* @brief Checks for support for AUTHENTICATE in L3 on a PICC
*
* Used to determine if a chip supports AUTHENTICATE, to differentiate between
* Ultralight and Ultralight C. Does not perform actual authentication.
*/
esp_err_t rc522_nxp_keyauth_supported(const rc522_handle_t rc522, const rc522_picc_t *picc);
/**
* @brief NXP Level 3 AUTHENTICATE
*
* If supported, performs key-based authentication with a PICC. Note support
* for DES and/or AES algorithms is required.
*
* TODO
*/
// esp_err_t rc522_nxp_key_auth(const rc522_handle_t rc522, const rc522_picc_t *picc,
// rc522_nxp_key_t *key);
/**
* @brief NXP Level 3 PWD_AUTH
*
* If supported, performs password-based authentication with a PICC.
*
* @param pwd Password to send to pick
* @param pack Password ACKnowledgement expected to be returned by PICC
* @param[out] out_state PICC state on return. Correct PWD with mismatched PACK
* will still result in AUTHENTICATED
*
* Supported PICCs: UL EV1, NTAG21x
*/
esp_err_t rc522_nxp_pwd_auth(const rc522_handle_t rc522, const rc522_picc_t *picc,
const uint8_t pwd[RC522_NXP_PWD_SIZE], const uint8_t pack[RC522_NXP_PACK_SIZE], rc522_picc_state_t *out_state);
/**
* @brief NXP Level 3 READ_SIG
*
* If supported, reads the ECC signature from the PICC. This signature can
* be used to verify originality. Does not actually perform verification.
*
* TODO: Implement verification per AN11350?
*
* Supported PICCs: UL EV1, UL AES, UL Nano, NTAG21x
*/
esp_err_t rc522_nxp_read_sig(const rc522_handle_t rc522, const rc522_picc_t *picc, rc522_nxp_sig_t *out_sig);
/**
* @brief NXP Level 3 WRITE_SIG
*
* If supported, writes a new signature to the PICC.
*
* TODO
*/
// esp_err_t rc522_nxp_write_sig(const rc522_handle_t rc522, const rc522_picc_t *picc,
// rc522_nxp_sig_t *sig);
/**
* @brief NXP Level 3 LOCK_SIG
*
* If supported, controls the originality signature lock on the PICC.
*
* @param argument 0x00 for unlock, 0x01 for lock, 0x02 for permanent lock
*
* TODO
*/
// esp_err_t rc522_nxp_lock_sig(const rc522_handle_t rc522, const rc522_picc_t *picc,
// rc522_nxp_sig_arg_t argument);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,26 @@
#pragma once
#include "rc522_types.h"
#ifdef __cplusplus
extern "C" {
#endif
ESP_EVENT_DECLARE_BASE(RC522_EVENTS);
esp_err_t rc522_create(const rc522_config_t *config, rc522_handle_t *out_rc522);
esp_err_t rc522_register_events(
const rc522_handle_t rc522, rc522_event_t event, esp_event_handler_t event_handler, void *event_handler_arg);
esp_err_t rc522_unregister_events(const rc522_handle_t rc522, rc522_event_t event, esp_event_handler_t event_handler);
esp_err_t rc522_start(rc522_handle_t rc522);
esp_err_t rc522_pause(rc522_handle_t rc522);
esp_err_t rc522_destroy(rc522_handle_t rc522);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,15 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct rc522_driver_handle *rc522_driver_handle_t;
esp_err_t rc522_driver_install(const rc522_driver_handle_t driver);
esp_err_t rc522_driver_uninstall(const rc522_driver_handle_t driver);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,33 @@
#pragma once
#include "rc522_types.h"
#ifdef __cplusplus
extern "C" {
#endif
enum // RC522_PCD_RF_CFG_REG
{
RC522_PCD_RX_GAIN_2_BIT = BIT6,
RC522_PCD_RX_GAIN_1_BIT = BIT5,
RC522_PCD_RX_GAIN_0_BIT = BIT4,
};
/**
* Receiver (antenna) gain
*/
typedef enum
{
RC522_PCD_18_DB_RX_GAIN = (RC522_PCD_RX_GAIN_1_BIT), /* 18 dB */
RC522_PCD_23_DB_RX_GAIN = (RC522_PCD_RX_GAIN_1_BIT | RC522_PCD_RX_GAIN_0_BIT), /* 23 dB */
RC522_PCD_33_DB_RX_GAIN = (RC522_PCD_RX_GAIN_2_BIT), /* 33 dB */
RC522_PCD_38_DB_RX_GAIN = (RC522_PCD_RX_GAIN_2_BIT | RC522_PCD_RX_GAIN_0_BIT), /* 38 dB */
RC522_PCD_43_DB_RX_GAIN = (RC522_PCD_RX_GAIN_2_BIT | RC522_PCD_RX_GAIN_1_BIT), /* 43 dB */
RC522_PCD_48_DB_RX_GAIN = (RC522_PCD_RX_GAIN_2_BIT | RC522_PCD_RX_GAIN_1_BIT | RC522_PCD_RX_GAIN_0_BIT), /* 48 dB */
} rc522_pcd_rx_gain_t;
esp_err_t rc522_pcd_set_rx_gain(const rc522_handle_t rc522, rc522_pcd_rx_gain_t gain);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,170 @@
#pragma once
#include "rc522_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RC522_PICC_UID_SIZE_MAX (10)
#define RC522_PICC_UID_SIZE_MIN (4)
#define RC522_PICC_UID_STR_BUFFER_SIZE_MAX (RC522_PICC_UID_SIZE_MAX * 3)
typedef struct
{
uint8_t value[RC522_PICC_UID_SIZE_MAX];
uint8_t length;
} rc522_picc_uid_t;
typedef enum
{
RC522_PICC_TYPE_UNKNOWN = -1,
RC522_PICC_TYPE_UNDEFINED = 0,
RC522_PICC_TYPE_ISO_14443_4, // PICC compliant with ISO/IEC 14443-4
RC522_PICC_TYPE_ISO_18092, // PICC compliant with ISO/IEC 18092 (NFC)
RC522_PICC_TYPE_MIFARE_MINI, // MIFARE Classic protocol, 320 bytes
RC522_PICC_TYPE_MIFARE_1K, // MIFARE Classic protocol, 1KB
RC522_PICC_TYPE_MIFARE_4K, // MIFARE Classic protocol, 4KB
RC522_PICC_TYPE_MIFARE_UL, // MIFARE Ultralight or Ultralight C
RC522_PICC_TYPE_MIFARE_PLUS, // MIFARE Plus
RC522_PICC_TYPE_MIFARE_DESFIRE, // MIFARE DESFire
RC522_PICC_TYPE_TNP3XXX, // Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
RC522_PICC_TYPE_MIFARE_UL_, // Ultralight MF0ICU1; 16x 4-byte pages
RC522_PICC_TYPE_MIFARE_UL_C, // Ultralight C MF0ICU2; 48x 4-byte pages
RC522_PICC_TYPE_MIFARE_UL_EV1_1, // Ultralight EV1 MF0UL11; 20x 4-byte pages
RC522_PICC_TYPE_MIFARE_UL_EV1_2, // Ultralight EV1 MF0UL21; 41x 4-byte pages
RC522_PICC_TYPE_MIFARE_UL_NANO, // Ultralight NANO; 40 bytes (probably 10x 4-byte pages)
RC522_PICC_TYPE_MIFARE_UL_AES, // Ultralight AES MF0AES(H)20; 60x 4-byte pages
RC522_PICC_TYPE_NTAG2xx, // NTAG 2xx; further information unknown
RC522_PICC_TYPE_NTAG213, // NTAG213; 45x 4-byte pages
RC522_PICC_TYPE_NTAG215, // NTAG215; 135x 4-byte pages
RC522_PICC_TYPE_NTAG216, // NTAG216; 231x 4-byte pages
} rc522_picc_type_t;
typedef enum
{
/**
* Not used! Ignore this one.
*
* In the POWER-OFF State, the PICC is not powered
* due to a lack of carrier energy.
*/
RC522_PICC_STATE_POWER_OFF = -1,
/**
* PICC is maybe in the field.
*
* In the IDLE State, the PICC shall recognize REQA and WUPA Commands.
* The PICC enters the READY State after it has received a valid
* REQA or WUPA Command and transmitted its ATQA.
*/
RC522_PICC_STATE_IDLE = 0,
/**
* In the READY State, either the bit frame anticollision or a proprietary
* anticollision method can be applied. Cascade levels are handled inside
* this state to get the complete UID.
*
* The PICC enters the ACTIVE State when it is selected with its complete UID.
*/
RC522_PICC_STATE_READY,
/**
* PICC is in the field.
*
* In the ACTIVE State, the PICC listens to any higher layer message.
* The PICC enters the HALT State when a valid HLTA Command is received.
*
* @note
* In the higher layer protocol, specific commands may be defined
* to return the PICC to its HALT State.
*/
RC522_PICC_STATE_ACTIVE,
/**
* In the HALT State, the PICC shall respond only to a WUPA Command.
*
* The PICC enters the READY* state after it has received a valid
* WUPA Command and transmitted its ATQA.
*/
RC522_PICC_STATE_HALT,
/**
* READY* State
*
* PICC is woken from HALT state by WUPA command.
*
* The READY* State is similar to the READY State, either the bit frame
* anticollision or a proprietary anticollision method can be applied.
* Cascade levels are handled inside this state to get complete UID.
*
* The PICC enters the ACTIVE* State when it is selected with its complete UID.
*/
RC522_PICC_STATE_READY_H,
/**
* ACTIVE* State
*
* PICC is still in the field. PICC enters this state
* when it is SELECTED in the READY* state.
*
* The ACTIVE* State is similar to the ACTIVE State, the PICC is selected and
* listens to any higher layer message.
*
* The PICC enters the HALT State when a valid HLTA Command is received.
*/
RC522_PICC_STATE_ACTIVE_H,
/**
* AUTHENTICATED State
*
* PICC has been authenticated, via either keys or passwords, and accessing
* protected areas is now possible. This is a Level 3 extension on some NXP
* PICCs.
*/
RC522_PICC_STATE_AUTHENTICATED,
} rc522_picc_state_t;
/**
* All RFU bits shall be set to zero.
*/
typedef struct
{
uint16_t source;
uint8_t rfu4 :4;
uint8_t prop_coding :4;
uint8_t uid_size :2; // 00b - single (4 bytes), 01b - double (7 bytes), 10b - triple (10 bytes)
uint8_t rfu1 :1;
uint8_t anticollision :5;
} rc522_picc_atqa_desc_t;
typedef struct
{
rc522_picc_atqa_desc_t atqa;
rc522_picc_uid_t uid;
uint8_t sak;
rc522_picc_type_t type;
rc522_picc_state_t state;
} rc522_picc_t;
typedef struct
{
rc522_picc_state_t old_state;
rc522_picc_t *picc;
} rc522_picc_state_changed_event_t;
char *rc522_picc_type_name(rc522_picc_type_t type);
/**
* @brief Convert PICC UID to (null-terminated) string
*/
esp_err_t rc522_picc_uid_to_str(const rc522_picc_uid_t *uid, char *buffer, uint8_t buffer_size);
/**
* @brief Print PICC information in a fancy way
*/
esp_err_t rc522_picc_print(const rc522_picc_t *picc);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,52 @@
#pragma once
#include <esp_err.h>
#include <esp_event.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "rc522_driver.h"
#include "rc522_picc.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RC522_X "X"
#define RC522_ERR_BASE (0xF522)
#define RC522_ERR_COLLISION (RC522_ERR_BASE + 1)
#define RC522_ERR_COLLISION_UNSOLVABLE (RC522_ERR_BASE + 2)
#define RC522_ERR_CRC_WRONG (RC522_ERR_BASE + 3)
#define RC522_ERR_INVALID_ATQA (RC522_ERR_BASE + 4)
#define RC522_ERR_RX_TIMEOUT (RC522_ERR_BASE + 5)
#define RC522_ERR_RX_TIMER_TIMEOUT (RC522_ERR_BASE + 6)
#define RC522_ERR_INVALID_SAK (RC522_ERR_BASE + 7)
#define RC522_ERR_PICC_POST_HEARTBEAT_MISSMATCH (RC522_ERR_BASE + 8)
#define RC522_ERR_PCD_FIFO_BUFFER_OVERFLOW (RC522_ERR_BASE + 9)
#define RC522_ERR_PCD_PARITY_CHECK_FAILED (RC522_ERR_BASE + 10)
#define RC522_ERR_PCD_PROTOCOL_ERROR (RC522_ERR_BASE + 11)
#define RC522_ERR_RST_PIN_UNUSED (RC522_ERR_BASE + 12)
#define RC522_ERR_PCD_FIFO_EMPTY (RC522_ERR_BASE + 13)
#define RC522_ERR_HLTA_NOT_ACKED (RC522_ERR_BASE + 14)
typedef struct rc522 *rc522_handle_t;
typedef struct
{
rc522_driver_handle_t driver;
uint16_t poll_interval_ms; /*<! Delay (in milliseconds) between polls */
size_t task_stack_size; /*<! Stack size of rc522 task */
uint8_t task_priority; /*<! Priority of rc522 task */
SemaphoreHandle_t task_mutex; /*<! Mutex for rc522 task */
} rc522_config_t;
typedef enum
{
RC522_EVENT_ANY = ESP_EVENT_ANY_ID,
RC522_EVENT_NONE,
RC522_EVENT_PICC_STATE_CHANGED,
} rc522_event_t;
#ifdef __cplusplus
}
#endif