CC2540自己的配置文件
首先要指出,字段属性有notify的不能同时有read,write属性,别问哥,哥也不知道,反正我做的就不能notify,只能read,write。
分享的程序段第一字段有notify属性,第二字段read,write属性。
费话少说,看代码,H文件:
#ifndef LOCKER_H #define LOCKER_H #ifdef __cplusplus extern "C" { #endif #define SERVAPP_NUM_ATTR_SUPPORTED (1+4+3) // Simple Profile Service UUID #define LOCKERPROFILE_SERV_UUID 0xFFF0 #define LOCKERPROFILE_NOTIFY_UUID 0xFFF1 #define LOCKERPROFILE_NOTIFY_MAX_LEN 5 #define LOCKERPROFILE_STREAM_UUID 0xFFF2 #define LOCKERPROFILE_STREAM_MAX_LEN 5 #define SIMPLEPROFILE_SERVICE 0x00000001 /********************************************************************* * Profile Callbacks */ // Callback when a characteristic value has changed typedef void (*app_input_cb_t)( uint16 uuid ,uint8 *pdata, int len); /********************************************************************* * lockerProfile_AddService- Initializes the Simple GATT 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. * @param cb - the function will be called, while service receive a message . * return always return SUCCESS */ bStatus_t lockerProfile_AddService( uint32 services ,app_input_cb_t cb); /* * lockerProfile_AddService - Set a Simple GATT Profile parameter. * uuid - which service's uuid as sender target * len - length of data to right * value - pointer to data to write. This is dependent on * the parameter uuid and WILL be cast to the appropriate * data type . */ bStatus_t locker_send( uint16 uuid,void *pdata , uint8 len); /* * locker_Read - Get a Simple GATT Profile parameter by uuid. * param - Profile uuid * value - pointer to data to write. This is dependent on * the parameter ID and WILL be cast to the appropriate * data type . * return : return data length, if op' failse it'll return -1; */ int locker_Read( uint16 uuid, void *pdata ); #ifdef __cplusplus } #endif #endif /* SIMPLEGATTPROFILE_H */
C文件:
/********************************************************************* * INCLUDES */ #include "bcomdef.h" #include "OSAL.h" #include "linkdb.h" #include "att.h" #include "gatt.h" #include "gatt_uuid.h" #include "gattservapp.h" #include "gapbondmgr.h" #include "locker.h" #include "stdio.h" /********************************************************************* * GLOBAL VARIABLES */ // Simple GATT Profile Service UUID: 0xFFF0 CONST uint8 lockerSvrUUID[ATT_BT_UUID_SIZE] = { LO_UINT16(LOCKERPROFILE_SERV_UUID), HI_UINT16(LOCKERPROFILE_SERV_UUID) }; // notify UUID: 0xFFF1 CONST uint8 lockerNotifyUUID[ATT_BT_UUID_SIZE] = { LO_UINT16(LOCKERPROFILE_NOTIFY_UUID), HI_UINT16(LOCKERPROFILE_NOTIFY_UUID) }; // stream UUID: 0xFFF2 CONST uint8 lockerStreamUUID[ATT_BT_UUID_SIZE] = { LO_UINT16(LOCKERPROFILE_STREAM_UUID), HI_UINT16(LOCKERPROFILE_STREAM_UUID) }; /********************************************************************* * LOCAL VARIABLES */ static app_input_cb_t app_input_cb = NULL; /********************************************************************* * Profile Attributes - variables */ // locker Profile Service attribute static CONST gattAttrType_t lockerProfileService = { ATT_BT_UUID_SIZE, lockerSvrUUID }; // locker Profile Notify Properties static uint8 lockerNotifyProps = GATT_PROP_NOTIFY; static uint8 lockerNotifyStream[LOCKERPROFILE_NOTIFY_MAX_LEN]; static uint8 lockerNotifyDesp[17] = "notify\0"; static gattCharCfg_t lockerNotifyConfig[GATT_MAX_NUM_CONN]; // locker Profile Stream Properties static uint8 lockerStreamProps = GATT_PROP_READ | GATT_PROP_WRITE; static uint8 lockerStream[LOCKERPROFILE_STREAM_MAX_LEN]; static uint8 lockerStreamDesp[17] = "stream\0"; /********************************************************************* * Profile Attributes - Table */ static gattAttribute_t LockerProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] = { // Simple Profile Service { { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */ GATT_PERMIT_READ, /* permissions */ 0, /* handle */ (uint8 *)&lockerProfileService /* pValue */ }, /**************notify attribute**********************/ // notify Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &lockerNotifyProps }, // notify stream buffer { { ATT_BT_UUID_SIZE, lockerNotifyUUID }, 0, 0, lockerNotifyStream }, // notify stream configuration { { ATT_BT_UUID_SIZE, clientCharCfgUUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8 *)lockerNotifyConfig }, // notify stream Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, lockerNotifyDesp }, /************************stream buffer attribute***********************/ // stream Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &lockerStreamProps }, // stream buffer { { ATT_BT_UUID_SIZE, lockerStreamUUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, lockerStream }, // stream Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, lockerStreamDesp }, }; /********************************************************************* * LOCAL FUNCTIONS */ static uint8 lockerReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen ); static bStatus_t lockerWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ); static void lockerHandleConnStatusCB( uint16 connHandle, uint8 changeType ); /********************************************************************* * PROFILE CALLBACKS */ // Simple Profile Service Callbacks CONST gattServiceCBs_t lockerProfileCBs = { lockerReadAttrCB, // Read callback function pointer lockerWriteAttrCB, // Write callback function pointer NULL // Authorization callback function pointer }; bStatus_t lockerProfile_AddService( uint32 services ,app_input_cb_t cb) { uint8 status = SUCCESS; printf("lockerProfile_AddService: \n"); // Initialize Client Characteristic Configuration attributes GATTServApp_InitCharCfg( INVALID_CONNHANDLE, lockerNotifyConfig ); // Register with Link DB to receive link status change callback VOID linkDB_Register( lockerHandleConnStatusCB ); if ( services & SIMPLEPROFILE_SERVICE ) { // Register GATT attribute list and CBs with GATT Server App status = GATTServApp_RegisterService( LockerProfileAttrTbl, GATT_NUM_ATTRS( LockerProfileAttrTbl ), &lockerProfileCBs ); } app_input_cb = cb; return ( status ); } bStatus_t locker_send( uint16 uuid,void *pdata , uint8 len) { bStatus_t ret = SUCCESS; switch ( uuid ) { case LOCKERPROFILE_NOTIFY_UUID: if ( len <= LOCKERPROFILE_NOTIFY_MAX_LEN) { printf("locker_send: uuid:%04x notify app \n",uuid); osal_memcpy(lockerNotifyStream,pdata,len); GATTServApp_ProcessCharCfg(lockerNotifyConfig,lockerNotifyStream, FALSE, LockerProfileAttrTbl, GATT_NUM_ATTRS( LockerProfileAttrTbl ), INVALID_TASK_ID ); } else { ret = bleInvalidRange; } break; case LOCKERPROFILE_STREAM_UUID: if ( len <= LOCKERPROFILE_STREAM_MAX_LEN) { printf("locker_Send: uuid:%04x write to stream buffer and waite to read \n",uuid); osal_memcpy(lockerStream,pdata,len); } else { ret = bleInvalidRange; } default: ret = INVALIDPARAMETER; break; } return ( ret ); } int locker_Read( uint16 uuid, void *pdata ) { int ret; printf("locker_Read: uuid:%04x \n",uuid); switch ( uuid ) { case LOCKERPROFILE_NOTIFY_UUID: osal_memcpy(pdata,lockerNotifyStream,LOCKERPROFILE_NOTIFY_MAX_LEN); ret = LOCKERPROFILE_NOTIFY_MAX_LEN; break; case LOCKERPROFILE_STREAM_UUID: osal_memcpy(pdata,lockerStream,LOCKERPROFILE_STREAM_MAX_LEN); ret = LOCKERPROFILE_NOTIFY_MAX_LEN; break; default: ret = -1; break; } return ( ret ); } static uint8 lockerReadAttrCB( 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]); printf("lockerProfile_ReadAttrCB: uuid:%04x \n",uuid); switch ( uuid ) { // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases; // gattserverapp handles those reads // characteristics 1 and 2 have read permissions // can be sent as a notification, it is included here case LOCKERPROFILE_NOTIFY_UUID: *pLen = LOCKERPROFILE_NOTIFY_MAX_LEN; osal_memcpy(pValue,pAttr->pValue,LOCKERPROFILE_NOTIFY_MAX_LEN); break; case LOCKERPROFILE_STREAM_UUID: *pLen = LOCKERPROFILE_STREAM_MAX_LEN; osal_memcpy(pValue,pAttr->pValue,LOCKERPROFILE_STREAM_MAX_LEN); 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 ); } static bStatus_t lockerWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; // 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]); printf("lockerProfile_WriteAttrCB: uuid:%04x \n",uuid); switch ( uuid ) { case LOCKERPROFILE_NOTIFY_UUID: status = ATT_ERR_INVALID_HANDLE; //Write the value break; case LOCKERPROFILE_STREAM_UUID: if((offset==0)&(app_input_cb!=NULL)) { if(len<=LOCKERPROFILE_STREAM_MAX_LEN) osal_memcpy(lockerStream,pValue,len); app_input_cb(LOCKERPROFILE_STREAM_UUID,pValue,len); } 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; } return ( status ); } static void lockerHandleConnStatusCB( 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 ) ) ) ) { printf("lockerProfile_HandleConnStatusCB: Reset Client Char Config if connection has dropped \n"); GATTServApp_InitCharCfg( connHandle, lockerNotifyConfig ); } } } /********************************************************************* *********************************************************************/
在simpleBLEPeripheral.c下增加input函数用于接收数据:
void input(uint16 uuid, uint8 *pdata , int len) { int i; printf("input from uuid: %04x len:%d data:",uuid,len); for(i=0;i<len;i++) printf("%02x ",pdata[i]); printf("\n"); }
初始化时:
void SimpleBLEPeripheral_Init( uint8 task_id ) { simpleBLEPeripheral_TaskID = task_id; // Setup the GAP VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL ); // Setup the GAP Peripheral Role Profile { uint8 initial_advertising_enable = TRUE; // By setting this to zero, the device will go into the waiting state after // being discoverable for 30.72 second, and will not being advertising again // until the enabler is set back to TRUE uint16 gapRole_AdvertOffTime = 0; uint8 enable_update_request = DEFAULT_ENABLE_UPDATE_REQUEST; uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; uint16 desired_slave_latency = DEFAULT_DESIRED_SLAVE_LATENCY; uint16 desired_conn_timeout = DEFAULT_DESIRED_CONN_TIMEOUT; // Set the GAP Role Parameters GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData ); GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, sizeof( uint8 ), &enable_update_request ); GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval ); GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval ); GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &desired_slave_latency ); GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &desired_conn_timeout ); } // Set the GAP Characteristics GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName ); // Set advertising interval { uint16 advInt = DEFAULT_ADVERTISING_INTERVAL; GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt ); GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, advInt ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, advInt ); } // Setup the GAP Bond Manager { uint32 passkey = 0; // passkey "000000" uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ; uint8 mitm = TRUE; uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY; uint8 bonding = TRUE; GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey ); GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode ); GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm ); GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap ); GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding ); } // Initialize GATT attributes GGS_AddService( GATT_ALL_SERVICES ); // GAP GATTServApp_AddService( GATT_ALL_SERVICES ); // GATT attributes DevInfo_AddService(); // Device Information Service lockerProfile_AddService( GATT_ALL_SERVICES,input); // Simple GATT Profile // Register for all key events - This app will handle all key events RegisterForKeys( simpleBLEPeripheral_TaskID ); // Enable clock divide on halt // This reduces active current while radio is active and CC254x MCU // is halted HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_DIVIDE_ON_HALT ); // Setup a delayed profile startup osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT ); }
good luck!!我的已经工作的,你的呢?