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/bind_helpers.h"
26 #include "base/callback.h"
27 #include "bt_types.h"
28 #include "btm_iso_api.h"
29 #include "btu.h"
30 #include "common/time_util.h"
31 #include "device/include/controller.h"
32 #include "osi/include/log.h"
33 
34 namespace bluetooth {
35 namespace hci {
36 namespace iso_manager {
37 static constexpr uint8_t kIsoDataInTsBtHdrOffset = 0x0C;
38 static constexpr uint8_t kIsoHeaderWithTsLen = 12;
39 static constexpr uint8_t kIsoHeaderWithoutTsLen = 8;
40 
41 static constexpr uint8_t kStateFlagsNone = 0x00;
42 static constexpr uint8_t kStateFlagIsConnected = 0x01;
43 static constexpr uint8_t kStateFlagHasDataPathSet = 0x02;
44 static constexpr uint8_t kStateFlagIsBroadcast = 0x04;
45 
46 struct iso_sync_info {
47   uint32_t first_sync_ts;
48   uint16_t seq_nb;
49 };
50 
51 struct iso_base {
52   union {
53     uint8_t cig_id;
54     uint8_t big_handle;
55   };
56 
57   struct iso_sync_info sync_info;
58   uint8_t state_flags;
59   uint32_t sdu_itv;
60 };
61 
62 typedef iso_base iso_cis;
63 typedef iso_base iso_bis;
64 
65 struct iso_impl {
iso_impliso_impl66   iso_impl() {
67     iso_credits_ = controller_get_interface()->get_iso_buffer_count();
68     iso_buffer_size_ = controller_get_interface()->get_iso_data_size();
69   }
70 
~iso_impliso_impl71   ~iso_impl() {}
72 
handle_register_cis_callbacksiso_impl73   void handle_register_cis_callbacks(CigCallbacks* callbacks) {
74     LOG_ASSERT(callbacks != nullptr) << "Invalid CIG callbacks";
75     cig_callbacks_ = callbacks;
76   }
77 
handle_register_big_callbacksiso_impl78   void handle_register_big_callbacks(BigCallbacks* callbacks) {
79     LOG_ASSERT(callbacks != nullptr) << "Invalid BIG callbacks";
80     big_callbacks_ = callbacks;
81   }
82 
on_set_cig_paramsiso_impl83   void on_set_cig_params(uint8_t cig_id, uint32_t sdu_itv_mtos, uint8_t* stream,
84                          uint16_t len) {
85     uint8_t cis_cnt;
86     uint16_t conn_handle;
87     cig_create_cmpl_evt evt;
88 
89     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
90     LOG_ASSERT(len >= 3) << "Invalid packet length.";
91 
92     STREAM_TO_UINT8(evt.status, stream);
93     STREAM_TO_UINT8(evt.cig_id, stream);
94     STREAM_TO_UINT8(cis_cnt, stream);
95 
96     uint8_t evt_code = IsCigKnown(cig_id) ? kIsoEventCigOnReconfigureCmpl
97                                           : kIsoEventCigOnCreateCmpl;
98 
99     if (evt.status == HCI_SUCCESS) {
100       LOG_ASSERT(len >= (3) + (cis_cnt * sizeof(uint16_t)))
101           << "Invalid CIS count.";
102 
103       /* Remove entries for the reconfigured CIG */
104       if (evt_code == kIsoEventCigOnReconfigureCmpl) {
105         auto cis_it = conn_hdl_to_cis_map_.cbegin();
106         while (cis_it != conn_hdl_to_cis_map_.cend()) {
107           if (cis_it->second->cig_id == evt.cig_id)
108             cis_it = conn_hdl_to_cis_map_.erase(cis_it);
109           else
110             ++cis_it;
111         }
112       }
113 
114       evt.conn_handles.reserve(cis_cnt);
115       for (int i = 0; i < cis_cnt; i++) {
116         STREAM_TO_UINT16(conn_handle, stream);
117 
118         evt.conn_handles.push_back(conn_handle);
119         conn_hdl_to_cis_map_[conn_handle] = std::unique_ptr<iso_cis>(
120             new iso_cis({.sync_info = {.first_sync_ts = 0, .seq_nb = 0},
121                          .cig_id = cig_id,
122                          .state_flags = kStateFlagsNone,
123                          .sdu_itv = sdu_itv_mtos}));
124       }
125     }
126 
127     cig_callbacks_->OnCigEvent(evt_code, &evt);
128   }
129 
create_cigiso_impl130   void create_cig(uint8_t cig_id,
131                   struct iso_manager::cig_create_params cig_params) {
132     LOG_ASSERT(!IsCigKnown(cig_id)) << "Invalid cig - already exists.";
133 
134     btsnd_hcic_set_cig_params(
135         cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom,
136         cig_params.sca, cig_params.packing, cig_params.framing,
137         cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos,
138         cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(),
139         base::BindOnce(&iso_impl::on_set_cig_params, base::Unretained(this),
140                        cig_id, cig_params.sdu_itv_mtos));
141   }
142 
reconfigure_cigiso_impl143   void reconfigure_cig(uint8_t cig_id,
144                        struct iso_manager::cig_create_params cig_params) {
145     LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig";
146 
147     btsnd_hcic_set_cig_params(
148         cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom,
149         cig_params.sca, cig_params.packing, cig_params.framing,
150         cig_params.max_trans_lat_stom, cig_params.max_trans_lat_mtos,
151         cig_params.cis_cfgs.size(), cig_params.cis_cfgs.data(),
152         base::BindOnce(&iso_impl::on_set_cig_params, base::Unretained(this),
153                        cig_id, cig_params.sdu_itv_mtos));
154   }
155 
on_remove_cigiso_impl156   void on_remove_cig(uint8_t* stream, uint16_t len) {
157     cig_remove_cmpl_evt evt;
158 
159     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
160     LOG_ASSERT(len == 2) << "Invalid packet length.";
161 
162     STREAM_TO_UINT8(evt.status, stream);
163     STREAM_TO_UINT8(evt.cig_id, stream);
164 
165     if (evt.status == HCI_SUCCESS) {
166       auto cis_it = conn_hdl_to_cis_map_.cbegin();
167       while (cis_it != conn_hdl_to_cis_map_.cend()) {
168         if (cis_it->second->cig_id == evt.cig_id)
169           cis_it = conn_hdl_to_cis_map_.erase(cis_it);
170         else
171           ++cis_it;
172       }
173     }
174 
175     cig_callbacks_->OnCigEvent(kIsoEventCigOnRemoveCmpl, &evt);
176   }
177 
remove_cigiso_impl178   void remove_cig(uint8_t cig_id) {
179     LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig";
180 
181     btsnd_hcic_remove_cig(cig_id, base::BindOnce(&iso_impl::on_remove_cig,
182                                                  base::Unretained(this)));
183   }
184 
on_status_establish_cisiso_impl185   void on_status_establish_cis(
186       struct iso_manager::cis_establish_params conn_params, uint8_t* stream,
187       uint16_t len) {
188     uint8_t status;
189 
190     LOG_ASSERT(len == 2) << "Invalid packet length: " << len;
191 
192     STREAM_TO_UINT16(status, stream);
193     if (status == HCI_SUCCESS) {
194       /* Wait for connection established event */
195       return;
196     }
197 
198     for (auto cis : conn_params.conn_pairs) {
199       cis_establish_cmpl_evt evt;
200 
201       evt.status = status;
202       evt.cis_conn_hdl = cis.cis_conn_handle;
203       evt.cig_id = 0xFF;
204       cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt);
205     }
206   }
207 
establish_cisiso_impl208   void establish_cis(struct iso_manager::cis_establish_params conn_params) {
209     for (auto& el : conn_params.conn_pairs) {
210       auto cis = GetCisIfKnown(el.cis_conn_handle);
211       LOG_ASSERT(cis) << "No such cis";
212       LOG_ASSERT(!(cis->state_flags & kStateFlagIsConnected))
213           << "Already connected";
214     }
215     btsnd_hcic_create_cis(conn_params.conn_pairs.size(),
216                           conn_params.conn_pairs.data(),
217                           base::BindOnce(&iso_impl::on_status_establish_cis,
218                                          base::Unretained(this), conn_params));
219   }
220 
disconnect_cisiso_impl221   void disconnect_cis(uint16_t cis_handle, uint8_t reason) {
222     auto cis = GetCisIfKnown(cis_handle);
223     LOG_ASSERT(cis) << "No such cis";
224     LOG_ASSERT(cis->state_flags & kStateFlagIsConnected) << "Not connected";
225     bluetooth::legacy::hci::GetInterface().Disconnect(
226         cis_handle, static_cast<tHCI_STATUS>(reason));
227   }
228 
on_setup_iso_data_pathiso_impl229   void on_setup_iso_data_path(uint8_t* stream, uint16_t len) {
230     uint8_t status;
231     uint16_t conn_handle;
232 
233     STREAM_TO_UINT8(status, stream);
234     STREAM_TO_UINT16(conn_handle, stream);
235 
236     iso_base* iso = GetIsoIfKnown(conn_handle);
237     LOG_ASSERT(iso != nullptr) << "Invalid connection handle: " << +conn_handle;
238 
239     if (status == HCI_SUCCESS) iso->state_flags |= kStateFlagHasDataPathSet;
240     if (iso->state_flags & kStateFlagIsBroadcast) {
241       LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks";
242       big_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->big_handle);
243     } else {
244       LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
245       cig_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->cig_id);
246     }
247   }
248 
setup_iso_data_pathiso_impl249   void setup_iso_data_path(
250       uint16_t conn_handle,
251       struct iso_manager::iso_data_path_params path_params) {
252     iso_base* iso = GetIsoIfKnown(conn_handle);
253     LOG_ASSERT(iso != nullptr) << "No such iso connection: " << +conn_handle;
254 
255     if (!(iso->state_flags & kStateFlagIsBroadcast)) {
256       LOG_ASSERT(iso->state_flags & kStateFlagIsConnected)
257           << "CIS not established";
258     }
259 
260     btsnd_hcic_setup_iso_data_path(
261         conn_handle, path_params.data_path_dir, path_params.data_path_id,
262         path_params.codec_id_format, path_params.codec_id_company,
263         path_params.codec_id_vendor, path_params.controller_delay,
264         std::move(path_params.codec_conf),
265         base::BindOnce(&iso_impl::on_setup_iso_data_path,
266                        base::Unretained(this)));
267   }
268 
on_remove_iso_data_pathiso_impl269   void on_remove_iso_data_path(uint8_t* stream, uint16_t len) {
270     uint8_t status;
271     uint16_t conn_handle;
272 
273     STREAM_TO_UINT8(status, stream);
274     STREAM_TO_UINT16(conn_handle, stream);
275 
276     iso_base* iso = GetIsoIfKnown(conn_handle);
277     LOG_ASSERT(iso != nullptr) << "Invalid connection handle: " << +conn_handle;
278 
279     if (status == HCI_SUCCESS) iso->state_flags &= ~kStateFlagHasDataPathSet;
280 
281     if (iso->state_flags & kStateFlagIsBroadcast) {
282       LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks";
283       big_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->big_handle);
284     } else {
285       LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
286       cig_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->cig_id);
287     }
288   }
289 
remove_iso_data_pathiso_impl290   void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) {
291     iso_base* iso = GetIsoIfKnown(iso_handle);
292     LOG_ASSERT(iso != nullptr) << "No such iso connection";
293     LOG_ASSERT((iso->state_flags & kStateFlagHasDataPathSet) ==
294                kStateFlagHasDataPathSet)
295         << "Data path not set";
296 
297     btsnd_hcic_remove_iso_data_path(
298         iso_handle, data_path_dir,
299         base::BindOnce(&iso_impl::on_remove_iso_data_path,
300                        base::Unretained(this)));
301   }
302 
on_iso_link_quality_readiso_impl303   void on_iso_link_quality_read(uint8_t* stream, uint16_t len) {
304     uint8_t status;
305     uint16_t conn_handle;
306     uint32_t txUnackedPackets;
307     uint32_t txFlushedPackets;
308     uint32_t txLastSubeventPackets;
309     uint32_t retransmittedPackets;
310     uint32_t crcErrorPackets;
311     uint32_t rxUnreceivedPackets;
312     uint32_t duplicatePackets;
313 
314     STREAM_TO_UINT8(status, stream);
315     if (status != HCI_SUCCESS) {
316       LOG(ERROR) << "Failed to Read ISO Link Quality, status: "
317                  << loghex(status);
318       return;
319     }
320 
321     STREAM_TO_UINT16(conn_handle, stream);
322 
323     iso_base* iso = GetIsoIfKnown(conn_handle);
324     LOG_ASSERT(iso != nullptr) << "Invalid connection handle: " << +conn_handle;
325 
326     STREAM_TO_UINT32(txUnackedPackets, stream);
327     STREAM_TO_UINT32(txFlushedPackets, stream);
328     STREAM_TO_UINT32(txLastSubeventPackets, stream);
329     STREAM_TO_UINT32(retransmittedPackets, stream);
330     STREAM_TO_UINT32(crcErrorPackets, stream);
331     STREAM_TO_UINT32(rxUnreceivedPackets, stream);
332     STREAM_TO_UINT32(duplicatePackets, stream);
333 
334     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
335     cig_callbacks_->OnIsoLinkQualityRead(
336         conn_handle, iso->cig_id, txUnackedPackets, txFlushedPackets,
337         txLastSubeventPackets, retransmittedPackets, crcErrorPackets,
338         rxUnreceivedPackets, duplicatePackets);
339   }
340 
read_iso_link_qualityiso_impl341   void read_iso_link_quality(uint16_t iso_handle) {
342     iso_base* iso = GetIsoIfKnown(iso_handle);
343     LOG_ASSERT(iso != nullptr) << "No such iso connection";
344 
345     btsnd_hcic_read_iso_link_quality(
346         iso_handle, base::BindOnce(&iso_impl::on_iso_link_quality_read,
347                                    base::Unretained(this)));
348   }
349 
prepare_ts_hci_packetiso_impl350   BT_HDR* prepare_ts_hci_packet(uint16_t iso_handle, uint32_t ts,
351                                 uint16_t seq_nb, uint16_t data_len) {
352     /* Add 2 for packet seq., 2 for length, 4 for the timestamp */
353     uint16_t iso_data_load_len = data_len + 8;
354 
355     /* Add 2 for handle, 2 for length */
356     uint16_t iso_full_len = iso_data_load_len + 4;
357     BT_HDR* packet = (BT_HDR*)osi_malloc(iso_full_len + sizeof(BT_HDR));
358     packet->len = iso_full_len;
359     packet->offset = 0;
360     packet->event = MSG_STACK_TO_HC_HCI_ISO;
361     packet->layer_specific = 0;
362 
363     uint8_t* packet_data = packet->data;
364     UINT16_TO_STREAM(packet_data, iso_handle);
365     UINT16_TO_STREAM(packet_data, iso_data_load_len);
366 
367     packet->layer_specific |= BT_ISO_HDR_CONTAINS_TS;
368     UINT32_TO_STREAM(packet_data, ts);
369 
370     UINT16_TO_STREAM(packet_data, seq_nb);
371     UINT16_TO_STREAM(packet_data, data_len);
372 
373     return packet;
374   }
375 
send_iso_data_hci_packetiso_impl376   void send_iso_data_hci_packet(BT_HDR* packet) {
377     bte_main_hci_send(packet, MSG_STACK_TO_HC_HCI_ISO | 0x0001);
378   }
379 
send_iso_dataiso_impl380   void send_iso_data(uint16_t iso_handle, const uint8_t* data,
381                      uint16_t data_len) {
382     iso_base* iso = GetIsoIfKnown(iso_handle);
383     LOG_ASSERT(iso != nullptr)
384         << "No such iso connection handle: " << +iso_handle;
385 
386     if (!(iso->state_flags & kStateFlagIsBroadcast)) {
387       LOG_ASSERT(iso->state_flags & kStateFlagIsConnected)
388           << "CIS not established";
389     }
390     LOG_ASSERT(iso->state_flags & kStateFlagHasDataPathSet)
391         << "Data path not set for handle: " << +iso_handle;
392 
393     /* Calculate sequence number for the ISO data packet.
394      * It should be incremented by 1 every SDU Interval.
395      */
396     uint32_t ts = bluetooth::common::time_get_os_boottime_us();
397     iso->sync_info.seq_nb = (ts - iso->sync_info.first_sync_ts) / iso->sdu_itv;
398 
399     if (iso_credits_ == 0 || data_len > iso_buffer_size_) {
400       LOG(WARNING) << __func__ << ", dropping ISO packet, len: "
401                    << static_cast<int>(data_len)
402                    << ", iso credits: " << static_cast<int>(iso_credits_);
403       return;
404     }
405 
406     iso_credits_--;
407 
408     BT_HDR* packet =
409         prepare_ts_hci_packet(iso_handle, ts, iso->sync_info.seq_nb, data_len);
410     memcpy(packet->data + kIsoDataInTsBtHdrOffset, data, data_len);
411     send_iso_data_hci_packet(packet);
412   }
413 
process_cis_est_pktiso_impl414   void process_cis_est_pkt(uint8_t len, uint8_t* data) {
415     cis_establish_cmpl_evt evt;
416 
417     LOG_ASSERT(len == 28) << "Invalid packet length";
418     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
419 
420     STREAM_TO_UINT8(evt.status, data);
421     STREAM_TO_UINT16(evt.cis_conn_hdl, data);
422 
423     auto cis = GetCisIfKnown(evt.cis_conn_hdl);
424     LOG_ASSERT(cis != nullptr) << "No such cis";
425 
426     cis->sync_info.first_sync_ts = bluetooth::common::time_get_os_boottime_us();
427 
428     STREAM_TO_UINT24(evt.cig_sync_delay, data);
429     STREAM_TO_UINT24(evt.cis_sync_delay, data);
430     STREAM_TO_UINT24(evt.trans_lat_mtos, data);
431     STREAM_TO_UINT24(evt.trans_lat_stom, data);
432     STREAM_TO_UINT8(evt.phy_mtos, data);
433     STREAM_TO_UINT8(evt.phy_stom, data);
434     STREAM_TO_UINT8(evt.nse, data);
435     STREAM_TO_UINT8(evt.bn_mtos, data);
436     STREAM_TO_UINT8(evt.bn_stom, data);
437     STREAM_TO_UINT8(evt.ft_mtos, data);
438     STREAM_TO_UINT8(evt.ft_stom, data);
439     STREAM_TO_UINT16(evt.max_pdu_mtos, data);
440     STREAM_TO_UINT16(evt.max_pdu_stom, data);
441     STREAM_TO_UINT16(evt.iso_itv, data);
442 
443     if (evt.status == HCI_SUCCESS) cis->state_flags |= kStateFlagIsConnected;
444 
445     evt.cig_id = cis->cig_id;
446     cig_callbacks_->OnCisEvent(kIsoEventCisEstablishCmpl, &evt);
447   }
448 
disconnection_completeiso_impl449   void disconnection_complete(uint16_t handle, uint8_t reason) {
450     /* Check if this is an ISO handle */
451     auto cis = GetCisIfKnown(handle);
452     if (cis == nullptr) return;
453 
454     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
455 
456     LOG_INFO("%s flags: %d", __func__, +cis->state_flags);
457     if (cis->state_flags & kStateFlagIsConnected) {
458       cis_disconnected_evt evt = {
459           .reason = reason,
460           .cis_conn_hdl = handle,
461           .cig_id = cis->cig_id,
462       };
463 
464       cig_callbacks_->OnCisEvent(kIsoEventCisDisconnected, &evt);
465       cis->state_flags &= ~kStateFlagIsConnected;
466       /* Data path is considered still valid, but can be reconfigured only once
467        * CIS is reestablished.
468        */
469     }
470   }
471 
handle_num_completed_pktsiso_impl472   void handle_num_completed_pkts(uint8_t* p, uint8_t evt_len) {
473     uint8_t num_handles;
474 
475     STREAM_TO_UINT8(num_handles, p);
476 
477     LOG_ASSERT(evt_len == num_handles * 4 + 1);
478 
479     for (int i = 0; i < num_handles; i++) {
480       uint16_t handle, num_sent;
481 
482       STREAM_TO_UINT16(handle, p);
483       STREAM_TO_UINT16(num_sent, p);
484 
485       if ((conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) &&
486           (conn_hdl_to_bis_map_.find(handle) == conn_hdl_to_bis_map_.end()))
487         continue;
488 
489       iso_credits_ += num_sent;
490     }
491   }
492 
process_create_big_cmpl_pktiso_impl493   void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) {
494     struct big_create_cmpl_evt evt;
495 
496     LOG_ASSERT(len >= 18) << "Invalid packet length";
497     LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks";
498 
499     STREAM_TO_UINT8(evt.status, data);
500     STREAM_TO_UINT8(evt.big_id, data);
501     STREAM_TO_UINT24(evt.big_sync_delay, data);
502     STREAM_TO_UINT24(evt.transport_latency_big, data);
503     STREAM_TO_UINT8(evt.phy, data);
504     STREAM_TO_UINT8(evt.nse, data);
505     STREAM_TO_UINT8(evt.bn, data);
506     STREAM_TO_UINT8(evt.pto, data);
507     STREAM_TO_UINT8(evt.irc, data);
508     STREAM_TO_UINT16(evt.max_pdu, data);
509     STREAM_TO_UINT16(evt.iso_interval, data);
510 
511     uint8_t num_bis;
512     STREAM_TO_UINT8(num_bis, data);
513 
514     LOG_ASSERT(num_bis != 0) << "Invalid bis count";
515     LOG_ASSERT(len == (18 + num_bis * sizeof(uint16_t)))
516         << "Invalid packet length";
517 
518     uint32_t ts = bluetooth::common::time_get_os_boottime_us();
519     for (auto i = 0; i < num_bis; ++i) {
520       uint16_t conn_handle;
521       STREAM_TO_UINT16(conn_handle, data);
522       evt.conn_handles.push_back(conn_handle);
523       LOG_INFO(" received BIS conn_hdl %d", +conn_handle);
524 
525       if (evt.status == HCI_SUCCESS) {
526         conn_hdl_to_bis_map_[conn_handle] = std::unique_ptr<iso_bis>(
527             new iso_bis({.sync_info = {.first_sync_ts = ts, .seq_nb = 0},
528                          .big_handle = evt.big_id,
529                          .state_flags = kStateFlagIsBroadcast,
530                          .sdu_itv = last_big_create_req_sdu_itv_}));
531       }
532     }
533 
534     big_callbacks_->OnBigEvent(kIsoEventBigOnCreateCmpl, &evt);
535   }
536 
process_terminate_big_cmpl_pktiso_impl537   void process_terminate_big_cmpl_pkt(uint8_t len, uint8_t* data) {
538     struct big_terminate_cmpl_evt evt;
539 
540     LOG_ASSERT(len == 2) << "Invalid packet length";
541     LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks";
542 
543     STREAM_TO_UINT8(evt.big_id, data);
544     STREAM_TO_UINT8(evt.reason, data);
545 
546     bool is_known_handle = false;
547     auto bis_it = conn_hdl_to_bis_map_.cbegin();
548     while (bis_it != conn_hdl_to_bis_map_.cend()) {
549       if (bis_it->second->big_handle == evt.big_id) {
550         bis_it = conn_hdl_to_bis_map_.erase(bis_it);
551         is_known_handle = true;
552       } else {
553         ++bis_it;
554       }
555     }
556 
557     LOG_ASSERT(is_known_handle) << "No such big";
558     big_callbacks_->OnBigEvent(kIsoEventBigOnTerminateCmpl, &evt);
559   }
560 
create_bigiso_impl561   void create_big(uint8_t big_id, struct big_create_params big_params) {
562     LOG_ASSERT(!IsBigKnown(big_id)) << "Invalid big - already exists";
563 
564     last_big_create_req_sdu_itv_ = big_params.sdu_itv;
565     btsnd_hcic_create_big(
566         big_id, big_params.adv_handle, big_params.num_bis, big_params.sdu_itv,
567         big_params.max_sdu_size, big_params.max_transport_latency,
568         big_params.rtn, big_params.phy, big_params.packing, big_params.framing,
569         big_params.enc, big_params.enc_code);
570   }
571 
terminate_bigiso_impl572   void terminate_big(uint8_t big_id, uint8_t reason) {
573     LOG_ASSERT(IsBigKnown(big_id)) << "No such big";
574 
575     btsnd_hcic_term_big(big_id, reason);
576   }
577 
on_iso_eventiso_impl578   void on_iso_event(uint8_t code, uint8_t* packet, uint16_t packet_len) {
579     switch (code) {
580       case HCI_BLE_CIS_EST_EVT:
581         process_cis_est_pkt(packet_len, packet);
582         break;
583       case HCI_BLE_CREATE_BIG_CPL_EVT:
584         process_create_big_cmpl_pkt(packet_len, packet);
585         break;
586       case HCI_BLE_TERM_BIG_CPL_EVT:
587         process_terminate_big_cmpl_pkt(packet_len, packet);
588         break;
589       case HCI_BLE_CIS_REQ_EVT:
590         /* Not supported */
591         break;
592       case HCI_BLE_BIG_SYNC_EST_EVT:
593         /* Not supported */
594         break;
595       case HCI_BLE_BIG_SYNC_LOST_EVT:
596         /* Not supported */
597         break;
598       default:
599         LOG_ERROR("Unhandled event code %d", +code);
600     }
601   }
602 
handle_iso_dataiso_impl603   void handle_iso_data(BT_HDR* p_msg) {
604     const uint8_t* stream = p_msg->data;
605     cis_data_evt evt;
606     uint16_t handle, seq_nb;
607 
608     if (p_msg->len <= ((p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS)
609                            ? kIsoHeaderWithTsLen
610                            : kIsoHeaderWithoutTsLen))
611       return;
612 
613     LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks";
614 
615     STREAM_TO_UINT16(handle, stream);
616     evt.cis_conn_hdl = HCID_GET_HANDLE(handle);
617 
618     iso_base* iso = GetCisIfKnown(evt.cis_conn_hdl);
619     if (iso == nullptr) {
620       LOG(ERROR) << __func__ << ", received data for the non-registered CIS!";
621       return;
622     }
623 
624     STREAM_SKIP_UINT16(stream);
625     if (p_msg->layer_specific & BT_ISO_HDR_CONTAINS_TS)
626       STREAM_TO_UINT32(evt.ts, stream);
627 
628     STREAM_TO_UINT16(seq_nb, stream);
629 
630     uint32_t ts = bluetooth::common::time_get_os_boottime_us();
631     uint32_t new_calc_seq_nb =
632         (ts - iso->sync_info.first_sync_ts) / iso->sdu_itv;
633     if (new_calc_seq_nb <= iso->sync_info.seq_nb)
634       new_calc_seq_nb = iso->sync_info.seq_nb + 1;
635 
636     if (iso->sync_info.seq_nb == 0) {
637       evt.evt_lost = 0;
638     } else {
639       evt.evt_lost = new_calc_seq_nb - iso->sync_info.seq_nb - 1;
640       if (evt.evt_lost > 0) {
641         LOG(WARNING) << evt.evt_lost << " packets possibly lost.";
642       }
643 
644       if (new_calc_seq_nb != seq_nb) {
645         LOG(WARNING) << "Sequence number mismatch. "
646                         "Adjusting own time reference point.";
647         iso->sync_info.first_sync_ts = ts - (seq_nb * iso->sdu_itv);
648         new_calc_seq_nb = seq_nb;
649       }
650     }
651     iso->sync_info.seq_nb = new_calc_seq_nb;
652 
653     evt.p_msg = p_msg;
654     evt.cig_id = iso->cig_id;
655     cig_callbacks_->OnCisEvent(kIsoEventCisDataAvailable, &evt);
656   }
657 
GetCisIfKnowniso_impl658   iso_cis* GetCisIfKnown(uint16_t cis_conn_handle) {
659     auto cis_it = conn_hdl_to_cis_map_.find(cis_conn_handle);
660     return (cis_it != conn_hdl_to_cis_map_.end()) ? cis_it->second.get()
661                                                   : nullptr;
662   }
663 
GetBisIfKnowniso_impl664   iso_bis* GetBisIfKnown(uint16_t bis_conn_handle) {
665     auto bis_it = conn_hdl_to_bis_map_.find(bis_conn_handle);
666     return (bis_it != conn_hdl_to_bis_map_.end()) ? bis_it->second.get()
667                                                   : nullptr;
668   }
669 
GetIsoIfKnowniso_impl670   iso_base* GetIsoIfKnown(uint16_t iso_handle) {
671     struct iso_base* iso = GetCisIfKnown(iso_handle);
672     return (iso != nullptr) ? iso : GetBisIfKnown(iso_handle);
673   }
674 
IsCigKnowniso_impl675   bool IsCigKnown(uint8_t cig_id) const {
676     auto const cis_it =
677         std::find_if(conn_hdl_to_cis_map_.cbegin(), conn_hdl_to_cis_map_.cend(),
678                      [&cig_id](auto& kv_pair) {
679                        return (kv_pair.second->cig_id == cig_id);
680                      });
681     return (cis_it != conn_hdl_to_cis_map_.cend());
682   }
683 
IsBigKnowniso_impl684   bool IsBigKnown(uint8_t big_id) const {
685     auto bis_it =
686         std::find_if(conn_hdl_to_bis_map_.cbegin(), conn_hdl_to_bis_map_.cend(),
687                      [&big_id](auto& kv_pair) {
688                        return (kv_pair.second->big_handle == big_id);
689                      });
690     return (bis_it != conn_hdl_to_bis_map_.cend());
691   }
692 
693   std::map<uint16_t, std::unique_ptr<iso_cis>> conn_hdl_to_cis_map_;
694   std::map<uint16_t, std::unique_ptr<iso_bis>> conn_hdl_to_bis_map_;
695 
696   uint16_t iso_credits_;
697   uint16_t iso_buffer_size_;
698   uint32_t last_big_create_req_sdu_itv_;
699 
700   CigCallbacks* cig_callbacks_ = nullptr;
701   BigCallbacks* big_callbacks_ = nullptr;
702 };
703 
704 }  // namespace iso_manager
705 }  // namespace hci
706 }  // namespace bluetooth
707