NFC功能介绍

NFC 目前使用的三种功能:

1. P2P模式:基于LLCP协议的基础上,以NDEF数据交换格式来通信。

2. 读写模式:当作为读卡器,对NFC Tag的读写。

3. 卡模拟模式:模块成卡,可以与读卡器(或pos机)进行数据通信。

移植过程

驱动移植:

kernel-3.10/drivers/misc/mediatek/nfc/nxp

Framework移植:

1. 增加 packages/apps/Nfc-nxp

2. 增加 vendor/NXP/device

3. 更改 hardware/libhardware/include/hardware/nfc.h

4. 增加 frameworks/base/gsma-extras/java/com/android/nfcgsma_extras/NfcAdapterGsmaExtras.java

5. 增加 frameworks/base/core/java/com/vzw

6. 增加 frameworks/base/core/java/com/nxp

7. 更改替换 frameworks/base/core/java/android/nfc

8. 更改替换 frameworks/base/Android.mk

9. 增加 external/libp61-jcop-kit

10.增加 external/libnfc-nci-nxp

11.增加 external/dta

12. 更改 device/mediatek/common/device.mk (增加对 vendor/NXP/device/device-NXP.mk 的编译选项)

NFC 启动过程

相关服务的启动

1. NfcService 在开机时 自动启动的。

Packages/app/Nfc-nxp/AndroidManifest.xml

     <application android:name=".NfcApplication"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.Material.Light"
android:persistent="true"

NfcApplication 会在Android SystemReady 时启动,从而会把NfcService 这个服务启动起来。

    public NfcService(Application nfcApplication) {
mUserId = ActivityManager.getCurrentUser();
mContext = nfcApplication; mNfcTagService = new TagService();
mNfcAdapter = new NfcAdapterService();
mNxpNfcAdapter = new NxpNfcAdapterService();
mExtrasService = new NfcAdapterExtrasService();
mNxpExtrasService = new NxpNfcAdapterExtrasService();

TagService 是对Tag的读写服务

NfcAdapterService 是 NfcAdapter 的远端服务。对NFC功能的操作的服务(包括打开,关闭,设置工作模式等)。

NxpNfcAdapterService 是NXP Ic 控制和设置的服务。有 获取控制的接口,选择路由,设置配置参数,还有对ese的访问等。

NfcAdapterExtraService 是卡模拟功能的服务。打开关闭卡模拟,获取,设置卡模拟路由。

NxpNfcAdapterExtrasService 是 ese 安全功能的服务。获取,指定安全访问路由。

NfcService初始化的时序图:

 NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
theInstance.Initialize(); //start GKI, NCI task, NFC task
创建NCI task 线程和 NFC task 线程 NFA_Init (halFuncEntries);
stat = NFA_Enable (nfaDeviceManagementCallback, nfaConnectionCallback); SecureElement::getInstance().initialize (getNative(e, o));
//setListenMode();
RoutingManager::getInstance().initialize(getNative(e, o));
HciRFParams::getInstance().initialize ();
sIsSecElemSelected = (SecureElement::getInstance().getActualNumEe() - 1 );
sIsSecElemDetected = sIsSecElemSelected;
nativeNfcTag_registerNdefTypeHandler ();
NfcTag::getInstance().initialize (getNative(e, o));
PeerToPeer::getInstance().initialize ();
PeerToPeer::getInstance().handleNfcOnOff (true);

这里面基本都是NXP 硬件 和 HAL层的初始化。重点看看 NfcAdaptation Initialize()

 void NfcAdaptation::Initialize ()
{
..........................................................
InitializeHalDeviceContext ();
.........................................................
}

继续看 InitializeHalDeviceContext()

 void NfcAdaptation::InitializeHalDeviceContext (){
….........................................................
ret = hw_get_module (nci_hal_module, &hw_module);
if (ret == )
{
ret = nfc_nci_open (hw_module, &mHalDeviceContext);
if (ret != )
ALOGE ("%s: nfc_nci_open fail", func);
}
}

这一块就对NFC HAL 做了初始化了,我们再继续往下跟会发现创建了两个线程,一个读线程,一个写线程:

 /* Create Reader and Writer threads */
pthread_create_status = pthread_create(&gpphTmlNfc_Context->readerThread,NULL,(void *)&phTmlNfc_TmlThread,
(void *)h_threadsEvent);
if( != pthread_create_status)
{
wStartStatus = NFCSTATUS_FAILED;
}
else
{
/*Start Writer Thread*/
pthread_create_status = pthread_create(&gpphTmlNfc_Context->writerThread,NULL,(void *)&phTmlNfc_TmlWriterThread, (void *)h_threadsEvent);
if( != pthread_create_status)
{
wStartStatus = NFCSTATUS_FAILED;
}
}

读线程调用select 对 设备节点/dev/pn544做了监听挂起, 有nfc 检测到有设备 中断上来时,会将数据写往此设备节点,此时监听线程 检测到有数据写入时,会唤醒线程来读出写入的数据。

 ret_Select = select((int)((intptr_t)pDevHandle + (int)), &rfds, NULL, NULL, &tv);
if (ret_Select < )
{
NXPLOG_TML_E("i2c select() errno : %x",errno);
return -;
}
else if (ret_Select == )
{
NXPLOG_TML_E("i2c select() Timeout");
return -;
}
else
{
ret_Read = read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead – numRead);

TAG的读写

当有TAG靠近手机NFC读写区域,驱动中会触发中断,把读到数据写入到设备节点中,i2c读线程会唤醒,读到数据后,将数据封装好,回调指定的回调函数,将数据和消息类型封装成一个消息,然后发送消息任务线程去处理,再回调指定的监听。

从jni中 NativeNfcManager.cpp 中 通过NotifyNdefMessageListeners回调到 NativeNfcManager.java中,再通过OnRemoteEndPointDiscovered回传到NfcService中. NfcSevice 再做Dispatch分发,将NDEF 消息格式解析中,再根据类型,找到最合适的Activity 来启动。

看看 NDEF 的格式:

Bundle extras = tag.getTechExtras(TagTechnology.NDEF);

if (extras != null) {

mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);

mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE);

