• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 HIMSA II K/S - www.himsa.com.
3  * Represented by EHIMA - 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 #pragma once
19 
20 #include <list>
21 #include <map>
22 #include <memory>
23 #include <mutex>
24 #include <set>
25 
26 #include "base/functional/bind.h"
27 #include "base/functional/callback.h"
28 #include "base/logging.h"
29 #include "bind_helpers.h"
30 #include "btm_dev.h"
31 #include "btm_iso_api.h"
32 #include "common/time_util.h"
33 #include "device/include/controller.h"
34 #include "hci/include/hci_layer.h"
35 #include "internal_include/stack_config.h"
36 #include "osi/include/allocator.h"
37 #include "osi/include/log.h"
38 #include "stack/include/bt_hdr.h"
39 #include "stack/include/btm_log_history.h"
40 #include "stack/include/hci_error_code.h"
41 #include "stack/include/hcidefs.h"
42 
43 namespace bluetooth {
44 namespace hci {
45 namespace iso_manager {
46 static constexpr uint8_t kIsoDataInTsBtHdrOffset = 0x0C;
47 static constexpr uint8_t kIsoHeaderWithTsLen = 12;
48 static constexpr uint8_t kIsoHeaderWithoutTsLen = 8;
49 
50 static constexpr uint8_t kStateFlagsNone = 0x00;
51 static constexpr uint8_t kStateFlagIsConnecting = 0x01;
52 static constexpr uint8_t kStateFlagIsConnected = 0x02;
53 static constexpr uint8_t kStateFlagHasDataPathSet = 0x04;
54 static constexpr uint8_t kStateFlagIsBroadcast = 0x10;
55 
56 constexpr char kBtmLogTag[] = "ISO";
57 
58 struct iso_sync_info {
59   uint32_t first_sync_ts;
60   uint16_t seq_nb;
61 };
62 
63 struct iso_base {
64   union {
65     uint8_t cig_id;
66     uint8_t big_handle;
67   };
68 
69   struct iso_sync_info sync_info;
70   std::atomic_uint8_t state_flags;
71   uint32_t sdu_itv;
72   std::atomic_uint16_t used_credits;
73 
74   struct credits_stats {
75     size_t credits_underflow_bytes = 0;
76     size_t credits_underflow_count = 0;
77     uint64_t credits_last_underflow_us = 0;
78   };
79 
80   struct event_stats {
81     size_t evt_lost_count = 0;
82     size_t seq_nb_mismatch_count = 0;
83     uint64_t evt_last_lost_us = 0;
84   };
85 
86   credits_stats cr_stats;
87   event_stats evt_stats;
88 };
89 
90 typedef iso_base iso_cis;
91 typedef iso_base iso_bis;
92 
93 struct iso_impl {
iso_impliso_impl94   iso_impl() {
95     iso_credits_ = controller_get_interface()->get_iso_buffer_count();
96     iso_buffer_size_ = controller_get_interface()->get_iso_data_size();
97   }
98 
~iso_impliso_impl99   ~iso_impl() {}
100 
handle_register_cis_callbacksiso_impl101   void handle_register_cis_callbacks(CigCallbacks* callbacks) {
102     LOG_ASSERT(callbacks != nullptr) << "Invalid CIG callbacks";
103     cig_callbacks_ = callbacks;
104   }
105 
handle_register_big_callbacksiso_impl106   void handle_register_big_callbacks(BigCallbacks* callbacks) {
107     LOG_ASSERT(callbacks != nullptr) << "Invalid BIG callbacks";
108     big_callbacks_ = callbacks;
109   }
110 
handle_register_on_iso_traffic_active_callbackiso_impl111   void handle_register_on_iso_traffic_active_callback(void callback(bool)) {
112     LOG_ASSERT(callback != nullptr) << "Invalid OnIsoTrafficActive callback";
113     const std::lock_guard<std::mutex> lock(
114         on_iso_traffic_active_callbacks_list_mutex_);
115     on_iso_traffic_active_callbacks_list_.push_back(callback);
116   }
117 
on_set_cig_paramsiso_impl118   void on_set_cig_params(uint8_t cig_id, uint32_t sdu_itv_mtos, uint8_t* stream,
119                          uint16_t len) {
120     uint8_t cis_cnt;
121     uint16_t conn_handle;
122     cig_create_cmpl_evt evt;
123 
124     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
125     LOG_ASSERT(len >= 3) << "Invalid packet length: " << +len;
126 
127     STREAM_TO_UINT8(evt.status, stream);
128     STREAM_TO_UINT8(evt.cig_id, stream);
129     STREAM_TO_UINT8(cis_cnt, stream);
130 
131     uint8_t evt_code = IsCigKnown(cig_id) ? kIsoEventCigOnReconfigureCmpl
132                                           : kIsoEventCigOnCreateCmpl;
133 
134     BTM_LogHistory(
135         kBtmLogTag, RawAddress::kEmpty, "CIG Create complete",
136         base::StringPrintf(
137             "cig_id:0x%02x, status: %s", evt.cig_id,
138             hci_status_code_text((tHCI_STATUS)(evt.status)).c_str()));
139 
140     if (evt.status == HCI_SUCCESS) {
141       LOG_ASSERT(len >= (3) + (cis_cnt * sizeof(uint16_t)))
142           << "Invalid CIS count: " << +cis_cnt;
143 
144       /* Remove entries for the reconfigured CIG */
145       if (evt_code == kIsoEventCigOnReconfigureCmpl) {
146         auto cis_it = conn_hdl_to_cis_map_.cbegin();
147         while (cis_it != conn_hdl_to_cis_map_.cend()) {
148           if (cis_it->second->cig_id == evt.cig_id)
149             cis_it = conn_hdl_to_cis_map_.erase(cis_it);
150           else
151             ++cis_it;
152         }
153       }
154 
155       evt.conn_handles.reserve(cis_cnt);
156       for (int i = 0; i < cis_cnt; i++) {
157         STREAM_TO_UINT16(conn_handle, stream);
158 
159         evt.conn_handles.push_back(conn_handle);
160 
161         auto cis = std::unique_ptr<iso_cis>(new iso_cis());
162         cis->cig_id = cig_id;
163         cis->sdu_itv = sdu_itv_mtos;
164         cis->sync_info = {.first_sync_ts = 0, .seq_nb = 0};
165         cis->used_credits = 0;
166         cis->state_flags = kStateFlagsNone;
167         conn_hdl_to_cis_map_[conn_handle] = std::move(cis);
168       }
169     }
170 
171     cig_callbacks_->OnCigEvent(evt_code, &evt);
172 
173     if (evt_code == kIsoEventCigOnCreateCmpl) {
174       const std::lock_guard<std::mutex> lock(
175           on_iso_traffic_active_callbacks_list_mutex_);
176       for (auto callback : on_iso_traffic_active_callbacks_list_) {
177         callback(true);
178       }
179     }
180   }
181 
create_cigiso_impl182   void create_cig(uint8_t cig_id,
183                   struct iso_manager::cig_create_params cig_params) {
184     LOG_ASSERT(!IsCigKnown(cig_id))
185         << "Invalid cig - already exists: " << +cig_id;
186 
187     btsnd_hcic_set_cig_params(
188         cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom,
189         cig_params.sca, cig_params.packing, cig_params.framing,
190         cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos,
191         cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(),
192         base::BindOnce(&iso_impl::on_set_cig_params, base::Unretained(this),
193                        cig_id, cig_params.sdu_itv_mtos));
194 
195     BTM_LogHistory(
196         kBtmLogTag, RawAddress::kEmpty, "CIG Create",
197         base::StringPrintf("cig_id:0x%02x, size: %d", cig_id,
198                            static_cast<int>(cig_params.cis_cfgs.size())));
199   }
200 
reconfigure_cigiso_impl201   void reconfigure_cig(uint8_t cig_id,
202                        struct iso_manager::cig_create_params cig_params) {
203     LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig: " << +cig_id;
204 
205     btsnd_hcic_set_cig_params(
206         cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom,
207         cig_params.sca, cig_params.packing, cig_params.framing,
208         cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos,
209         cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(),
210         base::BindOnce(&iso_impl::on_set_cig_params, base::Unretained(this),
211                        cig_id, cig_params.sdu_itv_mtos));
212   }
213 
on_remove_cigiso_impl214   void on_remove_cig(uint8_t* stream, uint16_t len) {
215     cig_remove_cmpl_evt evt;
216 
217     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
218     LOG_ASSERT(len == 2) << "Invalid packet length: " << +len;
219 
220     STREAM_TO_UINT8(evt.status, stream);
221     STREAM_TO_UINT8(evt.cig_id, stream);
222 
223     BTM_LogHistory(
224         kBtmLogTag, RawAddress::kEmpty, "CIG Remove complete",
225         base::StringPrintf(
226             "cig_id:0x%02x, status: %s", evt.cig_id,
227             hci_status_code_text((tHCI_STATUS)(evt.status)).c_str()));
228 
229     if (evt.status == HCI_SUCCESS) {
230       auto cis_it = conn_hdl_to_cis_map_.cbegin();
231       while (cis_it != conn_hdl_to_cis_map_.cend()) {
232         if (cis_it->second->cig_id == evt.cig_id)
233           cis_it = conn_hdl_to_cis_map_.erase(cis_it);
234         else
235           ++cis_it;
236       }
237     }
238 
239     cig_callbacks_->OnCigEvent(kIsoEventCigOnRemoveCmpl, &evt);
240 
241     {
242       const std::lock_guard<std::mutex> lock(
243           on_iso_traffic_active_callbacks_list_mutex_);
244       for (auto callback : on_iso_traffic_active_callbacks_list_) {
245         callback(false);
246       }
247     }
248   }
249 
remove_cigiso_impl250   void remove_cig(uint8_t cig_id, bool force) {
251     if (!force) {
252       LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig: " << +cig_id;
253     } else {
254       LOG_WARN("Forcing to remove CIG %d", cig_id);
255     }
256 
257     btsnd_hcic_remove_cig(cig_id, base::BindOnce(&iso_impl::on_remove_cig,
258                                                  base::Unretained(this)));
259     BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "CIG Remove",
260                    base::StringPrintf("cig_id:0x%02x (f:%d)", cig_id, force));
261   }
262 
on_status_establish_cisiso_impl263   void on_status_establish_cis(
264       struct iso_manager::cis_establish_params conn_params, uint8_t* stream,
265       uint16_t len) {
266     uint8_t status;
267 
268     LOG_ASSERT(len == 2) << "Invalid packet length: " << +len;
269 
270     STREAM_TO_UINT16(status, stream);
271 
272     for (auto cis_param : conn_params.conn_pairs) {
273       cis_establish_cmpl_evt evt;
274 
275       if (status != HCI_SUCCESS) {
276         auto cis = GetCisIfKnown(cis_param.cis_conn_handle);
277         LOG_ASSERT(cis != nullptr)
278             << "No such cis: " << +cis_param.cis_conn_handle;
279 
280         evt.status = status;
281         evt.cis_conn_hdl = cis_param.cis_conn_handle;
282         evt.cig_id = 0xFF;
283         cis->state_flags &= ~kStateFlagIsConnecting;
284         cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt);
285 
286         BTM_LogHistory(
287             kBtmLogTag, cis_hdl_to_addr[evt.cis_conn_hdl],
288             "Establish CIS failed ",
289             base::StringPrintf(
290                 "handle:0x%04x, status: %s", evt.cis_conn_hdl,
291                 hci_status_code_text((tHCI_STATUS)(status)).c_str()));
292         cis_hdl_to_addr.erase(evt.cis_conn_hdl);
293       }
294     }
295   }
296 
establish_cisiso_impl297   void establish_cis(struct iso_manager::cis_establish_params conn_params) {
298     for (auto& el : conn_params.conn_pairs) {
299       auto cis = GetCisIfKnown(el.cis_conn_handle);
300       LOG_ASSERT(cis) << "No such cis: " << +el.cis_conn_handle;
301       LOG_ASSERT(!(cis->state_flags &
302                    (kStateFlagIsConnected | kStateFlagIsConnecting)))
303           << "Already connected or connecting";
304       cis->state_flags |= kStateFlagIsConnecting;
305 
306       tBTM_SEC_DEV_REC* p_rec = btm_find_dev_by_handle(el.acl_conn_handle);
307       if (p_rec) {
308         cis_hdl_to_addr[el.cis_conn_handle] = p_rec->ble.pseudo_addr;
309         BTM_LogHistory(kBtmLogTag, p_rec->ble.pseudo_addr, "Establish CIS",
310                        base::StringPrintf("handle:0x%04x", el.acl_conn_handle));
311       }
312     }
313     btsnd_hcic_create_cis(conn_params.conn_pairs.size(),
314                           conn_params.conn_pairs.data(),
315                           base::BindOnce(&iso_impl::on_status_establish_cis,
316                                          base::Unretained(this), conn_params));
317   }
318 
disconnect_cisiso_impl319   void disconnect_cis(uint16_t cis_handle, uint8_t reason) {
320     auto cis = GetCisIfKnown(cis_handle);
321     LOG_ASSERT(cis) << "No such cis: " << +cis_handle;
322     LOG_ASSERT(cis->state_flags & kStateFlagIsConnected ||
323                cis->state_flags & kStateFlagIsConnecting)
324         << "Not connected";
325     bluetooth::legacy::hci::GetInterface().Disconnect(
326         cis_handle, static_cast<tHCI_STATUS>(reason));
327 
328     BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[cis_handle], "Disconnect CIS ",
329                    base::StringPrintf(
330                        "handle:0x%04x, reason:%s", cis_handle,
331                        hci_reason_code_text((tHCI_REASON)(reason)).c_str()));
332   }
333 
on_setup_iso_data_pathiso_impl334   void on_setup_iso_data_path(uint8_t* stream, uint16_t len) {
335     uint8_t status;
336     uint16_t conn_handle;
337 
338     STREAM_TO_UINT8(status, stream);
339     STREAM_TO_UINT16(conn_handle, stream);
340 
341     iso_base* iso = GetIsoIfKnown(conn_handle);
342     if (iso == nullptr) {
343       /* That can happen when ACL has been disconnected while ISO patch was
344        * creating */
345       LOG(WARNING) << __func__ << "Invalid connection handle: " << +conn_handle;
346       return;
347     }
348 
349     BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[conn_handle],
350                    "Setup data path complete",
351                    base::StringPrintf(
352                        "handle:0x%04x, status:%s", conn_handle,
353                        hci_status_code_text((tHCI_STATUS)(status)).c_str()));
354 
355     if (status == HCI_SUCCESS) iso->state_flags |= kStateFlagHasDataPathSet;
356     if (iso->state_flags & kStateFlagIsBroadcast) {
357       LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks";
358       big_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->big_handle);
359     } else {
360       LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
361       cig_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->cig_id);
362     }
363   }
364 
setup_iso_data_pathiso_impl365   void setup_iso_data_path(
366       uint16_t conn_handle,
367       struct iso_manager::iso_data_path_params path_params) {
368     iso_base* iso = GetIsoIfKnown(conn_handle);
369     LOG_ASSERT(iso != nullptr) << "No such iso connection: " << +conn_handle;
370 
371     if (!(iso->state_flags & kStateFlagIsBroadcast)) {
372       LOG_ASSERT(iso->state_flags & kStateFlagIsConnected)
373           << "CIS not established";
374     }
375 
376     btsnd_hcic_setup_iso_data_path(
377         conn_handle, path_params.data_path_dir, path_params.data_path_id,
378         path_params.codec_id_format, path_params.codec_id_company,
379         path_params.codec_id_vendor, path_params.controller_delay,
380         std::move(path_params.codec_conf),
381         base::BindOnce(&iso_impl::on_setup_iso_data_path,
382                        base::Unretained(this)));
383     BTM_LogHistory(
384         kBtmLogTag, cis_hdl_to_addr[conn_handle], "Setup data path",
385         base::StringPrintf(
386             "handle:0x%04x, dir:0x%02x, path_id:0x%02x, codec_id:0x%02x",
387             conn_handle, path_params.data_path_dir, path_params.data_path_id,
388             path_params.codec_id_format));
389   }
390 
on_remove_iso_data_pathiso_impl391   void on_remove_iso_data_path(uint8_t* stream, uint16_t len) {
392     uint8_t status;
393     uint16_t conn_handle;
394 
395     if (len < 3) {
396       LOG(WARNING) << __func__ << "Malformatted packet received";
397       return;
398     }
399     STREAM_TO_UINT8(status, stream);
400     STREAM_TO_UINT16(conn_handle, stream);
401 
402     iso_base* iso = GetIsoIfKnown(conn_handle);
403     if (iso == nullptr) {
404       /* That could happen when ACL has been disconnected while removing data
405        * path */
406       LOG(WARNING) << __func__ << "Invalid connection handle: " << +conn_handle;
407       return;
408     }
409 
410     BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[conn_handle],
411                    "Remove data path complete",
412                    base::StringPrintf(
413                        "handle:0x%04x, status:%s", conn_handle,
414                        hci_status_code_text((tHCI_STATUS)(status)).c_str()));
415 
416     if (status == HCI_SUCCESS) iso->state_flags &= ~kStateFlagHasDataPathSet;
417 
418     if (iso->state_flags & kStateFlagIsBroadcast) {
419       LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks";
420       big_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->big_handle);
421     } else {
422       LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
423       cig_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->cig_id);
424     }
425   }
426 
remove_iso_data_pathiso_impl427   void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) {
428     iso_base* iso = GetIsoIfKnown(iso_handle);
429     LOG_ASSERT(iso != nullptr) << "No such iso connection: " << loghex(iso_handle);
430     LOG_ASSERT((iso->state_flags & kStateFlagHasDataPathSet) ==
431                kStateFlagHasDataPathSet)
432         << "Data path not set";
433 
434     btsnd_hcic_remove_iso_data_path(
435         iso_handle, data_path_dir,
436         base::BindOnce(&iso_impl::on_remove_iso_data_path,
437                        base::Unretained(this)));
438     BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[iso_handle], "Remove data path",
439                    base::StringPrintf("handle:0x%04x, dir:0x%02x", iso_handle,
440                                       data_path_dir));
441   }
442 
on_iso_link_quality_readiso_impl443   void on_iso_link_quality_read(uint8_t* stream, uint16_t len) {
444     uint8_t status;
445     uint16_t conn_handle;
446     uint32_t txUnackedPackets;
447     uint32_t txFlushedPackets;
448     uint32_t txLastSubeventPackets;
449     uint32_t retransmittedPackets;
450     uint32_t crcErrorPackets;
451     uint32_t rxUnreceivedPackets;
452     uint32_t duplicatePackets;
453 
454     // 1 + 2 + 4 * 7
455 #define ISO_LINK_QUALITY_SIZE 31
456     if (len < ISO_LINK_QUALITY_SIZE) {
457       LOG(ERROR) << "Malformated link quality format, len=" << len;
458       return;
459     }
460 
461     STREAM_TO_UINT8(status, stream);
462     if (status != HCI_SUCCESS) {
463       LOG(ERROR) << "Failed to Read ISO Link Quality, status: "
464                  << loghex(status);
465       return;
466     }
467 
468     STREAM_TO_UINT16(conn_handle, stream);
469 
470     iso_base* iso = GetIsoIfKnown(conn_handle);
471     if (iso == nullptr) {
472       /* That could happen when ACL has been disconnected while waiting on the
473        * read respose */
474       LOG(WARNING) << __func__ << "Invalid connection handle: " << +conn_handle;
475       return;
476     }
477 
478     STREAM_TO_UINT32(txUnackedPackets, stream);
479     STREAM_TO_UINT32(txFlushedPackets, stream);
480     STREAM_TO_UINT32(txLastSubeventPackets, stream);
481     STREAM_TO_UINT32(retransmittedPackets, stream);
482     STREAM_TO_UINT32(crcErrorPackets, stream);
483     STREAM_TO_UINT32(rxUnreceivedPackets, stream);
484     STREAM_TO_UINT32(duplicatePackets, stream);
485 
486     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
487     cig_callbacks_->OnIsoLinkQualityRead(
488         conn_handle, iso->cig_id, txUnackedPackets, txFlushedPackets,
489         txLastSubeventPackets, retransmittedPackets, crcErrorPackets,
490         rxUnreceivedPackets, duplicatePackets);
491   }
492 
read_iso_link_qualityiso_impl493   void read_iso_link_quality(uint16_t iso_handle) {
494     iso_base* iso = GetIsoIfKnown(iso_handle);
495     if (iso == nullptr) {
496       LOG(ERROR) << __func__ << "No such iso connection: " << loghex(iso_handle);
497       return;
498     }
499 
500     btsnd_hcic_read_iso_link_quality(
501         iso_handle, base::BindOnce(&iso_impl::on_iso_link_quality_read,
502                                    base::Unretained(this)));
503   }
504 
prepare_ts_hci_packetiso_impl505   BT_HDR* prepare_ts_hci_packet(uint16_t iso_handle, uint32_t ts,
506                                 uint16_t seq_nb, uint16_t data_len) {
507     /* Add 2 for packet seq., 2 for length, 4 for the timestamp */
508     uint16_t iso_data_load_len = data_len + 8;
509 
510     /* Add 2 for handle, 2 for length */
511     uint16_t iso_full_len = iso_data_load_len + 4;
512     BT_HDR* packet = (BT_HDR*)osi_malloc(iso_full_len + sizeof(BT_HDR));
513     packet->len = iso_full_len;
514     packet->offset = 0;
515     packet->event = MSG_STACK_TO_HC_HCI_ISO;
516     packet->layer_specific = 0;
517 
518     uint8_t* packet_data = packet->data;
519     UINT16_TO_STREAM(packet_data, iso_handle);
520     UINT16_TO_STREAM(packet_data, iso_data_load_len);
521 
522     packet->layer_specific |= BT_ISO_HDR_CONTAINS_TS;
523     UINT32_TO_STREAM(packet_data, ts);
524 
525     UINT16_TO_STREAM(packet_data, seq_nb);
526     UINT16_TO_STREAM(packet_data, data_len);
527 
528     return packet;
529   }
530 
send_iso_data_hci_packetiso_impl531   void send_iso_data_hci_packet(BT_HDR* packet) {
532     bte_main_hci_send(packet, MSG_STACK_TO_HC_HCI_ISO | 0x0001);
533   }
534 
send_iso_dataiso_impl535   void send_iso_data(uint16_t iso_handle, const uint8_t* data,
536                      uint16_t data_len) {
537     iso_base* iso = GetIsoIfKnown(iso_handle);
538     LOG_ASSERT(iso != nullptr)
539         << "No such iso connection handle: " << loghex(iso_handle);
540 
541     if (!(iso->state_flags & kStateFlagIsBroadcast)) {
542       if (!(iso->state_flags & kStateFlagIsConnected)) {
543         LOG(WARNING) << __func__ << "Cis handle: " << loghex(iso_handle)
544                      << " not established";
545         return;
546       }
547     }
548 
549     if (!(iso->state_flags & kStateFlagHasDataPathSet)) {
550       LOG_WARN("Data path not set for handle: 0x%04x", iso_handle);
551       return;
552     }
553 
554     /* Calculate sequence number for the ISO data packet.
555      * It should be incremented by 1 every SDU Interval.
556      */
557     uint32_t ts = bluetooth::common::time_get_os_boottime_us();
558     iso->sync_info.seq_nb = (ts - iso->sync_info.first_sync_ts) / iso->sdu_itv;
559 
560     if (iso_credits_ == 0 || data_len > iso_buffer_size_) {
561       iso->cr_stats.credits_underflow_bytes += data_len;
562       iso->cr_stats.credits_underflow_count++;
563       iso->cr_stats.credits_last_underflow_us =
564           bluetooth::common::time_get_os_boottime_us();
565 
566       LOG(WARNING) << __func__ << ", dropping ISO packet, len: "
567                    << static_cast<int>(data_len)
568                    << ", iso credits: " << static_cast<int>(iso_credits_)
569                    << ", iso handle: " << loghex(iso_handle);
570       return;
571     }
572 
573     iso_credits_--;
574     iso->used_credits++;
575 
576     BT_HDR* packet =
577         prepare_ts_hci_packet(iso_handle, ts, iso->sync_info.seq_nb, data_len);
578     memcpy(packet->data + kIsoDataInTsBtHdrOffset, data, data_len);
579     send_iso_data_hci_packet(packet);
580   }
581 
process_cis_est_pktiso_impl582   void process_cis_est_pkt(uint8_t len, uint8_t* data) {
583     cis_establish_cmpl_evt evt;
584 
585     LOG_ASSERT(len == 28) << "Invalid packet length: " << +len;
586     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
587 
588     STREAM_TO_UINT8(evt.status, data);
589     STREAM_TO_UINT16(evt.cis_conn_hdl, data);
590 
591     auto cis = GetCisIfKnown(evt.cis_conn_hdl);
592     LOG_ASSERT(cis != nullptr) << "No such cis: " << +evt.cis_conn_hdl;
593 
594     BTM_LogHistory(kBtmLogTag, cis_hdl_to_addr[evt.cis_conn_hdl],
595                    "CIS established event",
596                    base::StringPrintf(
597                        "cis_handle:0x%04x status:%s", evt.cis_conn_hdl,
598                        hci_error_code_text((tHCI_STATUS)(evt.status)).c_str()));
599 
600     cis->sync_info.first_sync_ts = bluetooth::common::time_get_os_boottime_us();
601 
602     STREAM_TO_UINT24(evt.cig_sync_delay, data);
603     STREAM_TO_UINT24(evt.cis_sync_delay, data);
604     STREAM_TO_UINT24(evt.trans_lat_mtos, data);
605     STREAM_TO_UINT24(evt.trans_lat_stom, data);
606     STREAM_TO_UINT8(evt.phy_mtos, data);
607     STREAM_TO_UINT8(evt.phy_stom, data);
608     STREAM_TO_UINT8(evt.nse, data);
609     STREAM_TO_UINT8(evt.bn_mtos, data);
610     STREAM_TO_UINT8(evt.bn_stom, data);
611     STREAM_TO_UINT8(evt.ft_mtos, data);
612     STREAM_TO_UINT8(evt.ft_stom, data);
613     STREAM_TO_UINT16(evt.max_pdu_mtos, data);
614     STREAM_TO_UINT16(evt.max_pdu_stom, data);
615     STREAM_TO_UINT16(evt.iso_itv, data);
616 
617     if (evt.status == HCI_SUCCESS) {
618       cis->state_flags |= kStateFlagIsConnected;
619     } else {
620       cis_hdl_to_addr.erase(evt.cis_conn_hdl);
621     }
622 
623     cis->state_flags &= ~kStateFlagIsConnecting;
624 
625     evt.cig_id = cis->cig_id;
626     cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt);
627   }
628 
disconnection_completeiso_impl629   void disconnection_complete(uint16_t handle, uint8_t reason) {
630     /* Check if this is an ISO handle */
631     auto cis = GetCisIfKnown(handle);
632     if (cis == nullptr) return;
633 
634     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
635 
636     LOG_INFO("%s flags: %d", __func__, +cis->state_flags);
637 
638     BTM_LogHistory(
639         kBtmLogTag, cis_hdl_to_addr[handle], "CIS disconnected",
640         base::StringPrintf("cis_handle:0x%04x, reason:%s", handle,
641                            hci_error_code_text((tHCI_REASON)(reason)).c_str()));
642     cis_hdl_to_addr.erase(handle);
643 
644     if (cis->state_flags & kStateFlagIsConnected) {
645       cis_disconnected_evt evt = {
646           .reason = reason,
647           .cis_conn_hdl = handle,
648           .cig_id = cis->cig_id,
649       };
650 
651       cig_callbacks_->OnCisEvent(kIsoEventCisDisconnected, &evt);
652       cis->state_flags &= ~kStateFlagIsConnected;
653 
654       /* return used credits */
655       iso_credits_ += cis->used_credits;
656       cis->used_credits = 0;
657 
658       /* Data path is considered still valid, but can be reconfigured only once
659        * CIS is reestablished.
660        */
661     }
662   }
663 
handle_num_completed_pktsiso_impl664   void handle_num_completed_pkts(uint8_t* p, uint8_t evt_len) {
665     uint8_t num_handles;
666 
667     STREAM_TO_UINT8(num_handles, p);
668 
669     LOG_ASSERT(evt_len == num_handles * 4 + 1);
670 
671     for (int i = 0; i < num_handles; i++) {
672       uint16_t handle, num_sent;
673 
674       STREAM_TO_UINT16(handle, p);
675       STREAM_TO_UINT16(num_sent, p);
676 
677       auto iter = conn_hdl_to_cis_map_.find(handle);
678       if (iter != conn_hdl_to_cis_map_.end()) {
679         iter->second->used_credits -= num_sent;
680         iso_credits_ += num_sent;
681         continue;
682       }
683 
684       iter = conn_hdl_to_bis_map_.find(handle);
685       if (iter != conn_hdl_to_bis_map_.end()) {
686         iter->second->used_credits -= num_sent;
687         iso_credits_ += num_sent;
688         continue;
689       }
690     }
691   }
692 
handle_gd_num_completed_pktsiso_impl693   void handle_gd_num_completed_pkts(uint16_t handle, uint16_t credits) {
694     auto iter = conn_hdl_to_cis_map_.find(handle);
695     if (iter != conn_hdl_to_cis_map_.end()) {
696       iter->second->used_credits -= credits;
697       iso_credits_ += credits;
698       return;
699     }
700 
701     iter = conn_hdl_to_bis_map_.find(handle);
702     if (iter != conn_hdl_to_bis_map_.end()) {
703       iter->second->used_credits -= credits;
704       iso_credits_ += credits;
705     }
706   }
707 
process_create_big_cmpl_pktiso_impl708   void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) {
709     struct big_create_cmpl_evt evt;
710 
711     LOG_ASSERT(len >= 18) << "Invalid packet length: " << +len;
712     LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks";
713 
714     STREAM_TO_UINT8(evt.status, data);
715     STREAM_TO_UINT8(evt.big_id, data);
716     STREAM_TO_UINT24(evt.big_sync_delay, data);
717     STREAM_TO_UINT24(evt.transport_latency_big, data);
718     STREAM_TO_UINT8(evt.phy, data);
719     STREAM_TO_UINT8(evt.nse, data);
720     STREAM_TO_UINT8(evt.bn, data);
721     STREAM_TO_UINT8(evt.pto, data);
722     STREAM_TO_UINT8(evt.irc, data);
723     STREAM_TO_UINT16(evt.max_pdu, data);
724     STREAM_TO_UINT16(evt.iso_interval, data);
725 
726     uint8_t num_bis;
727     STREAM_TO_UINT8(num_bis, data);
728 
729     LOG_ASSERT(num_bis != 0) << "Bis count is 0";
730     LOG_ASSERT(len == (18 + num_bis * sizeof(uint16_t)))
731         << "Invalid packet length: " << len << ". Number of bis: " << +num_bis;
732 
733     uint32_t ts = bluetooth::common::time_get_os_boottime_us();
734     for (auto i = 0; i < num_bis; ++i) {
735       uint16_t conn_handle;
736       STREAM_TO_UINT16(conn_handle, data);
737       evt.conn_handles.push_back(conn_handle);
738       LOG_INFO(" received BIS conn_hdl %d", +conn_handle);
739 
740       if (evt.status == HCI_SUCCESS) {
741         auto bis = std::unique_ptr<iso_bis>(new iso_bis());
742         bis->big_handle = evt.big_id;
743         bis->sdu_itv = last_big_create_req_sdu_itv_;
744         bis->sync_info = {.first_sync_ts = ts, .seq_nb = 0};
745         bis->used_credits = 0;
746         bis->state_flags = kStateFlagIsBroadcast;
747         conn_hdl_to_bis_map_[conn_handle] = std::move(bis);
748       }
749     }
750 
751     big_callbacks_->OnBigEvent(kIsoEventBigOnCreateCmpl, &evt);
752 
753     {
754       const std::lock_guard<std::mutex> lock(
755           on_iso_traffic_active_callbacks_list_mutex_);
756       for (auto callbacks : on_iso_traffic_active_callbacks_list_) {
757         callbacks(true);
758       }
759     }
760   }
761 
process_terminate_big_cmpl_pktiso_impl762   void process_terminate_big_cmpl_pkt(uint8_t len, uint8_t* data) {
763     struct big_terminate_cmpl_evt evt;
764 
765     LOG_ASSERT(len == 2) << "Invalid packet length: " << +len;
766     LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks";
767 
768     STREAM_TO_UINT8(evt.big_id, data);
769     STREAM_TO_UINT8(evt.reason, data);
770 
771     bool is_known_handle = false;
772     auto bis_it = conn_hdl_to_bis_map_.cbegin();
773     while (bis_it != conn_hdl_to_bis_map_.cend()) {
774       if (bis_it->second->big_handle == evt.big_id) {
775         bis_it = conn_hdl_to_bis_map_.erase(bis_it);
776         is_known_handle = true;
777       } else {
778         ++bis_it;
779       }
780     }
781 
782     LOG_ASSERT(is_known_handle) << "No such big: " << +evt.big_id;
783     big_callbacks_->OnBigEvent(kIsoEventBigOnTerminateCmpl, &evt);
784 
785     {
786       const std::lock_guard<std::mutex> lock(
787           on_iso_traffic_active_callbacks_list_mutex_);
788       for (auto callbacks : on_iso_traffic_active_callbacks_list_) {
789         callbacks(false);
790       }
791     }
792   }
793 
create_bigiso_impl794   void create_big(uint8_t big_id, struct big_create_params big_params) {
795     LOG_ASSERT(!IsBigKnown(big_id))
796         << "Invalid big - already exists: " << +big_id;
797 
798     if (stack_config_get_interface()->get_pts_unencrypt_broadcast()) {
799       LOG_INFO("Force create broadcst without encryption for PTS test");
800       big_params.enc = 0;
801       big_params.enc_code = {0};
802     }
803 
804     last_big_create_req_sdu_itv_ = big_params.sdu_itv;
805     btsnd_hcic_create_big(
806         big_id, big_params.adv_handle, big_params.num_bis, big_params.sdu_itv,
807         big_params.max_sdu_size, big_params.max_transport_latency,
808         big_params.rtn, big_params.phy, big_params.packing, big_params.framing,
809         big_params.enc, big_params.enc_code);
810   }
811 
terminate_bigiso_impl812   void terminate_big(uint8_t big_id, uint8_t reason) {
813     LOG_ASSERT(IsBigKnown(big_id)) << "No such big: " << +big_id;
814 
815     btsnd_hcic_term_big(big_id, reason);
816   }
817 
on_iso_eventiso_impl818   void on_iso_event(uint8_t code, uint8_t* packet, uint16_t packet_len) {
819     switch (code) {
820       case HCI_BLE_CIS_EST_EVT:
821         process_cis_est_pkt(packet_len, packet);
822         break;
823       case HCI_BLE_CREATE_BIG_CPL_EVT:
824         process_create_big_cmpl_pkt(packet_len, packet);
825         break;
826       case HCI_BLE_TERM_BIG_CPL_EVT:
827         process_terminate_big_cmpl_pkt(packet_len, packet);
828         break;
829       case HCI_BLE_CIS_REQ_EVT:
830         /* Not supported */
831         break;
832       case HCI_BLE_BIG_SYNC_EST_EVT:
833         /* Not supported */
834         break;
835       case HCI_BLE_BIG_SYNC_LOST_EVT:
836         /* Not supported */
837         break;
838       default:
839         LOG_ERROR("Unhandled event code %d", +code);
840     }
841   }
842 
handle_iso_dataiso_impl843   void handle_iso_data(BT_HDR* p_msg) {
844     const uint8_t* stream = p_msg->data;
845     cis_data_evt evt;
846     uint16_t handle, seq_nb;
847 
848     if (p_msg->len <= ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS)
849                            ? kIsoHeaderWithTsLen
850                            : kIsoHeaderWithoutTsLen))
851       return;
852 
853     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
854 
855     STREAM_TO_UINT16(handle, stream);
856     evt.cis_conn_hdl = HCID_GET_HANDLE(handle);
857 
858     iso_base* iso = GetCisIfKnown(evt.cis_conn_hdl);
859     if (iso == nullptr) {
860       LOG(ERROR) << __func__ << ", received data for the non-registered CIS!";
861       return;
862     }
863 
864     STREAM_SKIP_UINT16(stream);
865     if (p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS) {
866       STREAM_TO_UINT32(evt.ts, stream);
867     } else {
868       evt.ts = 0;
869     }
870 
871     STREAM_TO_UINT16(seq_nb, stream);
872 
873     uint32_t ts = bluetooth::common::time_get_os_boottime_us();
874     uint32_t new_calc_seq_nb =
875         (ts - iso->sync_info.first_sync_ts) / iso->sdu_itv;
876     if (new_calc_seq_nb <= iso->sync_info.seq_nb)
877       new_calc_seq_nb = iso->sync_info.seq_nb + 1;
878 
879     if (iso->sync_info.seq_nb == 0) {
880       evt.evt_lost = 0;
881     } else {
882       evt.evt_lost = new_calc_seq_nb - iso->sync_info.seq_nb - 1;
883       if (evt.evt_lost > 0) {
884         iso->evt_stats.evt_lost_count += evt.evt_lost;
885         iso->evt_stats.evt_last_lost_us =
886             bluetooth::common::time_get_os_boottime_us();
887 
888         LOG(WARNING) << evt.evt_lost << " packets possibly lost.";
889       }
890 
891       if (new_calc_seq_nb != seq_nb) {
892         LOG(WARNING) << "Sequence number mismatch. "
893                         "Adjusting own time reference point.";
894         iso->sync_info.first_sync_ts = ts - (seq_nb * iso->sdu_itv);
895         new_calc_seq_nb = seq_nb;
896 
897         iso->evt_stats.seq_nb_mismatch_count++;
898       }
899     }
900     iso->sync_info.seq_nb = new_calc_seq_nb;
901 
902     evt.p_msg = p_msg;
903     evt.cig_id = iso->cig_id;
904     evt.seq_nb = seq_nb;
905     cig_callbacks_->OnCisEvent(kIsoEventCisDataAvailable, &evt);
906   }
907 
GetCisIfKnowniso_impl908   iso_cis* GetCisIfKnown(uint16_t cis_conn_handle) {
909     auto cis_it = conn_hdl_to_cis_map_.find(cis_conn_handle);
910     return (cis_it != conn_hdl_to_cis_map_.end()) ? cis_it->second.get()
911                                                   : nullptr;
912   }
913 
GetBisIfKnowniso_impl914   iso_bis* GetBisIfKnown(uint16_t bis_conn_handle) {
915     auto bis_it = conn_hdl_to_bis_map_.find(bis_conn_handle);
916     return (bis_it != conn_hdl_to_bis_map_.end()) ? bis_it->second.get()
917                                                   : nullptr;
918   }
919 
GetIsoIfKnowniso_impl920   iso_base* GetIsoIfKnown(uint16_t iso_handle) {
921     struct iso_base* iso = GetCisIfKnown(iso_handle);
922     return (iso != nullptr) ? iso : GetBisIfKnown(iso_handle);
923   }
924 
IsCigKnowniso_impl925   bool IsCigKnown(uint8_t cig_id) const {
926     auto const cis_it =
927         std::find_if(conn_hdl_to_cis_map_.cbegin(), conn_hdl_to_cis_map_.cend(),
928                      [&cig_id](auto& kv_pair) {
929                        return (kv_pair.second->cig_id == cig_id);
930                      });
931     return (cis_it != conn_hdl_to_cis_map_.cend());
932   }
933 
IsBigKnowniso_impl934   bool IsBigKnown(uint8_t big_id) const {
935     auto bis_it =
936         std::find_if(conn_hdl_to_bis_map_.cbegin(), conn_hdl_to_bis_map_.cend(),
937                      [&big_id](auto& kv_pair) {
938                        return (kv_pair.second->big_handle == big_id);
939                      });
940     return (bis_it != conn_hdl_to_bis_map_.cend());
941   }
942 
dump_credits_statsiso_impl943   static void dump_credits_stats(int fd, const iso_base::credits_stats& stats) {
944     uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
945 
946     dprintf(fd, "        Credits Stats:\n");
947     dprintf(fd, "          Credits underflow (count): %zu\n",
948             stats.credits_underflow_count);
949     dprintf(fd, "          Credits underflow (bytes): %zu\n",
950             stats.credits_underflow_bytes);
951     dprintf(
952         fd, "          Last underflow time ago (ms): %llu\n",
953         (stats.credits_last_underflow_us > 0
954              ? (unsigned long long)(now_us - stats.credits_last_underflow_us) /
955                    1000
956              : 0llu));
957   }
958 
dump_event_statsiso_impl959   static void dump_event_stats(int fd, const iso_base::event_stats& stats) {
960     uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
961 
962     dprintf(fd, "        Event Stats:\n");
963     dprintf(fd, "          Sequence number mismatch (count): %zu\n",
964             stats.seq_nb_mismatch_count);
965     dprintf(fd, "          Event lost (count): %zu\n", stats.evt_lost_count);
966     dprintf(fd, "          Last event lost time ago (ms): %llu\n",
967             (stats.evt_last_lost_us > 0
968                  ? (unsigned long long)(now_us - stats.evt_last_lost_us) / 1000
969                  : 0llu));
970   }
971 
dumpiso_impl972   void dump(int fd) const {
973     dprintf(fd, "  ----------------\n ");
974     dprintf(fd, "  ISO Manager:\n");
975     dprintf(fd, "    Available credits: %d\n", iso_credits_.load());
976     dprintf(fd, "    Controller buffer size: %d\n", iso_buffer_size_);
977     dprintf(fd, "    Num of ISO traffic callbacks: %lu\n",
978             static_cast<unsigned long>(
979                 on_iso_traffic_active_callbacks_list_.size()));
980     dprintf(fd, "    CISes:\n");
981     for (auto const& cis_pair : conn_hdl_to_cis_map_) {
982       dprintf(fd, "      CIS Connection handle: %d\n", cis_pair.first);
983       dprintf(fd, "        CIG ID: %d\n", cis_pair.second->cig_id);
984       dprintf(fd, "        Used Credits: %d\n",
985               cis_pair.second->used_credits.load());
986       dprintf(fd, "        SDU Interval: %d\n", cis_pair.second->sdu_itv);
987       dprintf(fd, "        State Flags: 0x%02hx\n",
988               cis_pair.second->state_flags.load());
989       dump_credits_stats(fd, cis_pair.second->cr_stats);
990       dump_event_stats(fd, cis_pair.second->evt_stats);
991     }
992     dprintf(fd, "    BISes:\n");
993     for (auto const& cis_pair : conn_hdl_to_bis_map_) {
994       dprintf(fd, "      BIS Connection handle: %d\n", cis_pair.first);
995       dprintf(fd, "        BIG Handle: %d\n", cis_pair.second->big_handle);
996       dprintf(fd, "        Used Credits: %d\n",
997               cis_pair.second->used_credits.load());
998       dprintf(fd, "        SDU Interval: %d\n", cis_pair.second->sdu_itv);
999       dprintf(fd, "        State Flags: 0x%02hx\n",
1000               cis_pair.second->state_flags.load());
1001       dump_credits_stats(fd, cis_pair.second->cr_stats);
1002       dump_event_stats(fd, cis_pair.second->evt_stats);
1003     }
1004     dprintf(fd, "  ----------------\n ");
1005   }
1006 
1007   std::map<uint16_t, std::unique_ptr<iso_cis>> conn_hdl_to_cis_map_;
1008   std::map<uint16_t, std::unique_ptr<iso_bis>> conn_hdl_to_bis_map_;
1009   std::map<uint16_t, RawAddress> cis_hdl_to_addr;
1010 
1011   std::atomic_uint16_t iso_credits_;
1012   uint16_t iso_buffer_size_;
1013   uint32_t last_big_create_req_sdu_itv_;
1014 
1015   CigCallbacks* cig_callbacks_ = nullptr;
1016   BigCallbacks* big_callbacks_ = nullptr;
1017   std::mutex on_iso_traffic_active_callbacks_list_mutex_;
1018   std::list<void (*)(bool)> on_iso_traffic_active_callbacks_list_;
1019 };
1020 
1021 }  // namespace iso_manager
1022 }  // namespace hci
1023 }  // namespace bluetooth
1024