CC2642 读取和设置FEATURES
一、读取本地Features,然后更改它的值
1、调用HCI_LE_ReadLocalSupportedFeaturesCmd,这个接口对应的事件是HCI_LE_READ_LOCAL_SUPPORTED_FEATURES,这个事件是在HCI_COMMAND_COMPLETE_EVENT_CODE(hciEvt_CmdComplete_t)里面
/**
* Read the LE locally supported features.
*
* @par Corresponding Events
* @ref hciEvt_CmdComplete_t with cmdOpcode
* @ref HCI_LE_READ_LOCAL_SUPPORTED_FEATURES
*
* @return @ref HCI_SUCCESS
*/
extern hciStatus_t HCI_LE_ReadLocalSupportedFeaturesCmd( void );
2、触发事件HCI_COMMAND_COMPLETE_EVENT_CODE->HCI_LE_READ_LOCAL_SUPPORTED_FEATURES
static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
{
// Always dealloc pMsg unless set otherwise
uint8_t safeToDealloc = TRUE;
switch (pMsg->event)
{
case HCI_GAP_EVENT_EVENT:
{
// Process HCI message
switch(pMsg->status)
{
// Process HCI Command Complete Events here
case HCI_COMMAND_COMPLETE_EVENT_CODE:
{
SimplePeripheral_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg);
}break;
}
}break;
}
return (safeToDealloc);
}
static void SimplePeripheral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
{
switch (pMsg->cmdOpcode)
{
case HCI_LE_READ_LOCAL_SUPPORTED_FEATURES:
{
u_printf("HCI_LE_READ_LOCAL_SUPPORTED_FEATURES\r\n");
// 0: Status
// 1..8: Local Supported Features
u_printf_hex((char *)pMsg->pReturnParam,9);
}break;
}
}
3、通过查看HCI_LE_READ_LOCAL_SUPPORTED_FEATURES事件发送源码,可以知道返回的数据格式
hciStatus_t HCI_LE_ReadLocalSupportedFeaturesCmd( void )
{
// 0: Status
// 1..8: Local Supported Features
uint8 rtnParam[9];
rtnParam[0] = MAP_LL_ReadLocalSupportedFeatures( &(rtnParam[1]) );
MAP_HCI_CommandCompleteEvent( HCI_LE_READ_LOCAL_SUPPORTED_FEATURES,
sizeof(rtnParam),
rtnParam );
return( HCI_SUCCESS );
}
4、更改本地Features值,读取到本地Features之后,更改它的值
case HCI_LE_READ_LOCAL_SUPPORTED_FEATURES:
{
u_printf("HCI_LE_READ_LOCAL_SUPPORTED_FEATURES\r\n");
// 0: Status
// 1..8: Local Supported Features
u_printf_hex((char *)pMsg->pReturnParam,9);
uint8_t featSet[8];
memcpy( featSet, &pMsg->pReturnParam[1], 8);
// Clear the CSA#2 feature bit
CLR_FEATURE_FLAG( featSet[1], LL_FEATURE_CHAN_ALGO_2 );
// Enable CTE
SET_FEATURE_FLAG( featSet[2], LL_FEATURE_CONNECTION_CTE_REQUEST );
SET_FEATURE_FLAG( featSet[2], LL_FEATURE_CONNECTION_CTE_RESPONSE );
SET_FEATURE_FLAG( featSet[2], LL_FEATURE_ANTENNA_SWITCHING_DURING_CTE_RX );
SET_FEATURE_FLAG( featSet[2], LL_FEATURE_RECEIVING_CTE );
HCI_EXT_SetLocalSupportedFeaturesCmd(featSet);
}break;
5、Features一共8个字节,每个字节对应如下
/*
** Bluetooth LE Feature Support
** Core Specification, Vol. 6, Part B, Section 4.6
*/
// Feature Set Related
#define LL_MAX_FEATURE_SET_SIZE 8 // in bytes
//
#define LL_FEATURE_NONE 0x00
// Byte 0
#define LL_FEATURE_ENCRYPTION 0x01
#define LL_FEATURE_CONN_PARAMS_REQ 0x02
#define LL_FEATURE_REJECT_EXT_IND 0x04
#define LL_FEATURE_SLV_FEATURES_EXCHANGE 0x08
#define LL_FEATURE_PING 0x10
#define LL_FEATURE_DATA_PACKET_LENGTH_EXTENSION 0x20
#define LL_FEATURE_PRIVACY 0x40
#define LL_FEATURE_EXTENDED_SCANNER_FILTER_POLICIES 0x80
// Byte 1
#define LL_FEATURE_2M_PHY 0x01
#define LL_FEATURE_STABLE_MODULATION_INDEX_TX 0x02
#define LL_FEATURE_STABLE_MODULATION_INDEX_RX 0x04
#define LL_FEATURE_CODED_PHY 0x08
#define LL_FEATURE_EXTENDED_ADVERTISING 0x10
#define LL_FEATURE_PERIODIC_ADVERTISING 0x20
#define LL_FEATURE_CHAN_ALGO_2 0x40
#define LL_FEATURE_LE_POWER_CLASS_1 0x80
// Byte 2
#define LL_FEATURE_MINIMUM_NUMBER_OF_USED_CHANNELS 0x01
#define LL_FEATURE_CONNECTION_CTE_REQUEST 0x02 // support CTE request procedure as initiator
#define LL_FEATURE_CONNECTION_CTE_RESPONSE 0x04 // support CTE request procedure as responder
#define LL_FEATURE_CONNECTIONLESS_CTE_TRANSMITTER 0x08
#define LL_FEATURE_CONNECTIONLESS_CTE_RECEIVER 0x10
#define LL_FEATURE_ANTENNA_SWITCHING_DURING_CTE_TX 0x20 // support LL_FEATURE_RECEIVING_CTE and switching antennas for AoD
#define LL_FEATURE_ANTENNA_SWITCHING_DURING_CTE_RX 0x40 // support LL_FEATURE_RECEIVING_CTE and switching antennas for AoA
#define LL_FEATURE_RECEIVING_CTE 0x80 // support receiving CTE in data PDUs and IQ sampling
// Byte 3
#define LL_FEATURE_PERIODIC_ADV_SYNC_TRANSFER_SEND 0x01
#define LL_FEATURE_PERIODIC_ADV_SYNC_TRANSFER_RECV 0x02
#define LL_FEATURE_SLEEP_CLOCK_ACCURACY_UPDATES 0x04
#define LL_FEATURE_REMOTE_PUBLIC_KEY_VALIDATION 0x08
#define LL_FEATURE_RESERVED4 0x10
#define LL_FEATURE_RESERVED5 0x20
#define LL_FEATURE_RESERVED6 0x40
#define LL_FEATURE_RESERVED7 0x80
// Byte 4 - Byte 7
#define LL_FEATURE_RESERVED0 0x01
#define LL_FEATURE_RESERVED1 0x02
#define LL_FEATURE_RESERVED2 0x04
#define LL_FEATURE_RESERVED3 0x08
#define LL_FEATURE_RESERVED4 0x10
#define LL_FEATURE_RESERVED5 0x20
#define LL_FEATURE_RESERVED6 0x40
#define LL_FEATURE_RESERVED7 0x80
可以通过下面的宏,操作对应的位
#define SET_FEATURE_FLAG( flags, flag ) ((flags) |= (flag))
#define TST_FEATURE_FLAG( flags, flag ) ((flags) & (flag))
#define CLR_FEATURE_FLAG( flags, flag ) ((flags) &= ~(flag))
二、读取远端设备的Features
1、调用接口HCI_LE_ReadRemoteUsedFeaturesCmd
2、回调函数如下
static uint8_t SimplePeripheral_processStackMsg(ICall_Hdr *pMsg)
{
// Always dealloc pMsg unless set otherwise
uint8_t safeToDealloc = TRUE;
switch (pMsg->event)
{
case HCI_GAP_EVENT_EVENT:
{
// Process HCI message
switch(pMsg->status)
{
// Process HCI Command Complete Events here
case HCI_COMMAND_COMPLETE_EVENT_CODE:
{
SimplePeripheral_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg);
}break;
case HCI_COMMAND_STATUS_EVENT_CODE:
{
SimplePeripheral_processCmdStatusEvt((hciEvt_CommandStatus_t *)pMsg);
}break;
}
}break;
}
return (safeToDealloc);
}
static void SimplePeripheral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
{
switch (pMsg->cmdOpcode)
{
case HCI_LE_READ_REMOTE_USED_FEATURES:
{
u_printf("HCI_LE_READ_REMOTE_USED_FEATURES. sta:%d\r\n",pMsg->pReturnParam[0]);
}break;
}
}
static void SimplePeripheral_processCmdStatusEvt(hciEvt_CommandStatus_t *pMsg)
{
u_printf("Cmd status: %02x\r\n",pMsg->cmdOpcode);
switch ( pMsg->cmdOpcode )
{
case HCI_LE_READ_REMOTE_USED_FEATURES:
{
u_printf("HCI_LE_READ_REMOTE_USED_FEATURES %d\r\n",pMsg->cmdStatus);
}break;
}
}
3、通过这个接口的源码可以知道,调用这个接口之后,都会执行HCI_COMMAND_STATUS_EVENT_CODE->HCI_LE_READ_REMOTE_USED_FEATURES事件,结果固定是成功。如果结果失败时还会执行1次HCI_COMMAND_COMPLETE_EVENT_CODE->HCI_LE_READ_REMOTE_USED_FEATURES事件
hciStatus_t HCI_LE_ReadRemoteUsedFeaturesCmd( uint16 connHandle )
{
hciStatus_t status;
MAP_HCI_CommandStatusEvent( HCI_SUCCESS, HCI_LE_READ_REMOTE_USED_FEATURES );
status = MAP_LL_ReadRemoteUsedFeatures( connHandle );
// check if something went wrong
// Note: If success is returned, then Command Complete is handled by Callback.
if ( status != HCI_SUCCESS )
{
MAP_HCI_CommandCompleteEvent( HCI_LE_READ_REMOTE_USED_FEATURES,
sizeof(status),
&status );
}
return( HCI_SUCCESS );
}
4、理论上读取成功之后会触发HCI_BLE_READ_REMOTE_FEATURE_COMPLETE_EVENT事件,实测没有。
调用HCI_LE_ReadRemoteUsedFeaturesCmd接口之后,可以通过下面代码轮询读取,如果featureRspRcved不等于LL_FEATURE_RSP_DONE,则还没获取成功
llConnState_t *myfeatPtr;
myfeatPtr = llDataGetConnPtr(0); //读取句柄0的设备
if(myfeatPtr != NULL && myfeatPtr->featureSetInfo.featureRspRcved == LL_FEATURE_RSP_DONE)
{
u_printf_hex((char *)myfeatPtr->featureSetInfo.featureSet,LL_MAX_FEATURE_SET_SIZE);
}