1 /*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "gatt"
18
19 #include <bluetooth/log.h>
20
21 #include <list>
22 #include <unordered_map>
23 #include <unordered_set>
24 #include <vector>
25
26 #include "bta_gatt_queue.h"
27 #include "os/log.h"
28 #include "osi/include/allocator.h"
29
30 using gatt_operation = BtaGattQueue::gatt_operation;
31 using namespace bluetooth;
32
33 constexpr uint8_t GATT_READ_CHAR = 1;
34 constexpr uint8_t GATT_READ_DESC = 2;
35 constexpr uint8_t GATT_WRITE_CHAR = 3;
36 constexpr uint8_t GATT_WRITE_DESC = 4;
37 constexpr uint8_t GATT_CONFIG_MTU = 5;
38 constexpr uint8_t GATT_READ_MULTI = 6;
39
40 struct gatt_read_op_data {
41 GATT_READ_OP_CB cb;
42 void* cb_data;
43 };
44
45 std::unordered_map<uint16_t, std::list<gatt_operation>>
46 BtaGattQueue::gatt_op_queue;
47 std::unordered_set<uint16_t> BtaGattQueue::gatt_op_queue_executing;
48
mark_as_not_executing(uint16_t conn_id)49 void BtaGattQueue::mark_as_not_executing(uint16_t conn_id) {
50 gatt_op_queue_executing.erase(conn_id);
51 }
52
gatt_read_op_finished(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)53 void BtaGattQueue::gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status,
54 uint16_t handle, uint16_t len,
55 uint8_t* value, void* data) {
56 gatt_read_op_data* tmp = (gatt_read_op_data*)data;
57 GATT_READ_OP_CB tmp_cb = tmp->cb;
58 void* tmp_cb_data = tmp->cb_data;
59
60 osi_free(data);
61
62 mark_as_not_executing(conn_id);
63 gatt_execute_next_op(conn_id);
64
65 if (tmp_cb) {
66 tmp_cb(conn_id, status, handle, len, value, tmp_cb_data);
67 return;
68 }
69 }
70
71 struct gatt_write_op_data {
72 GATT_WRITE_OP_CB cb;
73 void* cb_data;
74 };
75
gatt_write_op_finished(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)76 void BtaGattQueue::gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status,
77 uint16_t handle, uint16_t len,
78 const uint8_t* value, void* data) {
79 gatt_write_op_data* tmp = (gatt_write_op_data*)data;
80 GATT_WRITE_OP_CB tmp_cb = tmp->cb;
81 void* tmp_cb_data = tmp->cb_data;
82
83 osi_free(data);
84
85 mark_as_not_executing(conn_id);
86 gatt_execute_next_op(conn_id);
87
88 if (tmp_cb) {
89 tmp_cb(conn_id, status, handle, len, value, tmp_cb_data);
90 return;
91 }
92 }
93
94 struct gatt_configure_mtu_op_data {
95 GATT_CONFIGURE_MTU_OP_CB cb;
96 void* cb_data;
97 };
98
gatt_configure_mtu_op_finished(uint16_t conn_id,tGATT_STATUS status,void * data)99 void BtaGattQueue::gatt_configure_mtu_op_finished(uint16_t conn_id,
100 tGATT_STATUS status,
101 void* data) {
102 gatt_configure_mtu_op_data* tmp = (gatt_configure_mtu_op_data*)data;
103 GATT_CONFIGURE_MTU_OP_CB tmp_cb = tmp->cb;
104 void* tmp_cb_data = tmp->cb_data;
105
106 osi_free(data);
107
108 mark_as_not_executing(conn_id);
109 gatt_execute_next_op(conn_id);
110
111 if (tmp_cb) {
112 tmp_cb(conn_id, status, tmp_cb_data);
113 return;
114 }
115 }
116
117 struct gatt_read_multi_op_data {
118 GATT_READ_MULTI_OP_CB cb;
119 void* cb_data;
120 };
121
gatt_read_multi_op_finished(uint16_t conn_id,tGATT_STATUS status,tBTA_GATTC_MULTI & handles,uint16_t len,uint8_t * value,void * data)122 void BtaGattQueue::gatt_read_multi_op_finished(uint16_t conn_id,
123 tGATT_STATUS status,
124 tBTA_GATTC_MULTI& handles,
125 uint16_t len, uint8_t* value,
126 void* data) {
127 gatt_read_multi_op_data* tmp = (gatt_read_multi_op_data*)data;
128 GATT_READ_MULTI_OP_CB tmp_cb = tmp->cb;
129 void* tmp_cb_data = tmp->cb_data;
130
131 osi_free(data);
132
133 mark_as_not_executing(conn_id);
134 gatt_execute_next_op(conn_id);
135
136 if (tmp_cb) {
137 tmp_cb(conn_id, status, handles, len, value, tmp_cb_data);
138 return;
139 }
140 }
141
gatt_execute_next_op(uint16_t conn_id)142 void BtaGattQueue::gatt_execute_next_op(uint16_t conn_id) {
143 log::verbose("conn_id=0x{:x}", conn_id);
144 if (gatt_op_queue.empty()) {
145 log::verbose("op queue is empty");
146 return;
147 }
148
149 auto map_ptr = gatt_op_queue.find(conn_id);
150 if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) {
151 log::verbose("no more operations queued for conn_id {}", conn_id);
152 return;
153 }
154
155 if (gatt_op_queue_executing.count(conn_id)) {
156 log::verbose("can't enqueue next op, already executing");
157 return;
158 }
159
160 gatt_op_queue_executing.insert(conn_id);
161
162 std::list<gatt_operation>& gatt_ops = map_ptr->second;
163
164 gatt_operation& op = gatt_ops.front();
165
166 if (op.type == GATT_READ_CHAR) {
167 gatt_read_op_data* data =
168 (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data));
169 data->cb = op.read_cb;
170 data->cb_data = op.read_cb_data;
171 BTA_GATTC_ReadCharacteristic(conn_id, op.handle, GATT_AUTH_REQ_NONE,
172 gatt_read_op_finished, data);
173
174 } else if (op.type == GATT_READ_DESC) {
175 gatt_read_op_data* data =
176 (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data));
177 data->cb = op.read_cb;
178 data->cb_data = op.read_cb_data;
179 BTA_GATTC_ReadCharDescr(conn_id, op.handle, GATT_AUTH_REQ_NONE,
180 gatt_read_op_finished, data);
181
182 } else if (op.type == GATT_WRITE_CHAR) {
183 gatt_write_op_data* data =
184 (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data));
185 data->cb = op.write_cb;
186 data->cb_data = op.write_cb_data;
187 BTA_GATTC_WriteCharValue(conn_id, op.handle, op.write_type,
188 std::move(op.value), GATT_AUTH_REQ_NONE,
189 gatt_write_op_finished, data);
190
191 } else if (op.type == GATT_WRITE_DESC) {
192 gatt_write_op_data* data =
193 (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data));
194 data->cb = op.write_cb;
195 data->cb_data = op.write_cb_data;
196 BTA_GATTC_WriteCharDescr(conn_id, op.handle, std::move(op.value),
197 GATT_AUTH_REQ_NONE, gatt_write_op_finished, data);
198 } else if (op.type == GATT_CONFIG_MTU) {
199 gatt_configure_mtu_op_data* data =
200 (gatt_configure_mtu_op_data*)osi_malloc(sizeof(gatt_configure_mtu_op_data));
201 data->cb = op.mtu_cb;
202 data->cb_data = op.mtu_cb_data;
203 BTA_GATTC_ConfigureMTU(conn_id, static_cast<uint16_t>(op.value[0] |
204 (op.value[1] << 8)),
205 gatt_configure_mtu_op_finished, data);
206 } else if (op.type == GATT_READ_MULTI) {
207 gatt_read_multi_op_data* data =
208 (gatt_read_multi_op_data*)osi_malloc(sizeof(gatt_read_multi_op_data));
209 data->cb = op.read_multi_cb;
210 data->cb_data = op.read_cb_data;
211 BTA_GATTC_ReadMultiple(conn_id, op.handles, op.variable_len,
212 GATT_AUTH_REQ_NONE, gatt_read_multi_op_finished,
213 data);
214 }
215
216 gatt_ops.pop_front();
217 }
218
Clean(uint16_t conn_id)219 void BtaGattQueue::Clean(uint16_t conn_id) {
220 gatt_op_queue.erase(conn_id);
221 gatt_op_queue_executing.erase(conn_id);
222 }
223
ReadCharacteristic(uint16_t conn_id,uint16_t handle,GATT_READ_OP_CB cb,void * cb_data)224 void BtaGattQueue::ReadCharacteristic(uint16_t conn_id, uint16_t handle,
225 GATT_READ_OP_CB cb, void* cb_data) {
226 gatt_op_queue[conn_id].push_back({.type = GATT_READ_CHAR,
227 .handle = handle,
228 .read_cb = cb,
229 .read_cb_data = cb_data});
230 gatt_execute_next_op(conn_id);
231 }
232
ReadDescriptor(uint16_t conn_id,uint16_t handle,GATT_READ_OP_CB cb,void * cb_data)233 void BtaGattQueue::ReadDescriptor(uint16_t conn_id, uint16_t handle,
234 GATT_READ_OP_CB cb, void* cb_data) {
235 gatt_op_queue[conn_id].push_back({.type = GATT_READ_DESC,
236 .handle = handle,
237 .read_cb = cb,
238 .read_cb_data = cb_data});
239 gatt_execute_next_op(conn_id);
240 }
241
WriteCharacteristic(uint16_t conn_id,uint16_t handle,std::vector<uint8_t> value,tGATT_WRITE_TYPE write_type,GATT_WRITE_OP_CB cb,void * cb_data)242 void BtaGattQueue::WriteCharacteristic(uint16_t conn_id, uint16_t handle,
243 std::vector<uint8_t> value,
244 tGATT_WRITE_TYPE write_type,
245 GATT_WRITE_OP_CB cb, void* cb_data) {
246 gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_CHAR,
247 .handle = handle,
248 .write_cb = cb,
249 .write_cb_data = cb_data,
250 .write_type = write_type,
251 .value = std::move(value)});
252 gatt_execute_next_op(conn_id);
253 }
254
WriteDescriptor(uint16_t conn_id,uint16_t handle,std::vector<uint8_t> value,tGATT_WRITE_TYPE write_type,GATT_WRITE_OP_CB cb,void * cb_data)255 void BtaGattQueue::WriteDescriptor(uint16_t conn_id, uint16_t handle,
256 std::vector<uint8_t> value,
257 tGATT_WRITE_TYPE write_type,
258 GATT_WRITE_OP_CB cb, void* cb_data) {
259 gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_DESC,
260 .handle = handle,
261 .write_cb = cb,
262 .write_cb_data = cb_data,
263 .write_type = write_type,
264 .value = std::move(value)});
265 gatt_execute_next_op(conn_id);
266 }
267
ConfigureMtu(uint16_t conn_id,uint16_t mtu)268 void BtaGattQueue::ConfigureMtu(uint16_t conn_id, uint16_t mtu) {
269 log::info("mtu: {}", static_cast<int>(mtu));
270 std::vector<uint8_t> value = {static_cast<uint8_t>(mtu & 0xff),
271 static_cast<uint8_t>(mtu >> 8)};
272 gatt_op_queue[conn_id].push_back({.type = GATT_CONFIG_MTU,
273 .value = std::move(value)});
274 gatt_execute_next_op(conn_id);
275 }
276
ReadMultiCharacteristic(uint16_t conn_id,tBTA_GATTC_MULTI & handles,bool variable_len,GATT_READ_MULTI_OP_CB cb,void * cb_data)277 void BtaGattQueue::ReadMultiCharacteristic(uint16_t conn_id,
278 tBTA_GATTC_MULTI& handles,
279 bool variable_len,
280 GATT_READ_MULTI_OP_CB cb,
281 void* cb_data) {
282 gatt_op_queue[conn_id].push_back({.type = GATT_READ_MULTI,
283 .handles = handles,
284 .variable_len = variable_len,
285 .read_multi_cb = cb,
286 .read_cb_data = cb_data});
287 gatt_execute_next_op(conn_id);
288 }
289