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 #include "bta_gatt_queue.h"
18
19 #include <list>
20 #include <unordered_map>
21 #include <unordered_set>
22
23 using gatt_operation = BtaGattQueue::gatt_operation;
24
25 constexpr uint8_t GATT_READ_CHAR = 1;
26 constexpr uint8_t GATT_READ_DESC = 2;
27 constexpr uint8_t GATT_WRITE_CHAR = 3;
28 constexpr uint8_t GATT_WRITE_DESC = 4;
29
30 struct gatt_read_op_data {
31 GATT_READ_OP_CB cb;
32 void* cb_data;
33 };
34
35 std::unordered_map<uint16_t, std::list<gatt_operation>>
36 BtaGattQueue::gatt_op_queue;
37 std::unordered_set<uint16_t> BtaGattQueue::gatt_op_queue_executing;
38
mark_as_not_executing(uint16_t conn_id)39 void BtaGattQueue::mark_as_not_executing(uint16_t conn_id) {
40 gatt_op_queue_executing.erase(conn_id);
41 }
42
gatt_read_op_finished(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)43 void BtaGattQueue::gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status,
44 uint16_t handle, uint16_t len,
45 uint8_t* value, void* data) {
46 gatt_read_op_data* tmp = (gatt_read_op_data*)data;
47 GATT_READ_OP_CB tmp_cb = tmp->cb;
48 void* tmp_cb_data = tmp->cb_data;
49
50 osi_free(data);
51
52 mark_as_not_executing(conn_id);
53 gatt_execute_next_op(conn_id);
54
55 if (tmp_cb) {
56 tmp_cb(conn_id, status, handle, len, value, tmp_cb_data);
57 return;
58 }
59 }
60
61 struct gatt_write_op_data {
62 GATT_WRITE_OP_CB cb;
63 void* cb_data;
64 };
65
gatt_write_op_finished(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,void * data)66 void BtaGattQueue::gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status,
67 uint16_t handle, void* data) {
68 gatt_write_op_data* tmp = (gatt_write_op_data*)data;
69 GATT_WRITE_OP_CB tmp_cb = tmp->cb;
70 void* tmp_cb_data = tmp->cb_data;
71
72 osi_free(data);
73
74 mark_as_not_executing(conn_id);
75 gatt_execute_next_op(conn_id);
76
77 if (tmp_cb) {
78 tmp_cb(conn_id, status, handle, tmp_cb_data);
79 return;
80 }
81 }
82
gatt_execute_next_op(uint16_t conn_id)83 void BtaGattQueue::gatt_execute_next_op(uint16_t conn_id) {
84 APPL_TRACE_DEBUG("%s: conn_id=0x%x", __func__, conn_id);
85 if (gatt_op_queue.empty()) {
86 APPL_TRACE_DEBUG("%s: op queue is empty", __func__);
87 return;
88 }
89
90 auto map_ptr = gatt_op_queue.find(conn_id);
91 if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) {
92 APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", __func__,
93 conn_id);
94 return;
95 }
96
97 if (gatt_op_queue_executing.count(conn_id)) {
98 APPL_TRACE_DEBUG("%s: can't enqueue next op, already executing", __func__);
99 return;
100 }
101
102 gatt_op_queue_executing.insert(conn_id);
103
104 std::list<gatt_operation>& gatt_ops = map_ptr->second;
105
106 gatt_operation& op = gatt_ops.front();
107
108 if (op.type == GATT_READ_CHAR) {
109 gatt_read_op_data* data =
110 (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data));
111 data->cb = op.read_cb;
112 data->cb_data = op.read_cb_data;
113 BTA_GATTC_ReadCharacteristic(conn_id, op.handle, GATT_AUTH_REQ_NONE,
114 gatt_read_op_finished, data);
115
116 } else if (op.type == GATT_READ_DESC) {
117 gatt_read_op_data* data =
118 (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data));
119 data->cb = op.read_cb;
120 data->cb_data = op.read_cb_data;
121 BTA_GATTC_ReadCharDescr(conn_id, op.handle, GATT_AUTH_REQ_NONE,
122 gatt_read_op_finished, data);
123
124 } else if (op.type == GATT_WRITE_CHAR) {
125 gatt_write_op_data* data =
126 (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data));
127 data->cb = op.write_cb;
128 data->cb_data = op.write_cb_data;
129 BTA_GATTC_WriteCharValue(conn_id, op.handle, op.write_type,
130 std::move(op.value), GATT_AUTH_REQ_NONE,
131 gatt_write_op_finished, data);
132
133 } else if (op.type == GATT_WRITE_DESC) {
134 gatt_write_op_data* data =
135 (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data));
136 data->cb = op.write_cb;
137 data->cb_data = op.write_cb_data;
138 BTA_GATTC_WriteCharDescr(conn_id, op.handle, std::move(op.value),
139 GATT_AUTH_REQ_NONE, gatt_write_op_finished, data);
140 }
141
142 gatt_ops.pop_front();
143 }
144
Clean(uint16_t conn_id)145 void BtaGattQueue::Clean(uint16_t conn_id) {
146 gatt_op_queue.erase(conn_id);
147 gatt_op_queue_executing.erase(conn_id);
148 }
149
ReadCharacteristic(uint16_t conn_id,uint16_t handle,GATT_READ_OP_CB cb,void * cb_data)150 void BtaGattQueue::ReadCharacteristic(uint16_t conn_id, uint16_t handle,
151 GATT_READ_OP_CB cb, void* cb_data) {
152 gatt_op_queue[conn_id].push_back({.type = GATT_READ_CHAR,
153 .handle = handle,
154 .read_cb = cb,
155 .read_cb_data = cb_data});
156 gatt_execute_next_op(conn_id);
157 }
158
ReadDescriptor(uint16_t conn_id,uint16_t handle,GATT_READ_OP_CB cb,void * cb_data)159 void BtaGattQueue::ReadDescriptor(uint16_t conn_id, uint16_t handle,
160 GATT_READ_OP_CB cb, void* cb_data) {
161 gatt_op_queue[conn_id].push_back({.type = GATT_READ_DESC,
162 .handle = handle,
163 .read_cb = cb,
164 .read_cb_data = cb_data});
165 gatt_execute_next_op(conn_id);
166 }
167
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)168 void BtaGattQueue::WriteCharacteristic(uint16_t conn_id, uint16_t handle,
169 std::vector<uint8_t> value,
170 tGATT_WRITE_TYPE write_type,
171 GATT_WRITE_OP_CB cb, void* cb_data) {
172 gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_CHAR,
173 .handle = handle,
174 .write_cb = cb,
175 .write_cb_data = cb_data,
176 .write_type = write_type,
177 .value = std::move(value)});
178 gatt_execute_next_op(conn_id);
179 }
180
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)181 void BtaGattQueue::WriteDescriptor(uint16_t conn_id, uint16_t handle,
182 std::vector<uint8_t> value,
183 tGATT_WRITE_TYPE write_type,
184 GATT_WRITE_OP_CB cb, void* cb_data) {
185 gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_DESC,
186 .handle = handle,
187 .write_cb = cb,
188 .write_cb_data = cb_data,
189 .write_type = write_type,
190 .value = std::move(value)});
191 gatt_execute_next_op(conn_id);
192 }
193