Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ec77bca authored by Henri Chataing's avatar Henri Chataing
Browse files

Root-Canal: Add PDL definition of LL feature bits

The LE local supported features mask was previously defined
as an hexadecimal value, making it complex to read and edit.

Define an enum with LL feature bit values, and initialize the
le_supported_features_ field in DeviceProperties using
an explicit feature list.

Bug: 228326164
Test: VCS PTS tests against Eiffel
Change-Id: I2bbc1b6ac4f6f825437ad889ba910192e6a2d7d8
parent 18bc98f4
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -2994,6 +2994,58 @@ test LeReadBufferSizeV1Complete {
  "\x0e\x07\x01\x02\x20\x00\xfb\x00\x10",
}

enum LLFeaturesBits : 64 {
  // Byte 0
  LE_ENCRYPTION                                 = 0x0000000000000001,
  CONNECTION_PARAMETERS_REQUEST_PROCEDURE       = 0x0000000000000002,
  EXTENDED_REJECT_INDICATION                    = 0x0000000000000004,
  PERIPHERAL_INITIATED_FEATURES_EXCHANGE        = 0x0000000000000008,
  LE_PING                                       = 0x0000000000000010,
  LE_DATA_PACKET_LENGTH_EXTENSION               = 0x0000000000000020,
  LL_PRIVACY                                    = 0x0000000000000040,
  EXTENDED_SCANNER_FILTER_POLICIES              = 0x0000000000000080,

  // Byte 1
  LE_2M_PHY                                     = 0x0000000000000100,
  STABLE_MODULATION_INDEX_TRANSMITTER           = 0x0000000000000200,
  STABLE_MODULATION_INDEX_RECEIVER              = 0x0000000000000400,
  LE_CODED_PHY                                  = 0x0000000000000800,
  LE_EXTENDED_ADVERTISING                       = 0x0000000000001000,
  LE_PERIODIC_ADVERTISING                       = 0x0000000000002000,
  CHANNEL_SELECTION_ALGORITHM_2                 = 0x0000000000004000,
  LE_POWER_CLASS_1                              = 0x0000000000008000,

  // Byte 2
  MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE     = 0x0000000000010000,
  CONNECTION_CTE_REQUEST                        = 0x0000000000020000,
  CONNECTION_CTE_RESPONSE                       = 0x0000000000040000,
  CONNECTIONLESS_CTE_TRANSMITTER                = 0x0000000000080000,
  CONNECTIONLESS_CTE_RECEIVER                   = 0x0000000000100000,
  ANTENNA_SWITCHING_DURING_CTE_TRANSMISSION     = 0x0000000000200000,
  ANTENNA_SWITCHING_DURING_CTE_RECEPTION        = 0x0000000000400000,
  RECEIVING_CONSTANT_TONE_EXTENSIONS            = 0x0000000000800000,

  // Byte 3
  PERIODIC_ADVERTISING_SYNC_TRANSFER_SENDER     = 0x0000000001000000,
  PERIODIC_ADVERTISING_SYNC_TRANSFER_RECIPIENT  = 0x0000000002000000,
  SLEEP_CLOCK_ACCURACY_UPDATES                  = 0x0000000004000000,
  REMOTE_PUBLIC_KEY_VALIDATION                  = 0x0000000008000000,
  CONNECTED_ISOCHRONOUS_STREAM_CENTRAL          = 0x0000000010000000,
  CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL       = 0x0000000020000000,
  ISOCHRONOUS_BROADCASTER                       = 0x0000000040000000,
  SYNCHRONIZED_RECEIVER                         = 0x0000000080000000,

  // Byte 4
  CONNECTED_ISOCHRONOUS_STREAM_HOST_SUPPORT     = 0x0000000100000000,
  LE_POWER_CONTROL_REQUEST                      = 0x0000000200000000,
  LE_POWER_CONTROL_REQUEST_BIS                  = 0x0000000400000000,
  LE_PATH_LOSS_MONITORING                       = 0x0000000800000000,
  PERIODIC_ADVERTISING_ADI_SUPPORT              = 0x0000001000000000,
  CONNECTION_SUBRATING                          = 0x0000002000000000,
  CONNECTION_SUBRATING_HOST_SUPPORT             = 0x0000004000000000,
  CHANNEL_CLASSIFICATION                        = 0x0000008000000000,
}

packet LeReadLocalSupportedFeatures : Command (op_code = LE_READ_LOCAL_SUPPORTED_FEATURES) {
}

+19 −0
Original line number Diff line number Diff line
@@ -199,6 +199,7 @@ DualModeController::DualModeController(const std::string& properties_filename,
  SET_SUPPORTED(DELETE_STORED_LINK_KEY, DeleteStoredLinkKey);
  SET_SUPPORTED(REMOTE_NAME_REQUEST, RemoteNameRequest);
  SET_SUPPORTED(LE_SET_EVENT_MASK, LeSetEventMask);
  SET_SUPPORTED(LE_SET_HOST_FEATURE, LeSetHostFeature);
  SET_SUPPORTED(LE_READ_BUFFER_SIZE_V1, LeReadBufferSize);
  SET_SUPPORTED(LE_READ_BUFFER_SIZE_V2, LeReadBufferSizeV2);
  SET_SUPPORTED(LE_READ_LOCAL_SUPPORTED_FEATURES, LeReadLocalSupportedFeatures);
@@ -1598,6 +1599,19 @@ void DualModeController::LeSetEventMask(CommandView command) {
      kNumCommandPackets, ErrorCode::SUCCESS));
}

