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