Linux内核中的NFC子系统
近场通信(NFC)子系统重点解决两个问题:
- 标准化NFC设备驱动程序开发
- 2.创建统一的用户空间接口
本文档涵盖架构概述、设备驱动程序接口描述和用户空间接口描述。
架构概述
NFC子系统主要负责以下工作内容:
- NFC适配器管理;
- 轮询目标;
- 低级(Low-Level)数据交换;
如下图所示,core
一方面负责提供设备驱动程序接口,另一方面,它还负责提供控制操作和低级数据交换的接口。其中,控制操作可通过通用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协议集合
和操作回调集合
通知core
。 其中,必须实现的操作回调
如下:
-
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
套接字并调用connect
系统调用,并正确填充sockaddr_nfc
结构。所有信息均来自NFC_EVENT_TARGETS_FOUND netlink事件
。 由于目标可以支持多个NFC协议,因此用户必须告知它想要使用哪种协议。
在内部,connect
将导致对驱动程序的activate_target
调用。当套接字关闭时,目标被停用。
通过套接字交换的数据格式取决于NFC
协议。例如,当与MIFARE
标签通信时,交换的数据是MIFARE
命令及其响应。
第一个收到的包是对第一个发送的包的响应,依此类推。为了允许有效的“空”响应,接收到的每个数据都有1字节的NULL标头。