unleashed-firmware/lib/nfc/protocols/nfc_protocol.c
gornekich d92b0a82cc
NFC refactoring (#3050)
"A long time ago in a galaxy far, far away...." we started NFC subsystem refactoring.

Starring:

- @gornekich - NFC refactoring project lead, architect, senior developer
- @gsurkov - architect, senior developer
- @RebornedBrain - senior developer

Supporting roles:

- @skotopes, @DrZlo13, @hedger - general architecture advisors, code review
- @Astrrra, @doomwastaken, @Hellitron, @ImagineVagon333 - quality assurance

Special thanks:

@bettse, @pcunning, @nxv, @noproto, @AloneLiberty and everyone else who has been helping us all this time and contributing valuable knowledges, ideas and source code.
2023-10-24 12:08:09 +09:00

175 lines
5.9 KiB
C

/**
* @file nfc_protocol.c
* @brief Main protocol hierarchy definitions.
*
* To reduce code duplication, all NFC protocols are described as a tree, whose
* structure is shown in the diagram below. The (Start) node is actually
* nonexistent and is there only for clarity.
*
* All its child protocols are considered base protocols, which in turn serve
* as parents to other, usually vendor-specific ones.
*
* ```
* **************************** Protocol tree structure ***************************
*
* (Start)
* |
* +------------------------+-----------+---------+------------+
* | | | | |
* ISO14443-3A ISO14443-3B Felica ISO15693-3 ST25TB
* | | |
* +---------------+-------------+ ISO14443-4B SLIX
* | | |
* ISO14443-4A Mf Ultralight Mf Classic
* |
* Mf Desfire
* ```
*
* When implementing a new protocol, its place in the tree must be determined first.
* If no appropriate base protocols exists, then it must be a base protocol itself.
*
* This file is to be modified upon adding a new protocol (see below).
*
*/
#include "nfc_protocol.h"
#include <furi/furi.h>
/**
* @brief Tree node describing a protocol.
*
* All base protocols (see above) have NfcProtocolInvalid
* in the parent_protocol field.
*/
typedef struct {
NfcProtocol parent_protocol; /**< Parent protocol identifier. */
size_t children_num; /** < Number of the child protocols. */
const NfcProtocol* children_protocol; /**< Pointer to an array of child protocol identifiers. */
} NfcProtocolTreeNode;
/** List of ISO14443-3A child protocols. */
static const NfcProtocol nfc_protocol_iso14443_3a_children_protocol[] = {
NfcProtocolIso14443_4a,
NfcProtocolMfUltralight,
};
/** List of ISO14443-3B child protocols. */
static const NfcProtocol nfc_protocol_iso14443_3b_children_protocol[] = {
NfcProtocolIso14443_4b,
};
/** List of ISO14443-4A child protocols. */
static const NfcProtocol nfc_protocol_iso14443_4a_children_protocol[] = {
NfcProtocolMfDesfire,
};
/** List of ISO115693-3 child protocols. */
static const NfcProtocol nfc_protocol_iso15693_3_children_protocol[] = {
NfcProtocolSlix,
};
/* Add new child protocol lists here (if necessary) */
/**
* @brief Flattened description of the NFC protocol tree.
*
* When implementing a new protocol, add the node here under its
* own index defined in nfc_protocol.h.
*
* Additionally, if it has an already implemented protocol as a parent,
* add its identifier to its respective list of child protocols (see above).
*/
static const NfcProtocolTreeNode nfc_protocol_nodes[NfcProtocolNum] = {
[NfcProtocolIso14443_3a] =
{
.parent_protocol = NfcProtocolInvalid,
.children_num = COUNT_OF(nfc_protocol_iso14443_3a_children_protocol),
.children_protocol = nfc_protocol_iso14443_3a_children_protocol,
},
[NfcProtocolIso14443_3b] =
{
.parent_protocol = NfcProtocolInvalid,
.children_num = COUNT_OF(nfc_protocol_iso14443_3b_children_protocol),
.children_protocol = nfc_protocol_iso14443_3b_children_protocol,
},
[NfcProtocolIso14443_4a] =
{
.parent_protocol = NfcProtocolIso14443_3a,
.children_num = COUNT_OF(nfc_protocol_iso14443_4a_children_protocol),
.children_protocol = nfc_protocol_iso14443_4a_children_protocol,
},
[NfcProtocolIso14443_4b] =
{
.parent_protocol = NfcProtocolIso14443_3b,
.children_num = 0,
.children_protocol = NULL,
},
[NfcProtocolIso15693_3] =
{
.parent_protocol = NfcProtocolInvalid,
.children_num = COUNT_OF(nfc_protocol_iso15693_3_children_protocol),
.children_protocol = nfc_protocol_iso15693_3_children_protocol,
},
[NfcProtocolFelica] =
{
.parent_protocol = NfcProtocolInvalid,
.children_num = 0,
.children_protocol = NULL,
},
[NfcProtocolMfUltralight] =
{
.parent_protocol = NfcProtocolIso14443_3a,
.children_num = 0,
.children_protocol = NULL,
},
[NfcProtocolMfClassic] =
{
.parent_protocol = NfcProtocolIso14443_3a,
.children_num = 0,
.children_protocol = NULL,
},
[NfcProtocolMfDesfire] =
{
.parent_protocol = NfcProtocolIso14443_4a,
.children_num = 0,
.children_protocol = NULL,
},
[NfcProtocolSlix] =
{
.parent_protocol = NfcProtocolIso15693_3,
.children_num = 0,
.children_protocol = NULL,
},
[NfcProtocolSt25tb] =
{
.parent_protocol = NfcProtocolInvalid,
.children_num = 0,
.children_protocol = NULL,
},
/* Add new protocols here */
};
NfcProtocol nfc_protocol_get_parent(NfcProtocol protocol) {
furi_assert(protocol < NfcProtocolNum);
return nfc_protocol_nodes[protocol].parent_protocol;
}
bool nfc_protocol_has_parent(NfcProtocol protocol, NfcProtocol parent_protocol) {
furi_assert(protocol < NfcProtocolNum);
furi_assert(parent_protocol < NfcProtocolNum);
bool parent_found = false;
const NfcProtocolTreeNode* iter = &nfc_protocol_nodes[protocol];
while(iter->parent_protocol != NfcProtocolInvalid) {
if(iter->parent_protocol == parent_protocol) {
parent_found = true;
break;
}
iter = &nfc_protocol_nodes[iter->parent_protocol];
}
return parent_found;
}