424 lines
12 KiB
C
424 lines
12 KiB
C
/**************************************************************************************************
|
|
Filename: sbpProfile.c
|
|
Revised:
|
|
Revision:
|
|
Description: This file contains the Simple GATT profile sample GATT service
|
|
profile for use with the BLE sample application.
|
|
**************************************************************************************************/
|
|
|
|
/*********************************************************************
|
|
INCLUDES
|
|
*/
|
|
#include "bcomdef.h"
|
|
#include "config.h"
|
|
#include "OSAL.h"
|
|
#include "linkdb.h"
|
|
#include "att.h"
|
|
#include "gatt.h"
|
|
#include "gatt_uuid.h"
|
|
#include "gattservapp.h"
|
|
#include "gapbondmgr.h"
|
|
//#include "log.h"
|
|
#include "thb2_peripheral.h"
|
|
#include "bleperipheral.h"
|
|
#include "sbp_profile.h"
|
|
#include "cmd_parcer.h"
|
|
|
|
/*********************************************************************
|
|
* MACROS
|
|
*/
|
|
|
|
/*********************************************************************
|
|
* CONSTANTS
|
|
*/
|
|
/*********************************************************************
|
|
* TYPEDEFS
|
|
*/
|
|
|
|
/*********************************************************************
|
|
* GLOBAL VARIABLES
|
|
*/
|
|
// Simple GATT Profile Service UUID: 0xFFF0
|
|
CONST uint8_t simpleProfileServUUID[ATT_BT_UUID_SIZE] =
|
|
{
|
|
LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)
|
|
};
|
|
|
|
// Characteristic 1 UUID: 0xFFF3
|
|
CONST uint8_t simpleProfilechar1UUID[ATT_BT_UUID_SIZE] =
|
|
{
|
|
LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID)
|
|
};
|
|
|
|
// Characteristic 2 UUID: 0xFFF4
|
|
CONST uint8_t 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;
|
|
//static uint8_t ReadNotify_Len = 0;
|
|
|
|
/*********************************************************************
|
|
* Profile Attributes - variables
|
|
*/
|
|
|
|
// Simple Profile Service attribute 0xFFF0
|
|
static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID };
|
|
|
|
|
|
// Simple Profile Characteristic 1 Properties
|
|
static CONST uint8_t simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP;
|
|
//static CONST uint8_t simpleProfileChar1UserDesp[] = "OTA\0"; // Simple Profile Characteristic 1 User Description
|
|
|
|
static uint8_t ota_in_buffer[20]; // Characteristic 1 Value
|
|
static uint8_t ota_in_len;
|
|
|
|
// Simple Profile Characteristic 2 Properties
|
|
static CONST uint8_t simpleProfileChar2Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP | GATT_PROP_NOTIFY;
|
|
//static CONST uint8_t simpleProfileChar2UserDesp[] = "CMD\0"; // Simple Profile Characteristic 2 User Description
|
|
static gattCharCfg_t simpleProfileChar2Config[GATT_MAX_NUM_CONN]; //
|
|
|
|
static uint8_t cmd_in_buffer[32]; // Characteristic 2 Value
|
|
static uint8_t cmd_in_len; // Characteristic 2 Value
|
|
|
|
/*********************************************************************
|
|
* Profile Attributes - Table
|
|
*/
|
|
|
|
#define SERVAPP_NUM_ATTR_SUPPORTED 6
|
|
#define OTA_DATA_ATTR_IDX 2 // Position of OTA in attribute array
|
|
#define CDM_DATA_ATTR_IDX 4 // Position of CMD in attribute array
|
|
|
|
static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
|
|
{
|
|
// Simple Profile Service
|
|
{
|
|
{ ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
|
|
GATT_PERMIT_READ, /* permissions */
|
|
0, /* handle */
|
|
(uint8_t *)&simpleProfileService /* pValue */
|
|
},
|
|
|
|
// Characteristic 1 Declaration
|
|
{
|
|
{ ATT_BT_UUID_SIZE, characterUUID },
|
|
GATT_PERMIT_READ,
|
|
0,
|
|
(uint8_t *)&simpleProfileChar1Props
|
|
},
|
|
// Characteristic Value 1
|
|
{
|
|
{ ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
|
|
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
|
|
0,
|
|
(uint8_t *)&ota_in_buffer[0]
|
|
},
|
|
#if 0
|
|
// Characteristic 1 User Description
|
|
{
|
|
{ ATT_BT_UUID_SIZE, charUserDescUUID },
|
|
GATT_PERMIT_READ,
|
|
0,
|
|
(uint8_t *)simpleProfileChar1UserDesp
|
|
},
|
|
#endif
|
|
// Characteristic 2 Declaration
|
|
{
|
|
{ ATT_BT_UUID_SIZE, characterUUID },
|
|
GATT_PERMIT_READ,
|
|
0,
|
|
(uint8_t *)&simpleProfileChar2Props
|
|
},
|
|
// Characteristic Value 2
|
|
{
|
|
{ ATT_BT_UUID_SIZE, simpleProfilechar2UUID },
|
|
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
|
|
0,
|
|
(uint8_t *)&cmd_in_buffer[0]
|
|
},
|
|
// Characteristic 2 configuration
|
|
{
|
|
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
|
|
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
|
|
0,
|
|
(uint8_t *)simpleProfileChar2Config
|
|
},
|
|
#if 0
|
|
// Characteristic 2 User Description
|
|
{
|
|
{ ATT_BT_UUID_SIZE, charUserDescUUID },
|
|
GATT_PERMIT_READ,
|
|
0,
|
|
(uint8_t *)simpleProfileChar2UserDesp
|
|
},
|
|
#endif
|
|
};
|
|
|
|
|
|
/*********************************************************************
|
|
* LOCAL FUNCTIONS
|
|
*/
|
|
static bStatus_t simpleProfile_ReadAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint8_t maxLen );
|
|
static bStatus_t simpleProfile_WriteAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,uint8_t *pValue, uint16_t len, uint16_t offset );
|
|
static void simpleProfile_HandleConnStatusCB( uint16_t connHandle, uint8_t 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_t services )
|
|
{
|
|
uint8_t 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_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 bStatus_t simpleProfile_ReadAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,
|
|
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint8_t maxLen )
|
|
{
|
|
(void)connHandle;
|
|
(void)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_t uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
|
switch ( uuid )
|
|
{
|
|
// No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
|
|
// gattserverapp handles those reads
|
|
case SIMPLEPROFILE_CHAR1_UUID:
|
|
*pLen = sizeof(ota_in_buffer);
|
|
osal_memcpy( pValue, pAttr->pValue, *pLen );
|
|
LOG("Read_UUID1:\n");
|
|
break;
|
|
case SIMPLEPROFILE_CHAR2_UUID:
|
|
*pLen = sizeof(cfg);
|
|
osal_memcpy( pValue, &cfg, *pLen );
|
|
LOG("Read_UUID2:\n");
|
|
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
|
|
*
|
|
* @return Success or Failure
|
|
*/
|
|
static bStatus_t simpleProfile_WriteAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,
|
|
uint8_t *pValue, uint16_t len, uint16_t 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_t 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 > sizeof(ota_in_buffer))
|
|
status = ATT_ERR_INVALID_VALUE_SIZE;
|
|
} else
|
|
status = ATT_ERR_ATTR_NOT_LONG;
|
|
|
|
//Write the value
|
|
if ( status == SUCCESS) {
|
|
osal_memcpy( pAttr->pValue, pValue, len );
|
|
ota_in_len = len;
|
|
}
|
|
break;
|
|
|
|
case SIMPLEPROFILE_CHAR2_UUID:
|
|
// Validate the value
|
|
// Make sure it's not a blob oper
|
|
if ( offset == 0 ) {
|
|
if ( len > sizeof(cmd_in_buffer))
|
|
status = ATT_ERR_INVALID_VALUE_SIZE;
|
|
} else
|
|
status = ATT_ERR_ATTR_NOT_LONG;
|
|
// Write the value
|
|
if ( status == SUCCESS ) {
|
|
osal_memcpy(pAttr->pValue, pValue, len );
|
|
cmd_in_len = len;
|
|
LOG("receive data = 0x ");
|
|
LOG_DUMP_BYTE(pCurValue, len);
|
|
osal_set_event(simpleBLEPeripheral_TaskID, SBP_DEALDATA);
|
|
}
|
|
break;
|
|
|
|
case GATT_CLIENT_CHAR_CFG_UUID:
|
|
LOG("Enable/Disable Notity\n");
|
|
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 );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @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_t connHandle, uint8_t 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 );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void new_cmd(void) {
|
|
attHandleValueNoti_t noti;
|
|
noti.handle = simpleProfileAttrTbl[CDM_DATA_ATTR_IDX].handle;
|
|
noti.len = cmd_parser(noti.value, cmd_in_buffer, cmd_in_len);
|
|
if(noti.len) {
|
|
GATT_Notification(gapRole_ConnectionHandle, ¬i, FALSE );
|
|
}
|
|
}
|