1 // Copyright 2023 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 #include "pw_bluetooth_sapphire/internal/host/transport/sco_data_packet.h" 16 17 #include <endian.h> 18 19 #include "pw_bluetooth_sapphire/internal/host/common/log.h" 20 #include "pw_bluetooth_sapphire/internal/host/transport/slab_allocators.h" 21 22 namespace bt::hci { 23 // Type containing both a fixed packet storage buffer and a ScoDataPacket 24 // interface to the buffer. 25 using MaxScoDataPacket = 26 allocators::internal::FixedSizePacket<hci_spec::SynchronousDataHeader, 27 allocators::kMaxScoDataPacketSize>; 28 New(uint8_t payload_size)29std::unique_ptr<ScoDataPacket> ScoDataPacket::New(uint8_t payload_size) { 30 return std::make_unique<MaxScoDataPacket>(payload_size); 31 } 32 New(hci_spec::ConnectionHandle connection_handle,uint8_t payload_size)33std::unique_ptr<ScoDataPacket> ScoDataPacket::New( 34 hci_spec::ConnectionHandle connection_handle, uint8_t payload_size) { 35 std::unique_ptr<ScoDataPacket> packet = ScoDataPacket::New(payload_size); 36 packet->WriteHeader(connection_handle); 37 return packet; 38 } 39 connection_handle() const40hci_spec::ConnectionHandle ScoDataPacket::connection_handle() const { 41 // Return the lower 12-bits of the first two octets. 42 return le16toh(view().header().handle_and_flags) & 0x0FFF; 43 } packet_status_flag() const44hci_spec::SynchronousDataPacketStatusFlag ScoDataPacket::packet_status_flag() 45 const { 46 // Return bits 4-5 in the higher octet of |handle_and_flags|, i.e. 47 // 0b00xx000000000000. 48 return static_cast<hci_spec::SynchronousDataPacketStatusFlag>( 49 (le16toh(view().header().handle_and_flags) >> 12) & 0x0003); 50 } 51 InitializeFromBuffer()52void ScoDataPacket::InitializeFromBuffer() { 53 mutable_view()->Resize( 54 /*payload_size=*/le16toh(view().header().data_total_length)); 55 } 56 WriteHeader(hci_spec::ConnectionHandle connection_handle)57void ScoDataPacket::WriteHeader(hci_spec::ConnectionHandle connection_handle) { 58 // Handle must fit inside 12-bits. 59 BT_ASSERT(connection_handle <= 0x0FFF); 60 // This sets the Packet Status Flag (upper bits of handle_and_flags) to 0, 61 // which is required for Host->Controller SCO packets. 62 mutable_view()->mutable_header()->handle_and_flags = 63 htole16(connection_handle); 64 mutable_view()->mutable_header()->data_total_length = 65 static_cast<uint8_t>(view().payload_size()); 66 } 67 68 } // namespace bt::hci 69