15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 2003-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  This file contains the GATT client utility function.
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_target.h"
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
28f355ef5a4d7fb667fc57a0dfb60f738d870e252eMyles Watson
29258c2538e3b62a8cdb403f2730c45d721e5292b4Pavlin Radoslavov#include "bt_common.h"
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bta_gatts_int.h"
31cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson#include "bta_sys.h"
32cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson#include "utl.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
34cd1fd07f1306e08fe048682dd5918987e579f937Myles Watsonstatic const uint8_t base_uuid[LEN_UUID_128] = {
35cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
398af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
408af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Function         bta_gatt_convert_uuid16_to_uuid128
418af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
428af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Description      Convert a 16 bits UUID to be an standard 128 bits one.
438af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
448af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Returns          true if two uuid match; false otherwise.
458af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
468af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson ******************************************************************************/
47cd1fd07f1306e08fe048682dd5918987e579f937Myles Watsonstatic void bta_gatt_convert_uuid16_to_uuid128(uint8_t uuid_128[LEN_UUID_128],
48cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson                                               uint16_t uuid_16) {
49cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  uint8_t* p = &uuid_128[LEN_UUID_128 - 4];
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
51cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  memcpy(uuid_128, base_uuid, LEN_UUID_128);
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
53cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  UINT16_TO_STREAM(p, uuid_16);
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
568af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
578af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Function         bta_gatts_alloc_srvc_cb
588af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
598af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Description      allocate a service control block.
608af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
618af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Returns          pointer to the control block, or otherwise NULL when failed.
628af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
638af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson ******************************************************************************/
64cd1fd07f1306e08fe048682dd5918987e579f937Myles Watsonuint8_t bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB* p_cb, uint8_t rcb_idx) {
65cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  uint8_t i;
66cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson
67cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i++) {
68cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    if (!p_cb->srvc_cb[i].in_use) {
69cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson      p_cb->srvc_cb[i].in_use = true;
70cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson      p_cb->srvc_cb[i].rcb_idx = rcb_idx;
71cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson      return i;
725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
73cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  }
74cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  return BTA_GATTS_INVALID_APP;
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
788af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
798af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Function         bta_gatts_find_app_rcb_by_app_if
808af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
818af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Description      find the index of the application control block by app ID.
828af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
838af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Returns          pointer to the control block if success, otherwise NULL
848af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
858af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson ******************************************************************************/
86cd1fd07f1306e08fe048682dd5918987e579f937Myles WatsontBTA_GATTS_RCB* bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if) {
87cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  uint8_t i;
88cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  tBTA_GATTS_RCB* p_reg;
89cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson
90cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  for (i = 0, p_reg = bta_gatts_cb.rcb; i < BTA_GATTS_MAX_APP_NUM;
91cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson       i++, p_reg++) {
92cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    if (p_reg->in_use && p_reg->gatt_if == server_if) return p_reg;
93cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  }
94cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  return NULL;
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
988af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
998af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Function         bta_gatts_find_app_rcb_idx_by_app_if
1008af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1018af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Description      find the index of the application control block by app ID.
1028af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
103cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson * Returns          index of the control block, or BTA_GATTS_INVALID_APP if
1041baaae3f34a667058e7f0c5f778357d98320cf38Myles Watson *                  failed.
1058af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1068af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson ******************************************************************************/
1075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
108cd1fd07f1306e08fe048682dd5918987e579f937Myles Watsonuint8_t bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB* p_cb,
109cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson                                             tBTA_GATTS_IF server_if) {
110cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  uint8_t i;
1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
112cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i++) {
113cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    if (p_cb->rcb[i].in_use && p_cb->rcb[i].gatt_if == server_if) return i;
114cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  }
115cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  return BTA_GATTS_INVALID_APP;
1165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1188af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1198af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Function         bta_gatts_find_srvc_cb_by_srvc_id
1208af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1218af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Description      find the service control block by service ID.
1228af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1238af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Returns          pointer to the rcb.
1248af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1258af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson ******************************************************************************/
126cd1fd07f1306e08fe048682dd5918987e579f937Myles WatsontBTA_GATTS_SRVC_CB* bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB* p_cb,
127cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson                                                      uint16_t service_id) {
128cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  uint8_t i;
129cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  APPL_TRACE_DEBUG("bta_gatts_find_srvc_cb_by_srvc_id  service_id=%d",
130cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson                   service_id);
131cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i++) {
132cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    if (p_cb->srvc_cb[i].in_use && p_cb->srvc_cb[i].service_id == service_id) {
133cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson      APPL_TRACE_DEBUG(
134cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson          "bta_gatts_find_srvc_cb_by_srvc_id  found service cb index =%d", i);
135cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson      return &p_cb->srvc_cb[i];
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
137cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  }
138cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  return NULL;
1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1418af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1428af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Function         bta_gatts_find_srvc_cb_by_attr_id
1438af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1448af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Description      find the service control block by attribute ID.
1458af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1468af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Returns          pointer to the rcb.
1478af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1488af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson ******************************************************************************/
149cd1fd07f1306e08fe048682dd5918987e579f937Myles WatsontBTA_GATTS_SRVC_CB* bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB* p_cb,
150cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson                                                      uint16_t attr_id) {
151cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  uint8_t i;
152cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson
153cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  for (i = 0; i < (BTA_GATTS_MAX_SRVC_NUM); i++) {
154cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    if (/* middle service */
155cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson        (i < (BTA_GATTS_MAX_SRVC_NUM - 1) && p_cb->srvc_cb[i].in_use &&
156cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson         p_cb->srvc_cb[i + 1].in_use &&
157cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson         attr_id >= p_cb->srvc_cb[i].service_id &&
158cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson         attr_id < p_cb->srvc_cb[i + 1].service_id) ||
159cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson        /* last active service */
160cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson        (i < (BTA_GATTS_MAX_SRVC_NUM - 1) && p_cb->srvc_cb[i].in_use &&
161cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson         !p_cb->srvc_cb[i + 1].in_use &&
162cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson         attr_id >= p_cb->srvc_cb[i].service_id) ||
163cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson        /* last service incb */
164cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson        (i == (BTA_GATTS_MAX_SRVC_NUM - 1) &&
165cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson         attr_id >= p_cb->srvc_cb[i].service_id)) {
166cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson      return &p_cb->srvc_cb[i];
1675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
168cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  }
169cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  return NULL;
1705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1728af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1738af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Function         bta_gatts_uuid_compare
1748af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1758af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Description      Compare two UUID to see if they are the same.
1768af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1778af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson * Returns          true if two uuid match; false otherwise.
1788af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson *
1798af480e24549ba51a3f6858d9d9af504715e0beaMyles Watson ******************************************************************************/
180cd1fd07f1306e08fe048682dd5918987e579f937Myles Watsonbool bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src) {
181cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  uint8_t su[LEN_UUID_128], tu[LEN_UUID_128];
182cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  uint8_t *ps, *pt;
183cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson
184cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  /* any of the UUID is unspecified */
185cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  if (src.len == 0 || tar.len == 0) {
186cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    return true;
187cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  }
188cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson
189cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  /* If both are 16-bit, we can do a simple compare */
190cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  if (src.len == 2 && tar.len == 2) {
191cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    return src.uu.uuid16 == tar.uu.uuid16;
192cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  }
193cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson
194cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  /* One or both of the UUIDs is 128-bit */
195cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  if (src.len == LEN_UUID_16) {
196cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    /* convert a 16 bits UUID to 128 bits value */
197cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
198cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    ps = su;
199cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  } else
200cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    ps = src.uu.uuid128;
201cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson
202cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  if (tar.len == LEN_UUID_16) {
203cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    /* convert a 16 bits UUID to 128 bits value */
204cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
205cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    pt = tu;
206cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  } else
207cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson    pt = tar.uu.uuid128;
208cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson
209cd1fd07f1306e08fe048682dd5918987e579f937Myles Watson  return (memcmp(ps, pt, LEN_UUID_128) == 0);
2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
211