1 // Copyright 2024 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 #pragma once 16 17 #include <pw_bluetooth/hci_data.emb.h> 18 #include <pw_bluetooth/hci_events.emb.h> 19 #include <pw_function/function.h> 20 21 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h" 22 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h" 23 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h" 24 25 namespace bt::iso { 26 27 // Maximum possible size of an Isochronous data packet. 28 // See Core Spec v5.4, Volume 4, Part E, Section 5.4.5 29 constexpr size_t kMaxIsochronousDataPacketSize = 30 pw::bluetooth::emboss::IsoDataFrameHeader::MaxSizeInBytes() + 31 hci_spec::kMaxIsochronousDataPacketPayloadSize; 32 33 using IsoDataPacket = std::vector<std::byte>; 34 35 // Possible outcomes from an AcceptCis call 36 enum class AcceptCisStatus { 37 // We're now waiting for an incoming CIS request with the specified attributes 38 kSuccess, 39 40 // This connection is not operating as a peripheral 41 kNotPeripheral, 42 43 // A request is already pending for this CIG/CIS combination 44 kAlreadyExists, 45 }; 46 47 // Our internal representation of the parameters returned from the 48 // HCI_LE_CIS_Established event. 49 struct CisEstablishedParameters { 50 struct CisUnidirectionalParams { 51 // The actual transport latency, in microseconds. 52 uint32_t transport_latency; 53 54 // The transmitter PHY. 55 pw::bluetooth::emboss::IsoPhyType phy; 56 57 uint8_t burst_number; 58 59 // The flush timeout, in multiples of the ISO_Interval for the CIS, for each 60 // payload sent. 61 uint8_t flush_timeout; 62 63 // Maximum size, in octets, of the payload. 64 uint16_t max_pdu_size; 65 }; 66 67 // The maximum time, in microseconds, for transmission of PDUs of all CISes in 68 // a CIG event. 69 uint32_t cig_sync_delay; 70 71 // The maximum time, in microseconds, for transmission of PDUs of the 72 // specified CIS in a CIG event. 73 uint32_t cis_sync_delay; 74 75 // Maximum number of subevents in each CIS event. 76 uint8_t max_subevents; 77 78 // The "Iso Interval" is represented in units of 1.25ms. 79 // (Core Spec v5.4, Vol 4, Part E, Sec 7.7.65.25) 80 static constexpr size_t kIsoIntervalToMicroseconds = 1250; 81 82 // The time between two consecutive CIS anchor points. 83 uint16_t iso_interval; 84 85 // Central => Peripheral parameters 86 CisUnidirectionalParams c_to_p_params; 87 88 // Peripheral => Central parameters 89 CisUnidirectionalParams p_to_c_params; 90 }; 91 92 class IsoStream; 93 94 using CisEstablishedCallback = 95 pw::Callback<void(pw::bluetooth::emboss::StatusCode, 96 std::optional<WeakSelf<IsoStream>::WeakPtr>, 97 const std::optional<CisEstablishedParameters>&)>; 98 99 // A convenience class for holding an identifier that uniquely represents a 100 // CIG/CIS combination. 101 class CigCisIdentifier { 102 public: 103 CigCisIdentifier() = delete; CigCisIdentifier(hci_spec::CigIdentifier cig_id,hci_spec::CisIdentifier cis_id)104 CigCisIdentifier(hci_spec::CigIdentifier cig_id, 105 hci_spec::CisIdentifier cis_id) 106 : cig_id_(cig_id), cis_id_(cis_id) {} 107 108 bool operator==(const CigCisIdentifier other) const { 109 return (other.cig_id() == cig_id_) && (other.cis_id() == cis_id()); 110 } 111 cig_id()112 hci_spec::CigIdentifier cig_id() const { return cig_id_; } cis_id()113 hci_spec::CisIdentifier cis_id() const { return cis_id_; } 114 115 private: 116 hci_spec::CigIdentifier cig_id_; 117 hci_spec::CisIdentifier cis_id_; 118 }; 119 120 } // namespace bt::iso 121 122 namespace std { 123 // Implement hash operator for CigCisIdentifier. 124 template <> 125 struct hash<bt::iso::CigCisIdentifier> { 126 public: 127 std::size_t operator()(const bt::iso::CigCisIdentifier& id) const { 128 return ((static_cast<size_t>(id.cig_id()) << 8) | id.cis_id()); 129 } 130 }; 131 132 } // namespace std 133