M5Unit-NFC 0.0.3 git rev:59f5362
Loading...
Searching...
No Matches
ndef.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_UNIFIED_NFC_NDEF_NDEF_HPP
11#define M5_UNIT_UNIFIED_NFC_NDEF_NDEF_HPP
12
13#include <cstdint>
14#include <vector>
15#include <m5_utility/stl/extension.hpp>
16
17namespace m5 {
18namespace nfc {
23namespace ndef {
24
27constexpr uint8_t NDEF_MAJOR_VERSION{1};
28constexpr uint8_t NDEF_MINOR_VERSION{0};
29constexpr uint8_t MAGIC_NO_CC4{0xE1};
30constexpr uint8_t MAGIC_NO_CC8{0xE2};
31constexpr uint8_t ACCESS_FREE{0x00};
32constexpr uint8_t ACCESS_PROPRIETARY{0x02};
33
34constexpr uint8_t TYPE2_CC_BLOCK{3};
35constexpr uint16_t CC4_MAX_NDEF_LENGTH{2040};
37
42enum class Tag : uint8_t {
43 Null,
46 Message,
47 Proprietary = 0xFD,
49};
50
55using TagBits = uint8_t;
56
58constexpr inline TagBits tag_to_tagbit(const Tag t)
59{
60 return (t == Tag::Null) ? (1u << 0)
61 : (t == Tag::LockControl) ? (1u << 1)
62 : (t == Tag::MemoryControl) ? (1u << 2)
63 : (t == Tag::Message) ? (1u << 3)
64 : (t == Tag::Proprietary) ? (1u << 4)
65 : (t == Tag::Terminator) ? (1u << 5)
66 : 0u;
67}
68
70template <typename... Ts>
71struct are_all_tag : std::true_type {
72};
73template <typename T, typename... Ts>
74struct are_all_tag<T, Ts...> : std::integral_constant<bool, std::is_same<Tag, T>::value && are_all_tag<Ts...>::value> {
75};
76
77constexpr TagBits make_tag_bits_impl(TagBits acc)
78{
79 return acc;
80}
81
82template <typename... Rest>
83constexpr TagBits make_tag_bits_impl(TagBits acc, Tag head, Rest... rest)
84{
85 return make_tag_bits_impl(acc | tag_to_tagbit(head), rest...);
86}
88
94template <typename... T>
95constexpr TagBits make_tag_bits(T... tags)
96{
97 static_assert(sizeof...(tags) > 0, "At least one Tag is required");
98 static_assert(are_all_tag<T...>::value, "Arguments must be Tag");
99 return make_tag_bits_impl(0u, tags...);
100}
101
103inline constexpr bool contains_tag(const TagBits tb, const Tag t)
104{
105 return (tb & tag_to_tagbit(t)) != 0;
106}
107
110 make_tag_bits(m5::nfc::ndef::Tag::LockControl, m5::nfc::ndef::Tag::MemoryControl, m5::nfc::ndef::Tag::Message,
111 m5::nfc::ndef::Tag::Proprietary, m5::nfc::ndef::Tag::Terminator);
113constexpr TagBits tagBitsMessage = make_tag_bits(m5::nfc::ndef::Tag::Message);
114
116inline bool is_valid_tag(const uint8_t t)
117{
118 return t <= m5::stl::to_underlying(Tag::Message) || t == m5::stl::to_underlying(Tag::Proprietary) ||
119 t == m5::stl::to_underlying(Tag::Terminator);
120}
121
123inline bool is_terminator_tag(const uint8_t t)
124{
125 return t == m5::stl::to_underlying(Tag::Terminator);
126}
127
132enum class URIProtocol : uint8_t {
133 NA,
134 HTTP_WWW,
135 HTTPS_WWW,
136 HTTP,
137 HTTPS,
138 TEL,
139 MAILTO,
140 FTP_AA,
141 FTP_FTP,
142 FTPS,
143 SFTP,
144 SMB,
145 NFS,
146 FTP,
147 DEV,
148 NEWS,
149 TELNET,
150 IMAP,
151 RSTP,
152 URN,
153 POP,
154 SIP,
155 SIPS,
156 TFTP,
157 BTSPP,
158 BTL2CAP,
159 BTGOEP,
160 TCPOBEX,
161 IRDAOBEX,
162 FILE,
163 URN_EPC_ID,
167 URN_EPC,
168 NFC,
169};
170
172const char* get_uri_idc_string(const URIProtocol protocol);
173
178namespace type2 {
184 uint8_t block[4]{};
185
186 inline bool valid() const
187 {
188 return (block[0] == MAGIC_NO_CC4) && (major_version() >= NDEF_MAJOR_VERSION) &&
189 ((int16_t)minor_version() >= NDEF_MINOR_VERSION) && ndef_size();
190 }
191 inline bool can_read() const
192 {
193 return read_access() == ACCESS_FREE;
194 }
195 inline bool can_write() const
196 {
197 return write_access() == ACCESS_FREE;
198 }
199
200 // Getter
201 inline uint8_t major_version() const
202 {
203 return (block[1] >> 4) & 0x0F;
204 }
205 inline uint8_t minor_version() const
206 {
207 return block[1] & 0x0F;
208 }
209 inline uint16_t ndef_size() const
210 {
211 return (uint16_t)block[2] << 3;
212 }
213 inline uint8_t read_access() const
214 {
215 return (block[3] >> 4) & 0x0F;
216 }
217 inline uint8_t write_access() const
218 {
219 return block[3] & 0x0F;
220 }
221 // Setter
222 inline void major_version(const uint8_t v)
223 {
224 block[1] = (block[1] & 0x0F) | ((v & 0x0F) << 4);
225 }
226 inline void minor_version(const uint8_t v)
227 {
228 block[1] = (block[1] & 0xF0) | (v & 0x0F);
229 }
230 inline void ndef_size(const uint16_t sz)
231 {
232 block[2] = (sz > 2040) ? 0 : (sz >> 3);
233 }
234 inline void read_access(const uint8_t a)
235 {
236 block[3] = (block[3] & 0x0F) | ((a & 0x03) << 4);
237 }
238 inline void write_access(const uint8_t a)
239 {
240 block[3] = (block[3] & 0xF0) | (a & 0x03);
241 }
242};
243} // namespace type2
244
249namespace type3 {
255 uint8_t block[16]{};
256
257 static constexpr uint8_t DEFAULT_VERSION{0x10};
258
263 enum class WriteFlag : uint8_t {
264 Done,
265 InProgress = 0x0F,
266 };
267
272 enum class AccessFlag : uint8_t {
273 ReadOnly,
274 ReadWrite,
275 };
276 AttributeBlock() : block{DEFAULT_VERSION}
277 {
278 }
279
280 // Getter
281 inline uint8_t version() const
282 {
283 return block[0];
284 }
285 inline uint8_t max_block_to_read() const
286 {
287 return block[1];
288 }
289 inline uint8_t max_block_to_write() const
290 {
291 return block[2];
292 }
293 inline uint16_t blocks_for_ndef_storage() const
294 {
295 return ((uint16_t)block[3] << 8) | block[4];
296 }
297 inline WriteFlag write_flag() const
298 {
299 return (block[9] == 0) ? WriteFlag::Done : WriteFlag::InProgress;
300 }
301 inline AccessFlag access_flag() const
302 {
303 return (AccessFlag)block[10];
304 }
305 inline uint32_t current_ndef_message_length() const
306 {
307 return ((uint32_t)block[11] << 16) | ((uint32_t)block[12] << 8) | block[13];
308 }
309 inline uint16_t check_sum() const
310 {
311 return ((uint16_t)block[14] << 8) | block[15];
312 }
313
314 // Setter
315 inline void version(const uint8_t ver)
316 {
317 block[0] = ver;
318 }
319 inline void max_block_to_read(const uint8_t b)
320 {
321 block[1] = b;
322 }
323 inline void max_block_to_write(const uint8_t b)
324 {
325 block[2] = b;
326 }
327 inline void blocks_for_ndef_storage(const uint16_t s)
328 {
329 block[3] = s >> 8;
330 block[4] = s & 0xFF;
331 }
332 inline void write_flag(const WriteFlag f)
333 {
334 block[9] = m5::stl::to_underlying(f);
335 }
336 inline void access_flag(const AccessFlag f)
337 {
338 block[10] = m5::stl::to_underlying(f);
339 }
340 inline void current_ndef_message_length(const uint32_t len)
341 {
342 block[11] = len >> 16;
343 block[12] = len >> 8;
344 block[13] = len & 0xFF;
345 }
346
347 //
348 bool valid() const;
349 uint16_t calculate_check_sum() const;
350 uint16_t update_check_sum();
351};
352
353} // namespace type3
354
359namespace type4 {
360
361constexpr uint16_t CC_FILE_ID{0xE103};
362constexpr uint8_t NDEF_AID[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
363constexpr uint16_t NDEF_APP_FID{0xE110};
364constexpr uint16_t NDEF_FILE_ID{0xE104};
365
370enum class FileControlTag : uint8_t {
371 Message = 0x04,
372 Proprietary = 0x05,
373 // Extended = 0x06, //!< Extended NDEF (Over 32KB) Type 4 Tag Specification v2.0 or later
374};
375
380using FileControlTagBits = uint8_t;
381
383constexpr inline FileControlTagBits fc_to_fcbit(const FileControlTag t)
384{
385 return (t == FileControlTag::Message) ? (1u << 0) : ((t == FileControlTag::Proprietary) ? (1u << 1) : 0u);
386}
387
389template <typename... Ts>
390struct are_all_fc : std::true_type {
391};
392template <typename T, typename... Ts>
393struct are_all_fc<T, Ts...>
394 : std::integral_constant<bool, std::is_same<FileControlTag, T>::value && are_all_fc<Ts...>::value> {
395};
396
397constexpr FileControlTagBits make_fc_bits_impl(FileControlTagBits acc)
398{
399 return acc;
400}
401
402template <typename... Rest>
403constexpr FileControlTagBits make_fc_bits_impl(FileControlTagBits acc, FileControlTag head, Rest... rest)
404{
405 return make_fc_bits_impl(acc | fc_to_fcbit(head), rest...);
406}
408
414template <typename... T>
415constexpr FileControlTagBits make_fc_bits(T... fcs)
416{
417 static_assert(sizeof...(fcs) > 0, "At least one Fc is required");
418 static_assert(are_all_fc<T...>::value, "Arguments must be Fc");
419 return make_fc_bits_impl(0u, fcs...);
420}
421
423inline constexpr bool contains_file_control_tag(const FileControlTagBits tb, const FileControlTag t)
424{
425 return (tb & fc_to_fcbit(t)) != 0;
426}
427
429constexpr FileControlTagBits fcBitsAll = make_fc_bits(FileControlTag::Message, FileControlTag::Proprietary);
431constexpr FileControlTagBits fcBitsMessage = make_fc_bits(FileControlTag::Message);
432
438 uint8_t tag{};
439 uint8_t len{};
440 uint16_t ndef_file_id{};
441 uint16_t ndef_file_size{};
442 uint8_t read_access{};
443 uint8_t write_access{};
444
445 inline FileControlTag fctag() const
446 {
447 return static_cast<FileControlTag>(this->tag);
448 }
449};
450
456 uint16_t cclen{};
457 uint8_t mapping_version{};
458 uint16_t mle{};
459 uint16_t mlc{};
460 std::vector<FileControlTLV> fctlvs{};
461
462 inline uint8_t major_version() const
463 {
464 return (mapping_version >> 4) & 0x0F;
465 }
466 inline uint8_t minor_version() const
467 {
468 return mapping_version & 0x0F;
469 }
470 inline bool valid() const
471 {
472 return cclen > 7 && !this->fctlvs.empty();
473 }
474
475 inline FileControlTLV fctlv(const uint8_t index) const
476 {
477 return index < this->fctlvs.size() ? this->fctlvs[index] : FileControlTLV{};
478 }
479 FileControlTLV fctlv(const FileControlTag fc = FileControlTag::Message) const;
480
481 bool parse(const uint8_t* buf, const uint16_t len);
482};
483
484} // namespace type4
485
490namespace type5 {
496 uint8_t block[8]{};
497
498 inline bool valid() const
499 {
500 return ((block[0] == MAGIC_NO_CC4) || (block[0] == MAGIC_NO_CC8)) && (major_version() >= NDEF_MAJOR_VERSION) &&
501 ((int16_t)minor_version() >= NDEF_MINOR_VERSION) && ndef_size();
502 }
503 inline bool can_read() const
504 {
505 return read_access() == ACCESS_FREE;
506 }
507 inline bool can_write() const
508 {
509 return write_access() == ACCESS_FREE;
510 }
511 inline uint8_t size() const
512 {
513 return (block[0] == MAGIC_NO_CC4) ? 4 : ((block[0] == MAGIC_NO_CC8) ? 8 : 0);
514 }
515 // Getter
516 inline uint8_t major_version() const
517 {
518 return (block[1] >> 6) & 0x03;
519 }
520 inline uint8_t minor_version() const
521 {
522 return (block[1] >> 4) & 0x03;
523 }
524 inline uint16_t ndef_size() const
525 {
526 return (block[0] == MAGIC_NO_CC4) ? (((uint16_t)block[2]) << 3)
527 : (block[0] == MAGIC_NO_CC8) ? (((uint16_t)block[6] << 8) | block[7])
528 : 0;
529 }
530 inline uint8_t read_access() const
531 {
532 return (block[1] >> 2) & 0x03;
533 }
534 inline uint8_t write_access() const
535 {
536 return block[1] & 0x03;
537 }
538 inline uint8_t additional_feature() const
539 {
540 return block[3];
541 }
542 // Setter
543 inline void major_version(const uint8_t v)
544 {
545 block[1] = (block[1] & 0x3F) | ((v & 0x03) << 6);
546 }
547 inline void minor_version(const uint8_t v)
548 {
549 block[1] = (block[1] & 0xCF) | ((v & 0x03) << 4);
550 }
551 inline void ndef_size(const uint16_t sz)
552 {
553 if (block[0] == MAGIC_NO_CC4 && sz <= 2040) {
554 block[2] = (sz >> 3);
555 } else if (block[0] == MAGIC_NO_CC8) {
556 block[6] = (sz >> 8);
557 block[7] = sz & 0xFF;
558 }
559 }
560 inline void read_access(const uint8_t a)
561 {
562 block[1] = (block[1] & 0xF3) | ((a & 0x03) << 2);
563 }
564 inline void write_access(const uint8_t a)
565 {
566 block[1] = (block[1] & 0xFC) | (a & 0x03);
567 }
568 inline void additional_feature(const uint8_t af)
569 {
570 block[3] = af;
571 }
572};
573} // namespace type5
574
575} // namespace ndef
576} // namespace nfc
577} // namespace m5
578
579#endif
NFC-A definitions.
NFC-B definitions.
NFC-F definitions.
Top level namespace of M5stack.
For NDEF.
NFC related definitions.
For NDEF Type2.
For NDEF Type3.
For NDEF Type4.
For NDEF Type5.
NFC-V definitions.
constexpr FileControlTagBits make_fc_bits(T... fcs)
Make FileControlBit from FileControlTag.
Definition ndef.hpp:415
constexpr uint16_t NDEF_APP_FID
ISO DF FID for NDEF app.
Definition ndef.hpp:363
constexpr uint8_t TYPE2_CC_BLOCK
Block for CC type2.
Definition ndef.hpp:34
constexpr uint8_t NDEF_MINOR_VERSION
Support minor version.
Definition ndef.hpp:28
constexpr uint8_t NDEF_AID[]
AID for NDEF.
Definition ndef.hpp:362
constexpr uint8_t MAGIC_NO_CC4
4 byte CC
Definition ndef.hpp:29
FileControlTag
File control for File Control TLV for type4.
Definition ndef.hpp:370
constexpr uint8_t ACCESS_PROPRIETARY
Access condition (proprietary)
Definition ndef.hpp:32
uint8_t TagBits
TLV(Tag,Length,Value) tag bit group for type2/5.
Definition ndef.hpp:55
constexpr TagBits make_tag_bits(T... tags)
Make TagBit from tag.
Definition ndef.hpp:95
constexpr FileControlTagBits fcBitsAll
All fcs.
Definition ndef.hpp:429
constexpr TagBits tag_to_tagbit(const Tag t)
Tag to TagBit.
Definition ndef.hpp:58
URIProtocol
URI Identifier Code.
Definition ndef.hpp:132
@ FTP_AA
ftp://anonymous:anonymous@
constexpr TagBits tagBitsAll
All tags.
Definition ndef.hpp:109
constexpr TagBits tagBitsMessage
Message only.
Definition ndef.hpp:113
constexpr FileControlTagBits fcBitsMessage
Message only.
Definition ndef.hpp:431
constexpr FileControlTagBits fc_to_fcbit(const FileControlTag t)
Tag to TagBit.
Definition ndef.hpp:383
constexpr bool contains_file_control_tag(const FileControlTagBits tb, const FileControlTag t)
Check whether FileControlTagBits contains given FileControl.
Definition ndef.hpp:423
bool is_terminator_tag(const uint8_t t)
Is terminator?
Definition ndef.hpp:123
constexpr uint8_t ACCESS_FREE
Access condition (Free access)
Definition ndef.hpp:31
constexpr uint16_t CC_FILE_ID
CC file id.
Definition ndef.hpp:361
constexpr uint8_t MAGIC_NO_CC8
8 byte CC (Type5)
Definition ndef.hpp:30
Tag
TLV(Tag,Length,Value) tag for type2/5.
Definition ndef.hpp:42
@ Proprietary
Proprietary.
@ LockControl
Lock control.
@ MemoryControl
Memory control.
@ Terminator
Terminator.
constexpr uint16_t NDEF_FILE_ID
ISO EF FID for NDEF file.
Definition ndef.hpp:364
bool is_valid_tag(const uint8_t t)
Is valid tag?
Definition ndef.hpp:116
constexpr uint8_t NDEF_MAJOR_VERSION
Support major version.
Definition ndef.hpp:27
constexpr bool contains_tag(const TagBits tb, const Tag t)
Check whether TagBits contains given Tag.
Definition ndef.hpp:103
constexpr uint16_t CC4_MAX_NDEF_LENGTH
Maximum ndef length for 4 byte CC.
Definition ndef.hpp:35
NFC
NFC type.
Definition nfc.hpp:27
Capability container for Type2.
Definition ndef.hpp:183
For Type 3 tag (T3T)
Definition ndef.hpp:254
AccessFlag
Permission to read and write.
Definition ndef.hpp:272
WriteFlag
Flag for fault tolerance.
Definition ndef.hpp:263
Capability container for Type4.
Definition ndef.hpp:455
uint16_t cclen
CC length.
Definition ndef.hpp:456
uint16_t mlc
Maximum Lc.
Definition ndef.hpp:459
uint16_t mle
Maximum Le.
Definition ndef.hpp:458
uint8_t mapping_version
Mapping version.
Definition ndef.hpp:457
File control TLV.
Definition ndef.hpp:437
uint8_t tag
File control tag.
Definition ndef.hpp:438
uint8_t read_access
Read access.
Definition ndef.hpp:442
uint8_t len
Length.
Definition ndef.hpp:439
uint8_t write_access
Write access.
Definition ndef.hpp:443
uint16_t ndef_file_size
NDEF file size.
Definition ndef.hpp:441
uint16_t ndef_file_id
NDEF file ID.
Definition ndef.hpp:440
Capability container for Type5.
Definition ndef.hpp:495