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 #include "osi/include/allocator.h"
24 
25 #include <base/logging.h>
26 
27 using gatt_operation = BtaGattQueue::gatt_operation;
28 
29 constexpr uint8_t GATT_READ_CHAR = 1;
30 constexpr uint8_t GATT_READ_DESC = 2;
31 constexpr uint8_t GATT_WRITE_CHAR = 3;
32 constexpr uint8_t GATT_WRITE_DESC = 4;
33 constexpr uint8_t GATT_CONFIG_MTU = 5;
34 
35 struct gatt_read_op_data {
36   GATT_READ_OP_CB cb;
37   void* cb_data;
38 };
39 
40 std::unordered_map<uint16_t, std::list<gatt_operation>>
41     BtaGattQueue::gatt_op_queue;
42 std::unordered_set<uint16_t> BtaGattQueue::gatt_op_queue_executing;
43 
mark_as_not_executing(uint16_t conn_id)44 void BtaGattQueue::mark_as_not_executing(uint16_t conn_id) {
45   gatt_op_queue_executing.erase(conn_id);
46 }
47 
gatt_read_op_finished(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)48 void BtaGattQueue::gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status,
49                                          uint16_t handle, uint16_t len,
50                                          uint8_t* value, void* data) {
51   gatt_read_op_data* tmp = (gatt_read_op_data*)data;
52   GATT_READ_OP_CB tmp_cb = tmp->cb;
53   void* tmp_cb_data = tmp->cb_data;
54 
55   osi_free(data);
56 
57   mark_as_not_executing(conn_id);
58   gatt_execute_next_op(conn_id);
59 
60   if (tmp_cb) {
61     tmp_cb(conn_id, status, handle, len, value, tmp_cb_data);
62     return;
63   }
64 }
65 
66 struct gatt_write_op_data {
67   GATT_WRITE_OP_CB cb;
68   void* cb_data;
69 };
70 
gatt_write_op_finished(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)71 void BtaGattQueue::gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status,
72                                           uint16_t handle, uint16_t len,
73                                           const uint8_t* value, void* data) {
74   gatt_write_op_data* tmp = (gatt_write_op_data*)data;
75   GATT_WRITE_OP_CB tmp_cb = tmp->cb;
76   void* tmp_cb_data = tmp->cb_data;
77 
78   osi_free(data);
79 
80   mark_as_not_executing(conn_id);
81   gatt_execute_next_op(conn_id);
82 
83   if (tmp_cb) {
84     tmp_cb(conn_id, status, handle, len, value, tmp_cb_data);
85     return;
86   }
87 }
88 
89 struct gatt_configure_mtu_op_data {
90   GATT_CONFIGURE_MTU_OP_CB cb;
91   void* cb_data;
92 };
93 
gatt_configure_mtu_op_finished(uint16_t conn_id,tGATT_STATUS status,void * data)94 void BtaGattQueue::gatt_configure_mtu_op_finished(uint16_t conn_id,
95                                                   tGATT_STATUS status,
96                                                   void* data) {
97   gatt_configure_mtu_op_data* tmp = (gatt_configure_mtu_op_data*)data;
98   GATT_CONFIGURE_MTU_OP_CB tmp_cb = tmp->cb;
99   void* tmp_cb_data = tmp->cb_data;
100 
101   osi_free(data);
102 
103   mark_as_not_executing(conn_id);
104   gatt_execute_next_op(conn_id);
105 
106   if (tmp_cb) {
107     tmp_cb(conn_id, status, tmp_cb_data);
108     return;
109   }
110 }
111 
gatt_execute_next_op(uint16_t conn_id)112 void BtaGattQueue::gatt_execute_next_op(uint16_t conn_id) {
113   APPL_TRACE_DEBUG("%s: conn_id=0x%x", __func__, conn_id);
114   if (gatt_op_queue.empty()) {
115     APPL_TRACE_DEBUG("%s: op queue is empty", __func__);
116     return;
117   }
118 
119   auto map_ptr = gatt_op_queue.find(conn_id);
120   if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) {
121     APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", __func__,
122                      conn_id);
123     return;
124   }
125 
126   if (gatt_op_queue_executing.count(conn_id)) {
127     APPL_TRACE_DEBUG("%s: can't enqueue next op, already executing", __func__);
128     return;
129   }
130 
131   gatt_op_queue_executing.insert(conn_id);
132 
133   std::list<gatt_operation>& gatt_ops = map_ptr->second;
134 
135   gatt_operation& op = gatt_ops.front();
136 
137   if (op.type == GATT_READ_CHAR) {
138     gatt_read_op_data* data =
139         (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data));
140     data->cb = op.read_cb;
141     data->cb_data = op.read_cb_data;
142     BTA_GATTC_ReadCharacteristic(conn_id, op.handle, GATT_AUTH_REQ_NONE,
143                                  gatt_read_op_finished, data);
144 
145   } else if (op.type == GATT_READ_DESC) {
146     gatt_read_op_data* data =
147         (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data));
148     data->cb = op.read_cb;
149     data->cb_data = op.read_cb_data;
150     BTA_GATTC_ReadCharDescr(conn_id, op.handle, GATT_AUTH_REQ_NONE,
151                             gatt_read_op_finished, data);
152 
153   } else if (op.type == GATT_WRITE_CHAR) {
154     gatt_write_op_data* data =
155         (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data));
156     data->cb = op.write_cb;
157     data->cb_data = op.write_cb_data;
158     BTA_GATTC_WriteCharValue(conn_id, op.handle, op.write_type,
159                              std::move(op.value), GATT_AUTH_REQ_NONE,
160                              gatt_write_op_finished, data);
161 
162   } else if (op.type == GATT_WRITE_DESC) {
163     gatt_write_op_data* data =
164         (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data));
165     data->cb = op.write_cb;
166     data->cb_data = op.write_cb_data;
167     BTA_GATTC_WriteCharDescr(conn_id, op.handle, std::move(op.value),
168                              GATT_AUTH_REQ_NONE, gatt_write_op_finished, data);
169   } else if (op.type == GATT_CONFIG_MTU) {
170     gatt_configure_mtu_op_data* data =
171       (gatt_configure_mtu_op_data*)osi_malloc(sizeof(gatt_configure_mtu_op_data));
172     data->cb = op.mtu_cb;
173     data->cb_data = op.mtu_cb_data;
174     BTA_GATTC_ConfigureMTU(conn_id, static_cast<uint16_t>(op.value[0] |
175                                                           (op.value[1] << 8)),
176                            gatt_configure_mtu_op_finished, data);
177   }
178 
179   gatt_ops.pop_front();
180 }
181 
Clean(uint16_t conn_id)182 void BtaGattQueue::Clean(uint16_t conn_id) {
183   gatt_op_queue.erase(conn_id);
184   gatt_op_queue_executing.erase(conn_id);
185 }
186 
ReadCharacteristic(uint16_t conn_id,uint16_t handle,GATT_READ_OP_CB cb,void * cb_data)187 void BtaGattQueue::ReadCharacteristic(uint16_t conn_id, uint16_t handle,
188                                       GATT_READ_OP_CB cb, void* cb_data) {
189   gatt_op_queue[conn_id].push_back({.type = GATT_READ_CHAR,
190                                     .handle = handle,
191                                     .read_cb = cb,
192                                     .read_cb_data = cb_data});
193   gatt_execute_next_op(conn_id);
194 }
195 
ReadDescriptor(uint16_t conn_id,uint16_t handle,GATT_READ_OP_CB cb,void * cb_data)196 void BtaGattQueue::ReadDescriptor(uint16_t conn_id, uint16_t handle,
197                                   GATT_READ_OP_CB cb, void* cb_data) {
198   gatt_op_queue[conn_id].push_back({.type = GATT_READ_DESC,
199                                     .handle = handle,
200                                     .read_cb = cb,
201                                     .read_cb_data = cb_data});
202   gatt_execute_next_op(conn_id);
203 }
204 
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)205 void BtaGattQueue::WriteCharacteristic(uint16_t conn_id, uint16_t handle,
206                                        std::vector<uint8_t> value,
207                                        tGATT_WRITE_TYPE write_type,
208                                        GATT_WRITE_OP_CB cb, void* cb_data) {
209   gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_CHAR,
210                                     .handle = handle,
211                                     .write_cb = cb,
212                                     .write_cb_data = cb_data,
213                                     .write_type = write_type,
214                                     .value = std::move(value)});
215   gatt_execute_next_op(conn_id);
216 }
217 
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)218 void BtaGattQueue::WriteDescriptor(uint16_t conn_id, uint16_t handle,
219                                    std::vector<uint8_t> value,
220                                    tGATT_WRITE_TYPE write_type,
221                                    GATT_WRITE_OP_CB cb, void* cb_data) {
222   gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_DESC,
223                                     .handle = handle,
224                                     .write_cb = cb,
225                                     .write_cb_data = cb_data,
226                                     .write_type = write_type,
227                                     .value = std::move(value)});
228   gatt_execute_next_op(conn_id);
229 }
230 
ConfigureMtu(uint16_t conn_id,uint16_t mtu)231 void BtaGattQueue::ConfigureMtu(uint16_t conn_id, uint16_t mtu) {
232   LOG(INFO) << __func__ << ", mtu: " << static_cast<int>(mtu);
233   std::vector<uint8_t> value = {static_cast<uint8_t>(mtu & 0xff),
234                                 static_cast<uint8_t>(mtu >> 8)};
235   gatt_op_queue[conn_id].push_back({.type = GATT_CONFIG_MTU,
236                                     .value = std::move(value)});
237   gatt_execute_next_op(conn_id);
238 }
239