Pigweed
 
Loading...
Searching...
No Matches
h4_packet.h
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 <cstdint>
18
19#include "lib/stdcompat/utility.h"
20#include "pw_bluetooth/hci_h4.emb.h"
21#include "pw_function/function.h"
22#include "pw_span/span.h"
23
24namespace pw::bluetooth::proxy {
25
32 public:
33 H4PacketInterface() = default;
34
35 H4PacketInterface(const H4PacketInterface& other) = delete;
36
37 H4PacketInterface(H4PacketInterface&& other) = default;
38 H4PacketInterface& operator=(H4PacketInterface&& other) = default;
39
40 virtual ~H4PacketInterface() = default;
41
44 virtual emboss::H4PacketType GetH4Type() = 0;
45
47 virtual void SetH4Type(emboss::H4PacketType) = 0;
48
51 virtual pw::span<uint8_t> GetHciSpan() = 0;
52
53 protected:
54 H4PacketInterface& operator=(const H4PacketInterface& other) = default;
55};
56
58class H4PacketWithHci final : public H4PacketInterface {
59 public:
60 H4PacketWithHci(emboss::H4PacketType h4_type, pw::span<uint8_t> hci_span)
61 : hci_span_(hci_span), h4_type_(h4_type) {}
62
63 H4PacketWithHci(const H4PacketWithHci& other) = delete;
64
65 H4PacketWithHci(H4PacketWithHci&& other) = default;
66 H4PacketWithHci& operator=(H4PacketWithHci&& other) = default;
67
68 ~H4PacketWithHci() final = default;
69
70 emboss::H4PacketType GetH4Type() final { return h4_type_; }
71
72 void SetH4Type(emboss::H4PacketType h4_type) final { h4_type_ = h4_type; }
73
74 pw::span<uint8_t> GetHciSpan() final { return hci_span_; }
75
76 private:
77 H4PacketWithHci& operator=(const H4PacketWithHci& other) = default;
78
79 pw::span<uint8_t> hci_span_;
80
81 emboss::H4PacketType h4_type_;
82};
83
85class H4PacketWithH4 final : public H4PacketInterface {
86 public:
87 H4PacketWithH4() = default;
88 H4PacketWithH4(pw::span<uint8_t> h4_span) : h4_span_(h4_span) {}
89
91 H4PacketWithH4(pw::span<uint8_t> h4_span,
92 pw::Function<void(const uint8_t* buffer)>&& release_fn)
93 : h4_span_(h4_span), release_fn_(std::move(release_fn)) {}
94
95 H4PacketWithH4(emboss::H4PacketType h4_type, pw::span<uint8_t> h4_span)
96 : H4PacketWithH4(h4_span) {
97 SetH4Type(h4_type);
98 }
99
100 H4PacketWithH4(const H4PacketWithH4& other) = delete;
101 H4PacketWithH4& operator=(const H4PacketWithH4& other) = delete;
102
103 H4PacketWithH4(H4PacketWithH4&& other)
104 : h4_span_(other.h4_span_), release_fn_(std::move(other.release_fn_)) {
105 other.Reset();
106 }
107
108 H4PacketWithH4& operator=(H4PacketWithH4&& other) {
109 h4_span_ = other.h4_span_;
110 release_fn_ = std::move(other.release_fn_);
111 other.Reset();
112 return *this;
113 }
114
115 ~H4PacketWithH4() final {
116 if (release_fn_) {
117 release_fn_(h4_span_.data());
118 }
119 }
120
121 emboss::H4PacketType GetH4Type() final {
122 if (h4_span_.empty()) {
123 return emboss::H4PacketType::UNKNOWN;
124 }
125
126 return emboss::H4PacketType(h4_span_[0]);
127 }
128
129 void SetH4Type(emboss::H4PacketType h4_type) final {
130 if (!h4_span_.empty()) {
131 h4_span_.data()[0] = cpp23::to_underlying(h4_type);
132 }
133 }
134
135 bool HasReleaseFn() {
136 // pw::Function bool returns true if not-empty
137 return bool{release_fn_};
138 }
139
140 // Returns the release function (which could be empty) and resets the packet.
141 // Essentially it moves ownership of the buffer to the caller (who should have
142 // already stored `GetH4Span()` since packet's span will be reset by this
143 // call).
144 pw::Function<void(const uint8_t*)> ResetAndReturnReleaseFn() {
145 pw::Function<void(const uint8_t* packet)> fn = std::move(release_fn_);
146 Reset();
147 return fn;
148 }
149
150 pw::span<uint8_t> GetHciSpan() final {
151 // If h4_span is empty, then return an empty span for hci also.
152 if (h4_span_.empty()) {
153 return {};
154 }
155 return pw::span(h4_span_.data() + 1, h4_span_.size() - 1);
156 }
157
158 pw::span<uint8_t> GetH4Span() {
159 if (h4_span_.empty()) {
160 return {};
161 }
162 return h4_span_;
163 }
164
165 private:
166 void Reset() {
167 h4_span_ = pw::span<uint8_t>();
168 release_fn_ = nullptr;
169 }
170
171 pw::span<uint8_t> h4_span_;
172
173 pw::Function<void(const uint8_t* packet)> release_fn_{};
174};
175
176} // namespace pw::bluetooth::proxy
Definition: h4_packet.h:31
virtual void SetH4Type(emboss::H4PacketType)=0
Sets HCI packet type indicator.
virtual emboss::H4PacketType GetH4Type()=0
virtual pw::span< uint8_t > GetHciSpan()=0
H4PacketWithH4 is an H4Packet backed by an H4 buffer.
Definition: h4_packet.h:85
void SetH4Type(emboss::H4PacketType h4_type) final
Sets HCI packet type indicator.
Definition: h4_packet.h:129
pw::span< uint8_t > GetHciSpan() final
Definition: h4_packet.h:150
H4PacketWithH4(pw::span< uint8_t > h4_span, pw::Function< void(const uint8_t *buffer)> &&release_fn)
release_fn (if callable) will be called when H4PacketWithH4 is destructed.
Definition: h4_packet.h:91
emboss::H4PacketType GetH4Type() final
Definition: h4_packet.h:121
H4PacketWithHci is an H4Packet backed by an HCI buffer.
Definition: h4_packet.h:58
void SetH4Type(emboss::H4PacketType h4_type) final
Sets HCI packet type indicator.
Definition: h4_packet.h:72
emboss::H4PacketType GetH4Type() final
Definition: h4_packet.h:70
pw::span< uint8_t > GetHciSpan() final
Definition: h4_packet.h:74
fit::function_impl< function_internal::config::kInlineCallableSize, !function_internal::config::kEnableDynamicAllocation, FunctionType, PW_FUNCTION_DEFAULT_ALLOCATOR_TYPE > Function
Definition: function.h:74