CC2640R2F之配对绑定与解除绑定篇
蓝牙协议栈:simplelink_cc2640r2_sdk_1_40_00_45
IAR版本:IAR for ARM 8.11.3
开发板:CC2640R2F
蓝牙版本:BLE4.2
配对模式:PasscodeEntry 密码输入模式
主机端仅具有GAPBOND_IO_CAP_KEYBOARD_ONLY按键能力,从机端仅具有显示能力GAPBOND_IO_CAP_DISPLAY_ONLY。
从机端:
如果用手机做主机,开发板做从机,开发板显示密码,手机端输入密码,如果密码一直则配对成功。从机端使用协议栈自带例程simple_peropheral即可实现与手机的配对绑定,但此过程需要修改配对模式为uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;从机端初始化配对请求模式,否则主机端是不能收到配对过程中的输入密码请求的。
在此过程需要注意:手机大多是双模蓝牙,而手机配置界面大多是BDR蓝牙(非低功耗蓝牙),所以大多手机配置界面的自带蓝牙是不能与开发板进行配对绑定的,需要使用手机app,安卓建议nRF Connect,IOS端建议使用lightblue。
主机端
两个开发板一主一从,开发板作为从机实现与手机的配对与绑定后,从机端程序便可实现与另一开发板的配对绑定,我是基于simple_central例程修改主机端代码的。
初始化配置,在simple_central.c的static voidSimpleBLECentral_init(void)函数中,配置配对模式的初始化以及回调注册:
uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;// 配置主机端初始化配对请求;uint8_t bonding = TRUE;//配对完成后,进行绑定uint8_t mitm = TRUE;// 使用authenticated pairinguint8_t ioCap = GAPBOND_IO_CAP_KEYBOARD_ONLY;GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding); GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);GAPBondMgr_Register(&SimpleBLECentral_bondCB);
接下来编写回调函数:
static gapBondCBs_t SimpleBLECentral_bondCB = {(pfnPasscodeCB_t)SimpleBLECentral_passcodeCB, // Passcode callbackSimpleBLECentral_pairStateCB // Pairing / Bonding state Callback };static void SimpleBLECentral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,uint8_t uiInputs, uint8_t uiOutputs, uint32_t numComparison) {gapPasskeyNeededEvent_t *pData;// Allocate space for the passcode event.if ((pData = ICall_malloc(sizeof(gapPasskeyNeededEvent_t)))){memcpy(pData->deviceAddr, deviceAddr, B_ADDR_LEN);pData->connectionHandle = connHandle; pData->uiInputs = uiInputs;pData->uiOutputs = uiOutputs;pData->numComparison = numComparison;// Enqueue the event.SimpleBLECentral_enqueueMsg(SBC_PASSCODE_NEEDED_EVT, 0, (uint8_t *) pData);} }static void SimpleBLECentral_pairStateCB(uint16_t connHandle, uint8_t state,uint8_t status) {uint8_t *pData;// Allocate space for the event data.if ((pData = ICall_malloc(sizeof(uint8_t)))){*pData = status;// Queue the event.SimpleBLECentral_enqueueMsg(SBC_PAIRING_STATE_EVT, state, pData);} }
在static_processAppMsg(sbcEvt_t *pMsg)函数中添加对于SBC_PASSCODE_NEEDED_EVT和SBC_PAIRING_STATE_EVT两个事件的处理,代码如下static void SimpleBLECentral_processAppMsg(sbcEvt_t *pMsg) {switch (pMsg->hdr.event){case SBC_STATE_CHANGE_EVT:SimpleBLECentral_processStackMsg((ICall_Hdr *)pMsg->pData);// Free the stack messageICall_freeMsg(pMsg->pData);break;case SBC_KEY_CHANGE_EVT:SimpleBLECentral_handleKeys(0, pMsg->hdr.state);break;case SBC_RSSI_READ_EVT:{readRssi_t *pRssi = (readRssi_t *)pMsg->pData;// If link is up and RSSI reads activeif (pRssi->connHandle != GAP_CONNHANDLE_ALL &&linkDB_Up(pRssi->connHandle)){// Restart timerUtil_restartClock(pRssi->pClock, pRssi->period);// Read RSSIVOID HCI_ReadRssiCmd(pRssi->connHandle);}}break;// Pairing eventcase SBC_PAIRING_STATE_EVT:{SimpleBLECentral_processPairState(pMsg->hdr.state, *pMsg->pData);ICall_free(pMsg->pData);break;}// Passcode eventcase SBC_PASSCODE_NEEDED_EVT:{SimpleBLECentral_processPasscode(connHandle,(gapPasskeyNeededEvent_t *)pMsg->pData);ICall_free(pMsg->pData);break;}default:// Do nothing.break;} }static void SimpleBLECentral_processPasscode(uint16_t connectionHandle, gapPasskeyNeededEvent_t *pData) {if (pData->uiInputs) // if we are to enter passkey{ #if STATIC_PASSCODEpasscode = 123456; //此处使用的是静态密码,不需要主机端手动输入,只要默认和从机端一致,就可实现配对GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode); //发送密码响应 #else// user will enter passcodewaiting_for_passcode = TRUE; //此处由主机端手动输入从机端显示的配对密码passcode_connHandle = connectionHandle; #endif Display_print0(dispHandle, 4, 0, "Enter Passcode:");Display_print1(dispHandle, 5, 0, "%d", passcode); }else if (pData->uiOutputs) // if we are to display passkey{ #if STATIC_PASSCODEpasscode = 123456; #else// Create random passcodepasscode = Util_GetTRNG();passcode %= 1000000; #endif Display_print1(dispHandle, 4, 0, "Passcode: %d", passcode);// Send passcode responseGAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode); } }static void SimpleBLECentral_processPairState(uint8_t state, uint8_t status) {if (state == GAPBOND_PAIRING_STATE_STARTED){Display_print0(dispHandle, 2, 0, "Pairing started");}else if (state == GAPBOND_PAIRING_STATE_COMPLETE){if (status == SUCCESS){Display_print0(dispHandle, 2, 0, "Pairing success");}else{Display_print1(dispHandle, 2, 0, "Pairing fail: %d", status);}}else if (state == GAPBOND_PAIRING_STATE_BONDED){if (status == SUCCESS){Display_print0(dispHandle, 2, 0, "Bonding success");}}else if (state == GAPBOND_PAIRING_STATE_BOND_SAVED){if (status == SUCCESS){Display_print0(dispHandle, 2, 0, "Bond save success");}else{Display_print1(dispHandle, 2, 0, "Bond save failed: %d", status);}} }
至此,整个配对绑定过程,需要开发人员编写的代码便完成了,其余都是由底层实现,关于底层实现BLE4.0配对绑定过程的底层剖析这篇文章讲解很详细,有需要的朋友可以自行查阅。
绑定之后便存在解绑过程,经实际测试,单独在主机端解除绑定,在下次连接时会进行重新配对绑定,若单独在从机端解除绑定,主机连接从机会一直提示连接失败。
解除绑定是在连接断开后才执行,解绑有两种方式:一种是解除所有绑定设备 :GAPBondMgr_SetParameter(GAPBOND_ERASE_ALLBONDS, 0, NULL);
此模式调用这个函数,便可实现,不再赘述。
另一种是只解除单个设备绑定:GAPBondMgr_SetParameter(GAPBOND_ERASE_SINGLEBOND, B_ADDR_LEN + 1, DevAddr);
解除单个设备绑定过程由于对参数含义不清楚,实现此功能颇费周折,在此详细说下各个参数的含义。
参数1:GAPBONG_ERASE_SINGLEBONG这个参数很容易理解,解除单个设备绑定;
参数2:B_ADDR_LEN+1表示要解绑设备的地址长度加1,此处为何加1呢?详见参数3的说明;
参数3:此参数是由要解绑设备的地址类型和地址共同组合的一个数组,所以要在地址长度上加1,此外连接完成后的设备地址是由低字节向高字节的,而此处是需要待解绑地址的字节由高到低,所以需要反向字节,具体操作如下:uint8_t idx=0; idx = GAPBondMgr_ResolveAddr(pEvent->linkCmpl.devAddrType, pEvent->linkCmpl.devAddr, NULL);//找到待解绑设备的索引 //此处pEvent->linkCmpl.devAddrType是待解绑设备的地址类型,pEvent->linkCmpl.devAddr是待解绑地址,这是连接完成后的地址, Display_print1(dispHandle, 3, 0, "del idx: %d", idx); if(idx < GAP_BONDINGS_MAX)//在bond manager中找到地址 {DevAddr[0] = pEvent->linkCmpl.devAddrType; //此处将待解绑地址的地址类型复制在DevAddr的最低字节;memcpy(lsdevaddr, pEvent->linkCmpl.devAddr, B_ADDR_LEN); //此处将待解绑地址复制到lsdevaddr中 //反向字节 VOID osal_revmemcpy(&DevAddr[1],lsdevaddr,B_ADDR_LEN);//将lsdevaddr的顺序颠倒放置在DevAddr的1~B_ADDR_LEN+1字节中 } //最后将得到的字节传输至单个解绑的第三个参数 GAPBondMgr_SetParameter(GAPBOND_ERASE_SINGLEBOND, B_ADDR_LEN + 1, DevAddr);
CC2640R2F之配对绑定与解除绑定篇相关推荐
- 我的服装DRP之即时通讯——为WCF增加UDP绑定(应用篇)
发个牢骚,博客园发博文竟然不能写副标题.这篇既为我的服装DRP系列第二篇,也给为WCF增加UDP绑定系列收个尾.原本我打算记录开发过程中遇到的一些问题和个人见解,不过写到一半发现要写的东西实在太多,有 ...
- 双网卡oracle rac,Linux+Oracle 10g RAC双网卡绑定和解除绑定的实现(2)
解除双网卡绑定 十一.停数据库和crs 在rac1和rac2上停数据库和crs #cd /u01/app/oracle/product/10.2.0/crs_1/bin 停数据库实例 #./srvc ...
- (百度云服务器的)域名不加www可以访问,添加就不能访问 (添加域名绑定)- 解决篇
域名不加www可以访问,添加就不能访问: 解决这个问题,就是添加" 域名绑定 ". 403报错截图:(添加www的) 分析:是因为没有添加绑定对应的 · 域名解析规则导致的. 解决 ...
- Vue双向绑定:原理篇(详细)
文章目录 前言 什么是响应式 数据劫持 发布者-订阅者模式 模式简介 发布者 Observer 订阅器 dep 订阅者 Watcher 整体流程 初始化data data变为响应式数据 解析模板 收集 ...
- Android——BLE配对绑定实现
蓝牙配对绑定原理不再赘述了,终端的实现可以参照文章后的参考链接,本处主要记录总结下Android端的配对绑定实现过程. 1.动态注册系统广播,接收蓝牙配对请求 intentFilter = new I ...
- 一篇文章带你解读蓝牙配对绑定
BLE配对绑定解读 什么是低功耗蓝牙配对?什么又是绑定?配对和绑定有什么区别?配对有什么好处?如何删除绑定信息?如何确定配对的安全等级?just work的配对一定就不安全吗?如何开发自己的配对应用? ...
- ble连接过程建立_BLE配对绑定过程梳理
(一)BLE SM为以下三种procedure提供支持: 1. Pairing; 2. Bondig; 3. Encryption Re-establishment; 区别于传统蓝牙的配对过程,BLE ...
- BLE配对绑定过程梳理
(一)BLE SM为以下三种procedure提供支持: 1. Pairing; 2. Bondig; 3. Encryption Re-establishment; 区别于传统蓝牙的配对过程,BLE ...
- Android Service的绑定 基础概念篇
Creating a Bound Service 绑定Service的作用: 一个绑定的service(bound service)是客户端-服务器接口中的服务器. 绑定的service允许组件(比如 ...
最新文章
- Amazing ASP.NET Core 2.0
- Web服务cxf框架发布2
- Ubuntu 安装 opencv-nonfree
- activiti页面展示流程图乱码_activiti 5.17 流程图中文乱码问题
- 简练软考知识点整理-建设项目团队
- 从零开始通过 Artifactory 搭建公网的 maven 仓库
- 【分类汇总】110 天以来的题解分类汇总
- 2016峰会:项目管理与高级项目管理(广州站)
- mysql如何对字段加密_MySQL对指定字段进行加密(双向加密)
- 从数据库中读取数据,创建XML文件并更新维护XML
- android快速圣经,Android 中级圣经系列之Activity
- 华为服务器产品系列号查询,华为LIST全系列 服务器产品速查清单
- java keystore php,KeyStoreSpi
- Shader实现透明反射效果应用地板
- c语言中整数和实数能比较大小吗,c语言中,输入一个数字,怎么判断那个数字是整数还是实数,代码如下,输入实数后出现了死循环...
- 内网渗透-最实用的横向移动总结
- “免费午餐”成为销量第一,看明星吉杰淘宝直播如何抓取粉丝眼球
- 【Windows 安装JDK8】如何安装java JDK8
- 对苹果输入法产品评价
- 原理图中VCC、VDD、VEE、VSS等符号的意思