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