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