mNdefMsg = extras.getParcelable(EXTRA_NDEF_MSG);

mNdefType = extras.getInt(EXTRA_NDEF_TYPE);

}

P2P功能的send

看看时序图:

当两上机器靠近时,中断来了,驱动就会往/dev/pn544设备中写数据,从而唤醒i2c_reader 线程,从而根据报来的消息类型,会调用NativeNfcManager 去处理此类型消息,然后notifyLlcpLinkActivation, 告诉NativeNfcManager有P2P的消息来了,并且回调NfcService的onLlcpLinkActivated。NfcService 会把此消息交给NfcServiceHandler来处理,此时会调用P2PLinkManager的onLlcpActivated。然后 会调用P2pEventManager的onP2pSendConfirmationRequested来确认是否p2pSend。 这个P2PEventManager 会调用SendUi 里的 showPreSend. 这个sendUi就在界面上做UI处理了(这个是一个传界面的UI,还有一个fileSendUi 专用于传文件的UI显示,根据当前界面为判断用哪种UI来显示),就是我们看到缩小的界面图了。这个showPreSend 其实做了一个截屏的操作,然后加上了一个动画,让其缩小,并提示“触摸即可传输”。当我们点击屏幕,就是调用onTouch事件了, sendUi 显示一个动画,然后就是sendNdefMessage。

我们再来看看 sendNdefMessage的过程:

最后就是通过 SnepClient 通过SnepMessager 将消息发送出来。SnepClient 其实就是在sendNdefMessage之间就有个connect的操作, 这个connect就是创建了一个socket 去连接服务端的socket。sendMessage 就是通过socket 把这个给消息给发过去。

当然根据传的东西不同,如果传的文件,歌曲,图片,我们会启动 wifiDirect去传输。Android原生会调用蓝牙来传输。

P2P功能的接收

我们先看一下接收一个时序图:

P2P的接收就简单说明下,NfcService 启动的时候,会实例化P2PLinkManager, 同时 P2PLinkManager会实例化一个SnepServer (这时候应该想到send过程中的SnepClient),会开启两个进程,一个是Socket进程,就是会监听接收客户端的sockek连接。 另一个就是ConnectionThread,用于将连接到messager 处理,会回调 P2PLinkManager 的doGet 和 doPut.. 这时就成功能将Ndef的消息获取到了。之后的流程就与TAG的读过程差不多了,解析Message, 然后dispatcher, 启动对应的Activity.

