Flipper Zero Firmware
Loading...
Searching...
No Matches
nfc_protocol.h File Reference

Top-level NFC protocol definitions. More...

#include <stdbool.h>

Go to the source code of this file.

Enumerations

enum  NfcProtocol {
  NfcProtocolIso14443_3a , NfcProtocolIso14443_3b , NfcProtocolIso14443_4a , NfcProtocolIso14443_4b ,
  NfcProtocolIso15693_3 , NfcProtocolFelica , NfcProtocolMfUltralight , NfcProtocolMfClassic ,
  NfcProtocolMfPlus , NfcProtocolMfDesfire , NfcProtocolSlix , NfcProtocolSt25tb ,
  NfcProtocolNum , NfcProtocolInvalid
}
 Enumeration of all available NFC protocols. More...
 

Functions

NfcProtocol nfc_protocol_get_parent (NfcProtocol protocol)
 Get the immediate parent of a specific protocol.
 
bool nfc_protocol_has_parent (NfcProtocol protocol, NfcProtocol parent_protocol)
 Determine if a specific protocol has a parent on an arbitrary level.
 

Detailed Description

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 also
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 also
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:

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 also
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 also
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 also
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 also
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 also
nfc_supported_card_plugin.h for more information on supported card plugins.

Enumeration Type Documentation

◆ NfcProtocol

Enumeration of all available NFC protocols.

When implementing a new protocol, add its identifier before the NfcProtocolNum entry.

Enumerator
NfcProtocolNum 

Special value representing the number of available protocols.

NfcProtocolInvalid 

Special value representing an invalid state.

Function Documentation

◆ nfc_protocol_get_parent()

NfcProtocol nfc_protocol_get_parent ( NfcProtocol protocol)

Get the immediate parent of a specific protocol.

Parameters
[in]protocolidentifier of the protocol in question.
Returns
parent protocol identifier if it has one, or NfcProtocolInvalid otherwise.

◆ nfc_protocol_has_parent()

bool nfc_protocol_has_parent ( NfcProtocol protocol,
NfcProtocol parent_protocol )

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.

Parameters
[in]protocolidentifier of the protocol in question.
[in]parent_protocolidentifier of the parent protocol in question.
Returns
true if the parent of given type exists, false otherwise.