1ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta/******************************************************************************
2ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *
3c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski *  Copyright (C) 2017 The Android Open Source Project
4ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *
5ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  Licensed under the Apache License, Version 2.0 (the "License");
6ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  you may not use this file except in compliance with the License.
7ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  You may obtain a copy of the License at:
8ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *
9ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  http://www.apache.org/licenses/LICENSE-2.0
10ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *
11ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  Unless required by applicable law or agreed to in writing, software
12ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  distributed under the License is distributed on an "AS IS" BASIS,
13ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  See the License for the specific language governing permissions and
15ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *  limitations under the License.
16ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta *
17ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta ******************************************************************************/
18ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
194dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#include <base/logging.h>
200f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski#include <base/strings/stringprintf.h>
21ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#include <string.h>
22c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski#include <array>
23c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski#include <list>
24c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski#include <queue>
25ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#include "gap_api.h"
26ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta#include "gatt_api.h"
27ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
280f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowskiusing base::StringPrintf;
290f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski
30c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskinamespace {
31c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
32c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskitypedef struct {
33c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t uuid;
34c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_BLE_CMPL_CBACK* p_cback;
35c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski} tGAP_REQUEST;
36c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
37c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskitypedef struct {
389e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski  RawAddress bda;
39c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_BLE_CMPL_CBACK* p_cback;
40c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t conn_id;
41c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t cl_op_uuid;
42c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  bool connected;
43c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  std::queue<tGAP_REQUEST> requests;
44c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski} tGAP_CLCB;
45c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
46c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskitypedef struct {
47c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t handle;
48c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t uuid;
49c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_BLE_ATTR_VALUE attr_value;
50c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski} tGAP_ATTR;
51c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
52c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskivoid server_attr_request_cback(uint16_t, uint32_t, tGATTS_REQ_TYPE,
53c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                               tGATTS_DATA*);
549e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskivoid client_connect_cback(tGATT_IF, const RawAddress&, uint16_t, bool,
55c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                          tGATT_DISCONN_REASON, tGATT_TRANSPORT);
56c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskivoid client_cmpl_cback(uint16_t, tGATTC_OPTYPE, tGATT_STATUS,
57c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                       tGATT_CL_COMPLETE*);
58c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
59c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub PawlowskitGATT_CBACK gap_cback = {client_connect_cback,
60c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                         client_cmpl_cback,
61c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                         NULL,
62c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                         NULL,
63c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                         server_attr_request_cback,
64c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                         NULL,
65c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                         NULL,
66c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                         NULL,
67c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                         NULL};
68c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
69c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskiconstexpr int GAP_CHAR_DEV_NAME_SIZE = BD_NAME_LEN;
70c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskiconstexpr int GAP_MAX_CHAR_NUM = 4;
71c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
72c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskistd::vector<tGAP_CLCB> gap_clcbs;
73c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/* LE GAP attribute database */
74c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskistd::array<tGAP_ATTR, GAP_MAX_CHAR_NUM> gatt_attr;
75c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub PawlowskitGATT_IF gatt_if;
76c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
77c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** returns LCB with macthing bd address, or nullptr */
789e030fde05352ec4385d7baf6cc2af89e95e039cJakub PawlowskitGAP_CLCB* find_clcb_by_bd_addr(const RawAddress& bda) {
79c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  for (auto& cb : gap_clcbs)
80c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    if (cb.bda == bda) return &cb;
81c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
82c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  return nullptr;
83ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
84ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
85c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** returns LCB with macthing connection ID, or nullptr if not found  */
86c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub PawlowskitGAP_CLCB* ble_find_clcb_by_conn_id(uint16_t conn_id) {
87c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  for (auto& cb : gap_clcbs)
88c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    if (cb.connected && cb.conn_id == conn_id) return &cb;
89444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji
90c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  return nullptr;
91ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
92ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
93c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** allocates a GAP connection link control block */
949e030fde05352ec4385d7baf6cc2af89e95e039cJakub PawlowskitGAP_CLCB* clcb_alloc(const RawAddress& bda) {
95c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gap_clcbs.emplace_back();
96c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_CLCB& cb = gap_clcbs.back();
97c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  cb.bda = bda;
98c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  return &cb;
99ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
100717a4a9f3a044f264ec2482c2d1806ec3093707aPavlin Radoslavov
101c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** The function clean up the pending request queue in GAP */
102c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskivoid clcb_dealloc(tGAP_CLCB& clcb) {
103c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  // put last element into place of current element, and remove last one - just
104c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  // fast remove.
105c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  for (auto it = gap_clcbs.begin(); it != gap_clcbs.end(); it++) {
106c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    if (it->conn_id == clcb.conn_id) {
107c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      auto last_one = std::prev(gap_clcbs.end());
108c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      *it = *last_one;
109c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      gap_clcbs.erase(last_one);
110c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      return;
111c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    }
112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
113444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji}
114ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
115c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** GAP Attributes Database Request callback */
116c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub PawlowskitGATT_STATUS read_attr_value(uint16_t handle, tGATT_VALUE* p_value,
117c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                             bool is_long) {
118c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint8_t* p = p_value->value;
119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t offset = p_value->offset;
120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p_dev_name = NULL;
121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
122c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  for (const tGAP_ATTR& db_attr : gatt_attr) {
123c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    const tGAP_BLE_ATTR_VALUE& attr_value = db_attr.attr_value;
124c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    if (handle == db_attr.handle) {
125c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      if (db_attr.uuid != GATT_UUID_GAP_DEVICE_NAME && is_long == true)
126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return GATT_NOT_LONG;
127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
128c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      switch (db_attr.uuid) {
129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        case GATT_UUID_GAP_DEVICE_NAME:
130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          BTM_ReadLocalDeviceName((char**)&p_dev_name);
131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (strlen((char*)p_dev_name) > GATT_MAX_ATTR_LEN)
132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_value->len = GATT_MAX_ATTR_LEN;
133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          else
134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_value->len = (uint16_t)strlen((char*)p_dev_name);
135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (offset > p_value->len)
137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            return GATT_INVALID_OFFSET;
138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          else {
139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_value->len -= offset;
140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_dev_name += offset;
141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            ARRAY_TO_STREAM(p, p_dev_name, p_value->len);
1420f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski            DVLOG(1) << "GATT_UUID_GAP_DEVICE_NAME len=" << +p_value->len;
143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        case GATT_UUID_GAP_ICON:
147c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          UINT16_TO_STREAM(p, attr_value.icon);
148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_value->len = 2;
149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        case GATT_UUID_GAP_PREF_CONN_PARAM:
152c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          UINT16_TO_STREAM(p, attr_value.conn_param.int_min); /* int_min */
153c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          UINT16_TO_STREAM(p, attr_value.conn_param.int_max); /* int_max */
154c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          UINT16_TO_STREAM(p, attr_value.conn_param.latency); /* latency */
155c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          UINT16_TO_STREAM(p, attr_value.conn_param.sp_tout); /* sp_tout */
156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_value->len = 8;
157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* address resolution */
160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
161c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          UINT8_TO_STREAM(p, attr_value.addr_resolution);
162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_value->len = 1;
163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return GATT_SUCCESS;
166ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    }
167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return GATT_NOT_FOUND;
169ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
170ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
171c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** GAP Attributes Database Read/Read Blob Request process */
172c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub PawlowskitGATT_STATUS proc_read(tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data,
173c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                       tGATTS_RSP* p_rsp) {
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_data->is_long) p_rsp->attr_value.offset = p_data->offset;
175ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rsp->attr_value.handle = p_data->handle;
177ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
178c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  return read_attr_value(p_data->handle, &p_rsp->attr_value, p_data->is_long);
179ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
180ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
181c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** GAP ATT server process a write request */
182c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskiuint8_t proc_write_req(tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) {
183c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  for (const auto& db_addr : gatt_attr)
184c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    if (p_data->handle == db_addr.handle) return GATT_WRITE_NOT_PERMIT;
185c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return GATT_NOT_FOUND;
187ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
188ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
189c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** GAP ATT server attribute access request callback */
190c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskivoid server_attr_request_cback(uint16_t conn_id, uint32_t trans_id,
191c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                               tGATTS_REQ_TYPE type, tGATTS_DATA* p_data) {
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t status = GATT_INVALID_PDU;
193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool ignore = false;
194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1950f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski  DVLOG(1) << StringPrintf("%s: recv type (0x%02x)", __func__, type);
196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
197c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGATTS_RSP rsp_msg;
198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  switch (type) {
201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    case GATTS_REQ_TYPE_READ_DESCRIPTOR:
203c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      status = proc_read(type, &p_data->read_req, &rsp_msg);
204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      break;
205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!p_data->write_req.need_rsp) ignore = true;
209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
210c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      status = proc_write_req(type, &p_data->write_req);
211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      break;
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    case GATTS_REQ_TYPE_WRITE_EXEC:
214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      ignore = true;
2150f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski      DVLOG(1) << "Ignore GATTS_REQ_TYPE_WRITE_EXEC";
216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      break;
217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    case GATTS_REQ_TYPE_MTU:
2190f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski      DVLOG(1) << "Get MTU exchange new mtu size: " << +p_data->mtu;
220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      ignore = true;
221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      break;
222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    default:
2240f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski      DVLOG(1) << StringPrintf("Unknown/unexpected LE GAP ATT request: 0x%02x",
225c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                               type);
226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      break;
227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
228ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!ignore) GATTS_SendRsp(conn_id, trans_id, status, &rsp_msg);
230ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
231ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
232c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/**
233c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski * utility function to send a read request for a GAP charactersitic.
234c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski * Returns true if read started, else false if GAP is busy.
235c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski */
236c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskibool send_cl_read_request(tGAP_CLCB& clcb) {
237c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (!clcb.requests.size()) {
238c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    return false;
239c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  }
240c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
241c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_REQUEST& req = clcb.requests.front();
242c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  clcb.p_cback = req.p_cback;
243c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t uuid = req.uuid;
244c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  clcb.requests.pop();
245c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
246c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGATT_READ_PARAM param;
247c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  memset(&param, 0, sizeof(tGATT_READ_PARAM));
248c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
249c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  param.service.uuid.len = LEN_UUID_16;
250c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  param.service.uuid.uu.uuid16 = uuid;
251c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  param.service.s_handle = 1;
252c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  param.service.e_handle = 0xFFFF;
253c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  param.service.auth_req = 0;
254c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
255c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (GATTC_Read(clcb.conn_id, GATT_READ_BY_TYPE, &param) == GATT_SUCCESS) {
256c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    clcb.cl_op_uuid = uuid;
257c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  }
258c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
259c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  return true;
260c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski}
261c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
262c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** GAP client operation complete callback */
263c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskivoid cl_op_cmpl(tGAP_CLCB& clcb, bool status, uint16_t len, uint8_t* p_name) {
264c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_BLE_CMPL_CBACK* p_cback = clcb.p_cback;
265c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t op = clcb.cl_op_uuid;
266c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
2670f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski  DVLOG(1) << StringPrintf("%s: status: %d", __func__, status);
268c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
269c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  clcb.cl_op_uuid = 0;
270c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  clcb.p_cback = NULL;
271c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
272c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (p_cback && op) {
2730f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski    DVLOG(1) << __func__ << ": calling";
274c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    (*p_cback)(status, clcb.bda, len, (char*)p_name);
275c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  }
276c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
277c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  /* if no further activity is requested in callback, drop the link */
278c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (clcb.connected) {
279c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    if (!send_cl_read_request(clcb)) {
280c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      GATT_Disconnect(clcb.conn_id);
281c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      clcb_dealloc(clcb);
282c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    }
283c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  }
284c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski}
285c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
286c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** Client connection callback */
2879e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskivoid client_connect_cback(tGATT_IF, const RawAddress& bda, uint16_t conn_id,
288c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                          bool connected, tGATT_DISCONN_REASON reason,
289c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                          tGATT_TRANSPORT) {
290c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_CLCB* p_clcb = find_clcb_by_bd_addr(bda);
291c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (p_clcb == NULL) return;
292c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
293c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (connected) {
294c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    p_clcb->conn_id = conn_id;
295c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    p_clcb->connected = true;
296c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    /* start operation is pending */
297c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    send_cl_read_request(*p_clcb);
298c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  } else {
299c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    p_clcb->connected = false;
300c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    cl_op_cmpl(*p_clcb, false, 0, NULL);
301c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    /* clean up clcb */
302c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    clcb_dealloc(*p_clcb);
303c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  }
304c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski}
305c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
306c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski/** Client operation complete callback */
307c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowskivoid client_cmpl_cback(uint16_t conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
308c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                       tGATT_CL_COMPLETE* p_data) {
309c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_CLCB* p_clcb = ble_find_clcb_by_conn_id(conn_id);
310c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t op_type;
311c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t min, max, latency, tout;
312c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint16_t len;
313c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  uint8_t* pp;
314c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
315c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (p_clcb == NULL) return;
316c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
317c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  op_type = p_clcb->cl_op_uuid;
318c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
3190f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski  DVLOG(1) << StringPrintf(
3200f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski      "%s: - op_code: 0x%02x  status: 0x%02x  read_type: 0x%04x", __func__, op,
3210f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski      status, op_type);
322c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  /* Currently we only issue read commands */
323c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (op != GATTC_OPTYPE_READ) return;
324c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
325c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (status != GATT_SUCCESS) {
326c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    cl_op_cmpl(*p_clcb, false, 0, NULL);
327c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    return;
328c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  }
329c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
330c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  pp = p_data->att_value.value;
331c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  switch (op_type) {
332c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    case GATT_UUID_GAP_PREF_CONN_PARAM:
333c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      /* Extract the peripheral preferred connection parameters and save them */
334c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      STREAM_TO_UINT16(min, pp);
335c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      STREAM_TO_UINT16(max, pp);
336c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      STREAM_TO_UINT16(latency, pp);
337c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      STREAM_TO_UINT16(tout, pp);
338c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
339c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      BTM_BleSetPrefConnParams(p_clcb->bda, min, max, latency, tout);
340c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      /* release the connection here */
341c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      cl_op_cmpl(*p_clcb, true, 0, NULL);
342c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      break;
343c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
344c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    case GATT_UUID_GAP_DEVICE_NAME:
345c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      len = (uint16_t)strlen((char*)pp);
346c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      if (len > GAP_CHAR_DEV_NAME_SIZE) len = GAP_CHAR_DEV_NAME_SIZE;
347c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      cl_op_cmpl(*p_clcb, true, len, pp);
348c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      break;
349c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
350c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
351c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      cl_op_cmpl(*p_clcb, true, 1, pp);
352c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski      break;
353c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  }
354c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski}
355c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
3569e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskibool accept_client_operation(const RawAddress& peer_bda, uint16_t uuid,
357c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                             tGAP_BLE_CMPL_CBACK* p_cback) {
358c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (p_cback == NULL && uuid != GATT_UUID_GAP_PREF_CONN_PARAM) return false;
359c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
360c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_CLCB* p_clcb = find_clcb_by_bd_addr(peer_bda);
361c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (p_clcb == NULL) {
362c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    p_clcb = clcb_alloc(peer_bda);
363c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  }
364c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
365c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  DVLOG(1) << __func__ << ": BDA: " << peer_bda
366c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski           << StringPrintf(" cl_op_uuid: 0x%04x", uuid);
367c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
368c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (GATT_GetConnIdIfConnected(gatt_if, peer_bda, &p_clcb->conn_id,
369c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                                BT_TRANSPORT_LE))
370c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    p_clcb->connected = true;
371c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
372c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (!GATT_Connect(gatt_if, p_clcb->bda, true, BT_TRANSPORT_LE, true))
373c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    return false;
374c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
375c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  /* enqueue the request */
376c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  p_clcb->requests.push({.uuid = uuid, .p_cback = p_cback});
377c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
378c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  if (p_clcb->connected && p_clcb->cl_op_uuid == 0)
379c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    return send_cl_read_request(*p_clcb);
380c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  else /* wait for connection up or pending operation to finish */
381c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    return true;
382c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski}
383c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
384c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski}  // namespace
385c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski
386ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta/*******************************************************************************
387ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
388ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         btm_ble_att_db_init
389ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
390ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      GAP ATT database initalization.
391ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void.
393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid gap_attr_db_init(void) {
396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_UUID app_uuid = {LEN_UUID_128, {0}};
397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t service_handle;
398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fill our internal UUID with a fixed pattern 0x82 */
400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&app_uuid.uu.uuid128, 0x82, LEN_UUID_128);
401c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr.fill({});
402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
403c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_if = GATT_Register(&app_uuid, &gap_cback);
404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
405c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  GATT_StartIf(gatt_if);
406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bt_uuid_t svc_uuid, name_uuid, icon_uuid, pref_uuid, addr_res_uuid;
408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uuid_128_from_16(&svc_uuid, UUID_SERVCLASS_GAP_SERVER);
409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uuid_128_from_16(&name_uuid, GATT_UUID_GAP_DEVICE_NAME);
410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uuid_128_from_16(&icon_uuid, GATT_UUID_GAP_ICON);
411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uuid_128_from_16(&pref_uuid, GATT_UUID_GAP_PREF_CONN_PARAM);
412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uuid_128_from_16(&addr_res_uuid, GATT_UUID_GAP_CENTRAL_ADDR_RESOL);
413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btgatt_db_element_t service[] = {
415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = svc_uuid},
416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {.type = BTGATT_DB_CHARACTERISTIC,
417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .uuid = name_uuid,
418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .properties = GATT_CHAR_PROP_BIT_READ,
419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .permissions = GATT_PERM_READ},
420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {.type = BTGATT_DB_CHARACTERISTIC,
421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .uuid = icon_uuid,
422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .properties = GATT_CHAR_PROP_BIT_READ,
423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .permissions = GATT_PERM_READ},
424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {.type = BTGATT_DB_CHARACTERISTIC,
425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .uuid = addr_res_uuid,
426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .properties = GATT_CHAR_PROP_BIT_READ,
427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .permissions = GATT_PERM_READ}
428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#if (BTM_PERIPHERAL_ENABLED == TRUE) /* Only needed for peripheral testing */
429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    ,
430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {.type = BTGATT_DB_CHARACTERISTIC,
431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .uuid = pref_uuid,
432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .properties = GATT_CHAR_PROP_BIT_READ,
433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     .permissions = GATT_PERM_READ}
4347fa4fba6f59f97df00aff07dbe8fb21b114b3c2cGanesh Ganapathi Batta#endif
435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  };
4367fa4fba6f59f97df00aff07dbe8fb21b114b3c2cGanesh Ganapathi Batta
437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Add a GAP service */
438c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  GATTS_AddService(gatt_if, service,
439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                   sizeof(service) / sizeof(btgatt_db_element_t));
440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  service_handle = service[0].attribute_handle;
441444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji
4420f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski  DVLOG(1) << __func__ << ": service_handle = " << +service_handle;
443ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
444c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[0].uuid = GATT_UUID_GAP_DEVICE_NAME;
445c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[0].handle = service[1].attribute_handle;
446ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
447c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[1].uuid = GATT_UUID_GAP_ICON;
448c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[1].handle = service[2].attribute_handle;
449ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
450c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[2].uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
451c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[2].handle = service[3].attribute_handle;
452c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[2].attr_value.addr_resolution = 0;
453ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#if (BTM_PERIPHERAL_ENABLED == TRUE) /*  Only needed for peripheral testing */
455ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
456c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[3].uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
457c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[3].attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */
458c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[3].attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */
459c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[3].attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */
460c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[3].attr_value.conn_param.sp_tout =
461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      GAP_PREFER_CONN_SP_TOUT; /* 2000 */
462c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  gatt_attr[3].handle = service[4].attribute_handle;
463a641b6fa2a25e1b5382945d13c4fa49d36084a78Jakub Pawlowski#endif
464ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
465ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
466ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta/*******************************************************************************
467ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
468ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         GAP_BleAttrDBUpdate
469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      GAP ATT database update.
471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid GAP_BleAttrDBUpdate(uint16_t attr_uuid, tGAP_BLE_ATTR_VALUE* p_value) {
4740f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski  DVLOG(1) << StringPrintf("%s: attr_uuid=0x%04x", __func__, attr_uuid);
475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
476c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  for (tGAP_ATTR& db_attr : gatt_attr) {
477c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    if (db_attr.uuid == attr_uuid) {
4780f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski      DVLOG(1) << StringPrintf("Found attr_uuid=0x%04x", attr_uuid);
479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      switch (attr_uuid) {
481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        case GATT_UUID_GAP_ICON:
482c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          db_attr.attr_value.icon = p_value->icon;
483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        case GATT_UUID_GAP_PREF_CONN_PARAM:
486c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          memcpy((void*)&db_attr.attr_value.conn_param,
487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                 (const void*)&p_value->conn_param,
488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                 sizeof(tGAP_BLE_PREF_PARAM));
489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        case GATT_UUID_GAP_DEVICE_NAME:
492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          BTM_SetLocalDeviceName((char*)p_value->p_dev_name);
493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
496c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski          db_attr.attr_value.addr_resolution = p_value->addr_resolution;
497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      break;
500ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    }
501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
502ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return;
504ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
505ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
506ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta/*******************************************************************************
507ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
508ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         GAP_BleReadPeerPrefConnParams
509ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
510ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Start a process to read a connected peripheral's preferred
511ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  connection parameters
512ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
513ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if read started, else false if GAP is busy
514ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
515ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
5169e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskibool GAP_BleReadPeerPrefConnParams(const RawAddress& peer_bda) {
517c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  return accept_client_operation(peer_bda, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
518ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
519ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
520ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta/*******************************************************************************
521ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
522ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         GAP_BleReadPeerDevName
523ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
5249ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Start a process to read a connected peripheral's device
5259ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  name.
526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
527ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if request accepted
528ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
5309e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskibool GAP_BleReadPeerDevName(const RawAddress& peer_bda,
531c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                            tGAP_BLE_CMPL_CBACK* p_cback) {
532c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  return accept_client_operation(peer_bda, GATT_UUID_GAP_DEVICE_NAME, p_cback);
533ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
534ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
535444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji/*******************************************************************************
536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         GAP_BleReadPeerAddressResolutionCap
538ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
539ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Start a process to read peer address resolution capability
540ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
541ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if request accepted
542ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
543ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
5449e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskibool GAP_BleReadPeerAddressResolutionCap(const RawAddress& peer_bda,
545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                         tGAP_BLE_CMPL_CBACK* p_cback) {
546c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  return accept_client_operation(peer_bda, GATT_UUID_GAP_CENTRAL_ADDR_RESOL,
547c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski                                 p_cback);
548444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji}
5497fa4fba6f59f97df00aff07dbe8fb21b114b3c2cGanesh Ganapathi Batta
550ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta/*******************************************************************************
551ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
552ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         GAP_BleCancelReadPeerDevName
553ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
554ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Cancel reading a peripheral's device name.
555ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
556ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if request accepted
557ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
558ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
5599e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskibool GAP_BleCancelReadPeerDevName(const RawAddress& peer_bda) {
560c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  tGAP_CLCB* p_clcb = find_clcb_by_bd_addr(peer_bda);
561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
562c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  DVLOG(1) << __func__ << ": BDA: " << peer_bda
563c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski           << StringPrintf(" cl_op_uuid: 0x%04x",
564c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                           (p_clcb == NULL) ? 0 : p_clcb->cl_op_uuid);
565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_clcb == NULL) {
5670f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski    LOG(ERROR) << "Cannot cancel current op is not get dev name";
568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
570ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_clcb->connected) {
572c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski    if (!GATT_CancelConnect(gatt_if, peer_bda, true)) {
5730f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski      LOG(ERROR) << "Cannot cancel where No connection id";
574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return false;
575ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta    }
576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
577ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
578c21894e7f90fbdc92a31c20c3c286acf0bc06a99Jakub Pawlowski  cl_op_cmpl(*p_clcb, false, 0, NULL);
579ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
581ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta}
582