• 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 #pragma once
16 #include <cpp-string/string_printf.h>
17 
18 #include <cstdint>
19 #include <string>
20 
21 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
23 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
24 
25 namespace bt::hci_spec {
26 
27 // Remote devices and local controllers have a feature set defined by the
28 // Link Manager Protocol.
29 // LMP features are organized into "pages", each containing a bit-mask of
30 // supported controller features. See Core Spec v5.0, Vol 2, Part C, Section 3.3
31 // "Feature Mask Definition".
32 // Three of these pages (the standard page plus two "extended feature" pages)
33 // are defined by the spec.
34 
35 // See LMPFeature in hci_constants.h for the list of feature bits.
36 class LMPFeatureSet {
37  public:
38   // Creates a feature set with no pages set.
LMPFeatureSet()39   LMPFeatureSet() : valid_pages_{false}, last_page_number_(0) {}
40 
41   // The maximum extended page that we support
42   constexpr static uint8_t kMaxLastPageNumber = 2;
43   constexpr static uint8_t kMaxPages = kMaxLastPageNumber + 1;
44 
45   // Returns true if |bit| is set in the LMP Features.
46   // |page| is the page that this bit resides on.
47   // Page 0 is the standard features.
HasBit(size_t page,LMPFeature bit)48   inline bool HasBit(size_t page, LMPFeature bit) const {
49     return HasPage(page) && (features_[page] & static_cast<uint64_t>(bit));
50   }
51 
52   // Sets |page| features to |features|
SetPage(size_t page,uint64_t features)53   inline void SetPage(size_t page, uint64_t features) {
54     BT_ASSERT(page < kMaxPages);
55     features_[page] = features;
56     valid_pages_[page] = true;
57   }
58 
59   // Returns true if the feature page |page| has been set.
HasPage(size_t page)60   inline bool HasPage(size_t page) const {
61     return (page < kMaxPages) && valid_pages_[page];
62   }
63 
ToString()64   inline std::string ToString() const {
65     std::string str;
66     for (size_t i = 0; i <= last_page_number_; i++)
67       if (HasPage(i))
68         str += bt_lib_cpp_string::StringPrintf(
69             "[P%zu: 0x%016lx]", i, features_[i]);
70     return str;
71   }
72 
set_last_page_number(uint8_t page)73   inline void set_last_page_number(uint8_t page) {
74     if (page > kMaxLastPageNumber) {
75       bt_log(TRACE,
76              "hci",
77              "attempt to set lmp last page number to %u, capping at %u",
78              page,
79              kMaxLastPageNumber);
80       last_page_number_ = kMaxLastPageNumber;
81     } else {
82       last_page_number_ = page;
83     }
84   }
85 
last_page_number()86   inline uint8_t last_page_number() const { return last_page_number_; }
87 
88  private:
89   uint64_t features_[kMaxPages];
90   bool valid_pages_[kMaxPages];
91   uint8_t last_page_number_;
92 };
93 
94 }  // namespace bt::hci_spec
95