linux_libnfc-nci

repository·master·Indexed 41 days ago

https://github.com/nxpnfclinux/linux_libnfc-nci

A Linux-based NFC stack optimized for NXP NCI-based NFC controllers, such as the PN7150 and PN7120. It supports Tag interaction, Peer-to-Peer (SNEP), and Host Card Emulation (HCE) modes, providing APIs for NDEF data exchange and raw transceive operations.

Tokens
5.2K
Snippets
21
Records
28
Agent score
52%

What's inside libnfc-nci

  1. How the NFC configuration loading works

    master

    The NFC adaptation layer uses a singleton CNfcConfig to manage settings. It searches for configuration files in a specific order of precedence:

    1. Primary Config: It first attempts to load libnfc-nci.conf from the path defined by CONFIG_PATH (the alternative_config_path).
    2. Secondary Config: If the primary file is not found or empty, it attempts to load libnfc-nci.conf from /etc/ (the transport_config_path).

    Configuration File Format: Settings are defined in a key=value format. Supported value types include:

    • Strings: Enclosed in double quotes (e.g., KEY="VALUE").
    • Decimals: Standard base-10 numbers (e.g., KEY=123).
    • Hexadecimal: Prefixed with 0x (e.g., KEY=0xAB).
    • Hex-encoded Strings: Using curly braces {} to represent raw byte sequences (e.g., KEY={0xDE, 0xAD, 0xBE, 0xEF}).

    Comments are supported using the # character.

  2. NXP Configuration File Formats and Paths

    master

    The NXP configuration system uses .conf files. The files are named using the pattern libnfc-nxp-[type].conf where [type] is init, pn547, or pn548.

    Search Order:

    1. The system first looks in the alternative_config_path (e.g., /data/nfc/ on generic targets or a defined CONFIG_PATH).
    2. If not found, it looks in the transport_config_path (e.g., /etc/).

    File Syntax:

    • Comments: Lines starting with # are ignored.
    • Key-Value Pairs: key = value
    • String Values: Enclosed in double quotes: key = "value"
    • Hexadecimal/Numeric Values: Supports standard numbers and hex notation (e.g., 0x1234).
    • Hex-encoded Byte Arrays: Can be represented using {} syntax (e.g., {0xDE, 0xAD, 0xBE, 0xEF}).
  3. Cleanup and Deinitialize NFC Services

    master

    To release resources and stop NFC polling, you should deregister all callbacks and disable discovery. The following sequence is recommended:

    1. Stop the SNEP server: nfcSnep_stopServer().
    2. Disable discovery: nfcManager_disableDiscovery().
    3. Deregister all callbacks:
      • nfcSnep_deregisterClientCallback()
      • nfcManager_deregisterTagCallback()
      • nfcHce_deregisterHceCallback()
  4. Use the NFC demo application modes

    master

    The demo application provides four primary operational modes via CLI arguments:

    1. poll: Activates polling mode to scan for nearby NFC tags.
      • Command: nfcDemoApp poll
    2. write: Activates write mode to write NDEF data to a tag.
      • Command: nfcDemoApp write --type=Text -l en -r "Test"
    3. push: Activates push mode to send NDEF data to a P2P device.
      • Command: nfcDemoApp push -t URI -u http://www.nxp.com
      • Command (MIME): nfcDemoApp push --type=mime -m "application/vnd.bluetooth.ep.oob" -d "2200AC597405AF1C0E0947616C617879204E6F74652033040D0C024005031E110B11"
    4. share: Activates Tag Emulation (HCE) mode to emulate a tag.
      • Command: nfcDemoApp share -t URI -u http://www.nxp.com
  5. Initialize the NFC Service and Discovery

    master

    To start using the NFC stack, you must first initialize the NFC manager and then enable discovery for the desired technologies. You can configure the service to operate in Tag, P2P (SNEP), or HCE (Host Card Emulation) modes.

    Key steps:

    1. Call nfcManager_doInitialize() to start the service.
    2. Register callbacks for the specific modes you intend to use (Tag, SNEP Client, or HCE).
    3. Call nfcManager_enableDiscovery() with a technology mask to begin polling for NFC devices.
    // Example initialization sequence
    res = nfcManager_doInitialize();
    if(0x00 == res) {
        // Register Tag callbacks
        nfcManager_registerTagCallback(&g_TagCB);
        
        // Register SNEP Client callbacks
        nfcSnep_registerClientCallback(&g_SnepClientCB);
        
        // Register HCE callbacks
        nfcHce_registerHceCallback(&g_HceCB);
    
        // Enable discovery (hce is passed as a parameter to enable HCE mode)
        nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 0x00, hce_enabled, 0);
        
        // Start SNEP Server if P2P is required
        if(p2p_enabled) {
            nfcSnep_startServer(&g_SnepServerCB);
        }
    }
  6. Register Host Card Emulation (HCE) Callbacks

    master

    To use the device as an NFC tag (Host Card Emulation), register a nfc_host_card_emulation_callback_t structure using nfcHce_registerHceCallback. This allows your application to respond to reader interactions.

    Required callback members:

    • onDataReceived: Triggered when the NFC reader sends data to the emulated card.
    • onHostCardEmulationActivated: Triggered when HCE mode is activated by a reader.
    • onHostCardEmulationDeactivated: Triggered when the reader interaction ends.
    // Define the callback structure
    nfc_host_card_emulation_callback_t g_HceCB;
    
    // Assign functions
    g_HceCB.onDataReceived = my_on_hce_data;
    g_HceCB.onHostCardEmulationActivated = my_on_hce_activated;
    g_HceCB.onHostCardEmulationDeactivated = my_on_hce_deactivated;
    
    // Register with the HCE module
    nfcHce_registerHceCallback(&g_HceCB);
  7. Retrieve configuration numerical values with GetNumValue

    master

    Use the GetNumValue C API to retrieve numerical settings (unsigned long, unsigned short, or unsigned char) from the configuration files.

    Parameters:

    • name: The name of the configuration parameter.
    • pValue: A pointer to the memory where the value should be stored.
    • len: The size of the memory pointed to by pValue (must match the size of the type you are requesting).

    Supported Types (based on len):

    • sizeof(unsigned long)
    • sizeof(unsigned short)
    • sizeof(unsigned char)

    Returns:

    • true (non-zero) on success.
    • false (0) if the parameter is not found or the requested length is invalid.
    unsigned long val;
    if (GetNumValue("NXP_SOME_NUMERIC_SETTING", &val, sizeof(unsigned long))) {
        // Success: val contains the value
    }
  8. Perform raw transceive with nfcTag_transceive()

    master

    For specific tag types like TARGET_TYPE_MIFARE_CLASSIC or TARGET_TYPE_MIFARE_UL, you can use nfcTag_transceive to send custom command buffers and receive responses. This is useful for low-level authentication or reading specific blocks that are not part of the standard NDEF structure.

    res = nfcTag_transceive(TagInfo.handle, MifareAuthCmd, 12, MifareAuthResp, 255, 500);
  9. Retrieve NXP configuration numerical values

    master

    Use GetNxpNumValue to retrieve a numerical setting. The function supports different output types based on the len parameter provided. It can handle standard decimal numbers or hex-encoded strings that represent byte sequences.

    Supported len values for pValue:

    • sizeof(unsigned long)
    • sizeof(unsigned short)
    • sizeof(unsigned char)
    // Returns 1 if successful, 0 otherwise
    int GetNxpNumValue(const char* name, void* pValue, unsigned long len);