esp32/main/reader.h
raw ยท 2444 bytes
#ifndef HOMEKEY_READER_H
#define HOMEKEY_READER_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define NFC_UID_MAX 10
typedef struct {
uint8_t uid[NFC_UID_MAX];
uint8_t uid_len;
uint8_t target;
uint8_t sak;
} nfc_card_t;
typedef bool (*pn532_card_callback_t)(const nfc_card_t *card);
/* Blocks in the caller's task. Returns only after absence and successful
* PN532 PowerDown; caller must stop BLE and enter deep sleep. */
void start_polling(pn532_card_callback_t callback);
/* Only called by the NFC owner task while its target is active. */
int pn532_exchange(uint8_t target, const uint8_t *apdu, size_t length,
uint8_t *out, size_t capacity, size_t *out_length);
static inline bool nfc_uid_valid(size_t length)
{
return length == 4 || length == 7 || length == 10;
}
static inline bool nfc_card_equal(const nfc_card_t *a, const nfc_card_t *b)
{
return a->uid_len == b->uid_len &&
memcmp(a->uid, b->uid, a->uid_len) == 0;
}
typedef struct {
nfc_card_t last;
bool present;
unsigned misses;
} nfc_presence_t;
/* Only successful no-target scans count toward removal. */
static inline bool nfc_presence_update(nfc_presence_t *state, int result,
const nfc_card_t *card)
{
if (result == 1) {
state->misses = 0;
return !state->present || !nfc_card_equal(&state->last, card);
}
if (result == 0) {
if (state->present && ++state->misses >= 2) {
state->present = false;
}
} else {
state->misses = 0;
}
return false;
}
static inline void nfc_presence_accept(nfc_presence_t *state,
const nfc_card_t *card)
{
state->last = *card;
state->present = true;
}
/* Nonconnectable legacy ADV: one 128-bit service-data AD, at most 31 bytes.
* v2 payload = version(2), event_seq LE16, UID (length inferred).
* Flags/name/type are omitted to fit a full 10-byte UID.
*/
static inline size_t build_card_adv(uint8_t adv[31], const nfc_card_t *card,
uint16_t event_seq)
{
static const uint8_t uuid[16] = {
0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0xbc, 0x9a,
0x11, 0x4a, 0x1e, 0x7b, 0x01, 0x00, 0x1e, 0x7b,
};
if (!nfc_uid_valid(card->uid_len)) {
return 0;
}
adv[0] = (uint8_t)(20 + card->uid_len);
adv[1] = 0x21;
memcpy(adv + 2, uuid, sizeof(uuid));
// Protocol Version
adv[18] = 1;
adv[19] = (uint8_t)event_seq;
adv[20] = (uint8_t)(event_seq >> 8);
memcpy(adv + 21, card->uid, card->uid_len);
return 21 + card->uid_len;
}
#endif