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 <optional> 18 19 #include "pw_containers/flat_map.h" 20 #include "pw_span/span.h" 21 #include "pw_sync/lock_annotations.h" 22 #include "pw_sync/mutex.h" 23 24 namespace pw::bluetooth::proxy { 25 26 // Contains a configurable array of buffers to hold H4 packets. 27 class H4Storage { 28 public: 29 H4Storage(); 30 31 // Returns a free H4 buffer and marks it as occupied. If all H4 buffers are 32 // occupied, returns std::nullopt. 33 // 34 // TODO: https://pwbug.dev/369849508 - Take a variable size. 35 std::optional<pw::span<uint8_t>> ReserveH4Buff(); 36 37 // Marks an H4 buffer as unoccupied. 38 void ReleaseH4Buff(const uint8_t* buffer); 39 40 // Marks all H4 buffers as unoccupied. 41 void Reset(); 42 43 // Returns the number of slots in `h4_buffs_`. GetNumH4Buffs()44 static constexpr size_t GetNumH4Buffs() { return kNumH4Buffs; } 45 46 // Returns the size of a slot in `h4_buffs_`. GetH4BuffSize()47 static constexpr uint16_t GetH4BuffSize() { return kH4BuffSize; } 48 49 private: 50 // TODO: https://pwbug.dev/353734827 - Allow container to specify constants. 51 // To pass the unit tests, kNumH4Buffs >= L2capCoc::QueueCapacity(). 52 static constexpr size_t kNumH4Buffs = 10; 53 54 // Max LE ACL payload (251 bytes) + ACL header (4 bytes) + H4 type (1 byte). 55 // TODO: https://pwbug.dev/369849508 - Support variable size buffers with 56 // an allocator & replace this constant with total memory pool size. 57 static constexpr uint16_t kH4BuffSize = 256; 58 59 // Returns an initializer list for `h4_buff_occupied_` with each buffer 60 // address in `h4_buffs_` mapped to false. 61 std::array<containers::Pair<uint8_t*, bool>, kNumH4Buffs> InitOccupiedMap(); 62 63 sync::Mutex storage_mutex_; 64 65 // Each buffer is meant to hold one H4 packet containing an ACL PDU. 66 std::array<std::array<uint8_t, kH4BuffSize>, kNumH4Buffs> h4_buffs_ 67 PW_GUARDED_BY(storage_mutex_); 68 69 // Maps each H4 buffer to a flag that is set when the buffer holds an H4 70 // packet being sent through `acl_data_channel_` and cleared in that H4 71 // packet's release function to indicate that the H4 buffer is safe to 72 // overwrite. 73 containers::FlatMap<uint8_t*, bool, kNumH4Buffs> h4_buff_occupied_ 74 PW_GUARDED_BY(storage_mutex_); 75 }; 76 77 } // namespace pw::bluetooth::proxy 78