Fork ESP-IDF's bluetooth component

i want better sbc encoding, and no cla will stop me
This commit is contained in:
jacqueline
2024-03-28 14:32:49 +11:00
parent 239e6d8950
commit ee29c25b29
1761 changed files with 737738 additions and 0 deletions
@@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/******************************************************************************
*
* This file contains the action functions for gatts and gattc.
*
*
******************************************************************************/
#include "bta/bta_gatt_common.h"
#include "gatt_int.h"
void BTA_GATT_SetLocalMTU(uint16_t mtu)
{
gatt_set_local_mtu(mtu);
}
uint16_t BTA_GATT_GetLocalMTU(void)
{
return gatt_get_local_mtu();
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,137 @@
/******************************************************************************
*
* Copyright (C) 2010-2012 Broadcom Corporation
*
* 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.
*
******************************************************************************/
/******************************************************************************
*
* This is the implementation file for the GATT call-in functions.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(GATTC_INCLUDED) && (GATTC_INCLUDED == TRUE)
#include <string.h>
#include "bta/bta_api.h"
#include "bta/bta_sys.h"
#include "bta/bta_gattc_ci.h"
#include "bta/utl.h"
#include "osi/allocator.h"
/*******************************************************************************
**
** Function bta_gattc_ci_cache_open
**
** Description This function sends an event to indicate server cache open
** completed.
**
** Parameters server_bda - server BDA of this cache.
** status - BTA_GATT_OK if full buffer of data,
** BTA_GATT_FAIL if an error has occurred.
**
** Returns void
**
*******************************************************************************/
void bta_gattc_ci_cache_open(BD_ADDR server_bda, UINT16 evt, tBTA_GATT_STATUS status,
UINT16 conn_id)
{
tBTA_GATTC_CI_EVT *p_evt;
UNUSED(server_bda);
if ((p_evt = (tBTA_GATTC_CI_EVT *) osi_malloc(sizeof(tBTA_GATTC_CI_EVT))) != NULL) {
p_evt->hdr.event = evt;
p_evt->hdr.layer_specific = conn_id;
p_evt->status = status;
bta_sys_sendmsg(p_evt);
}
}
/*******************************************************************************
**
** Function bta_gattc_ci_cache_load
**
** Description This function sends an event to BTA indicating the phone has
** load the servere cache and ready to send it to the stack.
**
** Parameters server_bda - server BDA of this cache.
** num_bytes_read - number of bytes read into the buffer
** specified in the read callout-function.
** status - BTA_GATT_OK if full buffer of data,
** BTA_GATT_FAIL if an error has occurred.
**
** Returns void
**
*******************************************************************************/
void bta_gattc_ci_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
tBTA_GATTC_NV_ATTR *p_attr, tBTA_GATT_STATUS status,
UINT16 conn_id)
{
tBTA_GATTC_CI_LOAD *p_evt;
UNUSED(server_bda);
if ((p_evt = (tBTA_GATTC_CI_LOAD *) osi_malloc(sizeof(tBTA_GATTC_CI_LOAD))) != NULL) {
memset(p_evt, 0, sizeof(tBTA_GATTC_CI_LOAD));
p_evt->hdr.event = evt;
p_evt->hdr.layer_specific = conn_id;
p_evt->status = status;
p_evt->num_attr = (num_attr > BTA_GATTC_NV_LOAD_MAX) ? BTA_GATTC_NV_LOAD_MAX : num_attr;
if (p_evt->num_attr > 0 && p_attr != NULL) {
memcpy(p_evt->attr, p_attr, p_evt->num_attr * sizeof(tBTA_GATTC_NV_ATTR));
}
bta_sys_sendmsg(p_evt);
}
}
/*******************************************************************************
**
** Function bta_gattc_ci_cache_save
**
** Description This function sends an event to BTA indicating the phone has
** save the servere cache.
**
** Parameters server_bda - server BDA of this cache.
** evt - callin event code.
** status - BTA_GATT_OK if full buffer of data,
** BTA_GATT_ERROR if an error has occurred.
*8 conn_id - for this NV operation for.
**
** Returns void
**
*******************************************************************************/
void bta_gattc_ci_cache_save(BD_ADDR server_bda, UINT16 evt, tBTA_GATT_STATUS status,
UINT16 conn_id)
{
tBTA_GATTC_CI_EVT *p_evt;
UNUSED(server_bda);
if ((p_evt = (tBTA_GATTC_CI_EVT *) osi_malloc(sizeof(tBTA_GATTC_CI_EVT))) != NULL) {
p_evt->hdr.event = evt;
p_evt->hdr.layer_specific = conn_id;
p_evt->status = status;
bta_sys_sendmsg(p_evt);
}
}
#endif /* GATTC_INCLUDED */
@@ -0,0 +1,693 @@
/******************************************************************************
*
* Copyright (C) 2009-2013 Broadcom Corporation
*
* 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.
*
******************************************************************************/
#ifdef BT_SUPPORT_NVM
#include <unistd.h>
#endif /* BT_SUPPORT_NVM */
#include <string.h>
#include <stdio.h>
#include "bta/bta_gattc_co.h"
#include "bta/bta_gattc_ci.h"
// #include "btif_util.h"
#include "btm_int.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "osi/list.h"
#include "esp_err.h"
#include "osi/allocator.h"
#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
#if( defined BTA_GATT_INCLUDED ) && (GATTC_INCLUDED == TRUE)
// #if( defined GATTC_CACHE_NVS ) && (GATTC_CACHE_NVS == TRUE)
#define GATT_CACHE_PREFIX "gatt_"
#define INVALID_ADDR_NUM 0xff
#define MAX_DEVICE_IN_CACHE 50
#define MAX_ADDR_LIST_CACHE_BUF 2048
#ifdef BT_SUPPORT_NVM
static FILE *sCacheFD = 0;
static void getFilename(char *buffer, BD_ADDR bda)
{
sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX
, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
}
static void cacheClose(void)
{
if (sCacheFD != 0) {
fclose(sCacheFD);
sCacheFD = 0;
}
}
static bool cacheOpen(BD_ADDR bda, bool to_save)
{
char fname[255] = {0};
getFilename(fname, bda);
cacheClose();
sCacheFD = fopen(fname, to_save ? "w" : "r");
return (sCacheFD != 0);
}
static void cacheReset(BD_ADDR bda)
{
char fname[255] = {0};
getFilename(fname, bda);
unlink(fname);
}
#else
static const char *cache_key = "gattc_cache_key";
static const char *cache_addr = "cache_addr_tab";
typedef struct {
//save the service data in the list according to the address
nvs_handle_t cache_fp;
BOOLEAN is_open;
BD_ADDR addr;
hash_key_t hash_key;
list_t *assoc_addr;
}cache_addr_info_t;
typedef struct {
//save the address list in the cache
nvs_handle_t addr_fp;
BOOLEAN is_open;
UINT8 num_addr;
cache_addr_info_t cache_addr[MAX_DEVICE_IN_CACHE];
}cache_env_t;
static cache_env_t *cache_env = NULL;
static void getFilename(char *buffer, hash_key_t hash)
{
sprintf(buffer, "%s%02x%02x%02x%02x", GATT_CACHE_PREFIX,
hash[0], hash[1], hash[2], hash[3]);
}
static void cacheClose(BD_ADDR bda)
{
UINT8 index = 0;
if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) {
if (cache_env->cache_addr[index].is_open) {
nvs_close(cache_env->cache_addr[index].cache_fp);
cache_env->cache_addr[index].is_open = FALSE;
}
}
}
static bool cacheOpen(BD_ADDR bda, bool to_save, UINT8 *index)
{
UNUSED(to_save);
char fname[255] = {0};
UINT8 *assoc_addr = NULL;
esp_err_t status = ESP_FAIL;
hash_key_t hash_key = {0};
if (((*index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) ||
((assoc_addr = bta_gattc_co_cache_find_src_addr(bda, index)) != NULL)) {
if (cache_env->cache_addr[*index].is_open) {
return TRUE;
} else {
memcpy(hash_key, cache_env->cache_addr[*index].hash_key, sizeof(hash_key_t));
getFilename(fname, hash_key);
if ((status = nvs_open(fname, NVS_READWRITE, &cache_env->cache_addr[*index].cache_fp)) == ESP_OK) {
// Set the open flag to TRUE when success to open the hash file.
cache_env->cache_addr[*index].is_open = TRUE;
}
}
}
return ((status == ESP_OK) ? true : false);
}
static void cacheReset(BD_ADDR bda, BOOLEAN update)
{
char fname[255] = {0};
getFilename(fname, bda);
UINT8 index = 0;
//cache_env->cache_addr
if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) {
//clear the association address pending in the source address.
bta_gattc_co_cache_clear_assoc_addr(bda);
if (cache_env->cache_addr[index].is_open) {
nvs_erase_all(cache_env->cache_addr[index].cache_fp);
nvs_close(cache_env->cache_addr[index].cache_fp);
cache_env->cache_addr[index].is_open = FALSE;
} else {
cacheOpen(bda, false, &index);
if (index == INVALID_ADDR_NUM) {
APPL_TRACE_ERROR("%s INVALID ADDR NUM", __func__);
return;
}
if (cache_env->cache_addr[index].is_open) {
nvs_erase_all(cache_env->cache_addr[index].cache_fp);
nvs_close(cache_env->cache_addr[index].cache_fp);
cache_env->cache_addr[index].is_open = FALSE;
} else {
APPL_TRACE_ERROR("%s cacheOpen failed", __func__);
return;
}
}
if(cache_env->num_addr == 0) {
APPL_TRACE_ERROR("%s cache addr list error", __func__);
return;
}
UINT8 num = cache_env->num_addr;
//delete the server_bda in the addr_info list.
for(UINT8 i = index; i < (num - 1); i++) {
memcpy(&cache_env->cache_addr[i], &cache_env->cache_addr[i+1], sizeof(cache_addr_info_t));
}
//clear the last cache when delete a addr
memset(&cache_env->cache_addr[num-1], 0, sizeof(cache_addr_info_t));
//reduced the number address counter also
cache_env->num_addr--;
//don't need to update addr list to nvs flash
if (!update) {
return;
}
//update addr list to nvs flash
if(cache_env->num_addr > 0) {
//update
UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
if(!p_buf) {
APPL_TRACE_ERROR("%s malloc error", __func__);
return;
}
UINT16 length = cache_env->num_addr*(sizeof(BD_ADDR) + sizeof(hash_key_t));
for (UINT8 i = 0; i < cache_env->num_addr; i++) {
//copy the address to the buffer.
memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)), cache_env->cache_addr[i].addr, sizeof(BD_ADDR));
//copy the hash key to the buffer.
memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)) + sizeof(BD_ADDR),
cache_env->cache_addr[i].hash_key, sizeof(hash_key_t));
}
if (cache_env->is_open) {
if (nvs_set_blob(cache_env->addr_fp, cache_key, p_buf, length) != ESP_OK) {
APPL_TRACE_WARNING("%s, nvs set blob failed", __func__);
}
}
osi_free(p_buf);
} else {
//erase
if (cache_env->is_open) {
nvs_erase_all(cache_env->addr_fp);
nvs_close(cache_env->addr_fp);
cache_env->is_open = FALSE;
} else {
APPL_TRACE_WARNING("cache_env status is error");
}
}
}
}
#endif /* BT_SUPPORT_NVM */
/*****************************************************************************
** Function Declarations
*****************************************************************************/
/*******************************************************************************
**
** Function bta_gattc_co_cache_open
**
** Description This callout function is executed by GATTC when a GATT server
** cache is ready to be sent.
**
** Parameter server_bda: server bd address of this cache belongs to
** evt: call in event to be passed in when cache open is done.
** conn_id: connection ID of this cache operation attach to.
** to_save: open cache to save or to load.
**
** Returns void.
**
*******************************************************************************/
tBTA_GATT_STATUS bta_gattc_co_cache_open(BD_ADDR server_bda, BOOLEAN to_save, UINT8 *index)
{
/* open NV cache and send call in */
tBTA_GATT_STATUS status = BTA_GATT_OK;
if (!cacheOpen(server_bda, to_save, index)) {
status = BTA_GATT_ERROR;
}
APPL_TRACE_DEBUG("%s() - status=%d", __func__, status);
return status;
}
/*******************************************************************************
**
** Function bta_gattc_co_cache_load
**
** Description This callout function is executed by GATT when server cache
** is required to load.
**
** Parameter server_bda: server bd address of this cache belongs to
** evt: call in event to be passed in when cache save is done.
** num_attr: number of attribute to be save.
** attr_index: starting attribute index of the save operation.
** conn_id: connection ID of this cache operation attach to.
** Returns
**
*******************************************************************************/
tBTA_GATT_STATUS bta_gattc_co_cache_load(tBTA_GATTC_NV_ATTR *attr, UINT8 index)
{
#if (!CONFIG_BT_STACK_NO_LOG)
UINT16 num_attr = 0;
#endif
tBTA_GATT_STATUS status = BTA_GATT_ERROR;
size_t length = 0;
// Read the size of memory space required for blob
nvs_get_blob(cache_env->cache_addr[index].cache_fp, cache_key, NULL, &length);
// Read previously saved blob if available
esp_err_t err_code = nvs_get_blob(cache_env->cache_addr[index].cache_fp, cache_key, attr, &length);
#if (!CONFIG_BT_STACK_NO_LOG)
num_attr = length / sizeof(tBTA_GATTC_NV_ATTR);
#endif
status = (err_code == ESP_OK && length != 0) ? BTA_GATT_OK : BTA_GATT_ERROR;
APPL_TRACE_DEBUG("%s() - read=%d, status=%d, err_code = %d",
__func__, num_attr, status, err_code);
return status;
}
size_t bta_gattc_get_cache_attr_length(UINT8 index)
{
size_t length = 0;
if (index == INVALID_ADDR_NUM) {
return 0;
}
// Read the size of memory space required for blob
nvs_get_blob(cache_env->cache_addr[index].cache_fp, cache_key, NULL, &length);
return length;
}
/*******************************************************************************
**
** Function bta_gattc_co_cache_save
**
** Description This callout function is executed by GATT when a server cache
** is available to save.
**
** Parameter server_bda: server bd address of this cache belongs to
** evt: call in event to be passed in when cache save is done.
** num_attr: number of attribute to be save.
** p_attr: pointer to the list of attributes to save.
** attr_index: starting attribute index of the save operation.
** conn_id: connection ID of this cache operation attach to.
** Returns
**
*******************************************************************************/
void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 num_attr,
tBTA_GATTC_NV_ATTR *p_attr_list)
{
tBTA_GATT_STATUS status = BTA_GATT_OK;
hash_key_t hash_key = {0};
UINT8 index = INVALID_ADDR_NUM;
//calculate the hash value of the attribute table which should be added to the nvs flash.
hash_function_blob((unsigned char *)p_attr_list, sizeof(tBTA_GATTC_NV_ATTR)*num_attr, hash_key);
//save the address list to the nvs flash
bta_gattc_co_cache_addr_save(server_bda, hash_key);
if (cacheOpen(server_bda, TRUE, &index)) {
esp_err_t err_code = nvs_set_blob(cache_env->cache_addr[index].cache_fp, cache_key,
p_attr_list, sizeof(tBTA_GATTC_NV_ATTR)*num_attr);
status = (err_code == ESP_OK) ? BTA_GATT_OK : BTA_GATT_ERROR;
} else {
status = BTA_GATT_ERROR;
}
#if CONFIG_BT_STACK_NO_LOG
(void) status;
#endif
APPL_TRACE_DEBUG("%s() wrote hash_key = %x%x%x%x, num_attr = %d, status = %d.", __func__, hash_key[0], hash_key[1], hash_key[2], hash_key[3], num_attr, status);
}
/*******************************************************************************
**
** Function bta_gattc_co_cache_close
**
** Description This callout function is executed by GATTC when a GATT server
** cache is written completely.
**
** Parameter server_bda: server bd address of this cache belongs to
** conn_id: connection ID of this cache operation attach to.
**
** Returns void.
**
*******************************************************************************/
void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
{
UNUSED(conn_id);
//#ifdef BT_SUPPORT_NVM
cacheClose(server_bda);
//#endif /* BT_SUPPORT_NVM */
/* close NV when server cache is done saving or loading,
does not need to do anything for now on Insight */
BTIF_TRACE_DEBUG("%s()", __FUNCTION__);
}
/*******************************************************************************
**
** Function bta_gattc_co_cache_reset
**
** Description This callout function is executed by GATTC to reset cache in
** application
**
** Parameter server_bda: server bd address of this cache belongs to
**
** Returns void.
**
*******************************************************************************/
void bta_gattc_co_cache_reset(BD_ADDR server_bda)
{
cacheReset(server_bda, TRUE);
}
void bta_gattc_co_cache_addr_init(void)
{
nvs_handle_t fp;
esp_err_t err_code;
UINT8 num_addr;
size_t length = MAX_ADDR_LIST_CACHE_BUF;
UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
if (p_buf == NULL) {
APPL_TRACE_ERROR("%s malloc failed!", __func__);
return;
}
cache_env = (cache_env_t *)osi_malloc(sizeof(cache_env_t));
if (cache_env == NULL) {
APPL_TRACE_ERROR("%s malloc failed!", __func__);
osi_free(p_buf);
return;
}
memset(cache_env, 0x0, sizeof(cache_env_t));
if ((err_code = nvs_open(cache_addr, NVS_READWRITE, &fp)) == ESP_OK) {
cache_env->addr_fp = fp;
cache_env->is_open = TRUE;
// Read previously saved blob if available
if ((err_code = nvs_get_blob(fp, cache_key, p_buf, &length)) != ESP_OK) {
if(err_code != ESP_ERR_NVS_NOT_FOUND) {
APPL_TRACE_ERROR("%s, Line = %d, nvs flash get blob data fail, err_code = 0x%x", __func__, __LINE__, err_code);
}
osi_free(p_buf);
return;
}
num_addr = length / (sizeof(BD_ADDR) + sizeof(hash_key_t));
cache_env->num_addr = num_addr;
//read the address from nvs flash to cache address list.
for (UINT8 i = 0; i < num_addr; i++) {
memcpy(cache_env->cache_addr[i].addr, p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)), sizeof(BD_ADDR));
memcpy(cache_env->cache_addr[i].hash_key,
p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)) + sizeof(BD_ADDR), sizeof(hash_key_t));
APPL_TRACE_DEBUG("cache_addr[%x] = %x:%x:%x:%x:%x:%x", i, cache_env->cache_addr[i].addr[0], cache_env->cache_addr[i].addr[1], cache_env->cache_addr[i].addr[2],
cache_env->cache_addr[i].addr[3], cache_env->cache_addr[i].addr[4], cache_env->cache_addr[i].addr[5]);
APPL_TRACE_DEBUG("hash_key[%x] = %x%x%x%x", i, cache_env->cache_addr[i].hash_key[0], cache_env->cache_addr[i].hash_key[1],
cache_env->cache_addr[i].hash_key[2], cache_env->cache_addr[i].hash_key[3]);
bta_gattc_co_cache_new_assoc_list(cache_env->cache_addr[i].addr, i);
}
} else {
APPL_TRACE_ERROR("%s, Line = %d, nvs flash open fail, err_code = %x", __func__, __LINE__, err_code);
osi_free(p_buf);
return;
}
osi_free(p_buf);
return;
}
void bta_gattc_co_cache_addr_deinit(void)
{
if(!cache_env->is_open) {
return;
}
nvs_close(cache_env->addr_fp);
cache_env->is_open = false;
for(UINT8 i = 0; i< cache_env->num_addr; i++) {
cache_addr_info_t *addr_info = &cache_env->cache_addr[i];
if(addr_info) {
nvs_close(addr_info->cache_fp);
addr_info->is_open = false;
if(addr_info->assoc_addr) {
list_free(addr_info->assoc_addr);
}
}
}
osi_free(cache_env);
cache_env = NULL;
}
BOOLEAN bta_gattc_co_addr_in_cache(BD_ADDR bda)
{
UINT8 addr_index = 0;
UINT8 num = cache_env->num_addr;
cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
for (addr_index = 0; addr_index < num; addr_index++) {
if (!memcmp(addr_info->addr, bda, sizeof(BD_ADDR))) {
return TRUE;
}
}
return FALSE;
}
UINT8 bta_gattc_co_find_addr_in_cache(BD_ADDR bda)
{
UINT8 addr_index = 0;
UINT8 num = cache_env->num_addr;
cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
for (addr_index = 0; addr_index < num; addr_index++, addr_info++) {
if (!memcmp(addr_info->addr, bda, sizeof(BD_ADDR))) {
return addr_index;
}
}
return INVALID_ADDR_NUM;
}
UINT8 bta_gattc_co_find_hash_in_cache(hash_key_t hash_key)
{
UINT8 index = 0;
UINT8 num = cache_env->num_addr;
cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
for (index = 0; index < num; index++) {
if (!memcmp(addr_info->hash_key, hash_key, sizeof(hash_key_t))) {
return index;
}
}
return INVALID_ADDR_NUM;
}
UINT8 bta_gattc_co_get_addr_num(void)
{
if (cache_env == NULL) {
return 0;
}
return cache_env->num_addr;
}
void bta_gattc_co_get_addr_list(BD_ADDR *addr_list)
{
UINT8 num = cache_env->num_addr;
for (UINT8 i = 0; i < num; i++) {
memcpy(addr_list[i], cache_env->cache_addr[i].addr, sizeof(BD_ADDR));
}
}
void bta_gattc_co_cache_addr_save(BD_ADDR bd_addr, hash_key_t hash_key)
{
esp_err_t err_code;
UINT8 index = 0;
UINT8 new_index = cache_env->num_addr;
UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF);
if (p_buf == NULL) {
APPL_TRACE_ERROR("%s malloc failed!", __func__);
return;
}
// check the address list has the same address or not
// for the same address, it's hash key may be change due to service change
if ((index = bta_gattc_co_find_addr_in_cache(bd_addr)) != INVALID_ADDR_NUM) {
APPL_TRACE_DEBUG("%s the bd_addr already in the cache list, index = %x", __func__, index);
//if the bd_addr already in the address list, update the hash key in it.
memcpy(cache_env->cache_addr[index].addr, bd_addr, sizeof(BD_ADDR));
memcpy(cache_env->cache_addr[index].hash_key, hash_key, sizeof(hash_key_t));
} else {
if (cache_env->num_addr >= MAX_DEVICE_IN_CACHE) {
APPL_TRACE_WARNING("%s cache list full and remove the oldest addr info", __func__);
cacheReset(cache_env->cache_addr[0].addr, FALSE);
}
new_index = cache_env->num_addr;
assert(new_index < MAX_DEVICE_IN_CACHE);
memcpy(cache_env->cache_addr[new_index].addr, bd_addr, sizeof(BD_ADDR));
memcpy(cache_env->cache_addr[new_index].hash_key, hash_key, sizeof(hash_key_t));
cache_env->num_addr++;
APPL_TRACE_DEBUG("%s(), num = %d", __func__, cache_env->num_addr);
}
nvs_handle_t *fp = &cache_env->addr_fp;
UINT16 length = cache_env->num_addr * (sizeof(BD_ADDR) + sizeof(hash_key_t));
for (UINT8 i = 0; i < cache_env->num_addr; i++) {
//copy the address to the buffer.
memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)), cache_env->cache_addr[i].addr, sizeof(BD_ADDR));
//copy the hash key to the buffer.
memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)) + sizeof(BD_ADDR),
cache_env->cache_addr[i].hash_key, sizeof(hash_key_t));
}
if (cache_env->is_open) {
if ((err_code = nvs_set_blob(cache_env->addr_fp, cache_key, p_buf, length)) != ESP_OK) {
APPL_TRACE_WARNING("%s(), nvs set blob fail, err %d", __func__, err_code);
}
} else {
if ((err_code = nvs_open(cache_addr, NVS_READWRITE , fp)) == ESP_OK) {
cache_env->is_open = true;
if (( err_code = nvs_set_blob(cache_env->addr_fp, cache_key, p_buf, length)) != ESP_OK) {
APPL_TRACE_WARNING("%s(), nvs set blob fail, err %d", __func__, err_code);
}
} else {
APPL_TRACE_ERROR("%s, Line = %d, nvs flash open fail, err_code = %x", __func__, __LINE__, err_code);
}
}
//free the buffer after used.
osi_free(p_buf);
return;
}
BOOLEAN bta_gattc_co_cache_new_assoc_list(BD_ADDR src_addr, UINT8 index)
{
cache_addr_info_t *addr_info = &cache_env->cache_addr[index];
addr_info->assoc_addr = list_new(osi_free_func);
return (addr_info->assoc_addr != NULL ? TRUE : FALSE);
}
BOOLEAN bta_gattc_co_cache_append_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_addr)
{
UINT8 addr_index = 0;
cache_addr_info_t *addr_info;
UINT8 *p_assoc_buf = osi_malloc(sizeof(BD_ADDR));
if(!p_assoc_buf) {
return FALSE;
}
memcpy(p_assoc_buf, assoc_addr, sizeof(BD_ADDR));
if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
addr_info = &cache_env->cache_addr[addr_index];
if (addr_info->assoc_addr == NULL) {
addr_info->assoc_addr =list_new(NULL);
}
return list_append(addr_info->assoc_addr, p_assoc_buf);
} else {
osi_free(p_assoc_buf);
}
return FALSE;
}
BOOLEAN bta_gattc_co_cache_remove_assoc_addr(BD_ADDR src_addr, BD_ADDR assoc_addr)
{
UINT8 addr_index = 0;
cache_addr_info_t *addr_info;
if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
addr_info = &cache_env->cache_addr[addr_index];
if (addr_info->assoc_addr != NULL) {
for (list_node_t *sn = list_begin(addr_info->assoc_addr);
sn != list_end(addr_info->assoc_addr); sn = list_next(sn)) {
void *addr = list_node(sn);
if (!memcmp(addr, assoc_addr, sizeof(BD_ADDR))) {
return list_remove(addr_info->assoc_addr, addr);
}
}
//return list_remove(addr_info->assoc_addr, assoc_addr);
} else {
return FALSE;
}
}
return FALSE;
}
UINT8* bta_gattc_co_cache_find_src_addr(BD_ADDR assoc_addr, UINT8 *index)
{
UINT8 num = cache_env->num_addr;
cache_addr_info_t *addr_info = &cache_env->cache_addr[0];
UINT8 *addr_data;
//Check the assoc_addr list is NULL or not
if (addr_info->assoc_addr == NULL) {
*index = INVALID_ADDR_NUM;
return NULL;
}
for (int i = 0; i < num; i++) {
for (const list_node_t *node = list_begin(addr_info->assoc_addr); node != list_end(addr_info->assoc_addr);
node = list_next(node)) {
addr_data = (UINT8 *)list_node(node);
if (!memcmp(addr_data, assoc_addr, sizeof(BD_ADDR))) {
*index = i;
return (UINT8 *)addr_info->addr;
}
}
addr_info++;
if (addr_info->assoc_addr == NULL) {
*index = INVALID_ADDR_NUM;
return NULL;
}
}
*index = INVALID_ADDR_NUM;
return NULL;
}
BOOLEAN bta_gattc_co_cache_clear_assoc_addr(BD_ADDR src_addr)
{
UINT8 addr_index = 0;
cache_addr_info_t *addr_info;
if ((addr_index = bta_gattc_co_find_addr_in_cache(src_addr)) != INVALID_ADDR_NUM) {
addr_info = &cache_env->cache_addr[addr_index];
if (addr_info->assoc_addr != NULL) {
list_clear(addr_info->assoc_addr);
} else {
return FALSE;
}
return TRUE;
}
return FALSE;
}
// #endif /* #if( defined GATTC_CACHE_NVS ) && (GATTC_CACHE_NVS == TRUE) */
#endif /* #if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE) */
#endif /* #if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE) */
@@ -0,0 +1,550 @@
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
*
* 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.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the GATT client main functions and state machine.
*
******************************************************************************/
#include "common/bt_target.h"
#if (GATTC_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
#include <string.h>
#include "bta_gattc_int.h"
#include "osi/allocator.h"
/*****************************************************************************
** Constants and types
*****************************************************************************/
/* state machine action enumeration list */
enum {
BTA_GATTC_OPEN,
BTA_GATTC_OPEN_FAIL,
BTA_GATTC_OPEN_ERROR,
BTA_GATTC_CANCEL_OPEN,
BTA_GATTC_CANCEL_OPEN_OK,
BTA_GATTC_CANCEL_OPEN_ERROR,
BTA_GATTC_CONN,
BTA_GATTC_START_DISCOVER,
BTA_GATTC_DISC_CMPL,
BTA_GATTC_Q_CMD,
BTA_GATTC_CLOSE,
BTA_GATTC_CLOSE_FAIL,
BTA_GATTC_READ,
BTA_GATTC_WRITE,
BTA_GATTC_OP_CMPL,
BTA_GATTC_SEARCH,
BTA_GATTC_FAIL,
BTA_GATTC_CONFIRM,
BTA_GATTC_EXEC,
BTA_GATTC_READ_MULTI,
BTA_GATTC_IGNORE_OP_CMPL,
BTA_GATTC_DISC_CLOSE,
BTA_GATTC_RESTART_DISCOVER,
BTA_GATTC_CFG_MTU,
BTA_GATTC_READ_BY_TYPE,
BTA_GATTC_READ_MULTI_VAR,
BTA_GATTC_IGNORE
};
/* type for action functions */
typedef void (*tBTA_GATTC_ACTION)(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
/* action function list */
const tBTA_GATTC_ACTION bta_gattc_action[] = {
bta_gattc_open,
bta_gattc_open_fail,
bta_gattc_open_error,
bta_gattc_cancel_open,
bta_gattc_cancel_open_ok,
bta_gattc_cancel_open_error,
bta_gattc_conn,
bta_gattc_start_discover,
bta_gattc_disc_cmpl,
bta_gattc_q_cmd,
bta_gattc_close,
bta_gattc_close_fail,
bta_gattc_read,
bta_gattc_write,
bta_gattc_op_cmpl,
bta_gattc_search,
bta_gattc_fail,
bta_gattc_confirm,
bta_gattc_execute,
bta_gattc_read_multi,
bta_gattc_ignore_op_cmpl,
bta_gattc_disc_close,
bta_gattc_restart_discover,
bta_gattc_cfg_mtu,
bta_gattc_read_by_type,
bta_gattc_read_multi_var,
};
/* state table information */
#define BTA_GATTC_ACTIONS 1 /* number of actions */
#define BTA_GATTC_NEXT_STATE 1 /* position of next state */
#define BTA_GATTC_NUM_COLS 2 /* number of columns in state tables */
/* state table for idle state */
static const UINT8 bta_gattc_st_idle[][BTA_GATTC_NUM_COLS] = {
/* Event Action 1 Next state */
/* BTA_GATTC_API_OPEN_EVT */ {BTA_GATTC_OPEN, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_INT_OPEN_FAIL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_CANCEL_OPEN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_CFG_MTU_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_REFRESH_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_CACHE_CLEAN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_CONN, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_BY_TYPE_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_MULTI_VAR_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
};
/* state table for wait for open state */
static const UINT8 bta_gattc_st_w4_conn[][BTA_GATTC_NUM_COLS] = {
/* Event Action 1 Next state */
/* BTA_GATTC_API_OPEN_EVT */ {BTA_GATTC_OPEN, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_INT_OPEN_FAIL_EVT */ {BTA_GATTC_OPEN_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_CANCEL_OPEN_EVT */ {BTA_GATTC_CANCEL_OPEN, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */ {BTA_GATTC_CANCEL_OPEN_OK, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_CFG_MTU_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CANCEL_OPEN, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_REFRESH_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_CACHE_CLEAN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_CONN, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_OPEN_FAIL, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_BY_TYPE_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
/* BTA_GATTC_API_READ_MULTI_VAR_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
};
/* state table for open state */
static const UINT8 bta_gattc_st_connected[][BTA_GATTC_NUM_COLS] = {
/* Event Action 1 Next state */
/* BTA_GATTC_API_OPEN_EVT */ {BTA_GATTC_OPEN, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_OPEN_FAIL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_CANCEL_OPEN_EVT */ {BTA_GATTC_CANCEL_OPEN_ERROR, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_READ_EVT */ {BTA_GATTC_READ, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_WRITE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_EXEC, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_CFG_MTU_EVT */ {BTA_GATTC_CFG_MTU, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_SEARCH, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_CONFIRM, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_READ_MULTI, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_REFRESH_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_CACHE_CLEAN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_CONN, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_START_DISCOVER, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_OP_CMPL, BTA_GATTC_CONN_ST},
/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_BY_TYPE_EVT */ {BTA_GATTC_READ_BY_TYPE, BTA_GATTC_CONN_ST},
/* BTA_GATTC_API_READ_MULTI_VAR_EVT */ {BTA_GATTC_READ_MULTI_VAR, BTA_GATTC_CONN_ST},
};
/* state table for discover state */
static const UINT8 bta_gattc_st_discover[][BTA_GATTC_NUM_COLS] = {
/* Event Action 1 Next state */
/* BTA_GATTC_API_OPEN_EVT */ {BTA_GATTC_OPEN, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_INT_OPEN_FAIL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_CANCEL_OPEN_EVT */ {BTA_GATTC_CANCEL_OPEN_ERROR, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_READ_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_CFG_MTU_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_DISC_CLOSE, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_CONFIRM, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_REFRESH_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_CACHE_CLEAN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_CONN, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_RESTART_DISCOVER, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_DISC_CMPL, BTA_GATTC_CONN_ST},
/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE_OP_CMPL, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST},
/* BTA_GATTC_API_READ_BY_TYPE_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
/* BTA_GATTC_API_READ_MULTI_VAR_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
};
/* type for state table */
typedef const UINT8 (*tBTA_GATTC_ST_TBL)[BTA_GATTC_NUM_COLS];
/* state table */
const tBTA_GATTC_ST_TBL bta_gattc_st_tbl[] = {
bta_gattc_st_idle,
bta_gattc_st_w4_conn,
bta_gattc_st_connected,
bta_gattc_st_discover
};
/*****************************************************************************
** Global data
*****************************************************************************/
/* GATTC control block */
#if BTA_DYNAMIC_MEMORY == FALSE
tBTA_GATTC_CB bta_gattc_cb;
#else
tBTA_GATTC_CB *bta_gattc_cb_ptr;
#endif
#if BTA_GATT_DEBUG == TRUE
static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code);
static char *gattc_state_code(tBTA_GATTC_STATE state_code);
#endif
/*******************************************************************************
**
** Function bta_gattc_sm_execute
**
** Description State machine event handling function for GATTC
**
**
** Returns BOOLEAN : TRUE if queued client request buffer can be immediately released
** else FALSE
**
*******************************************************************************/
BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data)
{
tBTA_GATTC_ST_TBL state_table;
UINT8 action;
int i;
BOOLEAN rt = TRUE;
#if BTA_GATT_DEBUG == TRUE
tBTA_GATTC_STATE in_state = p_clcb->state;
UINT16 in_event = event;
APPL_TRACE_DEBUG("bta_gattc_sm_execute: State 0x%02x [%s], Event 0x%x[%s]", in_state,
gattc_state_code(in_state),
in_event,
gattc_evt_code(in_event));
#endif
/* look up the state table for the current state */
state_table = bta_gattc_st_tbl[p_clcb->state];
event &= 0x00FF;
/* set next state */
p_clcb->state = state_table[event][BTA_GATTC_NEXT_STATE];
/* execute action functions */
for (i = 0; i < BTA_GATTC_ACTIONS; i++) {
if ((action = state_table[event][i]) != BTA_GATTC_IGNORE) {
(*bta_gattc_action[action])(p_clcb, p_data);
if (p_clcb->p_q_cmd == p_data) {
/* buffer is queued, don't free in the bta dispatcher.
* we free it ourselves when a completion event is received.
*/
rt = FALSE;
}
} else {
break;
}
}
#if BTA_GATT_DEBUG == TRUE
if (in_state != p_clcb->state) {
APPL_TRACE_DEBUG("GATTC State Change: [%s] -> [%s] after Event [%s]",
gattc_state_code(in_state),
gattc_state_code(p_clcb->state),
gattc_evt_code(in_event));
}
#endif
return rt;
}
/*******************************************************************************
**
** Function bta_gattc_hdl_event
**
** Description GATT client main event handling function.
**
**
** Returns BOOLEAN
**
*******************************************************************************/
BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
{
tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
tBTA_GATTC_CLCB *p_clcb = NULL;
tBTA_GATTC_RCB *p_clreg;
BOOLEAN rt = TRUE;
#if BTA_GATT_DEBUG == TRUE
APPL_TRACE_DEBUG("bta_gattc_hdl_event: Event [%s]\n", gattc_evt_code(p_msg->event));
#endif
switch (p_msg->event) {
case BTA_GATTC_API_DISABLE_EVT:
bta_gattc_disable(p_cb);
break;
case BTA_GATTC_API_REG_EVT:
bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
case BTA_GATTC_INT_START_IF_EVT:
bta_gattc_start_if(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
case BTA_GATTC_API_DEREG_EVT:
p_clreg = bta_gattc_cl_get_regcb(((tBTA_GATTC_DATA *)p_msg)->api_dereg.client_if);
bta_gattc_deregister(p_cb, p_clreg);
break;
case BTA_GATTC_API_OPEN_EVT:
bta_gattc_process_api_open(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
case BTA_GATTC_API_CANCEL_OPEN_EVT:
bta_gattc_process_api_open_cancel(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
case BTA_GATTC_API_REFRESH_EVT:
bta_gattc_process_api_refresh(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
case BTA_GATTC_API_CACHE_ASSOC_EVT:
bta_gattc_process_api_cache_assoc(p_cb, (tBTA_GATTC_DATA *)p_msg);
break;
case BTA_GATTC_API_CACHE_GET_ADDR_LIST_EVT:
bta_gattc_process_api_cache_get_addr_list(p_cb, (tBTA_GATTC_DATA *)p_msg);
break;
case BTA_GATTC_API_CACHE_CLEAN_EVT:
bta_gattc_process_api_cache_clean(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
#if BLE_INCLUDED == TRUE
case BTA_GATTC_API_LISTEN_EVT:
bta_gattc_listen(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
case BTA_GATTC_API_BROADCAST_EVT:
bta_gattc_broadcast(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
#endif
case BTA_GATTC_ENC_CMPL_EVT:
bta_gattc_process_enc_cmpl(p_cb, (tBTA_GATTC_DATA *) p_msg);
break;
default:
if (p_msg->event == BTA_GATTC_INT_CONN_EVT) {
p_clcb = bta_gattc_find_int_conn_clcb((tBTA_GATTC_DATA *) p_msg);
p_clreg = bta_gattc_cl_get_regcb(((tBTA_GATTC_DATA *)p_msg)->int_conn.client_if);
if (p_clreg != NULL){
bta_gattc_conncback(p_clreg, (tBTA_GATTC_DATA *) p_msg);
}
} else if (p_msg->event == BTA_GATTC_INT_DISCONN_EVT) {
p_clreg = bta_gattc_cl_get_regcb(((tBTA_GATTC_DATA *)p_msg)->int_conn.client_if);
if (p_clreg != NULL){
bta_gattc_disconncback(p_clreg, (tBTA_GATTC_DATA *) p_msg);
}
p_clcb = bta_gattc_find_int_disconn_clcb((tBTA_GATTC_DATA *) p_msg);
} else {
p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific);
}
if (p_clcb != NULL) {
rt = bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA *) p_msg);
} else {
APPL_TRACE_DEBUG("Ignore unknown conn ID: %d\n", p_msg->layer_specific);
}
break;
}
return rt;
}
/*****************************************************************************
** Debug Functions
*****************************************************************************/
#if BTA_GATT_DEBUG == TRUE
/*******************************************************************************
**
** Function gattc_evt_code
**
** Description
**
** Returns void
**
*******************************************************************************/
static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code)
{
switch (evt_code) {
case BTA_GATTC_API_OPEN_EVT:
return "BTA_GATTC_API_OPEN_EVT";
case BTA_GATTC_INT_OPEN_FAIL_EVT:
return "BTA_GATTC_INT_OPEN_FAIL_EVT";
case BTA_GATTC_API_CANCEL_OPEN_EVT:
return "BTA_GATTC_API_CANCEL_OPEN_EVT";
case BTA_GATTC_INT_CANCEL_OPEN_OK_EVT:
return "BTA_GATTC_INT_CANCEL_OPEN_OK_EVT";
case BTA_GATTC_API_READ_EVT:
return "BTA_GATTC_API_READ_EVT";
case BTA_GATTC_API_WRITE_EVT:
return "BTA_GATTC_API_WRITE_EVT";
case BTA_GATTC_API_EXEC_EVT:
return "BTA_GATTC_API_EXEC_EVT";
case BTA_GATTC_API_CLOSE_EVT:
return "BTA_GATTC_API_CLOSE_EVT";
case BTA_GATTC_API_SEARCH_EVT:
return "BTA_GATTC_API_SEARCH_EVT";
case BTA_GATTC_API_CONFIRM_EVT:
return "BTA_GATTC_API_CONFIRM_EVT";
case BTA_GATTC_API_READ_MULTI_EVT:
return "BTA_GATTC_API_READ_MULTI_EVT";
case BTA_GATTC_INT_CONN_EVT:
return "BTA_GATTC_INT_CONN_EVT";
case BTA_GATTC_INT_DISCOVER_EVT:
return "BTA_GATTC_INT_DISCOVER_EVT";
case BTA_GATTC_DISCOVER_CMPL_EVT:
return "BTA_GATTC_DISCOVER_CMPL_EVT";
case BTA_GATTC_OP_CMPL_EVT:
return "BTA_GATTC_OP_CMPL_EVT";
case BTA_GATTC_INT_DISCONN_EVT:
return "BTA_GATTC_INT_DISCONN_EVT";
case BTA_GATTC_INT_START_IF_EVT:
return "BTA_GATTC_INT_START_IF_EVT";
case BTA_GATTC_API_REG_EVT:
return "BTA_GATTC_API_REG_EVT";
case BTA_GATTC_API_DEREG_EVT:
return "BTA_GATTC_API_DEREG_EVT";
case BTA_GATTC_API_REFRESH_EVT:
return "BTA_GATTC_API_REFRESH_EVT";
case BTA_GATTC_API_CACHE_CLEAN_EVT:
return "BTA_GATTC_API_CACHE_CLEAN_EVT";
case BTA_GATTC_API_LISTEN_EVT:
return "BTA_GATTC_API_LISTEN_EVT";
case BTA_GATTC_API_DISABLE_EVT:
return "BTA_GATTC_API_DISABLE_EVT";
case BTA_GATTC_API_CFG_MTU_EVT:
return "BTA_GATTC_API_CFG_MTU_EVT";
case BTA_GATTC_API_READ_BY_TYPE_EVT:
return "BTA_GATTC_API_READ_BY_TYPE_EVT";
case BTA_GATTC_API_READ_MULTI_VAR_EVT:
return "BTA_GATTC_API_READ_MULTI_VAR_EVT";
default:
return "unknown GATTC event code";
}
}
/*******************************************************************************
**
** Function gattc_state_code
**
** Description
**
** Returns void
**
*******************************************************************************/
static char *gattc_state_code(tBTA_GATTC_STATE state_code)
{
switch (state_code) {
case BTA_GATTC_IDLE_ST:
return "GATTC_IDLE_ST";
case BTA_GATTC_W4_CONN_ST:
return "GATTC_W4_CONN_ST";
case BTA_GATTC_CONN_ST:
return "GATTC_CONN_ST";
case BTA_GATTC_DISCOVER_ST:
return "GATTC_DISCOVER_ST";
default:
return "unknown GATTC state code";
}
}
#endif /* Debug Functions */
void bta_gattc_deinit(void)
{
#if BTA_DYNAMIC_MEMORY
memset(bta_gattc_cb_ptr, 0, sizeof(tBTA_GATTC_CB));
FREE_AND_RESET(bta_gattc_cb_ptr);
#endif /* #if BTA_DYNAMIC_MEMORY */
}
uint8_t bta_gattc_cl_rcb_active_count(void)
{
uint8_t count = 0;
for (uint8_t i = 0; i < BTA_GATTC_CL_MAX; i ++) {
if (bta_gattc_cb.cl_rcb[i].in_use) {
count++;
}
}
return count;
}
#endif /* GATTC_INCLUDED == TRUE && BLE_INCLUDED == TRUE */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,680 @@
/******************************************************************************
*
* Copyright (C) 2010-2012 Broadcom Corporation
*
* 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.
*
******************************************************************************/
/******************************************************************************
*
* This is the implementation of the API for GATT server of BTA.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(GATTS_INCLUDED) && (GATTS_INCLUDED == TRUE)
#include <string.h>
#include "bta/bta_sys.h"
#include "bta/bta_gatt_api.h"
#include "bta_gatts_int.h"
#include "osi/allocator.h"
#include "stack/l2c_api.h"
/*****************************************************************************
** Constants
*****************************************************************************/
static const tBTA_SYS_REG bta_gatts_reg = {
bta_gatts_hdl_event,
BTA_GATTS_Disable
};
/*******************************************************************************
**
** Function BTA_GATTS_Disable
**
** Description This function is called to disable GATTS module
**
** Parameters None.
**
** Returns None
**
*******************************************************************************/
void BTA_GATTS_Disable(void)
{
BT_HDR *p_buf;
if (bta_sys_is_register(BTA_ID_GATTS) == FALSE) {
APPL_TRACE_WARNING("GATTS Module not enabled/already disabled");
return;
}
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_GATTS_API_DISABLE_EVT;
bta_sys_sendmsg(p_buf);
}
bta_sys_deregister(BTA_ID_GATTS);
}
/*******************************************************************************
**
** Function BTA_GATTS_AppRegister
**
** Description This function is called to register application callbacks
** with BTA GATTS module.
**
** Parameters p_app_uuid - application UUID
** p_cback - pointer to the application callback function.
**
** Returns None
**
*******************************************************************************/
void BTA_GATTS_AppRegister(const tBT_UUID * p_app_uuid, tBTA_GATTS_CBACK *p_cback)
{
tBTA_GATTS_API_REG *p_buf;
/* register with BTA system manager */
if (bta_sys_is_register(BTA_ID_GATTS) == FALSE) {
bta_sys_register(BTA_ID_GATTS, &bta_gatts_reg);
}
if ((p_buf = (tBTA_GATTS_API_REG *) osi_malloc(sizeof(tBTA_GATTS_API_REG))) != NULL) {
p_buf->hdr.event = BTA_GATTS_API_REG_EVT;
if (p_app_uuid != NULL) {
memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
}
p_buf->p_cback = p_cback;
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_AppDeregister
**
** Description De-register with GATT Server.
**
** Parameters app_id: applicatino ID.
**
** Returns void
**
*******************************************************************************/
void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if)
{
tBTA_GATTS_API_DEREG *p_buf;
if ((p_buf = (tBTA_GATTS_API_DEREG *) osi_malloc(sizeof(tBTA_GATTS_API_DEREG))) != NULL) {
p_buf->hdr.event = BTA_GATTS_API_DEREG_EVT;
p_buf->server_if = server_if;
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_CreateService
**
** Description Create a service. When service creation is done, a callback
** event BTA_GATTS_CREATE_EVT is called to report status
** and service ID to the profile. The service ID obtained in
** the callback function needs to be used when adding included
** service and characteristics/descriptors into the service.
**
** Parameters app_id: Profile ID this service is belonged to.
** p_service_uuid: service UUID.
** inst: instance ID number of this service.
** num_handle: numble of handle requessted for this service.
** is_primary: is this service a primary one or not.
**
** Returns void
**
*******************************************************************************/
void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, const tBT_UUID * p_service_uuid, UINT8 inst,
UINT16 num_handle, BOOLEAN is_primary)
{
tBTA_GATTS_API_CREATE_SRVC *p_buf;
if ((p_buf = (tBTA_GATTS_API_CREATE_SRVC *) osi_malloc(sizeof(tBTA_GATTS_API_CREATE_SRVC))) != NULL) {
p_buf->hdr.event = BTA_GATTS_API_CREATE_SRVC_EVT;
p_buf->server_if = server_if;
p_buf->inst = inst;
memcpy(&p_buf->service_uuid, p_service_uuid, sizeof(tBT_UUID));
p_buf->num_handle = num_handle;
p_buf->is_pri = is_primary;
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_AddIncludeService
**
** Description This function is called to add an included service. After included
** service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
** is reported the included service ID.
**
** Parameters service_id: service ID to which this included service is to
** be added.
** included_service_id: the service ID to be included.
**
** Returns void
**
*******************************************************************************/
void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id)
{
tBTA_GATTS_API_ADD_INCL_SRVC *p_buf;
if ((p_buf =
(tBTA_GATTS_API_ADD_INCL_SRVC *) osi_malloc(sizeof(tBTA_GATTS_API_ADD_INCL_SRVC)))
!= NULL) {
p_buf->hdr.event = BTA_GATTS_API_ADD_INCL_SRVC_EVT;
p_buf->hdr.layer_specific = service_id;
p_buf->included_service_id = included_service_id;
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_AddCharacteristic
**
** Description This function is called to add a characteristic into a service.
**
** Parameters service_id: service ID to which this included service is to
** be added.
** p_char_uuid : Characteristic UUID.
** perm : Characteristic value declaration attribute permission.
** property : Characteristic Properties
**
** Returns None
**
*******************************************************************************/
void BTA_GATTS_AddCharacteristic (UINT16 service_id, const tBT_UUID * p_char_uuid,
tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property, tGATT_ATTR_VAL *attr_val,
tBTA_GATTS_ATTR_CONTROL *control)
{
tBTA_GATTS_API_ADD_CHAR *p_buf;
UINT16 len = 0;
if(attr_val != NULL){
len = attr_val->attr_len;
}
if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) osi_malloc(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL) {
memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR));
p_buf->hdr.event = BTA_GATTS_API_ADD_CHAR_EVT;
p_buf->hdr.layer_specific = service_id;
p_buf->perm = perm;
p_buf->property = property;
if(control !=NULL){
p_buf->control.auto_rsp = control->auto_rsp;
}
if(attr_val != NULL){
APPL_TRACE_DEBUG("!!!!!!attr_val->attr_len = %x\n",attr_val->attr_len);
APPL_TRACE_DEBUG("!!!!!!!attr_val->attr_max_len = %x\n",attr_val->attr_max_len);
p_buf->attr_val.attr_len = attr_val->attr_len;
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
p_buf->attr_val.attr_val = (uint8_t *)osi_malloc(len);
if(p_buf->attr_val.attr_val != NULL){
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
}
}
if (p_char_uuid) {
memcpy(&p_buf->char_uuid, p_char_uuid, sizeof(tBT_UUID));
}
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_AddCharDescriptor
**
** Description This function is called to add characteristic descriptor. When
** it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
** to report the status and an ID number for this descriptor.
**
** Parameters service_id: service ID to which this charatceristic descriptor is to
** be added.
** perm: descriptor access permission.
** p_descr_uuid: descriptor UUID.
**
** Returns returns status.
**
*******************************************************************************/
void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
tBTA_GATT_PERM perm,
const tBT_UUID * p_descr_uuid, tBTA_GATT_ATTR_VAL *attr_val,
tBTA_GATTS_ATTR_CONTROL *control)
{
tBTA_GATTS_API_ADD_DESCR *p_buf;
UINT16 value_len = 0;
if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) osi_malloc(sizeof(tBTA_GATTS_API_ADD_DESCR))) != NULL) {
memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_DESCR));
p_buf->hdr.event = BTA_GATTS_API_ADD_DESCR_EVT;
p_buf->hdr.layer_specific = service_id;
p_buf->perm = perm;
if(control != NULL){
p_buf->control.auto_rsp = control->auto_rsp;
}
if (p_descr_uuid) {
memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID));
}
if(attr_val != NULL){
p_buf->attr_val.attr_len = attr_val->attr_len;
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
value_len = attr_val->attr_len;
if (value_len != 0){
p_buf->attr_val.attr_val = (uint8_t*)osi_malloc(value_len);
if(p_buf->attr_val.attr_val != NULL){
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, value_len);
}
else{
APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
}
}
}
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_DeleteService
**
** Description This function is called to delete a service. When this is done,
** a callback event BTA_GATTS_DELETE_EVT is report with the status.
**
** Parameters service_id: service_id to be deleted.
**
** Returns returns none.
**
*******************************************************************************/
void BTA_GATTS_DeleteService(UINT16 service_id)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_GATTS_API_DEL_SRVC_EVT;
p_buf->layer_specific = service_id;
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_StartService
**
** Description This function is called to start a service.
**
** Parameters service_id: the service ID to be started.
** sup_transport: supported transport.
**
** Returns None.
**
*******************************************************************************/
void BTA_GATTS_StartService(UINT16 service_id, tBTA_GATT_TRANSPORT sup_transport)
{
tBTA_GATTS_API_START *p_buf;
if ((p_buf = (tBTA_GATTS_API_START *) osi_malloc(sizeof(tBTA_GATTS_API_START))) != NULL) {
p_buf->hdr.event = BTA_GATTS_API_START_SRVC_EVT;
p_buf->hdr.layer_specific = service_id;
p_buf->transport = sup_transport;
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_StopService
**
** Description This function is called to stop a service.
**
** Parameters service_id - service to be topped.
**
** Returns None
**
*******************************************************************************/
void BTA_GATTS_StopService(UINT16 service_id)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_GATTS_API_STOP_SRVC_EVT;
p_buf->layer_specific = service_id;
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_HandleValueIndication
**
** Description This function is called to read a characteristics descriptor.
**
** Parameters bda - remote device bd address to indicate.
** attr_id - attribute ID to indicate.
** data_len - indicate data length.
** p_data: data to indicate.
** need_confirm - if this indication expects a confirmation or not.
**
** Returns None
**
*******************************************************************************/
void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id, UINT16 data_len,
UINT8 *p_data, BOOLEAN need_confirm)
{
tBTA_GATTS_API_INDICATION *p_buf;
UINT16 len = sizeof(tBTA_GATTS_API_INDICATION);
if ((p_buf = (tBTA_GATTS_API_INDICATION *) osi_malloc(len)) != NULL) {
memset(p_buf, 0, len);
p_buf->hdr.event = BTA_GATTS_API_INDICATION_EVT;
p_buf->hdr.layer_specific = conn_id;
p_buf->attr_id = attr_id;
p_buf->need_confirm = need_confirm;
if (data_len > 0 && p_data != NULL) {
p_buf->len = data_len;
memcpy(p_buf->value, p_data, data_len);
}
if(need_confirm == false){
l2ble_update_att_acl_pkt_num(L2CA_DECREASE_BTC_NUM, NULL);
l2ble_update_att_acl_pkt_num(L2CA_ADD_BTU_NUM, NULL);
}
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_SendRsp
**
** Description This function is called to send a response to a request.
**
** Parameters conn_id - connection identifier.
** trans_id - transaction ID.
** status - response status
** p_msg - response data.
**
** Returns None
**
*******************************************************************************/
void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg)
{
tBTA_GATTS_API_RSP *p_buf;
UINT16 len = sizeof(tBTA_GATTS_API_RSP) + sizeof(tBTA_GATTS_RSP);
if ((p_buf = (tBTA_GATTS_API_RSP *) osi_malloc(len)) != NULL) {
memset(p_buf, 0, len);
p_buf->hdr.event = BTA_GATTS_API_RSP_EVT;
p_buf->hdr.layer_specific = conn_id;
p_buf->trans_id = trans_id;
p_buf->status = status;
if (p_msg != NULL) {
p_buf->p_rsp = (tBTA_GATTS_RSP *)(p_buf + 1);
memcpy(p_buf->p_rsp, p_msg, sizeof(tBTA_GATTS_RSP));
}
bta_sys_sendmsg(p_buf);
}
return;
}
void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
{
tBTA_GATTS_API_SET_ATTR_VAL *p_buf;
UINT16 len = sizeof(tBTA_GATTS_API_SET_ATTR_VAL);
if((p_buf = (tBTA_GATTS_API_SET_ATTR_VAL *)osi_malloc(
sizeof(tBTA_GATTS_API_SET_ATTR_VAL))) != NULL){
memset(p_buf, 0, len);
p_buf->hdr.event = BTA_GATTS_API_SET_ATTR_VAL_EVT;
p_buf->hdr.layer_specific = attr_handle;
p_buf->length = length;
if(value != NULL){
if((p_buf->value = (UINT8 *)osi_malloc(length)) != NULL){
memcpy(p_buf->value, value, length);
}
}
bta_sys_sendmsg(p_buf);
}
}
tBTA_GATT_STATUS BTA_GetAttributeValue(UINT16 attr_handle, UINT16 *length, UINT8 **value)
{
return bta_gatts_get_attr_value(attr_handle, length, value);
}
/*******************************************************************************
**
** Function BTA_GATTS_Open
**
** Description Open a direct open connection or add a background auto connection
** bd address
**
** Parameters server_if: server interface.
** remote_bda: remote device BD address.
** is_direct: direct connection or background auto connection
** transport : Transport on which GATT connection to be opened (BR/EDR or LE)
**
** Returns void
**
*******************************************************************************/
void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct,
tBTA_GATT_TRANSPORT transport)
{
tBTA_GATTS_API_OPEN *p_buf;
if ((p_buf = (tBTA_GATTS_API_OPEN *) osi_malloc(sizeof(tBTA_GATTS_API_OPEN))) != NULL) {
p_buf->hdr.event = BTA_GATTS_API_OPEN_EVT;
p_buf->server_if = server_if;
p_buf->is_direct = is_direct;
p_buf->transport = transport;
memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_CancelOpen
**
** Description Cancel a direct open connection or remove a background auto connection
** bd address
**
** Parameters server_if: server interface.
** remote_bda: remote device BD address.
** is_direct: direct connection or background auto connection
**
** Returns void
**
*******************************************************************************/
void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct)
{
tBTA_GATTS_API_CANCEL_OPEN *p_buf;
if ((p_buf = (tBTA_GATTS_API_CANCEL_OPEN *) osi_malloc(sizeof(tBTA_GATTS_API_CANCEL_OPEN))) != NULL) {
p_buf->hdr.event = BTA_GATTS_API_CANCEL_OPEN_EVT;
p_buf->server_if = server_if;
p_buf->is_direct = is_direct;
memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_Close
**
** Description Close a connection a remote device.
**
** Parameters conn_id: connection ID to be closed.
**
** Returns void
**
*******************************************************************************/
void BTA_GATTS_Close(UINT16 conn_id)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_GATTS_API_CLOSE_EVT;
p_buf->layer_specific = conn_id;
bta_sys_sendmsg(p_buf);
}
return;
}
void BTA_GATTS_SendServiceChangeIndication(tBTA_GATTS_IF server_if, BD_ADDR remote_bda)
{
tBTA_GATTS_API_SEND_SERVICE_CHANGE *p_buf;
if ((p_buf = (tBTA_GATTS_API_SEND_SERVICE_CHANGE *) osi_malloc(sizeof(tBTA_GATTS_API_SEND_SERVICE_CHANGE))) != NULL) {
memset(p_buf, 0, sizeof(tBTA_GATTS_API_SEND_SERVICE_CHANGE));
p_buf->hdr.event = BTA_GATTS_API_SEND_SERVICE_CHANGE_EVT;
p_buf->server_if = server_if;
memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
bta_sys_sendmsg(p_buf);
}
return;
}
/*******************************************************************************
**
** Function BTA_GATTS_Listen
**
** Description Start advertisement to listen for connection request for a
** GATT server
**
** Parameters server_if: server interface.
** start: to start or stop listening for connection
** remote_bda: remote device BD address, if listen to all device
** use NULL.
**
** Returns void
**
*******************************************************************************/
void BTA_GATTS_Listen(tBTA_GATTS_IF server_if, BOOLEAN start, BD_ADDR_PTR target_bda)
{
tBTA_GATTS_API_LISTEN *p_buf;
if ((p_buf = (tBTA_GATTS_API_LISTEN *) osi_malloc((UINT16)(sizeof(tBTA_GATTS_API_LISTEN) + BD_ADDR_LEN))) != NULL) {
p_buf->hdr.event = BTA_GATTS_API_LISTEN_EVT;
p_buf->server_if = server_if;
p_buf->start = start;
if (target_bda) {
p_buf->remote_bda = (UINT8 *)(p_buf + 1);
memcpy(p_buf->remote_bda, target_bda, BD_ADDR_LEN);
} else {
p_buf->remote_bda = NULL;
}
bta_sys_sendmsg(p_buf);
}
return;
}
uint8_t BTA_GATTS_SetServiceChangeMode(uint8_t mode)
{
tGATT_STATUS status;
APPL_TRACE_DEBUG("%s mode %u", __func__, mode);
status = GATTS_SetServiceChangeMode(mode);
if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s status %x", __func__, status);
return -1;
}
return 0;
}
uint8_t BTA_GATTS_SendMultiNotification(uint8_t gatt_if, uint16_t conn_id, void *tuples, uint16_t num_tuples)
{
tGATT_STATUS status;
conn_id = (UINT16)((((UINT8)conn_id) << 8) | gatt_if);
status = GATTS_HandleMultiValueNotification(conn_id, (tGATT_HLV *)tuples, num_tuples);
if (status != GATT_SUCCESS) {
APPL_TRACE_ERROR("%s status %x", __func__, status);
return -1;
}
return 0;
}
void BTA_GATTS_ShowLocalDatabase(void)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_GATTS_API_SHOW_LOCAL_DATABASE_EVT;
bta_sys_sendmsg(p_buf);
}
}
#endif /* BTA_GATT_INCLUDED */
@@ -0,0 +1,251 @@
/******************************************************************************
*
* Copyright (C) 2009-2013 Broadcom Corporation
*
* 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.
*
******************************************************************************/
#include "bta/bta_api.h"
#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
#if( defined GATTS_INCLUDED ) && (GATTS_INCLUDED == TRUE)
#include <stdlib.h>
#include <string.h>
#include "bta/bta_gatts_co.h"
#include "btc/btc_storage.h"
#include "btc/btc_ble_storage.h"
// #include "btif_util.h"
#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
/*****************************************************************************
** Local type definitions
*****************************************************************************/
#define BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE 50
typedef struct {
BOOLEAN enable;
UINT8 num_clients;
tBTA_GATTS_SRV_CHG srv_chg[BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE];
} __attribute__((packed)) btif_gatts_srv_chg_cb_t;
/*****************************************************************************
** Static variables
*****************************************************************************/
static btif_gatts_srv_chg_cb_t btif_gatts_srv_chg_cb;
/*****************************************************************************
** Static functions
*****************************************************************************/
static void btif_gatts_check_init(void)
{
btif_gatts_srv_chg_cb_t *p_cb = &btif_gatts_srv_chg_cb;
if (!p_cb->enable) {
memset(p_cb, 0, sizeof(btif_gatts_srv_chg_cb_t));
p_cb->enable = TRUE;
}
}
/*****************************************************************************
** Externally called functions
*****************************************************************************/
void btif_gatts_add_bonded_dev_from_nv(BD_ADDR bda)
{
btif_gatts_srv_chg_cb_t *p_cb = &btif_gatts_srv_chg_cb;
BOOLEAN found = FALSE;
UINT8 i;
btif_gatts_check_init();
for (i = 0; i != p_cb->num_clients; ++i) {
if (!memcmp(p_cb->srv_chg[i].bda, bda, sizeof(BD_ADDR))) {
found = TRUE;
break;
}
}
if (!found) {
if (p_cb->num_clients < BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE) {
bdcpy(p_cb->srv_chg[p_cb->num_clients].bda, bda);
p_cb->srv_chg[p_cb->num_clients].srv_changed = FALSE;
p_cb->num_clients++;
}
}
}
#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
/*****************************************************************************
** Call-out functions
*****************************************************************************/
/*******************************************************************************
**
** Function bta_gatts_co_update_handle_range
**
** Description This callout function is executed by GATTS when a GATT server
** handle range ios to be added or removed.
**
** Parameter is_add: true is to add a handle range; otherwise is to delete.
** p_hndl_range: handle range.
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_update_handle_range(BOOLEAN is_add, tBTA_GATTS_HNDL_RANGE *p_hndl_range)
{
UNUSED(is_add);
UNUSED(p_hndl_range);
}
/*******************************************************************************
**
** Function bta_gatts_co_srv_chg
**
** Description This call-out is to read/write/remove service change related
** informaiton. The request consists of the cmd and p_req and the
** response is returned in p_rsp
**
** Parameter cmd - request command
** p_req - request paramters
** p_rsp - response data for the request
**
** Returns TRUE - if the request is processed successfully and
** the response is returned in p_rsp.
** FALSE - if the request can not be processed
**
*******************************************************************************/
BOOLEAN bta_gatts_co_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
tBTA_GATTS_SRV_CHG_REQ *p_req,
tBTA_GATTS_SRV_CHG_RSP *p_rsp)
{
UNUSED(cmd);
UNUSED(p_req);
UNUSED(p_rsp);
return FALSE;
}
/*******************************************************************************
**
** Function bta_gatts_co_load_handle_range
**
** Description This callout function is executed by GATTS when a GATT server
** handle range is requested to be loaded from NV.
**
** Parameter
**
** Returns void.
**
*******************************************************************************/
BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
tBTA_GATTS_HNDL_RANGE *p_handle_range)
{
UNUSED(index);
UNUSED(p_handle_range);
return FALSE;
}
#if (SMP_INCLUDED == TRUE)
/*******************************************************************************
**
** Function bta_gatts_co_cl_feat_save
**
** Description This callout function is executed by GATTS when GATT server
** client support feature is requested to write to NV.
**
** Parameter remote_addr - remote device address
** feature - pointer of client support feature
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_cl_feat_save(BD_ADDR remote_addr, UINT8 *feature)
{
bt_bdaddr_t bd_addr;
memcpy(bd_addr.address, remote_addr, BD_ADDR_LEN);
btc_storage_set_gatt_cl_supp_feat(&bd_addr, feature, 1);
}
/*******************************************************************************
**
** Function bta_gatts_co_db_hash_save
**
** Description This callout function is executed by GATTS when GATT server
** client status is requested to write to NV.
**
** Parameter remote_addr - remote device address
** db_hash - pointer of GATT service datebase hash
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_db_hash_save(BD_ADDR remote_addr, BT_OCTET16 db_hash)
{
bt_bdaddr_t bd_addr;
memcpy(bd_addr.address, remote_addr, BD_ADDR_LEN);
btc_storage_set_gatt_db_hash(&bd_addr, db_hash, BT_OCTET16_LEN);
}
/*******************************************************************************
**
** Function bta_gatts_co_cl_feat_load
**
** Description This callout function is executed by GATTS when GATT server
** client status is requested to load from NV.
**
** Parameter remote_addr - remote device address
** feature - pointer of GATT service datebase hash
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_cl_feat_load(BD_ADDR remote_addr, UINT8 *feature)
{
bt_bdaddr_t bd_addr;
memcpy(bd_addr.address, remote_addr, BD_ADDR_LEN);
btc_storage_get_gatt_cl_supp_feat(&bd_addr, feature, 1);
}
/*******************************************************************************
**
** Function bta_gatts_co_db_hash_load
**
** Description This callout function is executed by GATTS when GATT server
** client status is requested to load from NV.
**
** Parameter remote_addr - remote device address
** db_hash - pointer of GATT service datebase hash
**
** Returns void.
**
*******************************************************************************/
void bta_gatts_co_db_hash_load(BD_ADDR remote_addr, BT_OCTET16 db_hash)
{
bt_bdaddr_t bd_addr;
memcpy(bd_addr.address, remote_addr, BD_ADDR_LEN);
btc_storage_get_gatt_db_hash(&bd_addr, db_hash, BT_OCTET16_LEN);
}
#endif // #if (SMP_INCLUDED == TRUE)
#endif // #if (GATTS_INCLUDED == TRUE)
#endif // #if (BLE_INCLUDED == TRUE)
@@ -0,0 +1,168 @@
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
*
* 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.
*
*****************************************************************************/
/******************************************************************************
*
* This file contains the GATT server main functions and state machine.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(GATTS_INCLUDED) && (GATTS_INCLUDED == TRUE)
#include <string.h>
#include "bta_gatts_int.h"
#include "osi/allocator.h"
/* type for service building action functions */
typedef void (*tBTA_GATTS_SRVC_ACT)(tBTA_GATTS_SRVC_CB *p_rcb, tBTA_GATTS_DATA *p_data);
/* service building action function list */
const tBTA_GATTS_SRVC_ACT bta_gatts_srvc_build_act[] = {
bta_gatts_add_include_srvc,
bta_gatts_add_char,
bta_gatts_add_char_descr,
bta_gatts_delete_service,
bta_gatts_start_service,
bta_gatts_stop_service,
};
/* GATTS control block */
#if BTA_DYNAMIC_MEMORY == FALSE
tBTA_GATTS_CB bta_gatts_cb;
#else
tBTA_GATTS_CB *bta_gatts_cb_ptr;
#endif
/*******************************************************************************
**
** Function bta_gatts_hdl_event
**
** Description BTA GATT server main event handling function.
**
**
** Returns void
**
*******************************************************************************/
BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg)
{
tBTA_GATTS_CB *p_cb = &bta_gatts_cb;
tBTA_GATTS_SRVC_CB *p_srvc_cb = NULL;
switch (p_msg->event) {
case BTA_GATTS_API_DISABLE_EVT:
bta_gatts_api_disable(p_cb);
break;
case BTA_GATTS_API_REG_EVT:
bta_gatts_register(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_INT_START_IF_EVT:
bta_gatts_start_if(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_DEREG_EVT:
bta_gatts_deregister(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_CREATE_SRVC_EVT:
bta_gatts_create_srvc(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_INDICATION_EVT:
bta_gatts_indicate_handle(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_OPEN_EVT:
bta_gatts_open(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_CANCEL_OPEN_EVT:
bta_gatts_cancel_open(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_CLOSE_EVT:
bta_gatts_close(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_RSP_EVT:
bta_gatts_send_rsp(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_SET_ATTR_VAL_EVT:{
UINT16 attr_id = ((tBTA_GATTS_DATA *) p_msg)->api_set_val.hdr.layer_specific;
p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id(p_cb, attr_id);
bta_gatts_set_attr_value(p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
break;
}
case BTA_GATTS_API_LISTEN_EVT:
bta_gatts_listen(p_cb, (tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_ADD_INCL_SRVC_EVT:
case BTA_GATTS_API_ADD_CHAR_EVT:
case BTA_GATTS_API_ADD_DESCR_EVT:
case BTA_GATTS_API_DEL_SRVC_EVT:
case BTA_GATTS_API_START_SRVC_EVT:
case BTA_GATTS_API_STOP_SRVC_EVT:
p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
((tBTA_GATTS_DATA *)p_msg)->api_add_incl_srvc.hdr.layer_specific);
if (p_srvc_cb != NULL) {
bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
} else {
APPL_TRACE_ERROR("service not created\n");
}
break;
case BTA_GATTS_API_SEND_SERVICE_CHANGE_EVT:
bta_gatts_send_service_change_indication((tBTA_GATTS_DATA *) p_msg);
break;
case BTA_GATTS_API_SHOW_LOCAL_DATABASE_EVT:
bta_gatts_show_local_database();
break;
default:
break;
}
return (TRUE);
}
void bta_gatts_deinit(void)
{
memset(&bta_gatts_cb, 0, sizeof(tBTA_GATTS_CB));
#if BTA_DYNAMIC_MEMORY
FREE_AND_RESET(bta_gatts_cb_ptr);
#endif /* #if BTA_DYNAMIC_MEMORY */
}
uint8_t bta_gatts_srvc_active_count(void)
{
uint8_t count = 0;
for (uint8_t i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++) {
if (bta_gatts_cb.srvc_cb[i].in_use) {
count++;
}
}
return count;
}
#endif /* GATTS_INCLUDED */
@@ -0,0 +1,224 @@
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
*
* 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.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the GATT client utility function.
*
******************************************************************************/
#include "common/bt_target.h"
#if defined(GATTS_INCLUDED) && (GATTS_INCLUDED == TRUE)
#include <string.h>
#include "bta/utl.h"
#include "bta/bta_sys.h"
#include "bta_gatts_int.h"
static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/*******************************************************************************
**
** Function bta_gatt_convert_uuid16_to_uuid128
**
** Description Convert a 16 bits UUID to be an standard 128 bits one.
**
** Returns TRUE if two uuid match; FALSE otherwise.
**
*******************************************************************************/
static void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
{
UINT8 *p = &uuid_128[LEN_UUID_128 - 4];
memcpy (uuid_128, base_uuid, LEN_UUID_128);
UINT16_TO_STREAM(p, uuid_16);
}
/*******************************************************************************
**
** Function bta_gatts_alloc_srvc_cb
**
** Description allocate a service control block.
**
** Returns pointer to the control block, or otherwise NULL when failed.
**
*******************************************************************************/
UINT8 bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB *p_cb, UINT8 rcb_idx)
{
UINT8 i;
for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++) {
if (!p_cb->srvc_cb[i].in_use) {
p_cb->srvc_cb[i].in_use = TRUE;
p_cb->srvc_cb[i].rcb_idx = rcb_idx;
return i;
}
}
return BTA_GATTS_INVALID_APP;
}
/*******************************************************************************
**
** Function bta_gatts_find_app_rcb_by_app_if
**
** Description find the index of the application control block by app ID.
**
** Returns pointer to the control block if success, otherwise NULL
**
*******************************************************************************/
tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if)
{
UINT8 i;
tBTA_GATTS_RCB *p_reg;
for (i = 0, p_reg = bta_gatts_cb.rcb; i < BTA_GATTS_MAX_APP_NUM; i ++, p_reg++) {
if (p_reg->in_use && p_reg->gatt_if == server_if) {
return p_reg;
}
}
return NULL;
}
/*******************************************************************************
**
** Function bta_gatts_find_app_rcb_idx_by_app_if
**
** Description find the index of the application control block by app ID.
**
** Returns index of the control block, or BTA_GATTS_INVALID_APP if failed.
**
*******************************************************************************/
UINT8 bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_IF server_if)
{
UINT8 i;
for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++) {
if (p_cb->rcb[i].in_use && p_cb->rcb[i].gatt_if == server_if) {
return i;
}
}
return BTA_GATTS_INVALID_APP;
}
/*******************************************************************************
**
** Function bta_gatts_find_srvc_cb_by_srvc_id
**
** Description find the service control block by service ID.
**
** Returns pointer to the rcb.
**
*******************************************************************************/
tBTA_GATTS_SRVC_CB *bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB *p_cb, UINT16 service_id)
{
UINT8 i;
APPL_TRACE_DEBUG("bta_gatts_find_srvc_cb_by_srvc_id service_id=%d", service_id);
for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++) {
if (p_cb->srvc_cb[i].in_use &&
p_cb->srvc_cb[i].service_id == service_id) {
APPL_TRACE_DEBUG("bta_gatts_find_srvc_cb_by_srvc_id found service cb index =%d", i);
return &p_cb->srvc_cb[i];
}
}
return NULL;
}
/*******************************************************************************
**
** Function bta_gatts_find_srvc_cb_by_attr_id
**
** Description find the service control block by attribute ID.
**
** Returns pointer to the rcb.
**
*******************************************************************************/
tBTA_GATTS_SRVC_CB *bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_cb, UINT16 attr_id)
{
UINT8 i;
for (i = 0; i < (BTA_GATTS_MAX_SRVC_NUM); i ++) {
if (/* middle service */
(i < (BTA_GATTS_MAX_SRVC_NUM - 1) &&
p_cb->srvc_cb[i].in_use &&
p_cb->srvc_cb[i + 1].in_use &&
attr_id >= p_cb->srvc_cb[i].service_id &&
attr_id < p_cb->srvc_cb[i + 1].service_id) ||
/* last active service */
(i < (BTA_GATTS_MAX_SRVC_NUM - 1) &&
p_cb->srvc_cb[i].in_use &&
!p_cb->srvc_cb[i + 1].in_use &&
attr_id >= p_cb->srvc_cb[i].service_id) ||
/* last service incb */
(i == (BTA_GATTS_MAX_SRVC_NUM - 1) &&
attr_id >= p_cb->srvc_cb[i].service_id)
) {
return &p_cb->srvc_cb[i];
}
}
return NULL;
}
/*******************************************************************************
**
** Function bta_gatts_uuid_compare
**
** Description Compare two UUID to see if they are the same.
**
** Returns TRUE if two uuid match; FALSE otherwise.
**
*******************************************************************************/
BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src)
{
UINT8 su[LEN_UUID_128], tu[LEN_UUID_128];
UINT8 *ps, *pt;
/* any of the UUID is unspecified */
if (src.len == 0 || tar.len == 0) {
return TRUE;
}
/* If both are 16-bit, we can do a simple compare */
if (src.len == 2 && tar.len == 2) {
return src.uu.uuid16 == tar.uu.uuid16;
}
/* One or both of the UUIDs is 128-bit */
if (src.len == LEN_UUID_16) {
/* convert a 16 bits UUID to 128 bits value */
bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
ps = su;
} else {
ps = src.uu.uuid128;
}
if (tar.len == LEN_UUID_16) {
/* convert a 16 bits UUID to 128 bits value */
bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
pt = tu;
} else {
pt = tar.uu.uuid128;
}
return (memcmp(ps, pt, LEN_UUID_128) == 0);
}
#endif /* GATTS_INCLUDED */
@@ -0,0 +1,559 @@
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
*
* 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.
*
******************************************************************************/
/******************************************************************************
*
* This is the private file for the file transfer client (FTC).
*
******************************************************************************/
#ifndef BTA_GATTC_INT_H
#define BTA_GATTC_INT_H
#include "common/bt_target.h"
#include "bta/bta_sys.h"
#include "bta/bta_gatt_api.h"
#include "bta/bta_gattc_ci.h"
#include "bta/bta_gattc_co.h"
#include "osi/fixed_queue.h"
#include "osi/mutex.h"
/*****************************************************************************
** Constants and data types
*****************************************************************************/
enum {
BTA_GATTC_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_GATTC),
BTA_GATTC_INT_OPEN_FAIL_EVT,
BTA_GATTC_API_CANCEL_OPEN_EVT,
BTA_GATTC_INT_CANCEL_OPEN_OK_EVT,
BTA_GATTC_API_READ_EVT,
BTA_GATTC_API_WRITE_EVT,
BTA_GATTC_API_EXEC_EVT,
BTA_GATTC_API_CFG_MTU_EVT,
BTA_GATTC_API_CLOSE_EVT,
BTA_GATTC_API_SEARCH_EVT,
BTA_GATTC_API_CONFIRM_EVT,
BTA_GATTC_API_READ_MULTI_EVT,
BTA_GATTC_API_REFRESH_EVT,
BTA_GATTC_API_CACHE_CLEAN_EVT,
BTA_GATTC_INT_CONN_EVT,
BTA_GATTC_INT_DISCOVER_EVT,
BTA_GATTC_DISCOVER_CMPL_EVT,
BTA_GATTC_OP_CMPL_EVT,
BTA_GATTC_INT_DISCONN_EVT,
BTA_GATTC_API_READ_BY_TYPE_EVT,
BTA_GATTC_API_READ_MULTI_VAR_EVT,
BTA_GATTC_INT_START_IF_EVT,
BTA_GATTC_API_REG_EVT,
BTA_GATTC_API_DEREG_EVT,
BTA_GATTC_API_LISTEN_EVT,
BTA_GATTC_API_BROADCAST_EVT,
BTA_GATTC_API_DISABLE_EVT,
BTA_GATTC_ENC_CMPL_EVT,
BTA_GATTC_API_CACHE_ASSOC_EVT,
BTA_GATTC_API_CACHE_GET_ADDR_LIST_EVT,
};
typedef UINT16 tBTA_GATTC_INT_EVT;
#define BTA_GATTC_SERVICE_CHANGED_LEN 4
typedef enum {
BTA_GATTC_SERVICE_INFO_FROM_REMOTE_DEVICE = 0,
BTA_GATTC_SERVICE_INFO_FROM_NVS_FLASH = 1,
BTA_GATTC_SERVICE_INFO_FROM_UNKNOWN = 2,
} tBTA_SERVICE_SOURCE_t;
/* max client application GATTC can support */
#ifndef BTA_GATTC_CL_MAX
#if (GATT_MAX_PHY_CHANNEL > 3)
#define BTA_GATTC_CL_MAX GATT_MAX_PHY_CHANNEL
#else
#define BTA_GATTC_CL_MAX 3 // The origin value is 10
#endif
#endif
/* max known devices GATTC can support */
#ifndef BTA_GATTC_KNOWN_SR_MAX
#if (GATT_MAX_PHY_CHANNEL > 3)
#define BTA_GATTC_KNOWN_SR_MAX GATT_MAX_PHY_CHANNEL
#else
#define BTA_GATTC_KNOWN_SR_MAX 3 // The origin value is 10
#endif
#endif
#define BTA_GATTC_CONN_MAX GATT_MAX_PHY_CHANNEL
#ifndef BTA_GATTC_CLCB_MAX
#define BTA_GATTC_CLCB_MAX GATT_CL_MAX_LCB
#endif
#define BTA_GATTC_WRITE_PREPARE GATT_WRITE_PREPARE
#define BTA_GATTC_INVALID_HANDLE 0
/* internal strucutre for GATTC register API */
typedef struct {
BT_HDR hdr;
tBT_UUID app_uuid;
tBTA_GATTC_CBACK *p_cback;
} tBTA_GATTC_API_REG;
typedef struct {
BT_HDR hdr;
tBTA_GATTC_IF client_if;
} tBTA_GATTC_INT_START_IF;
typedef tBTA_GATTC_INT_START_IF tBTA_GATTC_API_DEREG;
typedef tBTA_GATTC_INT_START_IF tBTA_GATTC_INT_DEREG;
typedef struct {
BT_HDR hdr;
BD_ADDR remote_bda;
tBTA_ADDR_TYPE remote_addr_type;
tBTA_GATTC_IF client_if;
BOOLEAN is_direct;
BOOLEAN is_aux;
tBTA_TRANSPORT transport;
} tBTA_GATTC_API_OPEN;
typedef tBTA_GATTC_API_OPEN tBTA_GATTC_API_CANCEL_OPEN;
typedef struct {
BT_HDR hdr;
tBTA_GATT_AUTH_REQ auth_req;
UINT16 handle;
UINT16 s_handle;
UINT16 e_handle;
tBT_UUID uuid;
tBTA_GATTC_EVT cmpl_evt;
} tBTA_GATTC_API_READ;
typedef struct {
BT_HDR hdr;
tBTA_GATT_AUTH_REQ auth_req;
UINT16 handle;
tBTA_GATTC_EVT cmpl_evt;
tBTA_GATTC_WRITE_TYPE write_type;
UINT16 offset;
UINT16 len;
UINT8 *p_value;
} tBTA_GATTC_API_WRITE;
typedef struct {
BT_HDR hdr;
BOOLEAN is_execute;
} tBTA_GATTC_API_EXEC;
typedef struct {
BT_HDR hdr;
UINT16 handle;
} tBTA_GATTC_API_CONFIRM;
typedef tGATT_CL_COMPLETE tBTA_GATTC_CMPL;
typedef struct {
BT_HDR hdr;
UINT8 op_code;
tGATT_STATUS status;
tBTA_GATTC_CMPL *p_cmpl;
} tBTA_GATTC_OP_CMPL;
typedef struct {
BT_HDR hdr;
tBT_UUID *p_srvc_uuid;
} tBTA_GATTC_API_SEARCH;
typedef struct {
BT_HDR hdr;
tBTA_GATT_AUTH_REQ auth_req;
UINT8 num_attr;
UINT16 handles[GATT_MAX_READ_MULTI_HANDLES];
tBTA_GATTC_EVT cmpl_evt;
}tBTA_GATTC_API_READ_MULTI;
typedef struct {
BT_HDR hdr;
BD_ADDR_PTR remote_bda;
tBTA_GATTC_IF client_if;
BOOLEAN start;
} tBTA_GATTC_API_LISTEN;
typedef struct {
BT_HDR hdr;
} tBTA_GATTC_API_CFG_MTU;
typedef struct {
BT_HDR hdr;
tBTA_GATTC_IF client_if;
BD_ADDR src_addr;
BD_ADDR assoc_addr;
BOOLEAN is_assoc;
} tBTA_GATTC_API_CACHE_ASSOC;
typedef struct {
BT_HDR hdr;
tBTA_GATTC_IF client_if;
} tBTA_GATTC_API_GET_ADDR;
typedef struct {
BT_HDR hdr;
BD_ADDR remote_bda;
tBTA_GATTC_IF client_if;
UINT8 role;
tBT_TRANSPORT transport;
tGATT_DISCONN_REASON reason;
BOOLEAN already_connect;
tBTA_GATT_CONN_PARAMS conn_params;
UINT8 ble_addr_type;
UINT16 conn_handle;
} tBTA_GATTC_INT_CONN;
typedef struct {
BT_HDR hdr;
BD_ADDR remote_bda;
tBTA_GATTC_IF client_if;
} tBTA_GATTC_ENC_CMPL;
typedef union {
BT_HDR hdr;
tBTA_GATTC_API_REG api_reg;
tBTA_GATTC_API_DEREG api_dereg;
tBTA_GATTC_API_OPEN api_conn;
tBTA_GATTC_API_CANCEL_OPEN api_cancel_conn;
tBTA_GATTC_API_READ api_read;
tBTA_GATTC_API_SEARCH api_search;
tBTA_GATTC_API_WRITE api_write;
tBTA_GATTC_API_CONFIRM api_confirm;
tBTA_GATTC_API_EXEC api_exec;
tBTA_GATTC_API_READ_MULTI api_read_multi;
tBTA_GATTC_API_CFG_MTU api_mtu;
tBTA_GATTC_API_CACHE_ASSOC api_assoc;
tBTA_GATTC_API_GET_ADDR api_get_addr;
tBTA_GATTC_OP_CMPL op_cmpl;
tBTA_GATTC_INT_CONN int_conn;
tBTA_GATTC_ENC_CMPL enc_cmpl;
tBTA_GATTC_INT_START_IF int_start_if;
tBTA_GATTC_INT_DEREG int_dereg;
/* if peripheral role is supported */
tBTA_GATTC_API_LISTEN api_listen;
} tBTA_GATTC_DATA;
/* GATT server cache on the client */
typedef struct {
tBT_UUID uuid;
UINT16 s_handle;
UINT16 e_handle;
// this field is set only for characteristic
UINT16 char_decl_handle;
BOOLEAN is_primary;
tBTA_GATT_CHAR_PROP property;
} tBTA_GATTC_ATTR_REC;
#define BTA_GATTC_ATTR_LIST_SIZE (BTA_GATTC_MAX_CACHE_CHAR * sizeof(tBTA_GATTC_ATTR_REC))
#ifndef BTA_GATTC_CACHE_SRVR_SIZE
#define BTA_GATTC_CACHE_SRVR_SIZE 600
#endif
enum {
BTA_GATTC_IDLE_ST = 0, /* Idle */
BTA_GATTC_W4_CONN_ST, /* Wait for connection - (optional) */
BTA_GATTC_CONN_ST, /* connected state */
BTA_GATTC_DISCOVER_ST /* discover is in progress */
};
typedef UINT8 tBTA_GATTC_STATE;
typedef struct {
BOOLEAN in_use;
BD_ADDR server_bda;
BOOLEAN connected;
#define BTA_GATTC_SERV_IDLE 0
#define BTA_GATTC_SERV_LOAD 1
#define BTA_GATTC_SERV_SAVE 2
#define BTA_GATTC_SERV_DISC 3
#define BTA_GATTC_SERV_DISC_ACT 4
UINT8 state;
list_t *p_srvc_cache; /* list of tBTA_GATTC_SERVICE */
UINT8 update_count; /* indication received */
UINT8 num_clcb; /* number of associated CLCB */
tBTA_GATTC_ATTR_REC *p_srvc_list;
UINT8 cur_srvc_idx;
UINT16 cur_char_idx;
UINT16 next_avail_idx;
UINT8 total_srvc;
UINT16 total_char;
UINT16 total_attr;
UINT8 srvc_hdl_chg; /* service handle change indication pending */
UINT16 attr_index; /* cahce NV saving/loading attribute index */
UINT16 mtu;
bool update_incl_srvc;
} tBTA_GATTC_SERV;
typedef struct {
BOOLEAN in_use;
BD_ADDR remote_bda;
UINT16 handle;
}tBTA_GATTC_NOTIF_REG;
typedef struct {
tBTA_GATTC_CBACK *p_cback;
BOOLEAN in_use;
tBTA_GATTC_IF client_if; /* client interface with BTE stack for this application */
UINT8 num_clcb; /* number of associated CLCB */
BOOLEAN dereg_pending;
tBT_UUID app_uuid;
tBTA_GATTC_NOTIF_REG notif_reg[BTA_GATTC_NOTIF_REG_MAX];
} tBTA_GATTC_RCB;
/* client channel is a mapping between a BTA client(cl_id) and a remote BD address */
typedef struct {
UINT16 bta_conn_id; /* client channel ID, unique for clcb */
BD_ADDR bda;
tBTA_TRANSPORT transport; /* channel transport */
tBTA_GATTC_RCB *p_rcb; /* pointer to the registration CB */
tBTA_GATTC_SERV *p_srcb; /* server cache CB */
tBTA_GATTC_DATA *p_q_cmd; /* command in queue waiting for execution */
list_t *p_cmd_list; /* The list to store the command to be sent */
BOOLEAN is_full; /* The gattc command queue is full or not */
#define BTA_GATTC_NO_SCHEDULE 0
#define BTA_GATTC_DISC_WAITING 0x01
#define BTA_GATTC_REQ_WAITING 0x10
UINT8 auto_update; /* auto update is waiting */
BOOLEAN disc_active;
BOOLEAN in_use;
tBTA_GATTC_STATE state;
tBTA_GATT_STATUS status;
UINT16 reason;
UINT8 searched_service_source;
} tBTA_GATTC_CLCB;
/* background connection tracking information */
#if GATT_MAX_APPS <= 8
typedef UINT8 tBTA_GATTC_CIF_MASK ;
#elif GATT_MAX_APPS <= 16
typedef UINT16 tBTA_GATTC_CIF_MASK;
#elif GATT_MAX_APPS <= 32
typedef UINT32 tBTA_GATTC_CIF_MASK;
#endif
typedef struct {
BOOLEAN in_use;
BD_ADDR remote_bda;
tBTA_GATTC_CIF_MASK cif_mask;
tBTA_GATTC_CIF_MASK cif_adv_mask;
} tBTA_GATTC_BG_TCK;
typedef struct {
BOOLEAN in_use;
BD_ADDR remote_bda;
UINT16 svc_change_descr_handle;
BOOLEAN write_remote_svc_change_ccc_done;
} tBTA_GATTC_CONN;
enum {
BTA_GATTC_STATE_DISABLED,
BTA_GATTC_STATE_ENABLING,
BTA_GATTC_STATE_ENABLED,
BTA_GATTC_STATE_DISABLING
};
typedef struct {
UINT8 state;
BOOLEAN auto_disc; /* internal use: true for auto discovering after connected */
tBTA_GATTC_CONN conn_track[BTA_GATTC_CONN_MAX];
tBTA_GATTC_BG_TCK bg_track[BTA_GATTC_KNOWN_SR_MAX];
tBTA_GATTC_RCB cl_rcb[BTA_GATTC_CL_MAX];
tBTA_GATTC_CLCB clcb[BTA_GATTC_CLCB_MAX];
tBTA_GATTC_SERV known_server[BTA_GATTC_KNOWN_SR_MAX];
}tBTA_GATTC_CB;
typedef enum {
SERVICE_CHANGE_CCC_WRITTEN_SUCCESS = 0,
SERVICE_CHANGE_CACHE_NOT_FOUND,
SERVICE_CHANGE_SERVICE_NOT_FOUND,
SERVICE_CHANGE_CHAR_NOT_FOUND,
SERVICE_CHANGE_CCC_NOT_FOUND,
SERVICE_CHANGE_WRITE_CCC_FAILED
}tBTA_GATTC_FIND_SERVICE_CB;
/*****************************************************************************
** Global data
*****************************************************************************/
/* GATTC control block */
#if BTA_DYNAMIC_MEMORY == FALSE
extern tBTA_GATTC_CB bta_gattc_cb;
#else
extern tBTA_GATTC_CB *bta_gattc_cb_ptr;
#define bta_gattc_cb (*bta_gattc_cb_ptr)
#endif
/*****************************************************************************
** Function prototypes
*****************************************************************************/
extern BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg);
extern BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data);
/* function processed outside SM */
extern void bta_gattc_disable(tBTA_GATTC_CB *p_cb);
extern void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
extern void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
extern void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB *p_clreg);
extern void bta_gattc_process_enc_cmpl(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
/* function within state machine */
extern void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_open_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_conncback(tBTA_GATTC_RCB *p_rcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_disconncback(tBTA_GATTC_RCB *p_rcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_disc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_read_by_type(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_free_command_data(tBTA_GATTC_CLCB *p_clcb);
extern void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_read_multi_var(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_ci_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern void bta_gattc_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_msg);
extern void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg);
extern void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data);
extern void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
BD_ADDR remote_bda, UINT16 conn_id, tBTA_TRANSPORT transport, UINT16 mtu);
extern void bta_gattc_send_connect_cback( tBTA_GATTC_RCB *p_clreg, BD_ADDR remote_bda, UINT16 conn_id,
tBTA_GATT_CONN_PARAMS conn_params, UINT8 link_role, UINT8 ble_addr_type, UINT16 conn_handle);
extern void bta_gattc_send_disconnect_cback( tBTA_GATTC_RCB *p_clreg, tGATT_DISCONN_REASON reason,
BD_ADDR remote_bda, UINT16 conn_id);
extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
extern void bta_gattc_process_api_cache_clean(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
extern void bta_gattc_process_api_cache_assoc(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
extern void bta_gattc_process_api_cache_get_addr_list(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
extern void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
#if BLE_INCLUDED == TRUE
extern void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
extern void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg);
#endif
/* utility functions */
extern tBTA_GATTC_CLCB *bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
extern tBTA_GATTC_CLCB *bta_gattc_find_clcb_by_conn_id (UINT16 conn_id);
extern tBTA_GATTC_CLCB *bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
extern void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb);
extern tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport);
extern tBTA_GATTC_RCB *bta_gattc_cl_get_regcb(UINT8 client_if);
extern tBTA_GATTC_SERV *bta_gattc_find_srcb(BD_ADDR bda);
extern tBTA_GATTC_SERV *bta_gattc_srcb_alloc(BD_ADDR bda);
extern tBTA_GATTC_SERV *bta_gattc_find_scb_by_cid (UINT16 conn_id);
extern tBTA_GATTC_CLCB *bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA *p_msg);
extern tBTA_GATTC_CLCB *bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg);
extern BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
extern BOOLEAN bta_gattc_uuid_compare (const tBT_UUID *p_src, const tBT_UUID *p_tar, BOOLEAN is_precise);
extern BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_SERV *p_srcb, tBTA_GATTC_NOTIFY *p_notify);
extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR_PTR remote_bda, BOOLEAN add, BOOLEAN is_listen);
extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, UINT8 role);
extern UINT8 bta_gattc_num_reg_app(void);
extern void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV *p_srcb, UINT16 conn_id, UINT16 start_handle, UINT16 end_handle);
extern void bta_gattc_clear_notif_registration_by_bda(tBTA_GATTC_RCB *p_clrcb, BD_ADDR remote_bda);
extern tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda);
/* discovery functions */
extern void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
extern void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status);
extern tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
extern tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid);
extern const list_t* bta_gattc_get_services(UINT16 conn_id);
extern const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(UINT16 conn_id, UINT16 handle);
tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle);
extern tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(UINT16 conn_id, UINT16 handle);
extern tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(UINT16 conn_id, UINT16 handle);
extern void bta_gattc_get_db_size_handle(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, UINT16 *count);
extern void bta_gattc_get_db_size_with_type_handle(UINT16 conn_id, bt_gatt_db_attribute_type_t type,
UINT16 start_handle, UINT16 end_handle, UINT16 char_handle, UINT16 *count);
extern void bta_gattc_get_service_with_uuid(UINT16 conn_id, tBT_UUID *svc_uuid,
btgatt_db_element_t **svc_db,
UINT16 *count);
extern void bta_gattc_get_db_with_opration(UINT16 conn_id,
bt_gatt_get_db_op_t op,
UINT16 char_handle,
tBT_UUID *incl_uuid,
tBT_UUID *char_uuid,
tBT_UUID *descr_uuid,
UINT16 start_handle, UINT16 end_handle,
btgatt_db_element_t **char_db,
UINT16 *count);
extern void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, UINT16 *count);
extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *attr);
extern void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
extern void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS status);
extern tBTA_GATTC_CONN *bta_gattc_conn_alloc(BD_ADDR remote_bda);
extern tBTA_GATTC_CONN *bta_gattc_conn_find(BD_ADDR remote_bda);
extern tBTA_GATTC_CONN *bta_gattc_conn_find_alloc(BD_ADDR remote_bda);
extern BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda);
extern bool bta_gattc_cache_load(tBTA_GATTC_CLCB *p_clcb);
extern void bta_gattc_cache_reset(BD_ADDR server_bda);
extern void bta_gattc_deinit(void);
#endif /* BTA_GATTC_INT_H */
@@ -0,0 +1,265 @@
/******************************************************************************
*
* Copyright (C) 2003-2012 Broadcom Corporation
*
* 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.
*
******************************************************************************/
/******************************************************************************
*
* This is the private file for the BTA GATT server.
*
******************************************************************************/
#ifndef BTA_GATTS_INT_H
#define BTA_GATTS_INT_H
#include "common/bt_target.h"
#include "bta/bta_sys.h"
#include "bta/bta_gatt_api.h"
#include "stack/gatt_api.h"
/*****************************************************************************
** Constants and data types
*****************************************************************************/
enum {
BTA_GATTS_API_REG_EVT = BTA_SYS_EVT_START(BTA_ID_GATTS),
BTA_GATTS_INT_START_IF_EVT,
BTA_GATTS_API_DEREG_EVT,
BTA_GATTS_API_CREATE_SRVC_EVT,
BTA_GATTS_API_INDICATION_EVT,
BTA_GATTS_API_ADD_INCL_SRVC_EVT,
BTA_GATTS_API_ADD_CHAR_EVT,
BTA_GATTS_API_ADD_DESCR_EVT,
BTA_GATTS_API_DEL_SRVC_EVT,
BTA_GATTS_API_START_SRVC_EVT,
BTA_GATTS_API_STOP_SRVC_EVT,
BTA_GATTS_API_RSP_EVT,
BTA_GATTS_API_SET_ATTR_VAL_EVT,
BTA_GATTS_API_OPEN_EVT,
BTA_GATTS_API_CANCEL_OPEN_EVT,
BTA_GATTS_API_CLOSE_EVT,
BTA_GATTS_API_LISTEN_EVT,
BTA_GATTS_API_DISABLE_EVT,
BTA_GATTS_API_SEND_SERVICE_CHANGE_EVT,
BTA_GATTS_API_SHOW_LOCAL_DATABASE_EVT
};
typedef UINT16 tBTA_GATTS_INT_EVT;
/* max number of application allowed on device */
#define BTA_GATTS_MAX_APP_NUM GATT_MAX_SR_PROFILES
/* max number of services allowed in the device */
#define BTA_GATTS_MAX_SRVC_NUM GATT_MAX_SR_PROFILES
/* internal strucutre for GATTC register API */
typedef struct {
BT_HDR hdr;
tBT_UUID app_uuid;
tBTA_GATTS_CBACK *p_cback;
} tBTA_GATTS_API_REG;
typedef struct {
BT_HDR hdr;
tBTA_GATTS_IF server_if;
} tBTA_GATTS_INT_START_IF;
typedef tBTA_GATTS_INT_START_IF tBTA_GATTS_API_DEREG;
typedef struct {
BT_HDR hdr;
tBTA_GATTS_IF server_if;
tBT_UUID service_uuid;
UINT16 num_handle;
UINT8 inst;
BOOLEAN is_pri;
} tBTA_GATTS_API_CREATE_SRVC;
typedef struct {
BT_HDR hdr;
tBT_UUID char_uuid;
tBTA_GATT_PERM perm;
tBTA_GATT_CHAR_PROP property;
tBTA_GATTS_ATTR_CONTROL control;
tBTA_GATT_ATTR_VAL attr_val;
} tBTA_GATTS_API_ADD_CHAR;
typedef struct {
BT_HDR hdr;
UINT16 included_service_id;
} tBTA_GATTS_API_ADD_INCL_SRVC;
typedef struct {
BT_HDR hdr;
tBT_UUID descr_uuid;
tBTA_GATT_PERM perm;
tBTA_GATTS_ATTR_CONTROL control;
tBTA_GATT_ATTR_VAL attr_val;
} tBTA_GATTS_API_ADD_DESCR;
typedef struct {
BT_HDR hdr;
UINT16 attr_id;
UINT16 len;
BOOLEAN need_confirm;
UINT8 value[BTA_GATT_MAX_ATTR_LEN];
} tBTA_GATTS_API_INDICATION;
typedef struct {
BT_HDR hdr;
UINT32 trans_id;
tBTA_GATT_STATUS status;
tBTA_GATTS_RSP *p_rsp;
} tBTA_GATTS_API_RSP;
typedef struct{
BT_HDR hdr;
UINT16 length;
UINT8 *value;
}tBTA_GATTS_API_SET_ATTR_VAL;
typedef struct {
BT_HDR hdr;
tBTA_GATT_TRANSPORT transport;
} tBTA_GATTS_API_START;
typedef struct {
BT_HDR hdr;
BD_ADDR remote_bda;
tBTA_GATTS_IF server_if;
BOOLEAN is_direct;
tBTA_GATT_TRANSPORT transport;
} tBTA_GATTS_API_OPEN;
typedef tBTA_GATTS_API_OPEN tBTA_GATTS_API_CANCEL_OPEN;
typedef struct {
BT_HDR hdr;
BD_ADDR_PTR remote_bda;
tBTA_GATTS_IF server_if;
BOOLEAN start;
} tBTA_GATTS_API_LISTEN;
typedef struct {
BT_HDR hdr;
tBTA_GATTS_IF server_if;
BD_ADDR remote_bda;
} tBTA_GATTS_API_SEND_SERVICE_CHANGE;
typedef union {
BT_HDR hdr;
tBTA_GATTS_API_REG api_reg;
tBTA_GATTS_API_DEREG api_dereg;
tBTA_GATTS_API_CREATE_SRVC api_create_svc;
tBTA_GATTS_API_ADD_INCL_SRVC api_add_incl_srvc;
tBTA_GATTS_API_ADD_CHAR api_add_char;
tBTA_GATTS_API_ADD_DESCR api_add_char_descr;
tBTA_GATTS_API_START api_start;
tBTA_GATTS_API_INDICATION api_indicate;
tBTA_GATTS_API_RSP api_rsp;
tBTA_GATTS_API_SET_ATTR_VAL api_set_val;
tBTA_GATTS_API_OPEN api_open;
tBTA_GATTS_API_CANCEL_OPEN api_cancel_open;
tBTA_GATTS_INT_START_IF int_start_if;
/* if peripheral role is supported */
tBTA_GATTS_API_LISTEN api_listen;
tBTA_GATTS_API_SEND_SERVICE_CHANGE api_send_service_change;
} tBTA_GATTS_DATA;
/* application registration control block */
typedef struct {
BOOLEAN in_use;
tBT_UUID app_uuid;
tBTA_GATTS_CBACK *p_cback;
tBTA_GATTS_IF gatt_if;
} tBTA_GATTS_RCB;
/* service registration control block */
typedef struct {
tBT_UUID service_uuid; /* service UUID */
UINT16 service_id; /* service handle */
UINT8 inst_num; /* instance ID */
UINT8 rcb_idx;
UINT8 idx; /* self index of serviec CB */
BOOLEAN in_use;
} tBTA_GATTS_SRVC_CB;
/* GATT server control block */
typedef struct {
BOOLEAN enabled;
tBTA_GATTS_RCB rcb[BTA_GATTS_MAX_APP_NUM];
tBTA_GATTS_SRVC_CB srvc_cb[BTA_GATTS_MAX_SRVC_NUM];
} tBTA_GATTS_CB;
/*****************************************************************************
** Global data
*****************************************************************************/
/* GATTC control block */
#if BTA_DYNAMIC_MEMORY == FALSE
extern tBTA_GATTS_CB bta_gatts_cb;
#else
extern tBTA_GATTS_CB *bta_gatts_cb_ptr;
#define bta_gatts_cb (*bta_gatts_cb_ptr)
#endif
/*****************************************************************************
** Function prototypes
*****************************************************************************/
extern BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg);
extern void bta_gatts_api_disable(tBTA_GATTS_CB *p_cb);
extern void bta_gatts_api_enable(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_data);
extern void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_start_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_set_attr_value(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern tGATT_STATUS bta_gatts_get_attr_value(UINT16 attr_handle, UINT16 *length, UINT8 **value);
extern void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_send_rsp(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_listen(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_send_service_change_indication (tBTA_GATTS_DATA *p_msg);
extern void bta_gatts_show_local_database (void);
extern BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src);
extern tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if);
extern UINT8 bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_IF server_if);
extern UINT8 bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB *p_cb, UINT8 rcb_idx);
extern tBTA_GATTS_SRVC_CB *bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB *p_cb, UINT16 service_id);
extern tBTA_GATTS_SRVC_CB *bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_cb, UINT16 attr_id);
extern void bta_gatts_deinit(void);
#endif /* BTA_GATTS_INT_H */