NXP NFC移植及学习笔记(原创)的更多相关文章

  1. jz2440-linux3.4.2-kernel移植【学习笔记】【原创】

    平台:jz2440 作者:庄泽彬(欢迎转载,请注明作者) 说明:韦东山二期视频学习笔记 交叉编译工具:arm-linux-gcc (GCC)4.3.2 linux:linu3.4.2 PC环境:ubu ...

  2. jz2440-uboot-201204版本移植【学习笔记】【原创】

    平台:jz2440 作者:庄泽彬(欢迎转载,请注明作者) 说明:韦东山二期视频学习笔记 交叉编译工具:arm-linux-gcc (GCC)4.3.2 PC环境:ubuntu18.04 一.uboot ...

  3. MongoDB 学习笔记(原创)

    MongoDB 学习笔记 mongodb 数据库 nosql 一.数据库的基本概念及操作 SQL术语/概念 MongoDB术语/概念 解释/说明 database database 数据库 table ...

  4. Angular源代码学习笔记-原创

    时间:2014年12月15日 14:15:10 /** * @license AngularJS v1.3.0-beta.15 * (c) 2010-2014 Google, Inc. http:// ...

  5. Python爬虫框架Scrapy学习笔记原创

     字号 scrapy [TOC] 开始 scrapy安装 首先手动安装windows版本的Twisted https://www.lfd.uci.edu/~gohlke/pythonlibs/#twi ...

  6. LwIP学习笔记——STM32 ENC28J60移植与入门

    0.前言     去年(2013年)的整理了LwIP相关代码,并在STM32上"裸奔"成功.一直没有时间深入整理,在这里借博文整理总结.LwIP的移植过程细节很多,博文也不可能一一 ...

  7. ucos实时操作系统学习笔记——操作系统在STM32的移植

    使用ucos实时操作系统是在上学的时候,导师科研项目中.那时候就是网上找到操作系统移植教程以及应用教程依葫芦画瓢,功能实现也就罢了,没有很深入的去研究过这个东西.后来工作了,闲来无聊就研究了一下这个只 ...

  8. [原创]java WEB学习笔记95:Hibernate 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  9. [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

随机推荐

  1. neo4j初次使用学习简单操作-cypher语言使用

    Neo4j 使用cypher语言进行操作 Cypher语言是在学习Neo4j时用到数据库操作语言(DML),涵盖对图数据的增删改查  neo4j数据库简单除暴理解的概念: Neo4j中不存在表的概念, ...

  2. 关于闭包(closure)的一些概念

    和其他大多数现代编程语言一样,JS也采用词法作用域,也就是说,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的.为了实现这种词法作用域,JS函数对象的内部状态不仅包含 ...

  3. Bzoj3041 水叮当的舞步

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 132  Solved: 75 Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物 ...

  4. LVM逻辑卷管理命令

    显示分区信息: [root@localhost /]# fdisk -l PV:物理硬盘格式化为物理卷(PV): [root@localhost /]# pvcreate /dev/sdb /dev/ ...

  5. (function($){...}) (jQuery)

    这里实际上是匿名函数 function(arg){...}这就定义了一个匿名函数,参数为arg 而调用函数 时,是在函数后面写上括号和实参的,由于操作符的优先级,函数本身也需要用括号,即:(funct ...

  6. sql 批量插入数据到Sqlserver中 效率较高的方法

    使用SqlBulk #region 方式二 static void InsertTwo() { Console.WriteLine("使用Bulk插入的实现方式"); Stopwa ...

  7. Nexus安装配置

    一.下载最新版本的nexus 1.下载地址:http://www.sonatype.org/nexus/go 2.官网如果下载不了,就找个zip下载,我下载的是:nexus-2.10.0-02-bun ...

  8. 简洁的div翻转案例

    <!DOCTYPE html> <html > <head> <title>test</title> <meta http-equiv ...

  9. SqlServer批量刷数据执行事务回滚语句备份

    企业进行对数据库执行刷数据工作,一段很长的语句希望同时成功或者失败时用到. 1.建立测试环境 /**************************************************** ...

  10. IE的F12开发人员工具不显示

    IE的F12开发人员工具不显示问题: 按下F12之后,开发人员工具在桌面上看不到,但是任务栏里有显示.将鼠标放在任务栏的开发人员工具上,出现一片透明的区域,选中之后却出不来.将鼠标移动到开发人员工具的 ...