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