• 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 #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)22 AdvertisingReportParser::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)46 bool 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()76 bool 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