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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/709089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序 uniapp+vue实习助学岗位系统springboot/php/python/nodejs

(一)研究目标: 对于本微信小程序实习系统的设计来讲,主要是采用了java语言和mysql数据库来完成对系统的设计,根据某高校的实习系统,提出解决问题的一个可行性方法,可以在手机端就能完成我们的工…

十三、Qt多线程与线程安全

一、多线程程序 QThread类提供了管理线程的方法:一个对象管理一个线程一般从QThread继承一个自定义类,重载run函数 1、实现程序 (1)创建项目,基于QDialog (2)添加类,修改基于QThr…

网络工程师笔记5

TCP/IP 常见协议 应用层 Telnet 数据网络中提供远程登录服务的标准协议23FTP 传输文件协议21,20HTTP 超文本传输协议80TFTPSNMPSMTPDNSDHCP 传输层 TCPUDP 网络层 ICMPIGMPIP 数据链路层 PPPOE Internet PPP 传输层 传输层协议接收…

【重要公告】BSV区块链协会宣布将启动多项动态安全增强措施

​​发表时间:2024年2月16日 2024年2月16日,瑞士楚格 - BSV区块链协议的管理机构BSV区块链协会(以下简称“BSV协会”)宣布对其运营模式实施全新的安全架构,其中包括引入网络访问规则和数字资产找回协议,以及…

密码学在 Web3 钱包中的应用:私钥是什么?bitget钱包为例

在非对称加密演算法中,私钥是一串随机生成的数字,通常以十六进制数表示(也就是由0、1、2、3、4、5、6、7、8、9、a、b、c、d、e和f组成)。私钥生成后,这串数字被作为一个单向数学函数中的输入值,计算产生的…

YAML管理接口框架配置的最佳实践

管理接口框架配置是构建强大的接口测试框架的关键一环。良好的配置管理可以提高测试效率、可维护性和可扩展性。在本文中,我们将重点介绍使用YAML(YAML Ain’t Markup Language)来管理接口框架配置的最佳实践,并通过实例演示其用法…

第七十天 APP攻防-微信小程序解包反编译数据抓包APK信息资源提取

第70天 APP攻防-微信小程序&解包反编译&数据抓包&APK信息资源提取 知识点: 0、APK信息资源提取 1、微信小程序致据抓包 2、做信小程序解包反编译 1、信息收集应用8资产提取&权限等 2、漏润发现-反编泽&脱壳&代码审计 3、安全评估组件8散密…

ctfshow——反序列化

文章目录 web 254——啥也没web 255——反序列化对变量进行赋值(1)web 256——反序列化对变量进行赋值(2)web 257——对象注入web 258——对象注入(绕过preg_match)web 259 web 254——啥也没 这里就是使用GET传输,use…

SpringMVC02、什么是SpringMVC

2、什么是SpringMVC 2.1、概述 Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。 查看官方文档:Web on Servlet Stack 我们为什么要学习SpringMVC呢? Spring MVC的特点: 轻量级,简单易学高效 , 基…

(C语言)Sleep函数,system函数,数组练习,详解与运用

一维数组详解:http://t.csdnimg.cn/zahZF 二维数组详解:http://t.csdnimg.cn/h2mLe 我们看过可一维数组与二维数组,现在我们来进行简单的练习。 题目:编写代码,演⽰多个字符从两端移动,向中间汇聚 1. …

如何使用Windows系统电脑无公网ip远程桌面Ubuntu系统

文章目录 前言1. ubuntu安装VNC2. 设置vnc开机启动3. windows 安装VNC viewer连接工具4. 内网穿透4.1 安装cpolar【支持使用一键脚本命令安装】4.2 创建隧道映射4.3 测试公网远程访问 5. 配置固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址5.3 测试…

QT Widget: 自定义Widget组件及创建和使用动静态库

学习自定义Widget组件,书中的案例: // 自定义QmyBattery组件 // QmyBattery.c #include "qmybattery.h"QmyBattery::QmyBattery(QWidget *parent) : QWidget(parent) {}/** 1.QPainter的viewport()与window()分别代表着物理坐标与逻辑坐标区域…

Topaz DeNoise AI:一键让照片重获清晰 mac/win激活版

Topaz DeNoise AI是一款革命性的图片降噪软件,它利用先进的人工智能算法,帮助用户轻松去除照片中的噪点,恢复图像的清晰度和细节。无论是专业摄影师还是摄影爱好者,Topaz DeNoise AI都能成为他们处理图片时的得力助手。 Topaz De…

57.仿简道云公式函数实战-文本函数-REPT

1. REPT函数 将文本重复一定次数。 2. 函数用法 REPT(text, number_times) 3. 函数示例 将文本重复一定次数。 text: 必需。需要重复显示的文本。 Number_times: 必需。用于指定文本重复次数的正数。 4. 代码实战 首先我们在function包下创建text包,在text…

Win UI3开发笔记(四)设置主题续

上文讲到过关于界面和标题栏以及普通文本的主题设置,这篇说一下关于对话框的主题设置。 我最终没找到办法,寻求办法的朋友可以不用接着看了,以下只是过程。 一个对话框包括标题部分、内容部分和按钮部分,其中,在Cont…

ISP代理是什么?跨境账号养号为什么要选择它?

在跨境出海业务中,代理IP对于您的在线任务至关重要,尤其是对于那些运行多个帐户的人来说。为您的帐户选择正确类型的代理对于确保帐户安全非常重要,劣质的IP容易使账号遭受封号风险。IPFoxy的多种代理IP类型应用范围各有侧重,其中…

Android Stdio Execution failed for task ‘:app:compileDebugKotlin‘ 报错解决

具体报错信息如下: compileDebugJavaWithJavac task (current target is 1.8) and compileDebugKotlin task (current target is 17)jvm target compatibility should be set to the same Java version.很显然,这是一个版本冲突问题,compile…

字符函数和字符串函数(C语言进阶)(三)

目录 前言 接上篇: 1.7 strtok 1.8 strerror 1.9 字符分类函数 总结 前言 C语言中对字符和字符串的处理是很频繁的,但是c语言本身是没有字符串类型的,字符串通常放在常量字符串中或着字符数组中。 字符串常量适用于那些对它不做修改的字…

安卓开发1- android stdio环境搭建

安卓开发1-android stdio环境搭建 Jdk环境搭建 1. 准备Jdk,这边已经准备好了jdk1.8.0,该文件直接使用即可 2. 系统变量添加 %JAVA_HOME%\bin JAVA_HOME 3. 系统变量,Path路径添加 4. 添加完成后,输入命令javac / java -version,验证环…

Java多线程算法总结

1. 标题三个线程同时运行,依次打印ABC,一共打印10次 算法代码如下: public class ThreadTest {private Object oa new Object();private Object ob new Object();private Object oc new Object();private static final String TAG &quo…