Apple iap2协议栈在蓝牙中的移植及MFi认证的实现

news/2024/11/1 22:19:46/

资料准备:iap2协议栈源码以及MFi Accessory spec规格书

一、iap2协议栈在蓝牙中的移植:

1,rfcomm注册iap2协议栈数据收发回调函数

iap2协议栈和hfp,spp一样都是基于rfcomm实现的,因此需要在rfcomm中单独注册一个数据收发和事件的回调函数,以便iap2协议栈能够通过rfcomm收发数据与iOS通信。注册好之后,配件可以通过接收数据的回调函数解析iOS发过来的数据包,解析完成之后会设置iap2协议栈的状态机。在设置注册好相关rfcomm之后,抓包可以看到sdp到了iap2协议栈的连接,如下:

图中可以看到,rfcomm ch 11已经被注册为iap2协议的channel,至此配件可以通过ch 11与iOS进行通信。

2,iap2协议栈状态机

iap2协议栈最主要的内容就是实现了状态机,状态机能够根据接收到的数据包设置当前状态,并且通过状态机的收发函数自动收发数据,状态机需要在开机之后实时运行以便及时进行MFi认证的数据交互。只有经过MFi数据的认证后,我们的配件(蓝牙)才能够与iOS进行正常的其他数据收发(比如音乐播放控制,APP启动等)。在iap2协议栈连接上iOS之后,需要创建iap2协议栈状态机,创建调用如下:

iap2_manager.bt_iap_ran_loop = iAP2LinkRunLoopCreateAccessory(&iap2_manager.iap2_syn_param, (void *)0,(iAP2LinkSendPacketCB_t)iap_eap_tx_data_handle,(iAP2LinkDataReadyCB_t)iap_eap_rx_data_handle,(void *)0, NULL, 0, 15, nullptr);

在接口参数中,传递了iap2的链路同步载荷,状态机数据收发函数等内容。创建函数返回的指针用于运行iap2协议栈状态机。

其中我们需要比较关注的是链路的同步载荷,因为载荷参数值设置的不对可能会影响MFi认证过程,导致无法通过MFi认证,在MFi spec中链路同步载荷描述如下:

在实际使用过程中需要微调参数以便iOS无报错通过认证,我们设置的一组载荷参数如下:

static const iAP2PacketSYNData_t iap2_default_synParam = { 1, //version5, //maxOutstandingPackets30, //maxRetransmissions3, //maxCumAck650, //maxPacketSize1500, //retransmitTimeout73, //cumAckTimeout2, //numSessionInfo5, //peerMaxOutstandingPackets650, //peerMaxPacketSize{{8,0,1},{11,2,1}}
};
3,iap2会话

iap2的会话是比较重要的内容,根据MFi spec描述,iap2会话主要有控制会话,文件传输会话和EA会话,其中控制会话主要用于前期配件与iOS通信认证过程,而EA会话主要用于正常的用户数据交互,文件传输会话可以用来传输文件,一般用的比较少,区分这一点很重要,因为会话类型不对可能会导致配件无法与iOS进行正确的通信,在spec中如下描述:

当配件正确创建了状态机后,接下去便可以进行MFi的认证了。

二、MFi认证过程

根据MFi accessory spec,MFi认证过程主要分为以下几个步骤:

a>请求认证

配件连接上iOS之后,iOS会下发请求认证命令给配件,第一步是请求认证过程,当配件状态机接收到这个命令数据包之后,配件需要返回从MFi芯片读取到的认证信息给iOS平台,代码举例如下:

	if (command == IAP2_RequestAuthenticationCertificate && data[0] == IAP2_SESSION_START_MSB){buffer[0] = 0x40;buffer[1] = 0x40;buffer[2] = 0x02;buffer[3] = 0x6b;buffer[4] = 0xaa;buffer[5] = 0x01;buffer[6] = 0x02;buffer[7] = 0x65;buffer[8] = 0x00;buffer[9] = 0x00;if (mfi_loadCertificateData_cb){ret = mfi_loadCertificateData_cb(&buffer[10], 609);}len = 10 + 609;ret = iAP2LinkQueueSendData(link, buffer, len, session, NULL, link_data_sent_cb);msg.id = TLK_MSG_IAP2_ReqAuthenCertificate;}

根据spec规定,配件从MFi芯片读出X.509证书返回给iOS。

b>认证挑战

