Linux NFC 子系统剖析

2024-02-29 15:52
文章标签 linux 剖析 nfc 子系统

本文主要是介绍Linux NFC 子系统剖析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.总览

linux源码中NFC在net/nfc下,文件结构如下图:

hci:Host Controller Interface

主要是针对NFC的主机-控制器接口协议

 nci:NFC Controller Interface

主要是NFC的控制器接口协议,用于NFCC(NFC Controller)和DH(Device Host)之间

core.c:

NFC子系统的核心,NFC整个协议栈从这里加载到内核中

af_nfc.c:Address Family

注册NFC协议族

digital_core.c、digital_dep.c、digital_technology.c:

NFC数字协议(NFC Digital Protocol)的协议栈实现

llcp_core.c、llcp_sock.c、llcp_commands.c:

NFC的逻辑链路控制协议(Logical Link Control Protocol)实现

netlink.c:

NFC的Generic netlink相关实现

rawsock.c:

NFC的raw sock相关实现

它们分别在NFC系统中实现了哪些功能?请看下图:

NFC驱动开发:

最底层一共三种方式:

1.直接通过NFC核心驱动框架开发

2.通过HCI接口驱动框架开发

3.通过NCI接口驱动框架开发

这三种方式最终还是通过核心驱动框架与应用层通信,通信的方式有generic netlink、rawsock。如果是llcp,那还会通过rawsock_llcp与应用层交互。

其中generic netlink主要是交互一些命令与事件,比如应用层向驱动层发送开始寻卡命令,寻找到卡后,驱动层会发送寻找到目标的事件。而rawsock主要是数据交互,比如向卡内写数据、读取卡内数据等。

NFC的应用开发:

1.通过dbus获取NFC相关事件

2.通过AF_NFC Sockets与内核交互数据

3.通过Neard AL与驱动层交互(本质还是generic netlink)

其实由驱动也可以看出来,Neard作为应用层的一个守护进程并不是必须的。

2.代码分析

nfc_init

nfc协议栈的起点是 nfc_init 函数,它被subsys_initcall调用后加载。

这个函数包含了nfc协议栈的所有初始化:

nfc类的注册不再赘述,注册成功后会有/sys/class/nfc目录。

nfc_genl_init

nfc_genl_init用来注册nfc的netlink接口:

这中间最重要的是变量 nfc_genl_family ,它包含了使用netlink实现的功能。它包含了两个最重要的元素:

其中name是用来匹配此协议簇,当我们在应用层与之匹配时,需要指明name是nfc,这样就能匹配成功。其次就是匹配成功后该协议簇所支持的一系列操作:

这些操作对应了我们驱动需要实现的功能。在内核有关nfc subsystem的说明文档中有提到:

也就是start_poll 、stop_poll 、activate_target 、deactivate_target 、data_exchange 这些操作是nfc子系统必须实现的,它们的含义:

start_poll :启动设备开始轮询目标

stop_poll :停止轮询操作

activate_target :选择和初始化其中一个发现的目标

deactivate_target :取消选择和恢复初始化目标

data_exchange :发送数据和接收应答

而这些我们需要实现的操作都被 nfc_genl_ops 中不同指令所对应的操作调用。比如start_poll:

上图中的info会由应用层指定,主要就是确定是哪个发起者开始轮询,毕竟系统中可能存在多个发起者。真正的启动轮询函数如下:

上图中的ops是重点,我们编写的驱动中实现的start_poll在这里被调用。对ops的赋值在函数 nfc_allocate_device 中,从函数名也可以看出是用来申请nfc device的,我们的驱动中需要使用此函数申请nfc_dev设备,申请的时候必须传入ops操作合集:

根据上述描述我们已经了解了用户层是如何通过generic netlink的CMD来操作不同设备寻卡、激活卡的,那寻找到卡后怎么通知到应用层?该调用哪些API呢?

很简单在include/uapi/linux/nfc.h中有枚举类型 nfc_commands ,里面包含了所有genl的CMD和事件,我们在net/nfc/netlink.c中搜索 NFC_EVENT_ 前缀的宏定义即可找到对应的函数,比如添加了一个device:

