xref: /aosp_15_r20/external/pigweed/pw_bluetooth_proxy/public/pw_bluetooth_proxy/internal/h4_storage.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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