blob: b506dc3715cd50514d3be79772bddf59406f46ac [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2020 Texas Instruments Incorporated
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file chipOBLeProfile.c
* This file contains the CHIPOBLE profile sample GATT service profile
* for use with the BLE Manager.
*/
/*********************************************************************
* INCLUDES
*/
#include <string.h>
#include <icall.h>
#include <util.h>
#include "icall_ble_api.h"
#include "ti_ble_config.h"
#include "chipOBleProfile.h"
/*********************************************************************
* GLOBAL VARIABLES
*/
// CHIPoBLE GATT Profile Service UUID
const uint8 chipOBleServUUID[ATT_BT_UUID_SIZE] = {
// 0xF6, 0xFF
LO_UINT16(CHIPOBLE_SERV_UUID), HI_UINT16(CHIPOBLE_SERV_UUID)
};
// CHIPoBLE Tx characteristic UUID
const uint8 chipOBleProfileTxCharUUID[ATT_UUID_SIZE] = {
// 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18
CHIPOBLEPROFILE_CHAR_UUID_BASE128(CHIPOBLEPROFILE_TX_CHAR_UUID)
};
// CHIPoBLE Rx characteristic UUID
const uint8 chipOBleProfileRxCharUUID[ATT_UUID_SIZE] = {
// 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18
CHIPOBLEPROFILE_CHAR_UUID_BASE128(CHIPOBLEPROFILE_RX_CHAR_UUID)
};
/*********************************************************************
* Profile Attributes - variables
*/
// CHIPoBLE GATT Profile Service attribute
static const gattAttrType_t chipoBleProfile = { ATT_BT_UUID_SIZE, chipOBleServUUID };
// CHIPoBLE Tx Characteristic Properties
static uint8_t chipOBleProfileTxCharProps = GATT_PROP_READ | GATT_PROP_INDICATE;
// CHIPoBLE Tx Characteristic Value
static uint8_t chipOBleProfileTxCharVal[CHIPOBLEPROFILE_CHAR_LEN] = { 0x00 };
// CHIPoBLE Tx Characteristic User Description
static uint8_t chipOBleProfileTxdDataUserDesp[CHIPOBLEPROFILE_MAX_DESCRIPTION_LEN] = "ChipOBLE Tx Char";
static gattCharCfg_t * chipOBleProfileTxStateDataConfig;
// CHIPoBLE Rx Characteristic Properties
static uint8_t chipOBleProfileRxCharProps = GATT_PROP_WRITE;
// CHIPoBLE Rx Characteristic Value
static uint8_t chipOBleProfileRxCharVal[CHIPOBLEPROFILE_CHAR_LEN] = { 0x00 };
// CHIPoBLE Rx Characteristic User Description
static uint8_t chipOBleProfileRxdDataUserDesp[CHIPOBLEPROFILE_MAX_DESCRIPTION_LEN] = "ChipOBLE Rx Char";
/*********************************************************************
* LOCAL VARIABLES
*/
static chipOBleProfileCBs_t * chipOBleProfile_AppCBs = NULL;
/*********************************************************************
* Profile Attributes - Table
*/
static gattAttribute_t chipoBleProfileAttrTbl[] = {
// CHIPoBLE Service
{
{ ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
GATT_PERMIT_READ, /* permissions */
0, /* handle */
(uint8 *) &chipoBleProfile /* pValue */
},
// CHIPoBLE Tx Characteristic Declaration
{ { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &chipOBleProfileTxCharProps },
// CHIPoBLE Tx Characteristic Value
{ { ATT_UUID_SIZE, chipOBleProfileTxCharUUID }, GATT_PERMIT_READ, 0, chipOBleProfileTxCharVal },
// CHIPoBLE Tx Characteristic configuration
{ { ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *) &chipOBleProfileTxStateDataConfig },
// CHIPoBLE Tx Characteristic User Description
{ { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, chipOBleProfileTxdDataUserDesp },
// CHIPoBLE Rx Characteristic Declaration
{ { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &chipOBleProfileRxCharProps },
// CHIPoBLE Rx Characteristic Value
{ { ATT_UUID_SIZE, chipOBleProfileRxCharUUID }, GATT_PERMIT_WRITE, 0, chipOBleProfileRxCharVal },
// CHIPoBLE Rx Characteristic User Description
{ { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, chipOBleProfileRxdDataUserDesp },
};
/*********************************************************************
* LOCAL FUNCTIONS
*/
static bStatus_t CHIPoBLEProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t * pAttr, uint8_t * pValue, uint16_t * pLen,
uint16_t offset, uint16_t maxLen, uint8_t method);
static bStatus_t CHIPoBLEProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t * pAttr, uint8_t * pValue, uint16_t len,
uint16_t offset, uint8_t method);
/*********************************************************************
* PROFILE CALLBACKS
*/
// CHIPoBLE Service Callbacks
// Note: When an operation on a characteristic requires authorization and
// pfnAuthorizeAttrCB is not defined for that characteristic's service, the
// Stack will report a status of ATT_ERR_UNLIKELY to the client. When an
// operation on a characteristic requires authorization the Stack will call
// pfnAuthorizeAttrCB to check a client's authorization prior to calling
// pfnReadAttrCB or pfnWriteAttrCB, so no checks for authorization need to be
// made within these functions.
const gattServiceCBs_t chipOBleProfileCBs = {
CHIPoBLEProfile_ReadAttrCB, // Read callback function pointer
CHIPoBLEProfile_WriteAttrCB, // Write callback function pointer
NULL // Authorization callback function pointer
};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn CHIPoBLEProfile_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 CHIPoBLEProfile_AddService(uint32 services)
{
uint8 status;
// Allocate Client Characteristic Configuration tables
chipOBleProfileTxStateDataConfig = (gattCharCfg_t *) ICall_malloc((uint_least16_t) (sizeof(gattCharCfg_t) * MAX_NUM_BLE_CONNS));
if (chipOBleProfileTxStateDataConfig == NULL)
{
return bleMemAllocError;
}
// Initialize Client Characteristic Configuration attributes
GATTServApp_InitCharCfg(LL_CONNHANDLE_INVALID, chipOBleProfileTxStateDataConfig);
if (services & CHIPOBLEPROFILE_SERVICE)
{
// Register GATT attribute list and CBs with GATT Server App
status = GATTServApp_RegisterService(chipoBleProfileAttrTbl, GATT_NUM_ATTRS(chipoBleProfileAttrTbl),
GATT_MAX_ENCRYPT_KEY_SIZE, &chipOBleProfileCBs);
}
else
{
status = SUCCESS;
}
return status;
}
/*********************************************************************
* @fn CHIPoBLEProfile_RegisterAppCBs
*
* @brief Registers the application callback function. Only call
* this function once.
*
* @param callbacks - pointer to application callbacks.
*
* @return SUCCESS or bleAlreadyInRequestedMode
*/
bStatus_t CHIPoBLEProfile_RegisterAppCBs(chipOBleProfileCBs_t * appCallbacks)
{
if (appCallbacks)
{
chipOBleProfile_AppCBs = appCallbacks;
return SUCCESS;
}
else
{
return bleAlreadyInRequestedMode;
}
}
/*********************************************************************
* @fn CHIPoBLEProfile_SetParameter
*
* @brief Set a CHIPoBLE Characteristic value
*
* @param param - Profile parameter ID
* @param len - length of data to write
* @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
*/
extern uint8 gattAppTaskID;
bStatus_t CHIPoBLEProfile_SetParameter(uint8 param, uint8 len, void * value, uint8_t taskId)
{
bStatus_t ret = SUCCESS;
switch (param)
{
case CHIPOBLEPROFILE_TX_CHAR:
VOID memcpy(chipOBleProfileTxCharVal, value, len);
// See if Indications has been enabled
ret = GATTServApp_ProcessCharCfg(chipOBleProfileTxStateDataConfig, chipOBleProfileTxCharVal, FALSE, chipoBleProfileAttrTbl,
GATT_NUM_ATTRS(chipoBleProfileAttrTbl), taskId, CHIPoBLEProfile_ReadAttrCB);
break;
default:
ret = INVALIDPARAMETER;
break;
}
return ret;
}
/*********************************************************************
* @fn CHIPoBLEProfile_GetParameter
*
* @brief Get a CHIPoBLE Characteristic value
*
* @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 CHIPoBLEProfile_GetParameter(uint8 param, void * value, uint16_t len)
{
bStatus_t ret = SUCCESS;
switch (param)
{
case CHIPOBLEPROFILE_RX_CHAR:
if (len != 0)
{
VOID memcpy(value, chipOBleProfileRxCharVal, len);
}
else
{
VOID memcpy(value, chipOBleProfileRxCharVal, CHIPOBLEPROFILE_CHAR_LEN);
}
break;
case CHIPOBLEPROFILE_CCCWrite:
*((uint8 *) value) = chipOBleProfileTxStateDataConfig->value;
break;
default:
ret = INVALIDPARAMETER;
break;
}
return ret;
}
/*********************************************************************
* @fn CHIPoBLEProfile_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
* @param method - type of read message
*
* @return SUCCESS, blePending or Failure
*/
static bStatus_t CHIPoBLEProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t * pAttr, uint8_t * pValue, uint16_t * pLen,
uint16_t offset, uint16_t maxLen, uint8_t method)
{
bStatus_t status = SUCCESS;
uint8 len = maxLen;
if (offset + maxLen > CHIPOBLEPROFILE_CHAR_LEN)
len = CHIPOBLEPROFILE_CHAR_LEN - offset;
*pLen = len;
VOID osal_memcpy(pValue, (pAttr->pValue) + offset, len);
return status;
}
/*********************************************************************
* @fn CHIPoBLEProfile_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 method - type of write message
*
* @return SUCCESS, blePending or Failure
*/
static bStatus_t CHIPoBLEProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t * pAttr, uint8_t * pValue, uint16_t len,
uint16_t offset, uint8_t method)
{
bStatus_t status = SUCCESS;
uint8 notifyApp = 0xFF;
if (pAttr->type.len == ATT_UUID_SIZE)
{
if (!memcmp(pAttr->type.uuid, chipOBleProfileRxCharUUID, pAttr->type.len))
{
VOID osal_memcpy((pAttr->pValue) + offset, pValue, len);
// Send notification to BLE Event handler
notifyApp = CHIPOBLEPROFILE_RX_CHAR;
}
else
{
status = ATT_ERR_ATTR_NOT_FOUND;
}
}
else if ((pAttr->type.len == ATT_BT_UUID_SIZE) &&
(BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]) == GATT_CLIENT_CHAR_CFG_UUID))
{
notifyApp = CHIPOBLEPROFILE_CCCWrite;
status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_INDICATE);
}
else
{
// unsupported length
status = ATT_ERR_INVALID_HANDLE;
}
// If a characteristic value changed then callback function to notify application of change
if ((notifyApp != 0xFF) && chipOBleProfile_AppCBs && chipOBleProfile_AppCBs->pfnchipOBleProfileChange)
{
chipOBleProfile_AppCBs->pfnchipOBleProfileChange(notifyApp, len, connHandle);
}
return status;
}