当前位置: 首页 > news >正文

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

资料准备: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.mrgr.cn/news/63614.html

相关文章:

  • Vue 3 Vite 项目打包优化:自动删除指定文件的方法
  • vue3+vant实现视频播放(含首次禁止进度条拖拽,视频看完后恢复,保存播放视频进度,刷新及下次进入继续播放,判断视频有无全部看完等)
  • android浏览器源码 可输入地址或关键词搜索 android studio 2024 可开发可改地址
  • COMSOL细观混凝土砂浆及界面过渡区受压损伤破坏
  • 求好的宠物空气净化器推荐!铲屎官们交出你们的双十一购物清单
  • DAYWEB69 攻防-Java 安全JWT 攻防Swagger 自动化算法签名密匙Druid 泄漏
  • 分账系统对电商多重要,为何电商平台都选择分账系统?
  • 【数据结构】数组和向量
  • 5G三大应用场景中的URLLC
  • 推荐一款功能强大的媒体播放管理:Zoom Player MAX
  • Python数字类型在“用户信息管理“项目中的应用
  • vue3项目中el-tooltip实现内容溢出时再显示,并设置tip的最大宽度
  • 每个软件开发人员都应该知道的 9 个定律
  • 【Linux内核大揭秘】程序地址空间
  • Cpp二叉搜索树的讲解与实现(21)
  • Node.js:Express 服务 路由
  • 干货速学,带你一文读懂嵌入式领域!
  • leetcode 2710 移除字符串中的尾随零
  • TON 区块链开发的深入概述#TON链开发#DAPP开发#交易平台#NFT#Gamefi链游
  • 前端通过nginx部署一个本地服务的方法
  • 【机器学习】22. 聚类cluster - K-means
  • 电阻的颜色有什么含义
  • OpenCv —— 为opencv支持中文,将freetype2库编译进opencv中(附详细编译流程、测试代码)
  • 【表格解决问题】EXCEL行数过多,WPS如何按逐行分别打印多个纸张中
  • JavaScript中this的指向和改变this指向的方法 - 2024最新版前端秋招面试短期突击面试题【100道】
  • 新浪新闻探索大会|赵世奇:文心智能体解锁AI浪潮中的商业新范式