本帖最后由 冒汗的心情 于 2016-4-13 17:10 编辑
CC2541的回调函数的定义和调用过程
转载,897503845@qq.com
一、回调函数简介
ti的BLE协议栈使用到大量的回调函数,函数名末尾带“CB”的通常都是回调函数,它是指“call back”,在状态有改变时会调用此函数。本篇以SimpleBLECentral工程中simpleBLECentralEventCB函数,来简要说明回调函数的定义和调用过程。
二、解析代码
1、定义一个“成员为函数指针”的结构体
1)定义一个函数指针
[cpp] view plain copy
/**
* Central Event Callback Function
*/
typedef void (*pfnGapCentralRoleEventCB_t)
(
gapCentralRoleEvent_t *pEvent //!< Pointer to event structure.
);
它的参数是一个gapCentralRoleEvent_t类型的消息指针*pEvent。
其中,gapCentralRoleEvent_t的类型如下
[cpp] view plain copy
/**
* Central Event Structure
*/
typedef union
{
gapEventHdr_t gap; //!< GAP_MSG_EVENT and status.
gapDeviceInitDoneEvent_t initDone; //!< GAP initialization done.
gapDeviceInfoEvent_t deviceInfo; //!< Discovery device information event structure.
gapDevDiscEvent_t discCmpl; //!< Discovery complete event structure.
gapEstLinkReqEvent_t linkCmpl; //!< Link complete event structure.
gapLinkUpdateEvent_t linkUpdate; //!< Link update event structure.
gapTerminateLinkEvent_t linkTerminate; //!< Link terminated event structure.
} gapCentralRoleEvent_t;
2)定义一个结构体
[cpp] view plain copy
/**
* Central Callback Structure
*/
typedef struct
{
pfnGapCentralRoleRssiCB_t rssiCB; //!< RSSI callback.
pfnGapCentralRoleEventCB_t eventCB; //!< Event callback.
} gapCentralRoleCB_t;
gapCentralRoleCB_t结构体有两个成员,一个是pfnGapCentralRoleRssiCB_t类型的成员,一个是pfnGapCentralRoleEventCB_t类型的成员。
2、写一个回调函数,并完成注册
1)定义一个函数simpleBLECentralEventCB
[cpp] view plain copy
/*********************************************************************
* @fn simpleBLECentralEventCB
*
* @brief Central event callback function.
*
* @param pEvent - pointer to event structure
*
* @Return none
*/
static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent )
{
switch ( pEvent->gap.opcode )
{
case GAP_DEVICE_INIT_DONE_EVENT:
{
LCD_WRITE_STRING( "BLE Central", HAL_LCD_LINE_1 );
LCD_WRITE_STRING( bdAddr2Str( pEvent->initDone.devAddr ), HAL_LCD_LINE_2 );
}
break;
case GAP_DEVICE_INFO_EVENT:
{
// if filtering device discovery results based on service UUID
if ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE )
{
if ( simpleBLEFindSvcUuid( SIMPLEPROFILE_SERV_UUID,
pEvent->deviceInfo.pEvtData,
pEvent->deviceInfo.dataLen ) )
{
simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );
}
}
}
break;
case GAP_DEVICE_DISCOVERY_EVENT:
{
// discovery complete
simpleBLEScanning = FALSE;
// if not filtering device discovery results based on service UUID
if ( DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE )
{
// Copy results
simpleBLEScanRes = pEvent->discCmpl.numDevs;
osal_memcpy( simpleBLEDevList, pEvent->discCmpl.pDevList,
(sizeof( gapDevRec_t ) * pEvent->discCmpl.numDevs) );
}
LCD_WRITE_STRING_VALUE( "Devices Found", simpleBLEScanRes,
10, HAL_LCD_LINE_1 );
if ( simpleBLEScanRes > 0 )
{
LCD_WRITE_STRING( "<- To Select", HAL_LCD_LINE_2 );
}
// initialize scan index to last device
simpleBLEScanIdx = simpleBLEScanRes;
}
break;
case GAP_LINK_ESTABLISHED_EVENT:
{
if ( pEvent->gap.hdr.status == SUCCESS )
{
simpleBLEState = BLE_STATE_CONNECTED;
simpleBLEConnHandle = pEvent->linkCmpl.connectionHandle;
simpleBLEProcedureInProgress = TRUE;
// If service discovery not performed initiate service discovery
if ( simpleBLECharHdl == 0 )
{
osal_start_timerEx( simpleBLETaskId, START_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY );
}
LCD_WRITE_STRING( "Connected", HAL_LCD_LINE_1 );
LCD_WRITE_STRING( bdAddr2Str( pEvent->linkCmpl.devAddr ), HAL_LCD_LINE_2 );
}
else
{
simpleBLEState = BLE_STATE_IDLE;
simpleBLEConnHandle = GAP_CONNHANDLE_INIT;
simpleBLERssi = FALSE;
simpleBLEDiscState = BLE_DISC_STATE_IDLE;
LCD_WRITE_STRING( "Connect Failed", HAL_LCD_LINE_1 );
LCD_WRITE_STRING_VALUE( "Reason:", pEvent->gap.hdr.status, 10, HAL_LCD_LINE_2 );
}
}
break;
case GAP_LINK_TERMINATED_EVENT:
{
simpleBLEState = BLE_STATE_IDLE;
simpleBLEConnHandle = GAP_CONNHANDLE_INIT;
simpleBLERssi = FALSE;
simpleBLEDiscState = BLE_DISC_STATE_IDLE;
simpleBLECharHdl = 0;
simpleBLEProcedureInProgress = FALSE;
LCD_WRITE_STRING( "Disconnected", HAL_LCD_LINE_1 );
LCD_WRITE_STRING_VALUE( "Reason:", pEvent->linkTerminate.reason,
10, HAL_LCD_LINE_2 );
}
break;
case GAP_LINK_PARAM_UPDATE_EVENT:
{
LCD_WRITE_STRING( "Param Update", HAL_LCD_LINE_1 );
}
break;
default:
break;
}
}
2)声明函数
[cpp] view plain copy
static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent );
3)使simpleBLECentralEventCB成为回调函数
[cpp] view plain copy
// GAP Role Callbacks
static const gapCentralRoleCB_t simpleBLERoleCB =
{
simpleBLECentralRssiCB, // RSSI callback
simpleBLECentralEventCB // Event callback
};
3、调用回调函数
1)定义一个新的函数指针变量pGapCentralRoleCB(central.c)
[cpp] view plain copy
// App callbacks
static gapCentralRoleCB_t *pGapCentralRoleCB;
2)将pGapCentralRoleCB指向回调函数simpleBLECentralEventCB,也就是注册回调函数。
[cpp] view plain copy
/**
* @brief Start the device in Central role. This function is typically
* called once during system startup.
*
* Public function defined in central.h.
*/
bStatus_t GAPCentralRole_StartDevice( gapCentralRoleCB_t *pAppCallbacks )
{
if ( pAppCallbacks )
{
pGapCentralRoleCB = pAppCallbacks;
}
return GAP_DeviceInit( gapCentralRoleTaskId, GAP_PROFILE_CENTRAL,
gapCentralRoleMaxScanRes, gapCentralRoleIRK,
gapCentralRoleSRK, &gapCentralRoleSignCounter );
}
3)调用回调函数
[cpp] view plain copy
// Pass event to app
if ( pGapCentralRoleCB && pGapCentralRoleCB->eventCB )
{
pGapCentralRoleCB->eventCB( (gapCentralRoleEvent_t *) pMsg );
}
注:实际上此时simpleBLECentralEventCB在第二步结束时,即可直接通过操作结构体来调用这个回调函数了。
但是之所以要将结构体中的simpleBLECentralEventCB函数首地址再传给simpleBLECentralEventCB(即第三点的1、2两个步骤),我认为是出于底层的profiles——central分层的考虑。
|