• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   kSolicitationUuid16Bit        = 0x14,
45   kSolicitationUuid128Bit       = 0x15,
46   kServiceData16Bit             = 0x16,
47   kAppearance                   = 0x19,
48   kSolicitationUuid32Bit        = 0x1F,
49   kServiceData32Bit             = 0x20,
50   kServiceData128Bit            = 0x21,
51   kURI                          = 0x24,
52   kResolvableSetIdentifier      = 0x2E,
53   kBroadcastName                = 0x30,
54   kManufacturerSpecificData     = 0xFF,
55   // TODO(armansito): Complete this list.
56 };
57 // clang-format on
58 
59 UUIDElemSize SizeForType(DataType type);
60 
61 using UuidFunction = fit::function<bool(const UUID&)>;
62 
63 // Parses `data` into `data.size()` / `uuid_size` UUIDs, calling `func` with
64 // each parsed UUID. Returns false without further parsing if `uuid_size` does
65 // not evenly divide `data.size()` or `func` returns false for any UUID,
66 // otherwise returns true.
67 bool ParseUuids(const BufferView& data,
68                 UUIDElemSize uuid_size,
69                 UuidFunction func);
70 
71 // Convenience classes for reading and writing the contents
72 // of Advertising Data, Scan Response Data, or Extended Inquiry Response Data
73 // payloads. The format in which data is stored looks like the following:
74 //
75 //    [1-octet LENGTH][1-octet TYPE][LENGTH-1 octets DATA]
76 //
77 // Used for parsing data in TLV-format as described at the beginning of the file
78 // above.
79 class SupplementDataReader {
80  public:
81   // |data| must point to a valid piece of memory for the duration in which this
82   // object is to remain alive.
83   explicit SupplementDataReader(const ByteBuffer& data);
84 
85   // Returns false if the fields of |data| have been formatted incorrectly. For
86   // example, this could happen if the length of an advertising data structure
87   // would exceed the bounds of the buffer.
is_valid()88   inline bool is_valid() const { return is_valid_; }
89 
90   // Returns the data and type fields of the next advertising data structure in
91   // |out_data| and |out_type|. Returns false if there is no more data to read
92   // or if the data is formatted incorrectly.
93   bool GetNextField(DataType* out_type, BufferView* out_data);
94 
95   // Returns true if there is more data to read. Returns false if the end of
96   // data has been reached or if the current segment is malformed in a way that
97   // would exceed the bounds of the data this reader was initialized with.
98   bool HasMoreData() const;
99 
100  private:
101   bool is_valid_;
102   BufferView remaining_;
103 };
104 
105 // Used for writing data in TLV-format as described at the beginning of the file
106 // above.
107 class SupplementDataWriter {
108  public:
109   // |buffer| is the piece of memory on which this SupplementDataWriter should
110   // operate. The buffer must out-live this instance and must point to a valid
111   // piece of memory.
112   explicit SupplementDataWriter(MutableByteBuffer* buffer);
113 
114   // Writes the given piece of type/tag and data into the next available segment
115   // in the underlying buffer. Returns false if there isn't enough space left in
116   // the buffer for writing. Returns true on success.
117   bool WriteField(DataType type, const ByteBuffer& data);
118 
119   // The total number of bytes that have been written into the buffer.
bytes_written()120   size_t bytes_written() const { return bytes_written_; }
121 
122  private:
123   MutableByteBuffer* buffer_;
124   size_t bytes_written_;
125 };
126 
127 }  // namespace bt
128