蓝牙4.0协议编程之回调函数
来源:互联网 发布:专卖店软件泰安 编辑:程序博客网 时间:2024/05/17 07:23
蓝牙4.0协议编程之回调函数
基于TI公司蓝牙4.0协议
转载出处:http://blog.csdn.net/zhcx2011/article/details/9010541
1.回调函数概念
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
2.回调函数实现的机制
⑴定义一个回调函数;⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
3.代码实例分析
实现第一步,定义结构和函数体:
在gapbondmgr.h文件中定义
Passcode回调函数
- /**
- * Passcode Callback Function
- */
- typedef void (*pfnPasscodeCB_t)
- (
- uint8 *deviceAddr, //!< address of device to pair with, and could be either public or random.
- uint16 connectionHandle, //!< Connection handle
- uint8 uiInputs, //!< Pairing User Interface Inputs - Ask user to input passcode
- uint8 uiOutputs //!< Pairing User Interface Outputs - Display passcode
- );
绑定状态回调函数
- /**
- * Pairing State Callback Function
- */
- typedef void (*pfnPairStateCB_t)
- (
- uint16 connectionHandle, //!< Connection handle
- uint8 state, //!< Pairing state @ref GAPBOND_PAIRING_STATE_DEFINES
- uint8 status //!< Pairing status
- );
定义回调函数结构体
- /**
- * Callback Registration Structure
- */
- typedef struct
- {
- pfnPasscodeCB_t passcodeCB; //!< Passcode callback
- pfnPairStateCB_t pairStateCB; //!< Pairing state callback
- } gapBondCBs_t;
在simpleBLECentral.c文件中定义
回调函数结构体实例:
- // Bond Manager Callbacks
- static const gapBondCBs_t simpleBLEBondCB =
- {
- simpleBLECentralPasscodeCB,
- simpleBLECentralPairStateCB
- };
- static void simpleBLECentralPasscodeCB( uint8 *deviceAddr, uint16 connectionHandle,
- uint8 uiInputs, uint8 uiOutputs )
- {
- #if (HAL_LCD == TRUE)
- uint32 passcode;
- uint8 str[7];
- // Create random passcode
- LL_Rand( ((uint8 *) &passcode), sizeof( uint32 ));
- passcode %= 1000000;
- // Display passcode to user
- if ( uiOutputs != 0 )
- {
- LCD_WRITE_STRING( "Passcode:", HAL_LCD_LINE_1 );
- LCD_WRITE_STRING( (char *) _ltoa(passcode, str, 10), HAL_LCD_LINE_2 );
- }
- // Send passcode response
- GAPBondMgr_PasscodeRsp( connectionHandle, SUCCESS, passcode );
- #endif
- }
- static void simpleBLECentralPairStateCB( uint16 connHandle, uint8 state, uint8 status )
- {
- if ( state == GAPBOND_PAIRING_STATE_STARTED )
- {
- LCD_WRITE_STRING( "Pairing started", HAL_LCD_LINE_1 );
- }
- else if ( state == GAPBOND_PAIRING_STATE_COMPLETE )
- {
- if ( status == SUCCESS )
- {
- LCD_WRITE_STRING( "Pairing success", HAL_LCD_LINE_1 );
- }
- else
- {
- LCD_WRITE_STRING_VALUE( "Pairing fail", status, 10, HAL_LCD_LINE_1 );
- }
- }
- else if ( state == GAPBOND_PAIRING_STATE_BONDED )
- {
- if ( status == SUCCESS )
- {
- LCD_WRITE_STRING( "Bonding success", HAL_LCD_LINE_1 );
- }
- }
- }
实现第二步:实现一个初始化函数,将回调函数的函数指针注册给调用者
初始化函数为:其函数体为:
- GAPBondMgr_Register( (gapBondCBs_t *) &simpleBLEBondCB );
- void GAPBondMgr_Register( gapBondCBs_t *pCB )
- {
- pGapBondCB = pCB;
- // Take over the processing of Authentication messages
- VOID GAP_SetParamValue( TGAP_AUTH_TASK_ID, gapBondMgr_TaskID );
- // Register with GATT Server App for event messages
- GATTServApp_RegisterForMsg( gapBondMgr_TaskID );
- }
其定义为:
- static const gapBondCBs_t *pGapBondCB = NULL;
实现第三步,使用函数指针调用回调函数
在文件gapbondmgr.c文件中有事件处理函数如下:
- void GAPBondMgr_ProcessGAPMsg( gapEventHdr_t *pMsg )
- {
- switch ( pMsg->opcode )
- {
- case GAP_PASSKEY_NEEDED_EVENT:
- {
- gapPasskeyNeededEvent_t *pPkt = (gapPasskeyNeededEvent_t *)pMsg;
- if ( pGapBondCB && pGapBondCB->passcodeCB )
- {
- // Ask app for a passcode
- <span style="color:#ff0000;">pGapBondCB->passcodeCB( pPkt->deviceAddr, pPkt->connectionHandle, pPkt->uiInputs, pPkt->uiOutputs );</span>
- }
- else
- {
- // No app support, use the default passcode
- if ( GAP_PasscodeUpdate( gapBond_Passcode, pPkt->connectionHandle ) != SUCCESS )
- {
- VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_PASSKEY_ENTRY_FAILED );
- }
- }
- }
- break;
- case GAP_AUTHENTICATION_COMPLETE_EVENT:
- {
- gapAuthCompleteEvent_t *pPkt = (gapAuthCompleteEvent_t *)pMsg;
- // Should we save bonding information
- if ( (pPkt->hdr.status == SUCCESS) && (pPkt->authState & SM_AUTH_STATE_BONDING) )
- {
- gapBondRec_t bondRec;
- VOID osal_memset( &bondRec, 0, sizeof ( gapBondRec_t ) ) ;
- // Do we have a public address in the data?
- if ( pPkt->pIdentityInfo )
- {
- VOID osal_memcpy( bondRec.publicAddr, pPkt->pIdentityInfo->bd_addr, B_ADDR_LEN );
- }
- else
- {
- linkDBItem_t *pLinkItem = linkDB_Find( pPkt->connectionHandle );
- if ( pLinkItem )
- {
- VOID osal_memcpy( bondRec.publicAddr, pLinkItem->addr, B_ADDR_LEN );
- }
- else
- {
- // We don't have an address, so ignore the message.
- break;
- }
- }
- // Save off of the authentication state
- bondRec.stateFlags |= (pPkt->authState & SM_AUTH_STATE_AUTHENTICATED) ? GAP_BONDED_STATE_AUTHENTICATED : 0;
- VOID gapBondMgrAddBond( &bondRec,
- (gapBondLTK_t *)pPkt->pSecurityInfo,
- (gapBondLTK_t *)pPkt->pDevSecInfo,
- ((uint8 *)((pPkt->pIdentityInfo) ? pPkt->pIdentityInfo->irk : NULL )),
- ((uint8 *)((pPkt->pSigningInfo) ? pPkt->pSigningInfo->srk : NULL )),
- ((uint32)((pPkt->pSigningInfo) ? pPkt->pSigningInfo->signCounter : GAP_INIT_SIGN_COUNTER )) );
- // Update NV to have same CCC values as GATT database
- gapBondMgr_SyncCharCfg( pPkt->connectionHandle );
- }
- // Call app state callback
- if ( pGapBondCB && pGapBondCB->pairStateCB )
- {
- <span style="color:#ff0000;">pGapBondCB->pairStateCB( pPkt->connectionHandle, GAPBOND_PAIRING_STATE_COMPLETE, pPkt->hdr.status );</span>
- }
- }
- break;
- case GAP_BOND_COMPLETE_EVENT:
- // This message is received when the bonding is complete. If hdr.status is SUCCESS
- // then call app state callback. If hdr.status is NOT SUCCESS, the connection will be
- // dropped at the LL because of a MIC failure, so again nothing to do.
- {
- gapBondCompleteEvent_t *pPkt = (gapBondCompleteEvent_t *)pMsg;
- // Update NV to have same CCC values as GATT database
- gapBondMgr_SyncCharCfg( pPkt->connectionHandle );
- if ( pGapBondCB && pGapBondCB->pairStateCB )
- {
- <span style="color:#ff0000;">pGapBondCB->pairStateCB( pPkt->connectionHandle, GAPBOND_PAIRING_STATE_BONDED, pMsg->hdr.status );</span>
- }
- }
- break;
- case GAP_SIGNATURE_UPDATED_EVENT:
- {
- uint8 idx;
- gapSignUpdateEvent_t *pPkt = (gapSignUpdateEvent_t *)pMsg;
- idx = GAPBondMgr_ResolveAddr( pPkt->addrType, pPkt->devAddr, NULL );
- if ( idx < GAP_BONDINGS_MAX )
- {
- // Save the sign counter
- VOID osal_snv_write( devSignCounterNvID(idx), sizeof ( uint32 ), &(pPkt->signCounter) );
- }
- }
- break;
4.总结
通过对整个回调函数的定义和调用过程分析,对回调函数的使用有了明确的理解。这一设计允许了底层代码调用在高层定义的子程序,有利于整个程序的分层设计。 0 0
- 蓝牙4.0协议编程之回调函数
- 蓝牙4.0协议编程之回调函数
- 新编程知识之回调函数
- c/c++编程之回调函数
- c++编程之回调函数
- 编程基础之回调函数
- C++编程思想之回调函数
- OO编程思想之四---回调函数,事件驱动
- 回调函数之精神
- 回调函数之精神
- android 之 回调函数
- java之回调函数
- 总结之回调函数
- Erlang之回调函数
- lwip之回调函数
- python之回调函数
- java之回调函数
- java之回调函数
- Tower of Hanoi
- Android数据库LitePal框架学习笔记(1)---数据库的adb操作以及LitePal使用入门
- 安装MySQL Enterprise Edition
- Chapter 1. Introduction to Web Automation
- 使用testFlight进行企业部署
- 蓝牙4.0协议编程之回调函数
- Java中WebService实例
- GRE写作必备句型
- Oracle与MySQL的转化差异
- cocos2dx 单点触摸的简单使用
- 开源日志系统比较
- Project Euler:Problem 61 Cyclical figurate numbers
- Adb 的使用
- 驱动之module_init/module_exit