• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
3  * www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <bluetooth/log.h>
19 
20 #include <map>
21 #include <vector>
22 
23 #include "bind_helpers.h"
24 #include "eatt.h"
25 #include "hci/controller_interface.h"
26 #include "internal_include/stack_config.h"
27 #include "l2c_api.h"
28 #include "main/shim/entry.h"
29 #include "osi/include/alarm.h"
30 #include "osi/include/allocator.h"
31 #include "stack/btm/btm_sec.h"
32 #include "stack/gatt/gatt_int.h"
33 #include "stack/include/bt_hdr.h"
34 #include "stack/include/bt_psm_types.h"
35 #include "stack/include/btm_sec_api.h"
36 #include "stack/include/l2cdefs.h"
37 #include "stack/include/main_thread.h"
38 
39 namespace bluetooth {
40 namespace eatt {
41 
42 #define BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK 0x01
43 
44 class eatt_device {
45  public:
46   RawAddress bda_;
47   uint16_t rx_mtu_;
48   uint16_t rx_mps_;
49 
50   tGATT_TCB* eatt_tcb_;
51 
52   std::map<uint16_t, std::shared_ptr<EattChannel>> eatt_channels;
53   bool collision;
eatt_device(const RawAddress & bd_addr,uint16_t mtu,uint16_t mps)54   eatt_device(const RawAddress& bd_addr, uint16_t mtu, uint16_t mps)
55       : rx_mtu_(mtu), rx_mps_(mps), eatt_tcb_(nullptr), collision(false) {
56     bda_ = bd_addr;
57   }
58 };
59 
60 struct eatt_impl {
61   std::vector<eatt_device> devices_;
62   uint16_t psm_;
63   uint16_t default_mtu_;
64   uint16_t max_mps_;
65   tL2CAP_APPL_INFO reg_info_;
66 
67   base::WeakPtrFactory<eatt_impl> weak_factory_{this};
68 
eatt_impleatt_impl69   eatt_impl() {
70     default_mtu_ = EATT_DEFAULT_MTU;
71     max_mps_ = EATT_MIN_MTU_MPS;
72     psm_ = BT_PSM_EATT;
73   };
74 
75   ~eatt_impl() = default;
76 
find_device_by_cideatt_impl77   eatt_device* find_device_by_cid(uint16_t lcid) {
78     /* This works only because Android CIDs are unique across the ACL
79      * connections */
80     auto iter = find_if(devices_.begin(), devices_.end(),
81                         [&lcid](const eatt_device& ed) {
82                           auto it = ed.eatt_channels.find(lcid);
83                           return it != ed.eatt_channels.end();
84                         });
85 
86     return (iter == devices_.end()) ? nullptr : &(*iter);
87   }
88 
find_channel_by_cideatt_impl89   EattChannel* find_channel_by_cid(uint16_t lcid) {
90     eatt_device* eatt_dev = find_device_by_cid(lcid);
91     if (!eatt_dev) return nullptr;
92 
93     auto it = eatt_dev->eatt_channels.find(lcid);
94     return (it == eatt_dev->eatt_channels.end()) ? nullptr : it->second.get();
95   }
96 
is_channel_connection_pendingeatt_impl97   bool is_channel_connection_pending(eatt_device* eatt_dev) {
98     for (const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el :
99          eatt_dev->eatt_channels) {
100       if (el.second->state_ == EattChannelState::EATT_CHANNEL_PENDING)
101         return true;
102     }
103     return false;
104   }
105 
find_channel_by_cideatt_impl106   EattChannel* find_channel_by_cid(const RawAddress& bdaddr, uint16_t lcid) {
107     eatt_device* eatt_dev = find_device_by_address(bdaddr);
108     if (!eatt_dev) return nullptr;
109 
110     auto it = eatt_dev->eatt_channels.find(lcid);
111     return (it == eatt_dev->eatt_channels.end()) ? nullptr : it->second.get();
112   }
113 
remove_channel_by_cideatt_impl114   void remove_channel_by_cid(eatt_device* eatt_dev, uint16_t lcid) {
115     auto channel = eatt_dev->eatt_channels[lcid];
116     if (!channel->cl_cmd_q_.empty()) {
117       log::warn("Channel {:c}, for device {} is not empty on disconnection.",
118                 lcid, channel->bda_);
119       channel->cl_cmd_q_.clear();
120     }
121 
122     eatt_dev->eatt_channels.erase(lcid);
123 
124     if (eatt_dev->eatt_channels.size() == 0) eatt_dev->eatt_tcb_ = NULL;
125   }
126 
remove_channel_by_cideatt_impl127   void remove_channel_by_cid(uint16_t lcid) {
128     eatt_device* eatt_dev = find_device_by_cid(lcid);
129     if (!eatt_dev) return;
130 
131     remove_channel_by_cid(eatt_dev, lcid);
132   }
133 
eatt_l2cap_connect_ind_commoneatt_impl134   bool eatt_l2cap_connect_ind_common(const RawAddress& bda,
135                                      std::vector<uint16_t>& lcids,
136                                      uint16_t /* psm */, uint16_t peer_mtu,
137                                      uint8_t identifier) {
138     /* The assumption is that L2CAP layer already check parameters etc.
139      * Get our capabilities and accept all the channels.
140      */
141     eatt_device* eatt_dev = this->find_device_by_address(bda);
142     if (!eatt_dev) {
143       /* If there is no device it means, Android did not read yet Server
144        * supported features, but according to Core 5.3, Vol 3,  Part G, 6.2.1,
145        * for LE case it is not necessary to read it before establish connection.
146        * Therefore assume, device supports EATT since we got request to create
147        * EATT channels. Just create device here. */
148       log::info("Adding device: {} on incoming EATT creation request", bda);
149       eatt_dev = add_eatt_device(bda);
150     }
151 
152     uint16_t max_mps =
153         shim::GetController()->GetLeBufferSize().le_data_packet_length_;
154 
155     tL2CAP_LE_CFG_INFO local_coc_cfg = {
156         .result = L2CAP_LE_RESULT_CONN_OK,
157         .mtu = eatt_dev->rx_mtu_,
158         .mps = eatt_dev->rx_mps_ < max_mps ? eatt_dev->rx_mps_ : max_mps,
159         .credits = L2CA_LeCreditDefault(),
160     };
161 
162     if (!L2CA_ConnectCreditBasedRsp(bda, identifier, lcids, L2CAP_CONN_OK,
163                                     &local_coc_cfg)) {
164       log::warn("Unable to respond L2CAP le_coc credit indication peer:{}",
165                 bda);
166       return false;
167     }
168 
169     if (!eatt_dev->eatt_tcb_) {
170       eatt_dev->eatt_tcb_ =
171           gatt_find_tcb_by_addr(eatt_dev->bda_, BT_TRANSPORT_LE);
172       log::assert_that(eatt_dev->eatt_tcb_ != nullptr,
173                        "assert failed: eatt_dev->eatt_tcb_ != nullptr");
174     }
175 
176     for (uint16_t cid : lcids) {
177       EattChannel* channel = find_eatt_channel_by_cid(bda, cid);
178       log::assert_that(channel == nullptr, "assert failed: channel == nullptr");
179 
180       auto chan = std::make_shared<EattChannel>(eatt_dev->bda_, cid, peer_mtu,
181                                                 eatt_dev->rx_mtu_);
182       eatt_dev->eatt_channels.insert({cid, chan});
183 
184       chan->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED);
185       eatt_dev->eatt_tcb_->eatt++;
186 
187       log::info("Channel connected CID 0x{:x}", cid);
188     }
189 
190     return true;
191   }
192 
193   /* This is for the L2CAP ECoC Testing. */
194   void upper_tester_send_data_if_needed(const RawAddress& bda,
195                                         uint16_t cid = 0) {
196     eatt_device* eatt_dev = find_device_by_address(bda);
197     auto num_of_sdu =
198         stack_config_get_interface()->get_pts_l2cap_ecoc_send_num_of_sdu();
199     log::info("device {}, num: {}", eatt_dev->bda_, num_of_sdu);
200 
201     if (num_of_sdu <= 0) {
202       return;
203     }
204 
205     uint16_t mtu = 0;
206     if (cid != 0) {
207       auto chan = find_channel_by_cid(cid);
208       mtu = chan->tx_mtu_;
209     } else {
210       for (const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el :
211            eatt_dev->eatt_channels) {
212         if (el.second->state_ == EattChannelState::EATT_CHANNEL_OPENED) {
213           cid = el.first;
214           mtu = el.second->tx_mtu_;
215           break;
216         }
217       }
218     }
219 
220     if (cid == 0 || mtu == 0) {
221       log::error("There is no OPEN cid or MTU is 0");
222       return;
223     }
224 
225     for (int i = 0; i < num_of_sdu; i++) {
226       BT_HDR* p_buf = (BT_HDR*)osi_malloc(mtu + sizeof(BT_HDR));
227       p_buf->offset = L2CAP_MIN_OFFSET;
228       p_buf->len = mtu;
229 
230       auto status = L2CA_DataWrite(cid, p_buf);
231       log::info("Data num: {} sent with status {}", i,
232                 static_cast<int>(status));
233     }
234   }
235 
236   /* This is for the L2CAP ECoC Testing. */
upper_tester_delay_connect_cbeatt_impl237   void upper_tester_delay_connect_cb(const RawAddress& bda) {
238     log::info("device {}", bda);
239     eatt_device* eatt_dev = find_device_by_address(bda);
240     if (eatt_dev == nullptr) {
241       log::error("device is not available");
242       return;
243     }
244 
245     connect_eatt_wrap(eatt_dev);
246   }
247 
upper_tester_delay_connecteatt_impl248   void upper_tester_delay_connect(const RawAddress& bda, int timeout_ms) {
249     bt_status_t status = do_in_main_thread_delayed(
250         FROM_HERE,
251         base::BindOnce(&eatt_impl::upper_tester_delay_connect_cb,
252                        weak_factory_.GetWeakPtr(), bda),
253         std::chrono::milliseconds(timeout_ms));
254 
255     log::info("Scheduled peripheral connect eatt for device with status: {}",
256               (int)status);
257   }
258 
upper_tester_l2cap_connect_indeatt_impl259   void upper_tester_l2cap_connect_ind(const RawAddress& bda,
260                                       std::vector<uint16_t>& lcids,
261                                       uint16_t psm, uint16_t peer_mtu,
262                                       uint8_t identifier) {
263     /* This is just for L2CAP PTS test cases*/
264     auto min_key_size =
265         stack_config_get_interface()->get_pts_l2cap_ecoc_min_key_size();
266     if (min_key_size > 0 && (min_key_size >= 7 && min_key_size <= 16)) {
267       auto key_size = btm_ble_read_sec_key_size(bda);
268       if (key_size < min_key_size) {
269         std::vector<uint16_t> empty;
270         log::error("Insufficient key size ({}<{}) for device {}", key_size,
271                    min_key_size, bda);
272         if (!L2CA_ConnectCreditBasedRsp(
273                 bda, identifier, empty,
274                 L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP_KEY_SIZE, nullptr)) {
275           log::warn("Unable to respond L2CAP le_coc credit indication peer:{}",
276                     bda);
277         }
278         return;
279       }
280     }
281 
282     if (!eatt_l2cap_connect_ind_common(bda, lcids, psm, peer_mtu, identifier)) {
283       log::debug("Reject L2CAP Connection request.");
284       return;
285     }
286 
287     /* Android let Central to create EATT (PTS initiates EATT). Some PTS test
288      * cases wants Android to do it anyway (Android initiates EATT).
289      */
290     if (stack_config_get_interface()
291             ->get_pts_eatt_peripheral_collision_support()) {
292       upper_tester_delay_connect(bda, 500);
293       return;
294     }
295 
296     upper_tester_send_data_if_needed(bda);
297 
298     if (stack_config_get_interface()->get_pts_l2cap_ecoc_reconfigure()) {
299       bt_status_t status = do_in_main_thread_delayed(
300           FROM_HERE,
301           base::BindOnce(&eatt_impl::reconfigure_all,
302                          weak_factory_.GetWeakPtr(), bda, 300),
303           std::chrono::seconds(4));
304       log::info("Scheduled ECOC reconfiguration with status: {}", (int)status);
305     }
306   }
307 
eatt_l2cap_connect_indeatt_impl308   void eatt_l2cap_connect_ind(const RawAddress& bda,
309                               std::vector<uint16_t>& lcids, uint16_t psm,
310                               uint16_t peer_mtu, uint8_t identifier) {
311     log::info("Device {}, num of cids: {}, psm 0x{:04x}, peer_mtu {}", bda,
312               static_cast<int>(lcids.size()), psm, peer_mtu);
313 
314     if (!stack_config_get_interface()
315              ->get_pts_connect_eatt_before_encryption() &&
316         !BTM_IsEncrypted(bda, BT_TRANSPORT_LE)) {
317       /* If Link is not encrypted, we shall not accept EATT channel creation. */
318       std::vector<uint16_t> empty;
319       uint16_t result = L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION;
320       if (BTM_IsLinkKeyKnown(bda, BT_TRANSPORT_LE)) {
321         result = L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP;
322       }
323       log::error("ACL to device {} is unencrypted.", bda);
324       if (!L2CA_ConnectCreditBasedRsp(bda, identifier, empty, result,
325                                       nullptr)) {
326         log::warn("Unable to respond L2CAP le_coc credit indication peer:{}",
327                   bda);
328       }
329       return;
330     }
331 
332     if (stack_config_get_interface()->get_pts_l2cap_ecoc_upper_tester()) {
333       log::info("Upper tester for the L2CAP ECoC enabled");
334       return upper_tester_l2cap_connect_ind(bda, lcids, psm, peer_mtu,
335                                             identifier);
336     }
337 
338     eatt_l2cap_connect_ind_common(bda, lcids, psm, peer_mtu, identifier);
339   }
340 
eatt_retry_after_collision_if_neededeatt_impl341   void eatt_retry_after_collision_if_needed(eatt_device* eatt_dev) {
342     if (!eatt_dev->collision) {
343       log::debug("No collision.");
344       return;
345     }
346     /* We are here, because remote device wanted to create channels when
347      * Android proceed its own EATT creation. How to handle it is described
348      * here: BT Core 5.3, Volume 3, Part G, 5.4
349      */
350     log::info(
351         "EATT collision detected. If we are Central we will retry right away");
352 
353     eatt_dev->collision = false;
354     uint8_t role = L2CA_GetBleConnRole(eatt_dev->bda_);
355     if (role == HCI_ROLE_CENTRAL) {
356       log::info("Retrying EATT setup due to previous collision for device {}",
357                 eatt_dev->bda_);
358       connect_eatt_wrap(eatt_dev);
359     } else if (stack_config_get_interface()
360                    ->get_pts_eatt_peripheral_collision_support()) {
361       /* This is only for the PTS. Android does not setup EATT when is a
362        * peripheral.
363        */
364       upper_tester_delay_connect(eatt_dev->bda_, 500);
365     }
366   }
367 
368   /* This is for the L2CAP ECoC Testing. */
upper_tester_l2cap_connect_cfmeatt_impl369   void upper_tester_l2cap_connect_cfm(eatt_device* eatt_dev) {
370     log::info("Upper tester for L2CAP Ecoc {}", eatt_dev->bda_);
371     if (is_channel_connection_pending(eatt_dev)) {
372       log::info("Waiting for all channels to be connected");
373       return;
374     }
375 
376     if (stack_config_get_interface()->get_pts_l2cap_ecoc_connect_remaining() &&
377         (static_cast<int>(eatt_dev->eatt_channels.size()) <
378          L2CAP_CREDIT_BASED_MAX_CIDS)) {
379       log::info("Connecting remaining channels {}",
380                 L2CAP_CREDIT_BASED_MAX_CIDS -
381                     static_cast<int>(eatt_dev->eatt_channels.size()));
382       upper_tester_delay_connect(eatt_dev->bda_, 1000);
383       return;
384     }
385     upper_tester_send_data_if_needed(eatt_dev->bda_);
386   }
387 
eatt_l2cap_connect_cfmeatt_impl388   void eatt_l2cap_connect_cfm(const RawAddress& bda, uint16_t lcid,
389                               uint16_t peer_mtu, uint16_t result) {
390     log::info("bda: {} cid: {}peer mtu: {} result {}", bda, lcid, peer_mtu,
391               result);
392 
393     eatt_device* eatt_dev = find_device_by_address(bda);
394     if (!eatt_dev) {
395       log::error("unknown device");
396       return;
397     }
398 
399     EattChannel* channel = this->find_channel_by_cid(bda, lcid);
400     if (!channel) {
401       log::error("unknown cid: 0x{:x}", lcid);
402       return;
403     }
404 
405     if (result != L2CAP_CONN_OK) {
406       log::error("Could not connect CoC result: 0x{:x}", result);
407       remove_channel_by_cid(eatt_dev, lcid);
408 
409       /* If there is no channels connected, check if there was collision */
410       if (!is_channel_connection_pending(eatt_dev)) {
411         eatt_retry_after_collision_if_needed(eatt_dev);
412       }
413       return;
414     }
415 
416     channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED);
417     channel->EattChannelSetTxMTU(peer_mtu);
418 
419     log::assert_that(eatt_dev->eatt_tcb_ != nullptr,
420                      "assert failed: eatt_dev->eatt_tcb_ != nullptr");
421     log::assert_that(eatt_dev->bda_ == channel->bda_,
422                      "assert failed: eatt_dev->bda_ == channel->bda_");
423     eatt_dev->eatt_tcb_->eatt++;
424 
425     log::info("Channel connected CID 0x{:04x}", lcid);
426 
427     if (stack_config_get_interface()->get_pts_l2cap_ecoc_upper_tester()) {
428       upper_tester_l2cap_connect_cfm(eatt_dev);
429     }
430   }
431 
eatt_l2cap_reconfig_completedeatt_impl432   void eatt_l2cap_reconfig_completed(const RawAddress& bda, uint16_t lcid,
433                                      bool is_local_cfg,
434                                      tL2CAP_LE_CFG_INFO* p_cfg) {
435     log::info("lcid: 0x{:x} local cfg?: {}", lcid, is_local_cfg);
436 
437     EattChannel* channel = find_channel_by_cid(bda, lcid);
438     if (!channel) return;
439 
440     // regardless of success result, we have finished reconfiguration
441     channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED);
442 
443     if (p_cfg->result != L2CAP_CFG_OK) {
444       log::info("reconfig failed lcid: 0x{:x} result: 0x{:x}", lcid,
445                 p_cfg->result);
446       return;
447     }
448 
449     /* On this layer we don't care about mps as this is handled in L2CAP layer
450      */
451     if (is_local_cfg)
452       channel->rx_mtu_ = p_cfg->mtu;
453     else
454       channel->EattChannelSetTxMTU(p_cfg->mtu);
455 
456     if (stack_config_get_interface()->get_pts_l2cap_ecoc_reconfigure()) {
457       /* Upper tester for L2CAP - schedule sending data */
458       do_in_main_thread_delayed(
459           FROM_HERE,
460           base::BindOnce(&eatt_impl::upper_tester_send_data_if_needed,
461                          weak_factory_.GetWeakPtr(), bda, lcid),
462           std::chrono::seconds(1));
463     }
464   }
465 
eatt_l2cap_collision_indeatt_impl466   void eatt_l2cap_collision_ind(const RawAddress& bda) {
467     eatt_device* eatt_dev = find_device_by_address(bda);
468     if (!eatt_dev) {
469       log::error("Device {} not available anymore:", bda);
470       return;
471     }
472     /* Remote wanted to setup channels as well. Let's retry remote's request
473      * when we are done with ours.*/
474     eatt_dev->collision = true;
475   }
476 
eatt_l2cap_error_cbeatt_impl477   void eatt_l2cap_error_cb(uint16_t lcid, uint16_t reason) {
478     EattChannel* channel = find_channel_by_cid(lcid);
479     if (!channel) {
480       log::error("Unknown cid: 0x{:x}, reason: 0x{:x}", lcid, reason);
481       return;
482     }
483 
484     eatt_device* eatt_dev = find_device_by_address(channel->bda_);
485     switch (channel->state_) {
486       case EattChannelState::EATT_CHANNEL_PENDING:
487         log::warn("Channel for cid: 0x{:x} is not extablished, reason: 0x{:x}",
488                   lcid, reason);
489         remove_channel_by_cid(eatt_dev, lcid);
490         break;
491       case EattChannelState::EATT_CHANNEL_RECONFIGURING:
492         /* Just go back to open state */
493         log::error("Reconfig failed fo cid: 0x{:x}, reason: 0x{:x}", lcid,
494                    reason);
495         channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED);
496         break;
497       default:
498         log::error("cid: 0x{:x}, reason: 0x{:x}, invalid state: {}", lcid,
499                    reason, static_cast<uint8_t>(channel->state_));
500         break;
501     }
502 
503     if (!is_channel_connection_pending(eatt_dev)) {
504       eatt_retry_after_collision_if_needed(eatt_dev);
505     }
506   }
507 
eatt_l2cap_disconnect_indeatt_impl508   void eatt_l2cap_disconnect_ind(uint16_t lcid, bool /* please_confirm */) {
509     log::info("cid: 0x{:x}", lcid);
510     eatt_device* eatt_dev = find_device_by_cid(lcid);
511     if (!eatt_dev) {
512       log::error("unknown cid: 0x{:x}", lcid);
513       return;
514     }
515 
516     eatt_dev->eatt_tcb_->eatt--;
517     remove_channel_by_cid(eatt_dev, lcid);
518   }
519 
eatt_l2cap_data_indeatt_impl520   void eatt_l2cap_data_ind(uint16_t lcid, BT_HDR* data_p) {
521     log::info("cid: 0x{:x}", lcid);
522     eatt_device* eatt_dev = find_device_by_cid(lcid);
523     if (!eatt_dev) {
524       log::error("unknown cid: 0x{:x}", lcid);
525       return;
526     }
527 
528     EattChannel* channel = find_channel_by_cid(eatt_dev->bda_, lcid);
529     if (!channel) {
530       log::error("Received data on closed channel 0x{:x}", lcid);
531       return;
532     }
533 
534     gatt_data_process(*eatt_dev->eatt_tcb_, channel->cid_, data_p);
535     osi_free(data_p);
536   }
537 
is_eatt_supported_by_peereatt_impl538   bool is_eatt_supported_by_peer(const RawAddress& bd_addr) {
539     return gatt_profile_get_eatt_support(bd_addr);
540   }
541 
find_device_by_addresseatt_impl542   eatt_device* find_device_by_address(const RawAddress& bd_addr) {
543     auto iter = find_if(
544         devices_.begin(), devices_.end(),
545         [&bd_addr](const eatt_device& ed) { return ed.bda_ == bd_addr; });
546 
547     return iter == devices_.end() ? nullptr : &(*iter);
548   }
549 
add_eatt_deviceeatt_impl550   eatt_device* add_eatt_device(const RawAddress& bd_addr) {
551     devices_.push_back(eatt_device(bd_addr, default_mtu_, max_mps_));
552     eatt_device* eatt_dev = &devices_.back();
553     return eatt_dev;
554   }
555 
connect_eatt_wrapeatt_impl556   void connect_eatt_wrap(eatt_device* eatt_dev) {
557     if (stack_config_get_interface()
558             ->get_pts_eatt_peripheral_collision_support()) {
559       /* For PTS case, lets assume we support only 5 channels */
560       log::info("Number of existing channels {}",
561                 (int)eatt_dev->eatt_channels.size());
562       connect_eatt(eatt_dev, L2CAP_CREDIT_BASED_MAX_CIDS -
563                                  (int)eatt_dev->eatt_channels.size());
564       return;
565     }
566 
567     connect_eatt(eatt_dev);
568   }
569 
570   void connect_eatt(eatt_device* eatt_dev,
571                     uint8_t num_of_channels = L2CAP_CREDIT_BASED_MAX_CIDS) {
572     /* Let us use maximum possible mps */
573     if (eatt_dev->rx_mps_ == EATT_MIN_MTU_MPS)
574       eatt_dev->rx_mps_ =
575           shim::GetController()->GetLeBufferSize().le_data_packet_length_;
576 
577     tL2CAP_LE_CFG_INFO local_coc_cfg = {
578         .result = L2CAP_LE_RESULT_CONN_OK,
579         .mtu = eatt_dev->rx_mtu_,
580         .mps = eatt_dev->rx_mps_,
581         .credits = L2CA_LeCreditDefault(),
582         .number_of_channels = num_of_channels,
583     };
584 
585     log::info("Connecting device {}, cnt count {}", eatt_dev->bda_,
586               num_of_channels);
587 
588     /* Warning! CIDs in Android are unique across the ACL connections */
589     std::vector<uint16_t> connecting_cids =
590         L2CA_ConnectCreditBasedReq(psm_, eatt_dev->bda_, &local_coc_cfg);
591 
592     if (connecting_cids.size() == 0) {
593       log::error("Unable to get cid");
594       return;
595     }
596 
597     log::info("Successfully sent CoC request, number of channel: {}",
598               connecting_cids.size());
599 
600     for (uint16_t cid : connecting_cids) {
601       log::info("\t cid: 0x{:x}", cid);
602 
603       auto chan = std::make_shared<EattChannel>(eatt_dev->bda_, cid, 0,
604                                                 eatt_dev->rx_mtu_);
605       eatt_dev->eatt_channels.insert({cid, chan});
606     }
607 
608     if (eatt_dev->eatt_tcb_) {
609       log::info("has tcb ? {}", eatt_dev->eatt_tcb_ == nullptr);
610       return;
611     }
612 
613     eatt_dev->eatt_tcb_ =
614         gatt_find_tcb_by_addr(eatt_dev->bda_, BT_TRANSPORT_LE);
615     log::assert_that(eatt_dev->eatt_tcb_ != nullptr,
616                      "assert failed: eatt_dev->eatt_tcb_ != nullptr");
617   }
618 
find_eatt_channel_by_cideatt_impl619   EattChannel* find_eatt_channel_by_cid(const RawAddress& bd_addr,
620                                         uint16_t cid) {
621     eatt_device* eatt_dev = find_device_by_address(bd_addr);
622     if (!eatt_dev) return nullptr;
623 
624     auto iter = find_if(
625         eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(),
626         [&cid](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) {
627           return el.first == cid;
628         });
629 
630     return iter == eatt_dev->eatt_channels.end() ? nullptr : iter->second.get();
631   }
632 
find_eatt_channel_by_transideatt_impl633   EattChannel* find_eatt_channel_by_transid(const RawAddress& bd_addr,
634                                             uint32_t trans_id) {
635     eatt_device* eatt_dev = find_device_by_address(bd_addr);
636     if (!eatt_dev) return nullptr;
637 
638     auto iter = find_if(
639         eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(),
640         [&trans_id](
641             const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) {
642           return el.second->server_outstanding_cmd_.trans_id == trans_id;
643         });
644 
645     return iter == eatt_dev->eatt_channels.end() ? nullptr : iter->second.get();
646   }
647 
is_indication_pendingeatt_impl648   bool is_indication_pending(const RawAddress& bd_addr,
649                              uint16_t indication_handle) {
650     eatt_device* eatt_dev = find_device_by_address(bd_addr);
651     if (!eatt_dev) return false;
652 
653     auto iter = find_if(
654         eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(),
655         [&indication_handle](
656             const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) {
657           return el.second->indicate_handle_ == indication_handle;
658         });
659 
660     return (iter != eatt_dev->eatt_channels.end());
661   };
662 
get_channel_available_for_indicationeatt_impl663   EattChannel* get_channel_available_for_indication(const RawAddress& bd_addr) {
664     eatt_device* eatt_dev = find_device_by_address(bd_addr);
665     auto iter = find_if(
666         eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(),
667         [](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) {
668           return el.second->state_ == EattChannelState::EATT_CHANNEL_OPENED &&
669                  !GATT_HANDLE_IS_VALID(el.second->indicate_handle_);
670         });
671 
672     return (iter == eatt_dev->eatt_channels.end()) ? nullptr
673                                                    : iter->second.get();
674   };
675 
get_channel_available_for_client_requesteatt_impl676   EattChannel* get_channel_available_for_client_request(
677       const RawAddress& bd_addr) {
678     eatt_device* eatt_dev = find_device_by_address(bd_addr);
679     if (!eatt_dev) return nullptr;
680 
681     auto iter = find_if(
682         eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(),
683         [](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) {
684           return el.second->state_ == EattChannelState::EATT_CHANNEL_OPENED &&
685                  el.second->cl_cmd_q_.empty();
686         });
687 
688     return (iter == eatt_dev->eatt_channels.end()) ? nullptr
689                                                    : iter->second.get();
690   }
691 
free_gatt_resourceseatt_impl692   void free_gatt_resources(const RawAddress& bd_addr) {
693     eatt_device* eatt_dev = find_device_by_address(bd_addr);
694     if (!eatt_dev) return;
695 
696     auto iter = eatt_dev->eatt_channels.begin();
697     while (iter != eatt_dev->eatt_channels.end()) {
698       EattChannel* channel = iter->second.get();
699 
700       fixed_queue_free(channel->server_outstanding_cmd_.multi_rsp_q, NULL);
701       channel->server_outstanding_cmd_.multi_rsp_q = NULL;
702       iter++;
703     }
704   }
705 
is_outstanding_msg_in_send_queueeatt_impl706   bool is_outstanding_msg_in_send_queue(const RawAddress& bd_addr) {
707     eatt_device* eatt_dev = find_device_by_address(bd_addr);
708     if (!eatt_dev) return false;
709 
710     auto iter = find_if(
711         eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(),
712         [](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) {
713           if (el.second->cl_cmd_q_.empty()) return false;
714 
715           tGATT_CMD_Q& cmd = el.second->cl_cmd_q_.front();
716           return cmd.to_send;
717         });
718     return (iter != eatt_dev->eatt_channels.end());
719   }
720 
get_channel_with_queued_dataeatt_impl721   EattChannel* get_channel_with_queued_data(const RawAddress& bd_addr) {
722     eatt_device* eatt_dev = find_device_by_address(bd_addr);
723     if (!eatt_dev) return nullptr;
724 
725     auto iter = find_if(
726         eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(),
727         [](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) {
728           if (el.second->cl_cmd_q_.empty()) return false;
729 
730           tGATT_CMD_Q& cmd = el.second->cl_cmd_q_.front();
731           return cmd.to_send;
732         });
733     return (iter == eatt_dev->eatt_channels.end()) ? nullptr
734                                                    : iter->second.get();
735   }
736 
eatt_ind_ack_timeouteatt_impl737   static void eatt_ind_ack_timeout(void* data) {
738     EattChannel* channel = (EattChannel*)data;
739     tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(channel->bda_, BT_TRANSPORT_LE);
740 
741     log::warn("send ack now");
742     attp_send_cl_confirmation_msg(*p_tcb, channel->cid_);
743   }
744 
eatt_ind_confirmation_timeouteatt_impl745   static void eatt_ind_confirmation_timeout(void* data) {
746     EattChannel* channel = (EattChannel*)data;
747     tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(channel->bda_, BT_TRANSPORT_LE);
748 
749     log::warn("disconnecting...");
750     gatt_disconnect(p_tcb);
751   }
752 
start_indication_confirm_timereatt_impl753   void start_indication_confirm_timer(const RawAddress& bd_addr, uint16_t cid) {
754     EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid);
755     if (!channel) {
756       log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr);
757       return;
758     }
759 
760     alarm_set_on_mloop(channel->ind_confirmation_timer_,
761                        GATT_WAIT_FOR_RSP_TIMEOUT_MS,
762                        eatt_ind_confirmation_timeout, channel);
763   }
764 
stop_indication_confirm_timereatt_impl765   void stop_indication_confirm_timer(const RawAddress& bd_addr, uint16_t cid) {
766     EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid);
767     if (!channel) {
768       log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr);
769       return;
770     }
771 
772     alarm_cancel(channel->ind_confirmation_timer_);
773   }
774 
start_app_indication_timereatt_impl775   void start_app_indication_timer(const RawAddress& bd_addr, uint16_t cid) {
776     EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid);
777     if (!channel) {
778       log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr);
779       return;
780     }
781 
782     alarm_set_on_mloop(channel->ind_ack_timer_, GATT_WAIT_FOR_RSP_TIMEOUT_MS,
783                        eatt_ind_ack_timeout, channel);
784   }
785 
stop_app_indication_timereatt_impl786   void stop_app_indication_timer(const RawAddress& bd_addr, uint16_t cid) {
787     EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid);
788     if (!channel) {
789       log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr);
790       return;
791     }
792 
793     alarm_cancel(channel->ind_ack_timer_);
794   }
795 
reconfigureeatt_impl796   void reconfigure(const RawAddress& bd_addr, uint16_t cid, uint16_t new_mtu) {
797     eatt_device* eatt_dev = find_device_by_address(bd_addr);
798     if (!eatt_dev) {
799       log::error("Unknown device {}", bd_addr);
800       return;
801     }
802 
803     EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid);
804     if (!channel) {
805       log::error("Unknown cid: 0x{:x} or device {}", cid, bd_addr);
806       return;
807     }
808 
809     if (new_mtu <= channel->rx_mtu_) {
810       log::error("Invalid mtu: 0x{:x}", new_mtu);
811       return;
812     }
813 
814     std::vector<uint16_t> cids = {cid};
815 
816     tL2CAP_LE_CFG_INFO cfg = {
817         .result = L2CAP_LE_RESULT_CONN_OK,
818         .mtu = new_mtu,
819         .mps = eatt_dev->rx_mps_};
820 
821     if (!L2CA_ReconfigCreditBasedConnsReq(eatt_dev->bda_, cids, &cfg)) {
822       log::error("Could not start reconfig cid: 0x{:x} or device {}", cid,
823                  bd_addr);
824       return;
825     }
826 
827     channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_RECONFIGURING);
828   }
829 
reconfigure_alleatt_impl830   void reconfigure_all(const RawAddress& bd_addr, uint16_t new_mtu) {
831     log::info("Device {}, new mtu {}", bd_addr, new_mtu);
832     eatt_device* eatt_dev = find_device_by_address(bd_addr);
833     if (!eatt_dev) {
834       log::error("Unknown device {}", bd_addr);
835       return;
836     }
837 
838     uint8_t num_of_channels = eatt_dev->eatt_channels.size();
839     if (num_of_channels == 0) {
840       log::error("No channels for device {}", bd_addr);
841       return;
842     }
843 
844     std::vector<uint16_t> cids;
845 
846     auto iter = eatt_dev->eatt_channels.begin();
847     while (iter != eatt_dev->eatt_channels.end()) {
848       uint16_t cid = iter->first;
849       cids.push_back(cid);
850       iter++;
851     }
852 
853     if (new_mtu <= EATT_MIN_MTU_MPS) {
854       log::error("Invalid mtu: 0x{:x}", new_mtu);
855       return;
856     }
857 
858     tL2CAP_LE_CFG_INFO cfg = {
859         .result = L2CAP_LE_RESULT_CONN_OK,
860         .mtu = new_mtu,
861         .mps = eatt_dev->rx_mps_};
862 
863     if (!L2CA_ReconfigCreditBasedConnsReq(eatt_dev->bda_, cids, &cfg)) {
864       log::error("Could not start reconfig for device {}", bd_addr);
865       return;
866     }
867 
868     for (auto& channel : eatt_dev->eatt_channels) {
869       channel.second->EattChannelSetState(
870           EattChannelState::EATT_CHANNEL_RECONFIGURING);
871     }
872   }
873 
supported_features_cbeatt_impl874   void supported_features_cb(uint8_t role, const RawAddress& bd_addr,
875                              uint8_t features) {
876     bool is_eatt_supported = features & BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK;
877 
878     log::info("{} is_eatt_supported = {}", bd_addr, int(is_eatt_supported));
879     if (!is_eatt_supported) return;
880 
881     eatt_device* eatt_dev = this->find_device_by_address(bd_addr);
882     if (!eatt_dev) {
883       log::info("Adding device: {} on supported features callback.", bd_addr);
884       eatt_dev = add_eatt_device(bd_addr);
885     }
886 
887     if (role != HCI_ROLE_CENTRAL) {
888       /* TODO For now do nothing, we could run a timer here and start EATT if
889        * not started by central */
890       log::info("EATT Should be connected by the central. Let's wait for it.");
891       return;
892     }
893 
894     connect_eatt_wrap(eatt_dev);
895   }
896 
disconnect_channeleatt_impl897   void disconnect_channel(uint16_t cid) {
898     if (!L2CA_DisconnectReq(cid)) {
899       log::warn("Unable to request L2CAP disconnect cid:{}", cid);
900     }
901   }
902 
disconnecteatt_impl903   void disconnect(const RawAddress& bd_addr, uint16_t cid) {
904     log::info("Device: {}, cid: 0x{:04x}", bd_addr, cid);
905 
906     eatt_device* eatt_dev = find_device_by_address(bd_addr);
907     if (!eatt_dev) {
908       log::warn("no eatt device found");
909       return;
910     }
911 
912     if (!eatt_dev->eatt_tcb_) {
913       log::assert_that(eatt_dev->eatt_channels.size() == 0,
914                        "assert failed: eatt_dev->eatt_channels.size() == 0");
915       log::warn("no eatt channels found");
916       return;
917     }
918 
919     if (cid != EATT_ALL_CIDS) {
920       auto chan = find_channel_by_cid(cid);
921       if (!chan) {
922         log::warn("Cid {} not found for device {}", cid, bd_addr);
923         return;
924       }
925       log::info("Disconnecting cid {}", cid);
926       disconnect_channel(cid);
927       remove_channel_by_cid(cid);
928       return;
929     }
930 
931     auto iter = eatt_dev->eatt_channels.begin();
932     while (iter != eatt_dev->eatt_channels.end()) {
933       uint16_t cid = iter->first;
934       disconnect_channel(cid);
935       /* When initiating disconnection, stack will not notify us that it is
936        * done. We need to assume success
937        */
938       iter = eatt_dev->eatt_channels.erase(iter);
939     }
940     eatt_dev->eatt_tcb_->eatt = 0;
941     eatt_dev->eatt_tcb_ = nullptr;
942     eatt_dev->collision = false;
943   }
944 
upper_tester_connecteatt_impl945   void upper_tester_connect(const RawAddress& bd_addr, eatt_device* eatt_dev,
946                             uint8_t role) {
947     log::info(
948         "L2CAP Upper tester enabled, {} ({}), role: {}({})", bd_addr,
949         fmt::ptr(eatt_dev),
950         role == HCI_ROLE_CENTRAL ? "HCI_ROLE_CENTRAL" : "HCI_ROLE_PERIPHERAL",
951         role);
952 
953     auto num_of_chan =
954         stack_config_get_interface()->get_pts_l2cap_ecoc_initial_chan_cnt();
955     if (num_of_chan <= 0) {
956       num_of_chan = L2CAP_CREDIT_BASED_MAX_CIDS;
957     }
958 
959     /* This is needed for L2CAP test cases */
960     if (stack_config_get_interface()->get_pts_connect_eatt_unconditionally()) {
961       /* Normally eatt_dev exist only if EATT is supported by remote device.
962        * Here it is created unconditionally */
963       if (eatt_dev == nullptr) eatt_dev = add_eatt_device(bd_addr);
964       /* For PTS just start connecting EATT right away */
965       connect_eatt(eatt_dev, num_of_chan);
966       return;
967     }
968 
969     if (eatt_dev != nullptr && role == HCI_ROLE_CENTRAL) {
970       connect_eatt(eatt_dev, num_of_chan);
971       return;
972     }
973 
974     /* If we don't know yet, read GATT server supported features. */
975     if (gatt_cl_read_sr_supp_feat_req(
976             bd_addr, base::BindOnce(&eatt_impl::supported_features_cb,
977                                     weak_factory_.GetWeakPtr(), role)) ==
978         false) {
979       log::info("Read server supported features failed for device {}", bd_addr);
980     }
981   }
982 
connecteatt_impl983   void connect(const RawAddress& bd_addr) {
984     eatt_device* eatt_dev = find_device_by_address(bd_addr);
985 
986     uint8_t role = L2CA_GetBleConnRole(bd_addr);
987     if (role == HCI_ROLE_UNKNOWN) {
988       log::error("Could not get device role{}", bd_addr);
989       return;
990     }
991 
992     if (stack_config_get_interface()->get_pts_l2cap_ecoc_upper_tester()) {
993       upper_tester_connect(bd_addr, eatt_dev, role);
994       return;
995     }
996 
997     log::info("Device {}, role {}", bd_addr,
998               role == HCI_ROLE_CENTRAL ? "central" : "peripheral");
999 
1000     if (eatt_dev) {
1001       /* We are reconnecting device we know that support EATT.
1002        * Just connect CoC
1003        */
1004       log::info("Known device, connect eCoC");
1005 
1006       if (role != HCI_ROLE_CENTRAL) {
1007         log::info(
1008             "EATT Should be connected by the central. Let's wait for it.");
1009         return;
1010       }
1011 
1012       connect_eatt_wrap(eatt_dev);
1013       return;
1014     }
1015 
1016     if (role != HCI_ROLE_CENTRAL) return;
1017 
1018     if (gatt_profile_get_eatt_support(bd_addr)) {
1019       log::debug("Eatt is supported for device {}", bd_addr);
1020       supported_features_cb(role, bd_addr, BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK);
1021       return;
1022     }
1023 
1024     /* If we don't know yet, read GATT server supported features. */
1025     if (gatt_cl_read_sr_supp_feat_req(
1026             bd_addr, base::BindOnce(&eatt_impl::supported_features_cb,
1027                                     weak_factory_.GetWeakPtr(), role)) ==
1028         false) {
1029       log::info("Read server supported features failed for device {}", bd_addr);
1030     }
1031   }
1032 
add_from_storageeatt_impl1033   void add_from_storage(const RawAddress& bd_addr) {
1034     eatt_device* eatt_dev = find_device_by_address(bd_addr);
1035 
1036     log::info("restoring: {}", bd_addr);
1037 
1038     if (!eatt_dev) add_eatt_device(bd_addr);
1039   }
1040 };
1041 
1042 }  // namespace eatt
1043 }  // namespace bluetooth
1044