/** * @file * @author chipsea * @brief * @version 0.1 * @date 2020-11-30 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd. * @note */ /********************************************************************* * INCLUDES */ #include "bcomdef.h" #include "OSAL.h" #include "att.h" #include "gatt.h" #include "gatt_uuid.h" #include "gattservapp.h" #include "gatt_profile_uuid.h" #include "gapbondmgr.h" #include "linkdb.h" #include "scanparamservice.h" /********************************************************************* * MACROS */ /********************************************************************* * CONSTANTS */ /********************************************************************* * TYPEDEFS */ /********************************************************************* * GLOBAL VARIABLES */ // Scan parameters service CONST uint8 scanParamServUUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SCAN_PARAM_SERV_UUID), HI_UINT16(SCAN_PARAM_SERV_UUID) }; // Scan interval window characteristic CONST uint8 scanIntervalWindowUUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SCAN_INTERVAL_WINDOW_UUID), HI_UINT16(SCAN_INTERVAL_WINDOW_UUID) }; // Scan parameter refresh characteristic CONST uint8 scanParamRefreshUUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SCAN_REFRESH_UUID), HI_UINT16(SCAN_REFRESH_UUID) }; /********************************************************************* * EXTERNAL VARIABLES */ /********************************************************************* * EXTERNAL FUNCTIONS */ /********************************************************************* * LOCAL VARIABLES */ // Application callback static scanParamServiceCB_t scanParamServiceCB; /********************************************************************* * Profile Attributes - variables */ // Scan Parameters Service attribute static CONST gattAttrType_t scanParamService = { ATT_BT_UUID_SIZE, scanParamServUUID }; // Scan Interval Window characteristic static uint8 scanIntervalWindowProps = GATT_PROP_WRITE_NO_RSP; static uint8 scanIntervalWindow[SCAN_INTERVAL_WINDOW_CHAR_LEN]; // Scan Parameter Refresh characteristic static uint8 scanParamRefreshProps = GATT_PROP_NOTIFY; static uint8 scanParamRefresh[SCAN_PARAM_REFRESH_LEN]; static gattCharCfg_t scanParamRefreshClientCharCfg[GATT_MAX_NUM_CONN]; /********************************************************************* * Profile Attributes - Table */ static gattAttribute_t scanParamAttrTbl[] = { // Scan Parameters Service attribute { { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */ GATT_PERMIT_READ, /* permissions */ 0, /* handle */ (uint8 *)&scanParamService /* pValue */ }, // Scan Interval Window declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &scanIntervalWindowProps }, // Scan Interval Window characteristic { { ATT_BT_UUID_SIZE, scanIntervalWindowUUID }, GATT_PERMIT_ENCRYPT_WRITE, 0, scanIntervalWindow }, // Scan Parameter Refresh declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &scanParamRefreshProps }, // Scan Parameter Refresh characteristic { { ATT_BT_UUID_SIZE, scanParamRefreshUUID }, 0, 0, scanParamRefresh }, // Scan Parameter Refresh characteristic client characteristic configuration { { ATT_BT_UUID_SIZE, clientCharCfgUUID }, GATT_PERMIT_READ | GATT_PERMIT_ENCRYPT_WRITE, 0, (uint8 *) &scanParamRefreshClientCharCfg } }; // Attribute index enumeration-- these indexes match array elements above enum { SCAN_PARAM_SERVICE_IDX, // Scan Parameters Service SCAN_PARAM_INTERVAL_DECL_IDX, // Scan Interval Window declaration SCAN_PARAM_INTERVAL_IDX, // Scan Interval Window characteristic SCAN_PARAM_REFRESH_DECL_IDX, // Scan Parameter Refresh declaration SCAN_PARAM_REFRESH_IDX, // Scan Parameter Refresh characteristic SCAN_PARAM_REFRESH_CCCD_IDX // Scan Parameter Refresh characteristic client characteristic configuration }; /********************************************************************* * LOCAL FUNCTIONS */ static bStatus_t scanParamWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 len, uint16 offset ); static uint8 scanParamReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 *pLen, uint16 offset, uint8 maxLen ); /********************************************************************* * PROFILE CALLBACKS */ // Service Callbacks CONST gattServiceCBs_t scanParamCBs = { scanParamReadAttrCB, // Read callback function pointer scanParamWriteAttrCB, // Write callback function pointer NULL // Authorization callback function pointer }; /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn ScanParam_AddService * * @brief Initializes the Battery Service by registering * GATT attributes with the GATT server. * * @return Success or Failure */ bStatus_t ScanParam_AddService( void ) { uint8 status = SUCCESS; // Initialize Client Characteristic Configuration attributes GATTServApp_InitCharCfg( INVALID_CONNHANDLE, scanParamRefreshClientCharCfg ); // Register GATT attribute list and CBs with GATT Server App status = GATTServApp_RegisterService( scanParamAttrTbl, GATT_NUM_ATTRS( scanParamAttrTbl ), &scanParamCBs ); return ( status ); } /********************************************************************* * @fn ScanParam_Register * * @brief Register a callback function with the Battery Service. * * @param pfnServiceCB - Callback function. * * @return None. */ extern void ScanParam_Register( scanParamServiceCB_t pfnServiceCB ) { scanParamServiceCB = pfnServiceCB; } /********************************************************************* * @fn ScanParam_SetParameter * * @brief Set a Battery Service 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 ScanParam_SetParameter( uint8 param, uint8 len, void *value ) { bStatus_t ret = SUCCESS; switch ( param ) { default: ret = INVALIDPARAMETER; break; } return ( ret ); } /********************************************************************* * @fn ScanParam_GetParameter * * @brief Get a Battery Service parameter. * * @param param - Profile parameter ID * @param value - pointer to data to get. 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 ScanParam_GetParameter( uint8 param, void *value ) { bStatus_t ret = SUCCESS; switch ( param ) { case SCAN_PARAM_PARAM_INTERVAL: *((uint16*)value) = BUILD_UINT16(scanIntervalWindow[0], scanIntervalWindow[1]); break; case SCAN_PARAM_PARAM_WINDOW: *((uint16*)value) = BUILD_UINT16(scanIntervalWindow[2], scanIntervalWindow[3]); break; default: ret = INVALIDPARAMETER; break; } return ( ret ); } /********************************************************************* * @fn ScanParam_RefreshNotify * * @brief Notify the peer to refresh the scan parameters. * * @param connHandle - connection handle * * @return None */ void ScanParam_RefreshNotify( uint16 connHandle ) { attHandleValueNoti_t noti; uint16 value; value = GATTServApp_ReadCharCfg( connHandle, scanParamRefreshClientCharCfg ); if ( value & GATT_CLIENT_CFG_NOTIFY ) { // send notification noti.handle = scanParamAttrTbl[SCAN_PARAM_REFRESH_CCCD_IDX].handle; noti.len = SCAN_PARAM_REFRESH_LEN; noti.value[0] = SCAN_PARAM_REFRESH_REQ; GATT_Notification( connHandle, ¬i, FALSE ); } } /********************************************************************* * @fn scanParamReadAttrCB * * @brief GATT read callback. * * @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 scanParamReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 *pLen, uint16 offset, uint8 maxLen ) { bStatus_t status = SUCCESS; return ( status ); } /********************************************************************* * @fn scanParamWriteAttrCB * * @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 scanParamWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 len, uint16 offset ) { bStatus_t status = SUCCESS; // Make sure it's not a blob operation (no attributes in the profile are long) if ( offset > 0 ) { return ( ATT_ERR_ATTR_NOT_LONG ); } uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); // Only one writeable attribute if ( uuid == SCAN_INTERVAL_WINDOW_UUID ) { if ( len == SCAN_INTERVAL_WINDOW_CHAR_LEN ) { uint16 interval = BUILD_UINT16( pValue[0], pValue[1] ); uint16 window = BUILD_UINT16( pValue[0], pValue[1] ); // Validate values if ( window <= interval ) { osal_memcpy( pAttr->pValue, pValue, len ); (*scanParamServiceCB)( SCAN_INTERVAL_WINDOW_SET ); } else { status = ATT_ERR_INVALID_VALUE; } } else { status = ATT_ERR_INVALID_VALUE_SIZE; } } else if ( uuid == GATT_CLIENT_CHAR_CFG_UUID ) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); } else { status = ATT_ERR_ATTR_NOT_FOUND; } return ( status ); } /********************************************************************* * @fn ScanParam_HandleConnStatusCB * * @brief Service link status change handler function. * * @param connHandle - connection handle * @param changeType - type of change * * @return none */ void ScanParam_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, scanParamRefreshClientCharCfg ); } } }