CC2540的Center查找特征失败
时间:10-02
整理:3721RD
点击:
我把center和peripheral的GATTProfile文件修改成char1能发送20个字节,错误。
if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { simpleBLECharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); LCD_WRITE_STRING( "Simple Svc Found", HAL_LCD_LINE_1 ); simpleBLEProcedureInProgress = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; }
不能进入到上述函数。
我修改的代码为:
simpleGATTprofile.h
// Profile Parameters #define SIMPLEPROFILE_CHAR1 0 // RW uint8 - Profile Characteristic 1 value #define SIMPLEPROFILE_CHAR2 1 // RW uint8 - Profile Characteristic 2 value // Simple Profile Service UUID #define SIMPLEPROFILE_SERV_UUID 0xFFF0 // Key Pressed UUID #define SIMPLEPROFILE_CHAR1_UUID 0xFFF1 #define SIMPLEPROFILE_CHAR2_UUID 0xFFF2 // Simple Keys Profile Services bit fields #define SIMPLEPROFILE_SERVICE 0x00000001 #define SIMPLEPROFILE_CHAR1_LEN 20
simpleGATTprofile.c
/********************************************************************* * CONSTANTS */ #define SERVAPP_NUM_ATTR_SUPPORTED 8 /********************************************************************* * TYPEDEFS */ /********************************************************************* * GLOBAL VARIABLES */ // Simple GATT Profile Service UUID: 0xFFF0 CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID) }; // Characteristic 1 UUID: 0xFFF1 CONST uint8 simpleProfilechar1UUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID) }; // Characteristic 2 UUID: 0xFFF2 CONST uint8 simpleProfilechar2UUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_CHAR2_UUID), HI_UINT16(SIMPLEPROFILE_CHAR2_UUID) }; /********************************************************************* * EXTERNAL VARIABLES */ /********************************************************************* * EXTERNAL FUNCTIONS */ /********************************************************************* * LOCAL VARIABLES */ static simpleProfileCBs_t *simpleProfile_AppCBs = NULL; /********************************************************************* * Profile Attributes - variables */ // Simple Profile Service attribute static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID }; // Simple Profile Characteristic 1 Properties static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE; // Characteristic 1 Value static uint8 simpleProfileChar1[SIMPLEPROFILE_CHAR1_LEN] =/*{0} ;*/ /**/{0xFC,0x02,0x03,0x05,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/**/ // Simple Profile Characteristic 1 User Description static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1\0"; // Simple Profile Characteristic 2 Properties static uint8 simpleProfileChar2Props = GATT_PROP_NOTIFY; // Characteristic 2 Value static uint8 simpleProfileChar2 = 0; // Simple Profile Characteristic 2 Configuration Each client has its own // instantiation of the Client Characteristic Configuration. Reads of the // Client Characteristic Configuration only shows the configuration for // that client and writes only affect the configuration of that client. static gattCharCfg_t simpleProfileChar2Config[GATT_MAX_NUM_CONN]; // Simple Profile Characteristic 2 User Description static uint8 simpleProfileChar2UserDesp[17] = "Characteristic 2\0"; /********************************************************************* * Profile Attributes - Table */ static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] = { // Simple Profile Service { { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */ GATT_PERMIT_READ, /* permissions */ 0, /* handle */ (uint8 *)&simpleProfileService /* pValue */ }, // Characteristic 1 Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &simpleProfileChar1Props }, // Characteristic Value 1 { { ATT_BT_UUID_SIZE, simpleProfilechar1UUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, simpleProfileChar1 }, // Characteristic 1 User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, simpleProfileChar1UserDesp }, // Characteristic 2 Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &simpleProfileChar2Props }, // Characteristic Value 2 { { ATT_BT_UUID_SIZE, simpleProfilechar2UUID }, 0, 0, &simpleProfileChar2 }, // Characteristic 2 configuration { { ATT_BT_UUID_SIZE, clientCharCfgUUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8 *)simpleProfileChar2Config }, // Characteristic 2 User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, simpleProfileChar2UserDesp }, }; /********************************************************************* * LOCAL FUNCTIONS */ static uint8 simpleProfile_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen ); static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ); static void simpleProfile_HandleConnStatusCB( uint16 connHandle, uint8 changeType ); /********************************************************************* * PROFILE CALLBACKS */ // Simple Profile Service Callbacks CONST gattServiceCBs_t simpleProfileCBs = { simpleProfile_ReadAttrCB, // Read callback function pointer simpleProfile_WriteAttrCB, // Write callback function pointer NULL // Authorization callback function pointer }; /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn SimpleProfile_AddService * * @brief Initializes the Simple Profile service by registering * GATT attributes with the GATT server. * * @param services - services to add. This is a bit map and can * contain more than one service. * * @return Success or Failure */ bStatus_t SimpleProfile_AddService( uint32 services ) { uint8 status = SUCCESS; // Initialize Client Characteristic Configuration attributes GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar2Config ); // Register with Link DB to receive link status change callback VOID linkDB_Register( simpleProfile_HandleConnStatusCB ); if ( services & SIMPLEPROFILE_SERVICE ) { // Register GATT attribute list and CBs with GATT Server App status = GATTServApp_RegisterService( simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ), &simpleProfileCBs ); } return ( status ); } /********************************************************************* * @fn SimpleProfile_RegisterAppCBs * * @brief Registers the application callback function. Only call * this function once. * * @param callbacks - pointer to application callbacks. * * @return SUCCESS or bleAlreadyInRequestedMode */ bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks ) { if ( appCallbacks ) { simpleProfile_AppCBs = appCallbacks; return ( SUCCESS ); } else { return ( bleAlreadyInRequestedMode ); } } /********************************************************************* * @fn SimpleProfile_SetParameter * * @brief Set a Simple Profile parameter. * * @param param - Profile parameter ID * @param len - length of data to right * @param value - pointer to data to write. This is dependent on * the parameter ID and WILL be cast to the appropriate * data type (example: data type of uint16 will be cast to * uint16 pointer). * * @return bStatus_t */ bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value ) { bStatus_t ret = SUCCESS; switch ( param ) { case SIMPLEPROFILE_CHAR1: if ( len <= SIMPLEPROFILE_CHAR1_LEN ) { VOID osal_memcpy( simpleProfileChar1, value, len ); } else { ret = bleInvalidRange; } break; case SIMPLEPROFILE_CHAR2: if ( len == sizeof ( uint8 ) ) { simpleProfileChar2 = *((uint8*)value); // See if Notification has been enabled GATTServApp_ProcessCharCfg( simpleProfileChar2Config, &simpleProfileChar2, FALSE, simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ), INVALID_TASK_ID ); } else { ret = bleInvalidRange; } break; default: ret = INVALIDPARAMETER; break; } return ( ret ); } /********************************************************************* * @fn SimpleProfile_GetParameter * * @brief Get a Simple Profile parameter. * * @param param - Profile parameter ID * @param value - pointer to data to put. This is dependent on * the parameter ID and WILL be cast to the appropriate * data type (example: data type of uint16 will be cast to * uint16 pointer). * * @return bStatus_t */ bStatus_t SimpleProfile_GetParameter( uint8 param, void *value ) { bStatus_t ret = SUCCESS; switch ( param ) { case SIMPLEPROFILE_CHAR1: VOID osal_memcpy( value, simpleProfileChar1, SIMPLEPROFILE_CHAR1_LEN ); //simpleProfileChar1 是数组名 break; case SIMPLEPROFILE_CHAR2: *((uint8*)value) = simpleProfileChar2; break; default: ret = INVALIDPARAMETER; break; } return ( ret ); } /********************************************************************* * @fn simpleProfile_ReadAttrCB * * @brief Read an attribute. * * @param connHandle - connection message was received on * @param pAttr - pointer to attribute * @param pValue - pointer to data to be read * @param pLen - length of data to be read * @param offset - offset of the first octet to be read * @param maxLen - maximum length of data to be read * * @return Success or Failure */ static uint8 simpleProfile_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen ) { bStatus_t status = SUCCESS; // If attribute permissions require authorization to read, return error if ( gattPermitAuthorRead( pAttr->permissions ) ) { // Insufficient authorization return ( ATT_ERR_INSUFFICIENT_AUTHOR ); } // Make sure it's not a blob operation (no attributes in the profile are long) if ( offset > 0 ) { return ( ATT_ERR_ATTR_NOT_LONG ); } if ( pAttr->type.len == ATT_BT_UUID_SIZE ) { // 16-bit UUID uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { case SIMPLEPROFILE_CHAR1_UUID: *pLen = SIMPLEPROFILE_CHAR1_LEN; VOID osal_memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR1_LEN ); break; case SIMPLEPROFILE_CHAR2_UUID: *pLen = 1; pValue[0] = *pAttr->pValue; break; default: // Should never get here! (characteristics 3 and 4 do not have read permissions) *pLen = 0; status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { // 128-bit UUID *pLen = 0; status = ATT_ERR_INVALID_HANDLE; } return ( status ); } /********************************************************************* * @fn simpleProfile_WriteAttrCB * * @brief Validate attribute data prior to a write operation * * @param connHandle - connection message was received on * @param pAttr - pointer to attribute * @param pValue - pointer to data to be written * @param len - length of data * @param offset - offset of the first octet to be written * @param complete - whether this is the last packet * @param oper - whether to validate and/or write attribute value * * @return Success or Failure */ static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; uint8 notifyApp = 0xFF; // If attribute permissions require authorization to write, return error if ( gattPermitAuthorWrite( pAttr->permissions ) ) { // Insufficient authorization return ( ATT_ERR_INSUFFICIENT_AUTHOR ); } if ( pAttr->type.len == ATT_BT_UUID_SIZE ) { // 16-bit UUID uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { case SIMPLEPROFILE_CHAR1_UUID: //Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len > SIMPLEPROFILE_CHAR1_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { // uint8 *pCurValue = (uint8 *)pAttr->pValue; // osal_memset(pCurValue,0,SIMPLEPROFILE_CHAR1_LEN); // VOID osal_memcpy( pCurValue, pValue, len ); uint8 i = 0; uint8 *pCurValue = (uint8 *)pAttr->pValue; for ( i = 0; i<len; i++) { *pCurValue = pValue[i]; pCurValue++; }; if(len < SIMPLEPROFILE_CHAR1_LEN) { for (; i<SIMPLEPROFILE_CHAR1_LEN; i++) { *pCurValue = 0; *pCurValue ++; } } notifyApp = SIMPLEPROFILE_CHAR1; } break; case GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); break; default: // Should never get here! (characteristics 2 and 4 do not have write permissions) status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { // 128-bit UUID status = ATT_ERR_INVALID_HANDLE; } // If a charactersitic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange ) { simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp ); //调用回调函数 simpleProfileChangeCB() } return ( status ); } /********************************************************************* * @fn simpleProfile_HandleConnStatusCB * * @brief Simple Profile link status change handler function. * * @param connHandle - connection handle * @param changeType - type of change * * @return none */ static void simpleProfile_HandleConnStatusCB( uint16 connHandle, uint8 changeType ) { // Make sure this is not loopback connection if ( connHandle != LOOPBACK_CONNHANDLE ) { // Reset Client Char Config if connection has dropped if ( ( changeType == LINKDB_STATUS_UPDATE_REMOVED ) || ( ( changeType == LINKDB_STATUS_UPDATE_STATEFLAGS ) && ( !linkDB_Up( connHandle ) ) ) ) { GATTServApp_InitCharCfg( connHandle, simpleProfileChar2Config ); } } }
具体的两个文件就修改成这样,好奇怪就是不行。后开我修改了simpleProfile_ReadAttrCB函数的:
case SIMPLEPROFILE_CHAR1_UUID: *pLen = SIMPLEPROFILE_CHAR1_LEN; VOID osal_memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR1_LEN ); break;
改成:
case SIMPLEPROFILE_CHAR1_UUID: *pLen = 16; VOID osal_memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR1_LEN ); break;
这就可以了。不明白为什么。
我查找特征部分代码:
static void simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg ) { attReadByTypeReq_t req; if ( simpleBLEDiscState == BLE_DISC_STATE_SVC ) { // Service found, store handles //当通过uuid GATT_DiscPrimaryServiceByUUID() 调用成功 if ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP && pMsg->msg.findByTypeValueRsp.numInfo > 0 ) { simpleBLESvcStartHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].handle; simpleBLESvcEndHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle; } // If procedure complete if ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP && pMsg->hdr.status == bleProcedureComplete ) || ( pMsg->method == ATT_ERROR_RSP ) ) { if ( simpleBLESvcStartHdl != 0 ) { // Discover characteristic simpleBLEDiscState = BLE_DISC_STATE_CHAR; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID); req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); //根据服务的UUID调用API函数GATT_ReadUsingCharUUID协议栈会返回该服务的Handle。 } } } else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR ) { if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { simpleBLECharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); LCD_WRITE_STRING( "Simple Svc Found11", HAL_LCD_LINE_1 ); simpleBLEProcedureInProgress = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; }else { simpleBLEDiscState = BLE_DISC_STATE_CHAR2; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR2_UUID); //获取特性值xxxxx的handle req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR2_UUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); } }else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR2 ) { if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { simpleBLECharHdl2 = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); LCD_WRITE_STRING( "Simple Svc Found22", HAL_LCD_LINE_1 ); simpleBLEProcedureInProgress = FALSE; LCD_WRITE_STRING( "0000000", HAL_LCD_LINE_8 ); attWriteReq_t AttReq; uint8 ValueBuf[2]; AttReq.handle = simpleBLECharHdl2; AttReq.len = 2; AttReq.sig = 0; AttReq.cmd = 0; ValueBuf[0] = 0x01; ValueBuf[1] = 0x00; osal_memcpy(AttReq.value,ValueBuf,2); GATT_WriteCharValue( 0, &AttReq, simpleBLETaskId ); } simpleBLEDiscState = BLE_DISC_STATE_IDLE; } }
他死活不能查找成功。