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 #include "pw_bluetooth_sapphire/internal/host/hci/advertising_report_parser.h" 16 17 #include "pw_bluetooth_sapphire/internal/host/common/assert.h" 18 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h" 19 20 namespace bt::hci { 21 AdvertisingReportParser(const EventPacket & event)22AdvertisingReportParser::AdvertisingReportParser(const EventPacket& event) 23 : encountered_error_(false) { 24 BT_DEBUG_ASSERT(event.event_code() == hci_spec::kLEMetaEventCode); 25 26 const auto& params = event.params<hci_spec::LEMetaEventParams>(); 27 BT_DEBUG_ASSERT(params.subevent_code == 28 hci_spec::kLEAdvertisingReportSubeventCode); 29 30 static const size_t report_packet_header_size = 31 sizeof(hci_spec::LEMetaEventParams) + 32 sizeof(hci_spec::LEAdvertisingReportSubeventParams); 33 34 BT_DEBUG_ASSERT(event.view().payload_size() <= UINT8_MAX); 35 BT_DEBUG_ASSERT(event.view().payload_size() >= report_packet_header_size); 36 37 auto subevent_params = 38 event.subevent_params<hci_spec::LEAdvertisingReportSubeventParams>(); 39 40 remaining_reports_ = subevent_params->num_reports; 41 42 remaining_bytes_ = event.view().payload_size() - report_packet_header_size; 43 ptr_ = subevent_params->reports; 44 } 45 GetNextReport(const hci_spec::LEAdvertisingReportData ** out_data,int8_t * out_rssi)46bool AdvertisingReportParser::GetNextReport( 47 const hci_spec::LEAdvertisingReportData** out_data, int8_t* out_rssi) { 48 BT_DEBUG_ASSERT(out_data); 49 BT_DEBUG_ASSERT(out_rssi); 50 51 if (encountered_error_ || !HasMoreReports()) 52 return false; 53 54 const hci_spec::LEAdvertisingReportData* data = 55 reinterpret_cast<const hci_spec::LEAdvertisingReportData*>(ptr_); 56 57 // Each report contains the all the report data, followed by the advertising 58 // payload, followed by a single octet for the RSSI. 59 size_t report_size = sizeof(*data) + data->length_data + 1; 60 if (report_size > remaining_bytes_) { 61 // Report exceeds the bounds of the packet. 62 encountered_error_ = true; 63 return false; 64 } 65 66 remaining_bytes_ -= report_size; 67 remaining_reports_--; 68 ptr_ += report_size; 69 70 *out_data = data; 71 *out_rssi = *(ptr_ - 1); 72 73 return true; 74 } 75 HasMoreReports()76bool AdvertisingReportParser::HasMoreReports() { 77 if (encountered_error_) 78 return false; 79 80 if (!!remaining_reports_ != !!remaining_bytes_) { 81 // There should be no bytes remaining if there are no reports left to parse. 82 encountered_error_ = true; 83 return false; 84 } 85 return !!remaining_reports_; 86 } 87 88 } // namespace bt::hci 89