mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-14 00:37:21 +00:00
b5964b9795
Co-authored-by: Willy-JL <49810075+Willy-JL@users.noreply.github.com>
220 lines
10 KiB
C
220 lines
10 KiB
C
/**
|
|
* @file nfc_protocol.h
|
|
* @brief Top-level NFC protocol definitions.
|
|
*
|
|
* This file is to be modified upon adding a new protocol (see below).
|
|
*
|
|
* # How to add a new NFC protocol
|
|
*
|
|
* ## 1. Gather information
|
|
*
|
|
* Having proper protocol documentation would be ideal, although they are often available only for a fee, or given under an NDA.
|
|
* As an alternative, reading code from relevant open-source projects or notes gathered by means of reverse engineering will do.
|
|
*
|
|
* ### 1.1 Technology
|
|
*
|
|
* Check whether the NFC technology required for the protocol is supported. If no support exists, adding the protocol may
|
|
* be problematic, since it is highly hardware-dependent.
|
|
*
|
|
* @see NfcTech for the enumeration of supported NFC technologies.
|
|
*
|
|
* ### 1.2 Base protocols
|
|
*
|
|
* Check whether the protocol to be implemented is built on top of some already supported protocol.
|
|
*
|
|
* @see NfcProtocol for the enumeration of supported NFC protocols.
|
|
*
|
|
* If the answer is "yes", then the protocol to be implemented is a child protocol. If no, then it will become a base protocol.
|
|
* Sometimes it will be necessary to implement both, e.g. when the target protocol is built on top of a base one,
|
|
* but the latter is currently not supported.
|
|
*
|
|
* ## 2. Create the files
|
|
*
|
|
* ### 2.1 Recommended file structure
|
|
*
|
|
* The recommended file structure for a protocol is as follows:
|
|
*
|
|
* ```text
|
|
* protocols
|
|
* |
|
|
* +- protocol_name
|
|
* |
|
|
* +- protocol_name.h
|
|
* |
|
|
* +- protocol_name.c
|
|
* |
|
|
* +- protocol_name_device_defs.h
|
|
* |
|
|
* +- protocol_name_poller.h
|
|
* |
|
|
* +- protocol_name_poller.c
|
|
* |
|
|
* +- protocol_name_poller_defs.h
|
|
* |
|
|
* .
|
|
* . (files below are optional)
|
|
* .
|
|
* |
|
|
* +- protocol_name_listener.h |
|
|
* | |
|
|
* +- protocol_name_listener.c |- add for emulation support
|
|
* | |
|
|
* +- protocol_name_listener_defs.h |
|
|
* |
|
|
* +- protocol_name_sync.h |
|
|
* | |- add for synchronous API support
|
|
* +- protocol_name_sync.c |
|
|
* |
|
|
* ```
|
|
*
|
|
* Additionally, an arbitrary amount of private `protocol_name_*_i.h` header files may be created. Do not put implementation
|
|
* details in the regular header files, as they will be exposed in the public firmware API later on.
|
|
*
|
|
* ### 2.2 File structure explanation
|
|
*
|
|
* | Filename | Explanation |
|
|
* |:------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|
|
|
* | protocol_name.h | Main protocol data structure and associated functions declarations. It is recommended to keep the former as opaque pointer. |
|
|
* | protocol_name.c | Implementations of functions declared in `protocol_name.h`. |
|
|
* | protocol_name_device_defs.h | Declarations for use by the NfcDevice library. See nfc_device_base_i.h for more info. |
|
|
* | protocol_name_poller.h | Protocol-specific poller and associated functions declarations. |
|
|
* | protocol_name_poller.c | Implementation of functions declared in `protocol_name_poller.h`. |
|
|
* | protocol_name_poller_defs.h | Declarations for use by the NfcPoller library. See nfc_poller_base.h for more info. |
|
|
* | protocol_name_listener.h | Protocol-specific listener and associated functions declarations. Optional, needed for emulation support. |
|
|
* | protocol_name_listener.c | Implementation of functions declared in `protocol_name_listener.h`. Optional, needed for emulation support. |
|
|
* | protocol_name_listener_defs.h | Declarations for use by the NfcListener library. See nfc_listener_base.h for more info. Optional, needed for emulation support. |
|
|
* | protocol_name_sync.h | Synchronous API declarations. (See below for sync API explanation). Optional. |
|
|
* | protocol_name_sync.c | Synchronous API implementation. Optional. |
|
|
*
|
|
* ## 3 Implement the code
|
|
*
|
|
* ### 3.1 Protocol data structure
|
|
*
|
|
* A protocol data structure is what holds all data that can be possibly read from a card of a certain type. It may include a unique identifier (UID),
|
|
* configuration bytes and flags, built-in memory, and so on.
|
|
* Additionally, it must implement the NfcDevice interface so that it could be used by the firmware.
|
|
*
|
|
* @see nfc_device_base_i.h for the device interface description.
|
|
*
|
|
* @note It is strongly recommended to implement such a structure as an opaque type and access it via specialised methods only.
|
|
*
|
|
* If the protocol being implemented is a child protocol, then its data must include a pointer to the parent protocol data structure.
|
|
* It is the protocol's responsibility to correctly create and delete the instance the pointer is pointing to.
|
|
*
|
|
* ### 3.2 Poller (reading functionality)
|
|
*
|
|
* A poller contains the functions necessary to successfully read a card of supported type. It must also implement a specific interface,
|
|
* namely described by the NfcPollerBase type.
|
|
*
|
|
* Upon creation, a poller instance will receive either a pointer to the Nfc instance (if it's a base protocol), or a pointer to another poller
|
|
* instance (if it is a child protocol) as the `alloc()` parameter.
|
|
*
|
|
* @see nfc_poller_base.h for the poller interface description.
|
|
*
|
|
* ### 3.3 Listener (emulation functionality)
|
|
*
|
|
* A listener implementation is optional, needed only when emulation is required/possible.
|
|
*
|
|
* Same considerations apply to the listener as for the poller. Additionally, upon creation it will receive an additional parameter
|
|
* in the form of a pointer to the matching protocol data structure, which will be used during emulation. The listener instance
|
|
* does not own this data and does not need to worry about its deletion.
|
|
*
|
|
* @see nfc_listener_base.h for the listener interface description.
|
|
*
|
|
* ### 3.4 Synchronous API
|
|
*
|
|
* Synchronous API does exaclty what it says -- it provides a set of blocking functions for easier use of pollers.
|
|
* Instead of creating all necessary instances and setting up callbacks manually, it does it automatically, at the
|
|
* expense of some flexibility.
|
|
*
|
|
* The most notable use of sync API is in the supported card plugins, so it's a good idea to implement it if such a plugin
|
|
* is to be implemented afterwards.
|
|
*
|
|
* ### 3.5 Registering the protocol
|
|
*
|
|
* After completing the protocol, it must be registered within the NfcProtocol system in order for it to be usable.
|
|
*
|
|
* 1. In nfc_protocol.h, add a new entry in the NfcProtocol enum in the form of NfcProtocolProtocolName.
|
|
* 2. In nfc_protocol.c, add a new entry in the `nfc_protocol_nodes[]` array under the appropriate index.
|
|
* 1. If it is a child protocol, register it as a child in the respective `nfc_base_protocol_name_children_protocol[]` array.
|
|
* 2. If the protocol has children on its own, create a `nfc_protocol_name_children_protocol[]` array
|
|
* with respective identifiers and register it in the protocol entry added in step 2.
|
|
* 3. In nfc_device_defs.c, include `protocol_name_device_defs.h` and add a pointer to the
|
|
* `protocol_name_device_defs` structure under the appropriate index.
|
|
* 4. In nfc_poller_defs.c, include `protocol_name_poller_defs.h` and add a pointer to the
|
|
* `protocol_name_poller_defs` structure under the appropriate index.
|
|
* 5. (Optional) If emulation support was implemented, do the step 4, but for the listener.
|
|
* 6. Add `protocol_name.h`, `protocol_name_poller.h`, and optionally, `protocol_name_listener.h`
|
|
* and `protocol_name_sync.h` into the `SDK_HEADERS` list in the SConscript file.
|
|
* This will export the protocol's types and functions for use by the applications.
|
|
* 7. Done!
|
|
*
|
|
* ## What's next?
|
|
*
|
|
* It's about time to integrate the newly implemented protocol into the main NFC application. Without that, reading a card
|
|
* of this type would crash it.
|
|
*
|
|
* @see nfc_protocol_support.h for more information on protocol integration.
|
|
*
|
|
* After having done that, a supported card plugin may be implemented to take further advantage of the new protocol.
|
|
*
|
|
* @see nfc_supported_card_plugin.h for more information on supported card plugins.
|
|
*
|
|
*/
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief Enumeration of all available NFC protocols.
|
|
*
|
|
* When implementing a new protocol, add its identifier before the
|
|
* NfcProtocolNum entry.
|
|
*/
|
|
typedef enum {
|
|
NfcProtocolIso14443_3a,
|
|
NfcProtocolIso14443_3b,
|
|
NfcProtocolIso14443_4a,
|
|
NfcProtocolIso14443_4b,
|
|
NfcProtocolIso15693_3,
|
|
NfcProtocolFelica,
|
|
NfcProtocolMfUltralight,
|
|
NfcProtocolMfClassic,
|
|
NfcProtocolMfDesfire,
|
|
NfcProtocolSlix,
|
|
NfcProtocolSt25tb,
|
|
NfcProtocolEmv,
|
|
/* Add new protocols here */
|
|
|
|
NfcProtocolNum, /**< Special value representing the number of available protocols. */
|
|
|
|
NfcProtocolInvalid, /**< Special value representing an invalid state. */
|
|
} NfcProtocol;
|
|
|
|
/**
|
|
* @brief Get the immediate parent of a specific protocol.
|
|
*
|
|
* @param[in] protocol identifier of the protocol in question.
|
|
* @returns parent protocol identifier if it has one, or NfcProtocolInvalid otherwise.
|
|
*/
|
|
NfcProtocol nfc_protocol_get_parent(NfcProtocol protocol);
|
|
|
|
/**
|
|
* @brief Determine if a specific protocol has a parent on an arbitrary level.
|
|
*
|
|
* Unlike nfc_protocol_get_parent(), this function will traverse the full protocol hierarchy
|
|
* and check each parent node for the matching protocol type.
|
|
*
|
|
* @param[in] protocol identifier of the protocol in question.
|
|
* @param[in] parent_protocol identifier of the parent protocol in question.
|
|
* @returns true if the parent of given type exists, false otherwise.
|
|
*/
|
|
bool nfc_protocol_has_parent(NfcProtocol protocol, NfcProtocol parent_protocol);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|