ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
pn532.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file pn532.h
6 * @brief PN532 NFC frame codec (PROTOCORE_ENABLE_PN532) - NXP PN532 NFC/RFID controller.
7 *
8 * The command-frame protocol of the NXP PN532 (the ubiquitous NFC reader on I2C / SPI /
9 * HSU breakouts): a tag read/write bridged to an HTTP / MQTT event. The host and the chip
10 * exchange **normal information frames**:
11 *
12 * 00 | 00 FF | LEN | LCS | TFI | PD0..PDn | DCS | 00
13 *
14 * where TFI is 0xD4 (host -> PN532) or 0xD5 (PN532 -> host), LEN counts TFI + PData, LCS is
15 * the length checksum (LEN + LCS == 0), and DCS is the data checksum (TFI + sum(PData) + DCS
16 * == 0). A short 6-byte **ACK frame** (00 00 FF 00 FF 00) confirms each command.
17 *
18 * protocore_pn532_build_frame() assembles a frame carrying a command + parameters, protocore_pn532_parse_frame()
19 * frames + verifies a response, and protocore_pn532_is_ack() detects the ACK. The per-command PData
20 * (GetFirmwareVersion, InListPassiveTarget, InDataExchange, ...) is the application's. Pure -
21 * you carry the bytes over your I2C / SPI / UART - so it is fully host-testable.
22 *
23 * @author Douglas Quigg (dstroy0)
24 * @date 2026
25 */
26
27#ifndef PROTOCORE_PN532_H
28#define PROTOCORE_PN532_H
29
30#include "protocore_config.h" // the entry point: protocore_types.h for the widths
31
32#if PROTOCORE_ENABLE_PN532
33
35
36// This module holds nothing between calls, so it carves no borrow and states none. An entry
37// takes one all the same, and never reads it, so every namespace in the tree is invoked the
38// same way.
39
40#define PN532_TFI_HOST 0xD4
41
42#define PN532_TFI_PN532 0xD5
43
44/** @brief What build_frame takes: tfi, data, len, out, cap. */
45typedef struct
46{
47 uint8_t tfi;
48 const uint8_t *data;
49 uint8_t len;
50 uint8_t *out;
51 uint16_t cap;
52} Pn532BuildFrameArgs;
53
54/** @brief What parse_frame takes: raw, len, tfi, pdata, pdata_len. */
55typedef struct
56{
57 const uint8_t *raw;
58 uint16_t len;
59 uint8_t *tfi;
60 const uint8_t **pdata;
61 uint8_t *pdata_len;
62} Pn532ParseFrameArgs;
63
64/** @brief What is_ack takes: raw, len. */
65typedef struct
66{
67 const uint8_t *raw;
68 uint16_t len;
69} Pn532IsAckArgs;
70
71/** @brief What build_ack takes: out, cap. */
72typedef struct
73{
74 uint8_t *out;
75 uint16_t cap;
76} Pn532BuildAckArgs;
77
78/**
79 * @brief PN532 NFC frame codec (PROTOCORE_ENABLE_PN532) - NXP PN532 NFC/RFID controller. The command-frame protocol of
80 * ...
81 *
82 * A caller sets the members a call takes, invokes it through ::Pn532 with the bytes it runs
83 * out of, and reads the outcome off the same handle.
84 *
85 * Pn532.build_frame_args.tfi = ...;
86 * Pn532.build_frame_args.data = ...;
87 * Pn532.build_frame_args.len = ...;
88 * Pn532.build_frame_args.out = ...;
89 * Pn532.build_frame_args.cap = ...;
90 * Pn532.build_frame(work);
91 * // Pn532.len is what the call reports
92 *
93 * @var Pn532Ns::build_frame_args what build_frame takes: tfi, data, len, out, cap
94 * @var Pn532Ns::parse_frame_args what parse_frame takes: raw, len, tfi, pdata, pdata_len
95 * @var Pn532Ns::is_ack_args what is_ack takes: raw, len
96 * @var Pn532Ns::build_ack_args what build_ack takes: out, cap
97 * @var Pn532Ns::ok a call's true/false outcome
98 * @var Pn532Ns::len the total frame length, or 0 if it would not fit cap or len exceeds ...
99 * @var Pn532Ns::n the frame length consumed (> 0), 0 if more bytes are needed, or -1 ...
100 * @var Pn532Ns::build_frame assemble a normal information frame carrying tfi + data into out
101 * @var Pn532Ns::parse_frame frame one normal information frame from the front of raw and verify ...
102 * @var Pn532Ns::is_ack true if raw starts with a PN532 ACK frame (00 00 FF 00 FF 00)
103 * @var Pn532Ns::build_ack write the 6-byte ACK frame into out. 6, or 0 if cap < 6
104 *
105 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
106 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
107 * a caller drives every namespace the same way.
108 */
109typedef struct
110{
111 Pn532BuildFrameArgs build_frame_args;
112 Pn532ParseFrameArgs parse_frame_args;
113 Pn532IsAckArgs is_ack_args;
114 Pn532BuildAckArgs build_ack_args;
115 proto_bool ok;
116 uint16_t len;
117 int n;
118} Pn532Vars;
119
120/** @brief The operands and the outcome. */
121extern Pn532Vars Pn532V;
122
123/** @brief The entries. */
124typedef struct
125{
126 void (*const build_frame)(uint8_t *work);
127 void (*const parse_frame)(uint8_t *work);
128 void (*const is_ack)(uint8_t *work);
129 void (*const build_ack)(uint8_t *work);
130} Pn532Ns;
131
132// What the table binds, defined once in the .c and taking one parameter each: everything
133// else an entry needs is an operand in Pn532V or a region of the borrow at a fixed offset.
134void protocore_pn532_build_frame(uint8_t *work);
135void protocore_pn532_parse_frame(uint8_t *work);
136void protocore_pn532_is_ack(uint8_t *work);
137void protocore_pn532_build_ack(uint8_t *work);
138
139// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
140// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
141// `Pn532.build_frame(work)` resolves to a named function and becomes a DIRECT call. An extern table
142// leaves the call indirect and the symbol live at every level, -O2 -flto included.
143static const Pn532Ns Pn532 __attribute__((unused)) = {
144 .build_frame = protocore_pn532_build_frame,
145 .parse_frame = protocore_pn532_parse_frame,
146 .is_ack = protocore_pn532_is_ack,
147 .build_ack = protocore_pn532_build_ack,
148};
149
151
152#endif // PROTOCORE_ENABLE_PN532
153
154#endif // PROTOCORE_PN532_H
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97