DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
pn532.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file pn532.cpp
6 * @brief PN532 NFC frame codec - implementation.
7 *
8 * Normal information frame: 00 | 00 FF | LEN | LCS | TFI | PData | DCS | 00, where
9 * (LEN + LCS) & 0xFF == 0 and (TFI + sum(PData) + DCS) & 0xFF == 0 (PN532 User Manual).
10 */
11
13
14#if DETWS_ENABLE_PN532
15
16namespace
17{
18const uint8_t ACK[6] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
19}
20
21uint16_t pn532_build_frame(uint8_t tfi, const uint8_t *data, uint8_t len, uint8_t *out, uint16_t cap)
22{
23 if (!out || len > DETWS_PN532_MAX_DATA || (data == nullptr && len > 0))
24 return 0;
25 uint16_t total = (uint16_t)(8 + len); // preamble+start(3) + LEN+LCS(2) + TFI + data + DCS + postamble
26 if (total > cap)
27 return 0;
28 uint8_t frame_len = (uint8_t)(1 + len); // TFI + PData
29 out[0] = 0x00;
30 out[1] = 0x00;
31 out[2] = 0xFF;
32 out[3] = frame_len;
33 out[4] = (uint8_t)(0x100 - frame_len); // LCS: LEN + LCS == 0
34 out[5] = tfi;
35 uint8_t sum = tfi;
36 for (uint8_t i = 0; i < len; i++)
37 {
38 out[6 + i] = data[i];
39 sum = (uint8_t)(sum + data[i]);
40 }
41 out[6 + len] = (uint8_t)(0x100 - sum); // DCS: TFI + sum(PData) + DCS == 0
42 out[7 + len] = 0x00; // postamble
43 return total;
44}
45
46int pn532_parse_frame(const uint8_t *raw, uint16_t len, uint8_t *tfi, const uint8_t **pdata, uint8_t *pdata_len)
47{
48 if (!raw || len < 1)
49 return 0;
50 if (raw[0] != 0x00)
51 return -1; // preamble
52 if (len < 5)
53 return 0; // need 00 00 FF LEN LCS
54 if (raw[1] != 0x00 || raw[2] != 0xFF)
55 return -1; // start code
56 uint8_t frame_len = raw[3];
57 if ((uint8_t)(frame_len + raw[4]) != 0)
58 return -1; // length checksum
59 if (frame_len == 0 || frame_len > DETWS_PN532_MAX_DATA + 1)
60 return -1; // no TFI, or implausible length
61 uint16_t total = (uint16_t)(7 + frame_len);
62 if (len < total)
63 return 0; // wait for TFI + PData + DCS + postamble
64 uint8_t sum = 0;
65 for (uint8_t i = 0; i < frame_len; i++)
66 sum = (uint8_t)(sum + raw[5 + i]); // TFI + PData
67 if ((uint8_t)(sum + raw[5 + frame_len]) != 0)
68 return -1; // data checksum
69 if (tfi)
70 *tfi = raw[5];
71 if (pdata)
72 *pdata = &raw[6];
73 if (pdata_len)
74 *pdata_len = (uint8_t)(frame_len - 1);
75 return (int)total;
76}
77
78bool pn532_is_ack(const uint8_t *raw, uint16_t len)
79{
80 if (!raw || len < 6)
81 return false;
82 for (uint8_t i = 0; i < 6; i++)
83 if (raw[i] != ACK[i])
84 return false;
85 return true;
86}
87
88uint16_t pn532_build_ack(uint8_t *out, uint16_t cap)
89{
90 if (!out || cap < 6)
91 return 0;
92 for (uint8_t i = 0; i < 6; i++)
93 out[i] = ACK[i];
94 return 6;
95}
96
97#endif // DETWS_ENABLE_PN532
#define DETWS_PN532_MAX_DATA
Reject a PN532 normal frame whose declared length exceeds this (framing sanity).
PN532 NFC frame codec (DETWS_ENABLE_PN532) - NXP PN532 NFC/RFID controller.