iOS接收到正确的认证信息后会请求配件认证挑战,同样配件需要从MFi芯片读出响应数据返回给iOS平台,代码如下:

	else if (command == IAP2_RequestAuthenticationChallengeResponse && data[0] == IAP2_SESSION_START_MSB){buffer[0] = 0x40;buffer[1] = 0x40;buffer[2] = 0x00;buffer[3] = 0x4a;buffer[4] = 0xaa;buffer[5] = 0x03;buffer[6] = 0x00;buffer[7] = 0x44;buffer[8] = 0x00;buffer[9] = 0x00;if (mfi_loadChallengeData_cb){mfi_loadChallengeData_cb(&data[10], ((data[6]<<8)|data[7])-4, &buffer[10], 64);}len = 10 + 64;ret = iAP2LinkQueueSendData(link, buffer, len, session, NULL, link_data_sent_cb);msg.id = TLK_MSG_IAP2_ReqAuthenChallengeResp;}
c>ID认证

认证挑战成功之后,iOS会请求ID认证,前面2个步骤可以认为是有人来敲门,确定了是人在敲门而不是其他,这里的ID认证就是确定你是否是我想要见到的人,亮明身份,身份哪里来?这就要求配件需要拿到MFi认证的实验室去过认证,认证过完之后实验室会给出相应的ID数据,这里代码如下所示:

	else if (command == IAP2_StartIdentification && data[0] == IAP2_SESSION_START_MSB){buffer[0] = 0x40;buffer[1] = 0x40;buffer[4] = IAP2_IdentificationInformation >> 8;buffer[5] = IAP2_IdentificationInformation & 0xff;pos = 6;if (iap2_manager.iap2_add_item_cb){pos += iap2_manager.iap2_add_item_cb(&buffer[pos]);}buffer[2] = (uint08)(pos>>8);buffer[3] = (uint08)pos;len = pos;ret = iAP2LinkQueueSendData(link, buffer, len, session, NULL, link_data_sent_cb);msg.id = TLK_MSG_IAP2_StartIdentification;}

当正确的ID信息被iOS识别后,iOS会下发0x1d02的指令给到配件:

至此,认证全部完成,后续配件可以通过EA会话与iOS进行其他正常的通信了!


http://www.ppmy.cn/news/1543701.html

相关文章

Linux版更新流程

一.下载更新包 下载地址&#xff1a;https://www.nvisual.com/%e4%b8%8b%e8%bd%bd/ 二.更新包组成 更新包由三部分组成&#xff1a; 前端更新包&#xff1a;压缩的ZIP文件&#xff0c;例如&#xff1a;dist-2.2.26-20231227.zip (2.2.26是版本号 20231227是发布日期)后端更…

第J4周:DenseNet与ResNet结合探索

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 本次尝试根据DenseNet与ResNet的特征来构建一个新的模型结构&#xff0c;目前的思路&#xff1a;将ResNet的残差结构加入到DenseNet中&#xff0c;也就是说把D…

MATLAB实现变领域搜索算法(VNS)

MATLAB实现变领域搜索算法(VNS) 1.算法介绍 变邻域搜索算法&#xff08;Variable Neighborhood Search&#xff0c;VNS&#xff09;是一种改进型的局部搜索算法&#xff0c;旨在通过不断变化问题的邻域结构来寻找更好的解决方案。 邻域&#xff1a;指对当前解进行一个操作&a…

算法工程师重生之第四十一天(每日温度 下一个更大元素 I 下一个更大元素II)

参考文献 代码随想录 一、每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该…

【论文分享】利用多源数据理解盐城迷你公园游览的影响因素

本次我们给大家带来一篇SCI论文的全文翻译&#xff0c;该论文通过整合手机数据、社交媒体数据和腾讯用户密度数据&#xff0c;显著提升了迷你公园游览性研究的精度&#xff0c;并揭示了开放区域面积、座位设置和周边设施对游览量的显著影响&#xff0c;为高密度地区的城市规划提…

java执行python时脚本引用动态配置文件遇到的问题

java执行python时脚本引用动态配置文件遇到的问题 当使用java去执行python脚本的时候&#xff0c;有时候会根据不同的传入参数去导入不同的组件。如我会根据传入的json参数param.username&#xff0c;去指定不同用户的配置文件&#xff0c;例如 import importlibdef load_con…

《双指针篇》---双指针算法原理

利用数组下标来充当指针。 1.双指针算法本质&#xff1a; 将数据划分为三个区间&#xff0c;我们以移动零为例&#xff1a; 给定数组中。 【0&#xff0c;left】&#xff1a;全是非0元素。 【left1&#xff0c;cur-1】&#xff1a;全是0元素。 【cur&#xff0c;n-1】&#xff…

【MySQL】视图特性 用户管理

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解什么是视图&#xff0c;我们又该如何管理用户。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! >…