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 #pragma once
16 #include <lib/fit/function.h>
17 
18 #include <cstddef>
19 #include <cstdint>
20 
21 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/uuid.h"
23 
24 namespace bt {
25 
26 // EIR Data Type, Advertising Data Type (AD Type), OOB Data Type definitions.
27 // TODO(fxbug.dev/337934217): Switch to using the Emboss defined versions
28 // of this enum class
29 // clang-format off
30 enum class DataType : uint8_t {
31   kFlags                        = 0x01,
32   kIncomplete16BitServiceUuids  = 0x02,
33   kComplete16BitServiceUuids    = 0x03,
34   kIncomplete32BitServiceUuids  = 0x04,
35   kComplete32BitServiceUuids    = 0x05,
36   kIncomplete128BitServiceUuids = 0x06,
37   kComplete128BitServiceUuids   = 0x07,
38   kShortenedLocalName           = 0x08,
39   kCompleteLocalName            = 0x09,
40   kTxPowerLevel                 = 0x0A,
41   kClassOfDevice                = 0x0D,
42   kSSPOOBHash                   = 0x0E,
43   kSSPOOBRandomizer             = 0x0F,
44   kServiceData16Bit             = 0x16,
45   kAppearance                   = 0x19,
46   kServiceData32Bit             = 0x20,
47   kServiceData128Bit            = 0x21,
48   kURI                          = 0x24,
49   kResolvableSetIdentifier      = 0x2E,
50   kBroadcastName                = 0x30,
51   kManufacturerSpecificData     = 0xFF,
52   // TODO(armansito): Complete this list.
53 };
54 // clang-format on
55 
56 UUIDElemSize SizeForType(DataType type);
57 
58 using UuidFunction = fit::function<bool(const UUID&)>;
59 
60 // Parses `data` into `data.size()` / `uuid_size` UUIDs, calling `func` with
61 // each parsed UUID. Returns false without further parsing if `uuid_size` does
62 // not evenly divide `data.size()` or `func` returns false for any UUID,
63 // otherwise returns true.
64 bool ParseUuids(const BufferView& data,
65                 UUIDElemSize uuid_size,
66                 UuidFunction func);
67 
68 // Convenience classes for reading and writing the contents
69 // of Advertising Data, Scan Response Data, or Extended Inquiry Response Data
70 // payloads. The format in which data is stored looks like the following:
71 //
72 //    [1-octet LENGTH][1-octet TYPE][LENGTH-1 octets DATA]
73 //
74 // Used for parsing data in TLV-format as described at the beginning of the file
75 // above.
76 class SupplementDataReader {
77  public:
78   // |data| must point to a valid piece of memory for the duration in which this
79   // object is to remain alive.
80   explicit SupplementDataReader(const ByteBuffer& data);
81 
82   // Returns false if the fields of |data| have been formatted incorrectly. For
83   // example, this could happen if the length of an advertising data structure
84   // would exceed the bounds of the buffer.
is_valid()85   inline bool is_valid() const { return is_valid_; }
86 
87   // Returns the data and type fields of the next advertising data structure in
88   // |out_data| and |out_type|. Returns false if there is no more data to read
89   // or if the data is formatted incorrectly.
90   bool GetNextField(DataType* out_type, BufferView* out_data);
91 
92   // Returns true if there is more data to read. Returns false if the end of
93   // data has been reached or if the current segment is malformed in a way that
94   // would exceed the bounds of the data this reader was initialized with.
95   bool HasMoreData() const;
96 
97  private:
98   bool is_valid_;
99   BufferView remaining_;
100 };
101 
102 // Used for writing data in TLV-format as described at the beginning of the file
103 // above.
104 class SupplementDataWriter {
105  public:
106   // |buffer| is the piece of memory on which this SupplementDataWriter should
107   // operate. The buffer must out-live this instance and must point to a valid
108   // piece of memory.
109   explicit SupplementDataWriter(MutableByteBuffer* buffer);
110 
111   // Writes the given piece of type/tag and data into the next available segment
112   // in the underlying buffer. Returns false if there isn't enough space left in
113   // the buffer for writing. Returns true on success.
114   bool WriteField(DataType type, const ByteBuffer& data);
115 
116   // The total number of bytes that have been written into the buffer.
bytes_written()117   size_t bytes_written() const { return bytes_written_; }
118 
119  private:
120   MutableByteBuffer* buffer_;
121   size_t bytes_written_;
122 };
123 
124 }  // namespace bt
125