Linux NFC 子系统

近场通信 (NFC) 子系统用于标准化 NFC 设备驱动程序的开发,并创建一个统一的用户空间接口。

本文档涵盖了架构概述、设备驱动程序接口描述和用户空间接口描述。

架构概述

NFC 子系统负责:
  • NFC 适配器管理;

  • 轮询目标;

  • 低级数据交换;

该子系统分为几个部分。“核心”负责提供设备驱动程序接口。另一方面,它还负责提供用于控制操作和低级数据交换的接口。

控制操作可通过通用 netlink 提供给用户空间。

低级数据交换接口由新的套接字系列 PF_NFC 提供。NFC_SOCKPROTO_RAW 执行与 NFC 目标的原始通信。

+--------------------------------------+
|              USER SPACE              |
+--------------------------------------+
    ^                       ^
    | low-level             | control
    | data exchange         | operations
    |                       |
    |                       v
    |                  +-----------+
    | AF_NFC           |  netlink  |
    | socket           +-----------+
    | raw                   ^
    |                       |
    v                       v
+---------+            +-----------+
| rawsock | <--------> |   core    |
+---------+            +-----------+
                            ^
                            |
                            v
                       +-----------+
                       |  driver   |
                       +-----------+

设备驱动程序接口

在 NFC 子系统上注册时,设备驱动程序必须将支持的 NFC 协议集和 ops 回调集告知核心。必须实现的 ops 回调如下:

  • start_poll - 设置设备以轮询目标

  • stop_poll - 停止正在进行的轮询操作

  • activate_target - 选择并初始化找到的目标之一

  • deactivate_target - 取消选择并取消初始化选定的目标

  • data_exchange - 发送数据并接收响应(收发操作)

用户空间接口

用户空间接口分为控制操作和低级数据交换操作。

控制操作

通用 netlink 用于实现控制操作的接口。这些操作由命令和事件组成,所有这些都列在下面:

  • NFC_CMD_GET_DEVICE - 获取特定设备信息或转储设备列表

  • NFC_CMD_START_POLL - 设置特定设备以轮询目标

  • NFC_CMD_STOP_POLL - 停止特定设备中的轮询操作

  • NFC_CMD_GET_TARGET - 转储特定设备找到的目标列表

  • NFC_EVENT_DEVICE_ADDED - 报告 NFC 设备添加

  • NFC_EVENT_DEVICE_REMOVED - 报告 NFC 设备移除

  • NFC_EVENT_TARGETS_FOUND - 当找到 1 个或多个目标时报告 START_POLL 结果

用户必须调用 START_POLL 来轮询 NFC 目标,并通过 NFC_ATTR_PROTOCOLS 属性传递所需的 NFC 协议。设备将保持轮询状态,直到找到任何目标。但是,用户可以通过调用 STOP_POLL 命令来停止轮询操作。在这种情况下,将检查 STOP_POLL 的请求者是否与 START_POLL 的请求者相同。

如果轮询操作找到一个或多个目标,则会发送 TARGETS_FOUND 事件(包括设备 ID)。用户必须调用 GET_TARGET 来获取此设备找到的所有目标的列表。每个回复消息都具有目标属性,其中包含相关信息,例如支持的 NFC 协议。

通过一个 netlink 套接字请求的所有轮询操作在其关闭时都会停止。

低级数据交换

用户空间必须使用 PF_NFC 套接字来执行与目标的任何数据通信。所有 NFC 套接字都使用 AF_NFC

struct sockaddr_nfc {
       sa_family_t sa_family;
       __u32 dev_idx;
       __u32 target_idx;
       __u32 nfc_protocol;
};

要与一个目标建立连接,用户必须创建一个 NFC_SOCKPROTO_RAW 套接字,并使用正确填充的 sockaddr_nfc 结构调用“connect”系统调用。所有信息都来自 NFC_EVENT_TARGETS_FOUND netlink 事件。由于一个目标可以支持多个 NFC 协议,因此用户必须告知要使用哪个协议。

在内部,“connect”将导致对驱动程序进行 activate_target 调用。当套接字关闭时,目标将被停用。

通过套接字交换的数据格式与 NFC 协议相关。例如,在与 MIFARE 标签通信时,交换的数据是 MIFARE 命令及其响应。

第一个接收到的包是对第一个发送的包的响应,依此类推。为了允许有效的“空”响应,每个接收到的数据都有一个 1 字节的 NULL 标头。