penguin/homekey-relay

homekey-relay

esp32/main/reader.h

raw ยท 2380 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;
} nfc_card_t;

typedef bool (*pn532_card_callback_t)(const nfc_card_t *card);

/* Blocks in the caller's task. Callback returns false if its queue is full. */
void start_polling(pn532_card_callback_t callback);

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