可以看到这个函数主要功能就是广播一条内容为 NFC_EVENT_DEVICE_ADDED 的事件,这个函数只在 nfc_register_device 函数中被调用,所以申请完nfc device后,我们还要调用这个函数注册设备。

所以我们只需要关注我们需要发送哪些事件,即可知道需要调用哪几个函数:

Tips--这里解释一些缩写: 

TM:Target mode

LLC:Logic Link Control,逻辑链路控制,用于P2P模式

SE:Secure Element,安全单元,通常用于CE模式

rawsock_init

该函数用于注册新协议注册。

不用关心如何注册,我们只需要关注下面的变量:

这中间最重要的是 rawsock_ops 和 rawsock_raw_ops 操作函数合集。

当应用层使用下面的操作创建sock时:

socket(AF_NFC, SOCK_SEQPACKET, NFC_SOCKPROTO_RAW)

对应的各个操作函数就是 rawsock_ops了。然后通信的时候先connect,再send/recv。在connect的时候,根据传入的addr中的设备ID和目标ID,确定通过哪个发起者和哪张卡通信。

其中发送函数先把需要发送的数据放在队列里,然后使用tx工作队列:

在创建rawsock的时候,指定了tx_work的执行函数:

传输的关键就在于nfc_data_exchange 函数:

上述 im_transceive 函数也是注册nfc_dev的时候传入的操作函数。 

特定名词

NFC(Near Filed Communication) 近场通信

R/W MOD 读写模式

CE MOD(Card Emulation Mod) 卡仿真模式

P2P MOD 点对点模式

PCD(VCD) 近(疏)耦合设备

PICC(VICC) 近(疏)IC卡

LLCP 逻辑链路控制协议

RF 射频

RFID 设备识别

NDEP NFC数据交换协议

NFCIP NFC接口和协议

NDEF NFC数据交换格式

DEP 数据交换协议

SNEP 简单NDEF交换协议

CHP(Connection Handover Protocol) 连接切换协议

WUPA 唤醒A类卡

ATQ 对请求的应答

ATQA 对A型卡请求的应答

ATQB 对B型卡请求的应答

ATR 对重新启动的请求的应答

ATS 对选择请求的应答

ATQ-ID 对ID号请求的应答

CRC 环检验码

RATS 对选择应答请求

PPS 协议和参数的选择

REQA 对A型卡的请求

REQB 对B型卡的请求

REQ-ID 请求ID号

RESEL 重新选择的请求

文章推荐:

LINUX NFC SUBSYSTM | SVEN

http://t.csdnimg.cn/zN4a2

这篇关于Linux NFC 子系统剖析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/759313

相关文章

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的

Linux编译器--gcc/g++使用方式

《Linux编译器--gcc/g++使用方式》文章主要介绍了C/C++程序的编译过程,包括预编译、编译、汇编和链接四个阶段,并详细解释了每个阶段的作用和具体操作,同时,还介绍了调试和发布版本的概念... 目录一、预编译指令1.1预处理功能1.2指令1.3问题扩展二、编译(生成汇编)三、汇编(生成二进制机器语

Rsnapshot怎么用? 基于Rsync的强大Linux备份工具使用指南

《Rsnapshot怎么用?基于Rsync的强大Linux备份工具使用指南》Rsnapshot不仅可以备份本地文件,还能通过SSH备份远程文件,接下来详细介绍如何安装、配置和使用Rsnaps... Rsnapshot 是一款开源的文件系统快照工具。它结合了 Rsync 和 SSH 的能力,可以帮助你在 li

Linux部署jar包过程

《Linux部署jar包过程》文章介绍了在Linux系统上部署Java(jar)包时需要注意的几个关键点,包括统一JDK版本、添加打包插件、修改数据库密码以及正确执行jar包的方法... 目录linux部署jar包1.统一jdk版本2.打包插件依赖3.修改密码4.执行jar包总结Linux部署jar包部署