void DualModeController::LeSetHostFeature(CommandView command) {
  auto command_view = gd_hci::LeSetHostFeatureView::Create(command);
  ASSERT(command_view.IsValid());
  // TODO: if the controller has active connections, return COMMAND_DISALLOED
  ErrorCode error_code = properties_.SetLeHostFeature(
                             static_cast<uint8_t>(command_view.GetBitNumber()),
                             static_cast<uint8_t>(command_view.GetBitValue()))
                             ? ErrorCode::SUCCESS
                             : ErrorCode::UNSUPORTED_FEATURE_OR_PARAMETER_VALUE;
  send_event_(bluetooth::hci::LeSetHostFeatureCompleteBuilder::Create(
      kNumCommandPackets, error_code));
}

void DualModeController::LeReadBufferSize(CommandView command) {
  auto command_view = gd_hci::LeReadBufferSizeV1View::Create(command);
  ASSERT(command_view.IsValid());
@@ -1652,6 +1666,11 @@ void DualModeController::LeSetResovalablePrivateAddressTimeout(
void DualModeController::LeReadLocalSupportedFeatures(CommandView command) {
  auto command_view = gd_hci::LeReadLocalSupportedFeaturesView::Create(command);
  ASSERT(command_view.IsValid());
  LOG_INFO(
      "%s | LeReadLocalSupportedFeatures (%016llx)",
      properties_.GetAddress().ToString().c_str(),
      static_cast<unsigned long long>(properties_.GetLeSupportedFeatures()));

  send_event_(
      bluetooth::hci::LeReadLocalSupportedFeaturesCompleteBuilder::Create(
          kNumCommandPackets, ErrorCode::SUCCESS,
+3 −0
Original line number Diff line number Diff line
@@ -586,6 +586,9 @@ class DualModeController : public Device {
  void LeSetupIsoDataPath(CommandView packet_view);
  void LeRemoveIsoDataPath(CommandView packet_view);

  // 7.8.115
  void LeSetHostFeature(CommandView packet_view);

  // Vendor-specific Commands

  void LeVendorSleepMode(CommandView args);
+19 −1
Original line number Diff line number Diff line
@@ -74,7 +74,6 @@ DeviceProperties::DeviceProperties(const std::string& file_name)
  // Use SetSupportedComands() to change what's supported.
  for (int i = 35; i < 64; i++) supported_commands_[i] = 0x00;

  le_supported_features_ = 0x1f;
  le_supported_states_ = 0x3ffffffffff;
  le_vendor_cap_ = {};

@@ -122,4 +121,23 @@ DeviceProperties::DeviceProperties(const std::string& file_name)
               &le_resolving_list_ignore_reasons_);
}

bool DeviceProperties::SetLeHostFeature(uint8_t bit_number, uint8_t bit_value) {
  if (bit_number >= 64 || bit_value > 1) return false;

  uint64_t bit_mask = UINT64_C(1) << bit_number;
  if (bit_mask !=
          static_cast<uint64_t>(
              LLFeaturesBits::CONNECTED_ISOCHRONOUS_STREAM_HOST_SUPPORT) &&
      bit_mask != static_cast<uint64_t>(
                      LLFeaturesBits::CONNECTION_SUBRATING_HOST_SUPPORT))
    return false;

  if (bit_value == 0)
    le_supported_features_ &= ~bit_mask;
  else if (bit_value == 1)
    le_supported_features_ |= bit_mask;

  return true;
}

}  // namespace rootcanal
+26 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ namespace rootcanal {
using ::bluetooth::hci::Address;
using ::bluetooth::hci::ClassOfDevice;
using ::bluetooth::hci::EventCode;
using ::bluetooth::hci::LLFeaturesBits;
using ::bluetooth::hci::LMPFeaturesPage0Bits;
using ::bluetooth::hci::LMPFeaturesPage1Bits;

@@ -102,6 +103,28 @@ static constexpr uint64_t Page1LmpFeatures() {
  return value;
}

static constexpr uint64_t LlFeatures() {
  LLFeaturesBits features[] = {
      LLFeaturesBits::LE_ENCRYPTION,
      LLFeaturesBits::CONNECTION_PARAMETERS_REQUEST_PROCEDURE,
      LLFeaturesBits::EXTENDED_REJECT_INDICATION,
      LLFeaturesBits::PERIPHERAL_INITIATED_FEATURES_EXCHANGE,
      LLFeaturesBits::LE_PING,

      LLFeaturesBits::EXTENDED_SCANNER_FILTER_POLICIES,
      LLFeaturesBits::LE_EXTENDED_ADVERTISING,

      // TODO: breaks AVD boot tests with LE audio
      // LLFeaturesBits::CONNECTED_ISOCHRONOUS_STREAM_CENTRAL,
      // LLFeaturesBits::CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL,
  };

  uint64_t value = 0;
  for (unsigned i = 0; i < sizeof(features) / sizeof(*features); i++)
    value |= static_cast<uint64_t>(features[i]);
  return value;
}

class DeviceProperties {
 public:
  explicit DeviceProperties(const std::string& file_name = "");
@@ -278,6 +301,8 @@ class DeviceProperties {

  void SetEventMask(uint64_t mask) { event_mask_ = mask; }

  bool SetLeHostFeature(uint8_t bit_number, uint8_t bit_value);

  bool IsUnmasked(EventCode event) const {
    uint64_t bit = UINT64_C(1) << (static_cast<uint8_t>(event) - 1);
    return (event_mask_ & bit) != 0;
@@ -445,7 +470,7 @@ class DeviceProperties {
  uint8_t num_le_data_packets_;
  uint8_t le_connect_list_size_;
  uint8_t le_resolving_list_size_;
  uint64_t le_supported_features_{0x075b3fd8fe8ffeff};
  uint64_t le_supported_features_{LlFeatures()};
  int8_t le_advertising_physical_channel_tx_power_{0x00};
  uint64_t le_supported_states_;
  uint64_t le_event_mask_{0x01f};