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

Commit 9e0dea31 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "RootCanal: Add Classic Connection Management commands"

parents 67bba2df 7d9d9e70
Loading
Loading
Loading
Loading
+93 −0
Original line number Diff line number Diff line
@@ -147,12 +147,18 @@ DualModeController::DualModeController(const std::string& properties_filename, u
  SET_HANDLER(OpCode::WRITE_INQUIRY_SCAN_TYPE, HciWriteInquiryScanType);
  SET_HANDLER(OpCode::AUTHENTICATION_REQUESTED, HciAuthenticationRequested);
  SET_HANDLER(OpCode::SET_CONNECTION_ENCRYPTION, HciSetConnectionEncryption);
  SET_HANDLER(OpCode::CHANGE_CONNECTION_LINK_KEY, HciChangeConnectionLinkKey);
  SET_HANDLER(OpCode::WRITE_AUTHENTICATION_ENABLE, HciWriteAuthenticationEnable);
  SET_HANDLER(OpCode::READ_AUTHENTICATION_ENABLE, HciReadAuthenticationEnable);
  SET_HANDLER(OpCode::WRITE_CLASS_OF_DEVICE, HciWriteClassOfDevice);
  SET_HANDLER(OpCode::WRITE_PAGE_TIMEOUT, HciWritePageTimeout);
  SET_HANDLER(OpCode::WRITE_LINK_SUPERVISION_TIMEOUT, HciWriteLinkSupervisionTimeout);
  SET_HANDLER(OpCode::HOLD_MODE, HciHoldMode);
  SET_HANDLER(OpCode::SNIFF_MODE, HciSniffMode);
  SET_HANDLER(OpCode::EXIT_SNIFF_MODE, HciExitSniffMode);
  SET_HANDLER(OpCode::QOS_SETUP, HciQosSetup);
  SET_HANDLER(OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS, HciWriteDefaultLinkPolicySettings);
  SET_HANDLER(OpCode::FLOW_SPECIFICATION, HciFlowSpecification);
  SET_HANDLER(OpCode::WRITE_LINK_POLICY_SETTINGS, HciWriteLinkPolicySettings);
  SET_HANDLER(OpCode::CHANGE_CONNECTION_PACKET_TYPE, HciChangeConnectionPacketType);
  SET_HANDLER(OpCode::WRITE_LOCAL_NAME, HciWriteLocalName);
@@ -567,6 +573,17 @@ void DualModeController::HciSetConnectionEncryption(packets::PacketView<true> ar
  SendCommandStatus(status, OpCode::SET_CONNECTION_ENCRYPTION);
}

void DualModeController::HciChangeConnectionLinkKey(
    packets::PacketView<true> args) {
  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
  auto args_itr = args.begin();
  uint16_t handle = args_itr.extract<uint16_t>();

  hci::Status status = link_layer_controller_.ChangeConnectionLinkKey(handle);

  SendCommandStatus(status, OpCode::CHANGE_CONNECTION_LINK_KEY);
}

void DualModeController::HciWriteAuthenticationEnable(packets::PacketView<true> args) {
  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
  properties_.SetAuthenticationEnable(args[0]);
@@ -592,11 +609,87 @@ void DualModeController::HciWritePageTimeout(packets::PacketView<true> args) {
  SendCommandCompleteSuccess(OpCode::WRITE_PAGE_TIMEOUT);
}

void DualModeController::HciHoldMode(packets::PacketView<true> args) {
  CHECK(args.size() == 6) << __func__ << " size=" << args.size();
  auto args_itr = args.begin();
  uint16_t handle = args_itr.extract<uint16_t>();
  uint16_t hold_mode_max_interval = args_itr.extract<uint16_t>();
  uint16_t hold_mode_min_interval = args_itr.extract<uint16_t>();

  hci::Status status = link_layer_controller_.HoldMode(
      handle, hold_mode_max_interval, hold_mode_min_interval);

  SendCommandStatus(status, OpCode::HOLD_MODE);
}

void DualModeController::HciSniffMode(packets::PacketView<true> args) {
  CHECK(args.size() == 10) << __func__ << " size=" << args.size();
  auto args_itr = args.begin();
  uint16_t handle = args_itr.extract<uint16_t>();
  uint16_t sniff_max_interval = args_itr.extract<uint16_t>();
  uint16_t sniff_min_interval = args_itr.extract<uint16_t>();
  uint16_t sniff_attempt = args_itr.extract<uint16_t>();
  uint16_t sniff_timeout = args_itr.extract<uint16_t>();

  hci::Status status = link_layer_controller_.SniffMode(
      handle, sniff_max_interval, sniff_min_interval, sniff_attempt,
      sniff_timeout);

  SendCommandStatus(status, OpCode::SNIFF_MODE);
}

void DualModeController::HciExitSniffMode(packets::PacketView<true> args) {
  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
  auto args_itr = args.begin();
  uint16_t handle = args_itr.extract<uint16_t>();

  hci::Status status = link_layer_controller_.ExitSniffMode(handle);

  SendCommandStatus(status, OpCode::EXIT_SNIFF_MODE);
}

void DualModeController::HciQosSetup(packets::PacketView<true> args) {
  CHECK(args.size() == 20) << __func__ << " size=" << args.size();
  auto args_itr = args.begin();
  uint16_t handle = args_itr.extract<uint16_t>();
  args_itr.extract<uint8_t>();  // unused
  uint8_t service_type = args_itr.extract<uint8_t>();
  uint32_t token_rate = args_itr.extract<uint32_t>();
  uint32_t peak_bandwidth = args_itr.extract<uint32_t>();
  uint32_t latency = args_itr.extract<uint32_t>();
  uint32_t delay_variation = args_itr.extract<uint32_t>();

  hci::Status status =
      link_layer_controller_.QosSetup(handle, service_type, token_rate,
                                      peak_bandwidth, latency, delay_variation);

  SendCommandStatus(status, OpCode::QOS_SETUP);
}

void DualModeController::HciWriteDefaultLinkPolicySettings(packets::PacketView<true> args) {
  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
  SendCommandCompleteSuccess(OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS);
}

void DualModeController::HciFlowSpecification(packets::PacketView<true> args) {
  CHECK(args.size() == 21) << __func__ << " size=" << args.size();
  auto args_itr = args.begin();
  uint16_t handle = args_itr.extract<uint16_t>();
  args_itr.extract<uint8_t>();  // unused
  uint8_t flow_direction = args_itr.extract<uint8_t>();
  uint8_t service_type = args_itr.extract<uint8_t>();
  uint32_t token_rate = args_itr.extract<uint32_t>();
  uint32_t token_bucket_size = args_itr.extract<uint32_t>();
  uint32_t peak_bandwidth = args_itr.extract<uint32_t>();
  uint32_t access_latency = args_itr.extract<uint32_t>();

  hci::Status status = link_layer_controller_.FlowSpecification(
      handle, flow_direction, service_type, token_rate, token_bucket_size,
      peak_bandwidth, access_latency);

  SendCommandStatus(status, OpCode::FLOW_SPECIFICATION);
}

void DualModeController::HciWriteLinkPolicySettings(packets::PacketView<true> args) {
  CHECK(args.size() == 4) << __func__ << " size=" << args.size();

+18 −0
Original line number Diff line number Diff line
@@ -124,6 +124,9 @@ class DualModeController : public Device {
  // 7.1.16
  void HciSetConnectionEncryption(packets::PacketView<true> args);

  // 7.1.17
  void HciChangeConnectionLinkKey(packets::PacketView<true> args);

  // 7.1.19
  void HciRemoteNameRequest(packets::PacketView<true> args);

@@ -166,12 +169,27 @@ class DualModeController : public Device {
  // Link Policy Commands
  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.2

  // 7.2.1
  void HciHoldMode(packets::PacketView<true> args);

  // 7.2.2
  void HciSniffMode(packets::PacketView<true> args);

  // 7.2.3
  void HciExitSniffMode(packets::PacketView<true> args);

  // 7.2.6
  void HciQosSetup(packets::PacketView<true> args);

  // 7.2.10
  void HciWriteLinkPolicySettings(packets::PacketView<true> args);

  // 7.2.12
  void HciWriteDefaultLinkPolicySettings(packets::PacketView<true> args);

  // 7.2.13
  void HciFlowSpecification(packets::PacketView<true> args);

  // 7.2.14
  void HciSniffSubrating(packets::PacketView<true> args);

+90 −2
Original line number Diff line number Diff line
@@ -960,7 +960,8 @@ void LinkLayerController::HandleSetConnectionEncryption(const Address& peer, uin

hci::Status LinkLayerController::SetConnectionEncryption(uint16_t handle, uint8_t encryption_enable) {
  if (!connections_.HasHandle(handle)) {
    LOG_INFO(LOG_TAG, "Authentication Requested for unknown handle %04x", handle);
    LOG_INFO(LOG_TAG, "Set Connection Encryption for unknown handle %04x",
             handle);
    return hci::Status::UNKNOWN_CONNECTION;
  }

@@ -969,10 +970,13 @@ hci::Status LinkLayerController::SetConnectionEncryption(uint16_t handle, uint8_
  }
  Address remote = connections_.GetAddress(handle);

  if (security_manager_.ReadKey(remote) == 0) {
    return hci::Status::PIN_OR_KEY_MISSING;
  }

  ScheduleTask(milliseconds(5), [this, remote, handle, encryption_enable]() {
    HandleSetConnectionEncryption(remote, handle, encryption_enable);
  });

  return hci::Status::SUCCESS;
}

@@ -1090,6 +1094,74 @@ hci::Status LinkLayerController::ChangeConnectionPacketType(uint16_t handle, uin
  return hci::Status::SUCCESS;
}

hci::Status LinkLayerController::ChangeConnectionLinkKey(uint16_t handle) {
  if (!connections_.HasHandle(handle)) {
    return hci::Status::UNKNOWN_CONNECTION;
  }

  // TODO: implement real logic
  return hci::Status::COMMAND_DISALLOWED;
}

hci::Status LinkLayerController::HoldMode(uint16_t handle,
                                          uint16_t hold_mode_max_interval,
                                          uint16_t hold_mode_min_interval) {
  if (!connections_.HasHandle(handle)) {
    return hci::Status::UNKNOWN_CONNECTION;
  }

  if (hold_mode_max_interval < hold_mode_min_interval) {
    return hci::Status::INVALID_HCI_COMMAND_PARAMETERS;
  }

  // TODO: implement real logic
  return hci::Status::COMMAND_DISALLOWED;
}

hci::Status LinkLayerController::SniffMode(uint16_t handle,
                                           uint16_t sniff_max_interval,
                                           uint16_t sniff_min_interval,
                                           uint16_t sniff_attempt,
                                           uint16_t sniff_timeout) {
  if (!connections_.HasHandle(handle)) {
    return hci::Status::UNKNOWN_CONNECTION;
  }

  if (sniff_max_interval < sniff_min_interval || sniff_attempt < 0x0001 ||
      sniff_attempt > 0x7FFF || sniff_timeout > 0x7FFF) {
    return hci::Status::INVALID_HCI_COMMAND_PARAMETERS;
  }

  // TODO: implement real logic
  return hci::Status::COMMAND_DISALLOWED;
}

hci::Status LinkLayerController::ExitSniffMode(uint16_t handle) {
  if (!connections_.HasHandle(handle)) {
    return hci::Status::UNKNOWN_CONNECTION;
  }

  // TODO: implement real logic
  return hci::Status::COMMAND_DISALLOWED;
}

hci::Status LinkLayerController::QosSetup(uint16_t handle, uint8_t service_type,
                                          uint32_t /* token_rate */,
                                          uint32_t /* peak_bandwidth */,
                                          uint32_t /* latency */,
                                          uint32_t /* delay_variation */) {
  if (!connections_.HasHandle(handle)) {
    return hci::Status::UNKNOWN_CONNECTION;
  }

  if (service_type > 0x02) {
    return hci::Status::INVALID_HCI_COMMAND_PARAMETERS;
  }

  // TODO: implement real logic
  return hci::Status::COMMAND_DISALLOWED;
}

hci::Status LinkLayerController::WriteLinkPolicySettings(uint16_t handle, uint16_t) {
  if (!connections_.HasHandle(handle)) {
    return hci::Status::UNKNOWN_CONNECTION;
@@ -1097,6 +1169,22 @@ hci::Status LinkLayerController::WriteLinkPolicySettings(uint16_t handle, uint16
  return hci::Status::SUCCESS;
}

hci::Status LinkLayerController::FlowSpecification(
    uint16_t handle, uint8_t flow_direction, uint8_t service_type,
    uint32_t /* token_rate */, uint32_t /* token_bucket_size */,
    uint32_t /* peak_bandwidth */, uint32_t /* access_latency */) {
  if (!connections_.HasHandle(handle)) {
    return hci::Status::UNKNOWN_CONNECTION;
  }

  if (flow_direction > 0x01 || service_type > 0x02) {
    return hci::Status::INVALID_HCI_COMMAND_PARAMETERS;
  }

  // TODO: implement real logic
  return hci::Status::COMMAND_DISALLOWED;
}

hci::Status LinkLayerController::WriteLinkSupervisionTimeout(uint16_t handle, uint16_t) {
  if (!connections_.HasHandle(handle)) {
    return hci::Status::UNKNOWN_CONNECTION;
+15 −0
Original line number Diff line number Diff line
@@ -191,7 +191,22 @@ class LinkLayerController {
  void SetPageScanEnable(bool enable);

  hci::Status ChangeConnectionPacketType(uint16_t handle, uint16_t types);
  hci::Status ChangeConnectionLinkKey(uint16_t handle);
  hci::Status HoldMode(uint16_t handle, uint16_t hold_mode_max_interval,
                       uint16_t hold_mode_min_interval);
  hci::Status SniffMode(uint16_t handle, uint16_t sniff_max_interval,
                        uint16_t sniff_min_interval, uint16_t sniff_attempt,
                        uint16_t sniff_timeout);
  hci::Status ExitSniffMode(uint16_t handle);
  hci::Status QosSetup(uint16_t handle, uint8_t service_type,
                       uint32_t token_rate, uint32_t peak_bandwidth,
                       uint32_t latency, uint32_t delay_variation);
  hci::Status WriteLinkPolicySettings(uint16_t handle, uint16_t settings);
  hci::Status FlowSpecification(uint16_t handle, uint8_t flow_direction,
                                uint8_t service_type, uint32_t token_rate,
                                uint32_t token_bucket_size,
                                uint32_t peak_bandwidth,
                                uint32_t access_latency);
  hci::Status WriteLinkSupervisionTimeout(uint16_t handle, uint16_t timeout);

 protected: