xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/gap/android_vendor_capabilities.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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/gap/android_vendor_capabilities.h"
16 
17 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
18 
19 namespace bt::gap {
20 
21 namespace android_emb = pw::bluetooth::vendor::android_hci;
22 
23 namespace {
AsBool(const android_emb::Capability & capability)24 bool AsBool(const android_emb::Capability& capability) {
25   return capability == android_emb::Capability::CAPABLE;
26 }
27 }  // namespace
28 
SupportsVersion(uint8_t major,uint8_t minor) const29 bool AndroidVendorCapabilities::SupportsVersion(uint8_t major,
30                                                 uint8_t minor) const {
31   if (version_major_ > major) {
32     return true;
33   }
34 
35   if (version_major_ == major && version_minor_ >= minor) {
36     return true;
37   }
38 
39   return false;
40 }
41 
New(const android_emb::LEGetVendorCapabilitiesCommandCompleteEventView & e)42 AndroidVendorCapabilities AndroidVendorCapabilities::New(
43     const android_emb::LEGetVendorCapabilitiesCommandCompleteEventView& e) {
44   AndroidVendorCapabilities c;
45 
46   if (e.status().Read() != pw::bluetooth::emboss::StatusCode::SUCCESS) {
47     bt_log(INFO,
48            "android_vendor_extensions",
49            "refusing to parse non-success vendor capabilities");
50     return c;
51   }
52 
53   // Version 0.55
54   c.max_simultaneous_advertisement_ = e.max_advt_instances().Read();
55   c.supports_offloaded_rpa_ =
56       AsBool(e.offloaded_resolution_of_private_address().Read());
57   c.scan_results_storage_bytes_ = e.total_scan_results_storage().Read();
58   c.irk_list_size_ = e.max_irk_list_sz().Read();
59   c.supports_filtering_ = AsBool(e.filtering_support().Read());
60   c.max_filters_ = e.max_filter().Read();
61   c.supports_activity_energy_info_ =
62       AsBool(e.activity_energy_info_support().Read());
63 
64   // There can be various versions of this command complete event sent by the
65   // Controller. As fields are added, the version_supported field is incremented
66   // to signify which fields are available. However, version_supported was only
67   // introduced into the command in Version 0.95. Controllers that use the base
68   // version, Version 0.55, don't have the version_supported field. As such, we
69   // must jump through some hoops to figure out which version we received,
70   // exactly.
71   //
72   // NOTE: Android's definition for this command complete event is available in
73   // AOSP: LeGetVendorCapabilitiesComplete and friends
74   // https://cs.android.com/android/platform/superproject/+/main:packages/modules/Bluetooth/system/gd/hci/hci_packets.pdl
75   //
76   // NOTE: An example implementation of how this command is filled in by a
77   // Controller is available within AOSP:
78   // le_get_vendor_capabilities_handler(...)
79   // https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Bluetooth/system/gd/hci/controller.cc
80   if (e.version_supported().major_number().IsComplete()) {
81     c.version_major_ = e.version_supported().major_number().Read();
82   }
83 
84   if (e.version_supported().minor_number().IsComplete()) {
85     c.version_minor_ = e.version_supported().minor_number().Read();
86   }
87 
88   // If we didn't receive a version number from the Controller, assume it's the
89   // base version, Version 0.55.
90   if (c.version_major_ == 0 && c.version_minor_ == 0) {
91     c.version_minor_ = 55;
92   }
93 
94   // Version 0.95
95   if (c.SupportsVersion(0, 95)) {
96     c.max_advertisers_tracked_ = e.total_num_of_advt_tracked().Read();
97     c.supports_extended_scan_ = AsBool(e.extended_scan_support().Read());
98     c.supports_debug_logging_ = AsBool(e.debug_logging_supported().Read());
99   }
100 
101   // Version 0.96
102   if (c.SupportsVersion(0, 96)) {
103     c.supports_offloading_le_address_generation_ =
104         AsBool(e.le_address_generation_offloading_support().Read());
105   }
106 
107   // Version 0.98
108   if (c.SupportsVersion(0, 98)) {
109     c.a2dp_source_offload_capability_mask_ =
110         e.a2dp_source_offload_capability_mask().BackingStorage().ReadUInt();
111     c.supports_bluetooth_quality_report_ =
112         AsBool(e.bluetooth_quality_report_support().Read());
113   }
114 
115   // Version 1.03
116   if (c.SupportsVersion(1, 03)) {
117     c.supports_dynamic_audio_buffer_ =
118         e.dynamic_audio_buffer_support().BackingStorage().ReadUInt();
119   }
120 
121   // Version 1.04
122   if (c.SupportsVersion(1, 04)) {
123     c.a2dp_offload_v2_support_ = AsBool(e.a2dp_offload_v2_support().Read());
124   }
125 
126   return c;
127 }
128 
129 }  // namespace bt::gap
130