我把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_SUPPORTED8 /********************************************************************* * 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 pointersimpleProfile_WriteAttrCB, // Write callback function pointerNULL// Authorization callback function pointer }; /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fnSimpleProfile_AddService * * @briefInitializes the Simple Profile service by registering *GATT attributes with the GATT server. * * @paramservices - 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 attributesGATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar2Config );// Register with Link DB to receive link status change callbackVOID linkDB_Register( simpleProfile_HandleConnStatusCB );if ( services & SIMPLEPROFILE_SERVICE ){// Register GATT attribute list and CBs with GATT Server Appstatus = GATTServApp_RegisterService( simpleProfileAttrTbl,GATT_NUM_ATTRS( simpleProfileAttrTbl ),&simpleProfileCBs );}return ( status ); } /********************************************************************* * @fnSimpleProfile_RegisterAppCBs * * @briefRegisters the application callback function. Only call *this function once. * * @paramcallbacks - 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 );} } /********************************************************************* * @fnSimpleProfile_SetParameter * * @briefSet a Simple Profile parameter. * * @paramparam - Profile parameter ID * @paramlen - length of data to right * @paramvalue - 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 enabledGATTServApp_ProcessCharCfg( simpleProfileChar2Config, &simpleProfileChar2, FALSE,simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),INVALID_TASK_ID );}else{ret = bleInvalidRange;}break;default:ret = INVALIDPARAMETER;break;}return ( ret ); } /********************************************************************* * @fnSimpleProfile_GetParameter * * @briefGet a Simple Profile parameter. * * @paramparam - Profile parameter ID * @paramvalue - 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 ); } /********************************************************************* * @fnsimpleProfile_ReadAttrCB * * @briefRead an attribute. * * @paramconnHandle - connection message was received on * @parampAttr - pointer to attribute * @parampValue - pointer to data to be read * @parampLen - length of data to be read * @paramoffset - offset of the first octet to be read * @parammaxLen - maximum length of data to be read * * @returnSuccess 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 errorif ( gattPermitAuthorRead( pAttr->permissions ) ){// Insufficient authorizationreturn ( 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 UUIDuint16 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 ); } /********************************************************************* * @fnsimpleProfile_WriteAttrCB * * @briefValidate attribute data prior to a write operation * * @paramconnHandle - connection message was received on * @parampAttr - pointer to attribute * @parampValue - pointer to data to be written * @paramlen - length of data * @paramoffset - offset of the first octet to be written * @paramcomplete - whether this is the last packet * @paramoper - 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 errorif ( gattPermitAuthorWrite( pAttr->permissions ) ){// Insufficient authorizationreturn ( ATT_ERR_INSUFFICIENT_AUTHOR );}if ( pAttr->type.len == ATT_BT_UUID_SIZE ){// 16-bit UUIDuint16 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 operif ( offset == 0 ){if ( len > SIMPLEPROFILE_CHAR1_LEN ){status = ATT_ERR_INVALID_VALUE_SIZE;}}else{status = ATT_ERR_ATTR_NOT_LONG;}//Write the valueif ( 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 UUIDstatus = ATT_ERR_INVALID_HANDLE;}// If a charactersitic value changed then callback function to notify application of changeif ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange ){simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp ); //调用回调函数 simpleProfileChangeCB()}return ( status ); } /********************************************************************* * @fnsimpleProfile_HandleConnStatusCB * * @briefSimple Profile link status change handler function. * * @paramconnHandle - connection handle * @paramchangeType - type of change * * @returnnone */ static void simpleProfile_HandleConnStatusCB( uint16 connHandle, uint8 changeType ) {// Make sure this is not loopback connectionif ( connHandle != LOOPBACK_CONNHANDLE ){// Reset Client Char Config if connection has droppedif ( ( 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;
这就可以了。不明白为什么。
Jiaming Li:
我查找特征部分代码:
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 completeif ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP&&pMsg->hdr.status == bleProcedureComplete ) ||( pMsg->method == ATT_ERROR_RSP ) ){if ( simpleBLESvcStartHdl != 0 ) {// Discover characteristicsimpleBLEDiscState = 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的handlereq.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;} }他死活不能查找成功。