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

Commit 5c1e1a99 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Gd shim updates"

parents 7c5aa34e bad90728
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -28,25 +28,25 @@ namespace bluetooth {
namespace shim {

using ConnectionClosedCallback = std::function<void(uint16_t cid, int error_code)>;
using Postable = std::function<void(std::function<void(uint16_t cid)>)>;
using ConnectionOpenCallback = std::function<void(uint16_t psm, uint16_t cid, Postable postable)>;
using ConnectionOpenCallback = std::function<void(std::string string_address, uint16_t psm, uint16_t cid)>;
using ReadDataReadyCallback = std::function<void(uint16_t cid, std::vector<const uint8_t> data)>;

struct IL2cap {
  virtual void RegisterService(uint16_t psm, ConnectionOpenCallback on_open, std::promise<void> completed) = 0;
  virtual void UnregisterService(uint16_t psm) = 0;

  virtual void CreateConnection(uint16_t psm, const std::string address, std::promise<uint16_t> completed) = 0;
  virtual void CreateConnection(uint16_t psm, const std::string address, ConnectionOpenCallback on_open,
                                std::promise<uint16_t> completed) = 0;
  virtual void CloseConnection(uint16_t cid) = 0;

  virtual void SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) = 0;
  virtual void SetConnectionClosedCallback(uint16_t cid, ConnectionClosedCallback on_closed) = 0;

  virtual bool Write(uint16_t cid, const uint8_t* data, size_t len) = 0;
  virtual bool WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) = 0;
  virtual bool WriteNonFlushable(uint16_t cid, const uint8_t* data, size_t len) = 0;
  virtual void Write(uint16_t cid, const uint8_t* data, size_t len) = 0;
  virtual void WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) = 0;
  virtual void WriteNonFlushable(uint16_t cid, const uint8_t* data, size_t len) = 0;

  virtual bool IsCongested(uint16_t cid) = 0;
  virtual void SendLoopbackResponse(std::function<void()>) = 0;
  virtual ~IL2cap() {}
};

+155 −142
Original line number Diff line number Diff line
@@ -163,28 +163,46 @@ struct ConnectionInterfaceManager {

  bool Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet);

  void SetHandler(os::Handler* handler) {
    handler_ = handler;
  }

  size_t NumberOfActiveConnections() const {
    return cid_to_interface_map_.size();
  }

  ConnectionInterfaceManager();
  void GeneralCallback(ConnectionOpenCallback on_open, hci::Address address, l2cap::Psm psm,
                       ConnectionInterfaceDescriptor cid) {
    on_open(address.ToString(), static_cast<uint16_t>(psm), static_cast<uint16_t>(cid));
  }

  void ConnectionOpened(ConnectionOpenCallback on_open, hci::Address address, l2cap::Psm psm,
                        ConnectionInterfaceDescriptor cid) {
    LOG_DEBUG("%s address:%s psm:%hd cid:%hd", __func__, address.ToString().c_str(), psm, cid);
    handler_->Post(common::BindOnce(&ConnectionInterfaceManager::GeneralCallback, common::Unretained(this), on_open,
                                    address, psm, cid));
    // TODO(cmanton) queue this pending connection address/psm tuple up for deletion
    // There may be multiple, so only remove one
  }

  void ConnectionFailed(hci::Address address, l2cap::Psm psm) {
    LOG_DEBUG("%s Connection Failed", __func__);
    // TODO(cmanton) queue this pending connection address/psm tuple up for deletion
    // There may be multiple, so only remove one
  }

  ConnectionInterfaceManager(os::Handler* handler);

 private:
  std::unordered_map<ConnectionInterfaceDescriptor, std::unique_ptr<ConnectionInterface>> cid_to_interface_map_;
  ConnectionInterfaceDescriptor current_connection_interface_descriptor_;
  os::Handler* handler_;
  ConnectionInterfaceDescriptor current_connection_interface_descriptor_;

  bool HasResources() const;
  bool Exists(ConnectionInterfaceDescriptor id) const;

  std::unordered_map<ConnectionInterfaceDescriptor, std::unique_ptr<ConnectionInterface>> cid_to_interface_map_;
  ConnectionInterfaceDescriptor AllocateConnectionInterfaceDescriptor();
  ConnectionInterfaceManager() = delete;
};

ConnectionInterfaceManager::ConnectionInterfaceManager()
    : current_connection_interface_descriptor_(kStartConnectionInterfaceDescriptor) {}
ConnectionInterfaceManager::ConnectionInterfaceManager(os::Handler* handler)
    : handler_(handler), current_connection_interface_descriptor_(kStartConnectionInterfaceDescriptor) {}

bool ConnectionInterfaceManager::Exists(ConnectionInterfaceDescriptor cid) const {
  return cid_to_interface_map_.find(cid) != cid_to_interface_map_.end();
@@ -242,11 +260,58 @@ bool ConnectionInterfaceManager::Write(ConnectionInterfaceDescriptor cid, std::u
  return true;
}

class PendingConnection {
 public:
  PendingConnection(ConnectionInterfaceManager* connection_interface_manager, l2cap::Psm psm, hci::Address address,
                    ConnectionOpenCallback on_open, std::promise<uint16_t> completed)
      : connection_interface_manager_(connection_interface_manager), psm_(psm), address_(address),
        on_open_(std::move(on_open)), completed_(std::move(completed)) {}

  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
    LOG_DEBUG("Local initiated connection is open to device:%s for psm:%hd", address_.ToString().c_str(), psm_);
    ConnectionInterfaceDescriptor cid = connection_interface_manager_->AddChannel(std::move(channel));
    completed_.set_value(cid);
    // Attempt to avoid async race condition with upper stack
    std::this_thread::yield();
    connection_interface_manager_->ConnectionOpened(std::move(on_open_), address_, psm_, cid);
  }

  void OnConnectionFailure(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
    LOG_DEBUG("Connection failed to device:%s for psm:%hd", address_.ToString().c_str(), psm_);
    switch (result.connection_result_code) {
      case l2cap::classic::DynamicChannelManager::ConnectionResultCode::SUCCESS:
        LOG_WARN("Connection failed result:success hci:%s", hci::ErrorCodeText(result.hci_error).c_str());
        break;
      case l2cap::classic::DynamicChannelManager::ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED:
        LOG_DEBUG("Connection failed result:no service registered hci:%s",
                  hci::ErrorCodeText(result.hci_error).c_str());
        break;
      case l2cap::classic::DynamicChannelManager::ConnectionResultCode::FAIL_HCI_ERROR:
        LOG_DEBUG("Connection failed result:hci error hci:%s", hci::ErrorCodeText(result.hci_error).c_str());
        break;
      case l2cap::classic::DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR:
        LOG_DEBUG("Connection failed result:l2cap error hci:%s l2cap:%s", hci::ErrorCodeText(result.hci_error).c_str(),
                  l2cap::ConnectionResponseResultText(result.l2cap_connection_response_result).c_str());
        break;
    }
    completed_.set_value(kInvalidConnectionInterfaceDescriptor);
    connection_interface_manager_->ConnectionFailed(address_, psm_);
  }

 private:
  ConnectionInterfaceManager* connection_interface_manager_;
  const l2cap::Psm psm_;
  const hci::Address address_;
  ConnectionOpenCallback on_open_;
  std::promise<uint16_t> completed_;
};

class ServiceInterface {
 public:
  ServiceInterface(uint16_t psm, ServiceInterfaceCallback register_callback,
                   ConnectionInterfaceCallback connection_callback)
      : psm_(psm), register_callback_(register_callback), connection_callback_(connection_callback) {}
  ServiceInterface(ConnectionInterfaceManager* connection_interface_manager, l2cap::Psm psm,
                   ConnectionOpenCallback on_open, std::promise<void> completed)
      : connection_interface_manager_(connection_interface_manager), psm_(psm), on_open_(on_open),
        completed_(std::move(completed)) {}

  void OnRegistrationComplete(l2cap::classic::DynamicChannelManager::RegistrationResult result,
                              std::unique_ptr<l2cap::classic::DynamicChannelService> service) {
@@ -254,12 +319,15 @@ class ServiceInterface {
    ASSERT(psm_ == service->GetPsm());
    LOG_DEBUG("Registration is complete for psm:%hd", psm_);
    service_ = std::move(service);
    register_callback_(psm_, result);
    completed_.set_value();
  }

  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
    LOG_DEBUG("Connection is open to device:%s for psm:%hd", channel->GetDevice().ToString().c_str(), psm_);
    connection_callback_(psm_, std::move(channel));
    LOG_DEBUG("Remote initiated connection is open from device:%s for psm:%hd", channel->GetDevice().ToString().c_str(),
              psm_);
    hci::Address address = channel->GetDevice();
    ConnectionInterfaceDescriptor cid = connection_interface_manager_->AddChannel(std::move(channel));
    connection_interface_manager_->ConnectionOpened(on_open_, address, psm_, cid);
  }

  l2cap::SecurityPolicy GetSecurityPolicy() const {
@@ -276,133 +344,59 @@ class ServiceInterface {
  }

 private:
  ConnectionInterfaceManager* connection_interface_manager_;
  const l2cap::Psm psm_;
  ConnectionOpenCallback on_open_;
  std::promise<void> completed_;

  std::unique_ptr<l2cap::classic::DynamicChannelService> service_;

  const l2cap::SecurityPolicy security_policy_;
  ServiceInterfaceCallback register_callback_;
  ConnectionInterfaceCallback connection_callback_;
};

struct L2cap::impl {
  void RegisterService(l2cap::Psm psm, ConnectionOpenCallback on_open, std::promise<void> completed);
  void UnregisterService(l2cap::Psm psm);

  void CreateConnection(l2cap::Psm psm, hci::Address address, std::promise<uint16_t> completed);
  void CreateConnection(l2cap::Psm psm, hci::Address address, ConnectionOpenCallback on_open,
                        std::promise<uint16_t> completed);
  void CloseConnection(ConnectionInterfaceDescriptor cid);

  void OnConnectionOpenNever(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
  void OnConnectionFailureNever(l2cap::classic::DynamicChannelManager::ConnectionResult result);
  void SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid, ReadDataReadyCallback on_data_ready);
  void SetConnectionClosedCallback(ConnectionInterfaceDescriptor cid, ConnectionClosedCallback on_closed);

  bool Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet);
  void Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet);

  impl(L2cap& module, l2cap::classic::L2capClassicModule* l2cap_module);
  ConnectionInterfaceManager connection_interface_manager_;
  void SendLoopbackResponse(std::function<void()> function);

  void OpenConnection(l2cap::Psm psm, ConnectionInterfaceDescriptor cid);
  impl(L2cap& module, l2cap::classic::L2capClassicModule* l2cap_module);

 private:
  L2cap& module_;
  l2cap::classic::L2capClassicModule* l2cap_module_{nullptr};
  l2cap::classic::L2capClassicModule* l2cap_module_;
  os::Handler* handler_;
  ConnectionInterfaceManager connection_interface_manager_;

  std::unique_ptr<l2cap::classic::DynamicChannelManager> dynamic_channel_manager_;

  std::unordered_map<l2cap::Psm, std::shared_ptr<ServiceInterface>> psm_to_service_interface_map_;
  std::unordered_map<l2cap::Psm, ConnectionOpenCallback> psm_to_on_open_map_;

  std::mutex mutex_;
  std::unordered_map<l2cap::Psm, std::promise<void>> psm_to_register_complete_map_;
  std::unordered_map<l2cap::Psm, std::queue<std::promise<uint16_t>>> psm_to_connect_completed_queue_;

  os::Handler* handler_;
  std::unordered_map<l2cap::Psm, std::shared_ptr<PendingConnection>> psm_to_pending_connection_map_;
};

L2cap::impl::impl(L2cap& module, l2cap::classic::L2capClassicModule* l2cap_module)
    : module_(module), l2cap_module_(l2cap_module) {
  handler_ = module_.GetHandler();
    : module_(module), l2cap_module_(l2cap_module), handler_(module_.GetHandler()),
      connection_interface_manager_(handler_) {
  dynamic_channel_manager_ = l2cap_module_->GetDynamicChannelManager();
  connection_interface_manager_.SetHandler(handler_);
}

void L2cap::impl::OnConnectionOpenNever(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
  ASSERT(false);
}

void L2cap::impl::OnConnectionFailureNever(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
  ASSERT(false);
  switch (result.connection_result_code) {
    case l2cap::classic::DynamicChannelManager::ConnectionResultCode::SUCCESS:
      LOG_WARN("Connection failed result:success hci:%s", hci::ErrorCodeText(result.hci_error).c_str());
      break;
    case l2cap::classic::DynamicChannelManager::ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED:
      LOG_DEBUG("Connection failed result:no service registered hci:%s", hci::ErrorCodeText(result.hci_error).c_str());
      break;
    case l2cap::classic::DynamicChannelManager::ConnectionResultCode::FAIL_HCI_ERROR:
      LOG_DEBUG("Connection failed result:hci error hci:%s", hci::ErrorCodeText(result.hci_error).c_str());
      break;
    case l2cap::classic::DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR:
      LOG_DEBUG("Connection failed result:l2cap error hci:%s l2cap:%s", hci::ErrorCodeText(result.hci_error).c_str(),
                l2cap::ConnectionResponseResultText(result.l2cap_connection_response_result).c_str());
      break;
  }
}

void L2cap::impl::OpenConnection(l2cap::Psm psm, ConnectionInterfaceDescriptor cid) {
  LOG_INFO("About to call back to client indicating open connection psm:%hd cid:%hd", psm, cid);
  psm_to_on_open_map_[psm](psm, cid, [cid](std::function<void(uint16_t cid)> func) {
    LOG_DEBUG("About to run postable on this thread and inform sdp that connection is open");
    func(cid);
  });
}

void L2cap::impl::RegisterService(l2cap::Psm psm, ConnectionOpenCallback on_open, std::promise<void> completed) {
  ASSERT(psm_to_service_interface_map_.find(psm) == psm_to_service_interface_map_.end());
  ASSERT(psm_to_register_complete_map_.find(psm) == psm_to_register_complete_map_.end());
  ASSERT(psm_to_on_open_map_.find(psm) == psm_to_on_open_map_.end());

  {
    std::unique_lock<std::mutex> lock(mutex_);
    psm_to_on_open_map_[psm] = on_open;
    psm_to_register_complete_map_[psm] = std::move(completed);
  }

  psm_to_service_interface_map_.emplace(
      psm, std::make_shared<ServiceInterface>(
               psm,
               [this](l2cap::Psm psm, l2cap::classic::DynamicChannelManager::RegistrationResult result) {
                 LOG_DEBUG("Service has been registered");
                 ASSERT(psm_to_register_complete_map_.find(psm) != psm_to_register_complete_map_.end());
                 {
                   std::unique_lock<std::mutex> lock(mutex_);
                   auto completed = std::move(psm_to_register_complete_map_[psm]);
                   psm_to_register_complete_map_.erase(psm);
                   completed.set_value();
                 }
               },

               [this](l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
                 ConnectionInterfaceDescriptor cid = connection_interface_manager_.AddChannel(std::move(channel));
                 LOG_DEBUG("Connection has been opened cid:%hd psm:%hd", cid, psm);
                 {
                   // If initiated locally unblock requestor that
                   // we now have a connection by providing the
                   // cid.
                   std::unique_lock<std::mutex> lock(mutex_);
                   if (psm_to_connect_completed_queue_.find(psm) != psm_to_connect_completed_queue_.end()) {
                     if (!psm_to_connect_completed_queue_[psm].empty()) {
                       LOG_DEBUG("Locally initiated, so inform waiting client of the cid %hd", cid);
                       auto completed = std::move(psm_to_connect_completed_queue_[psm].front());
                       psm_to_connect_completed_queue_[psm].pop();
                       completed.set_value(cid);
                     }
                   }
                   std::this_thread::yield();
                 }
                 if (cid != kInvalidConnectionInterfaceDescriptor) {
                   handler_->Post(common::BindOnce(&L2cap::impl::OpenConnection, common::Unretained(this), psm, cid));
                 }
                 usleep(10);
               }));

  psm_to_service_interface_map_.find(psm)->second->RegisterService(
  auto service_interface =
      std::make_shared<ServiceInterface>(&connection_interface_manager_, psm, on_open, std::move(completed));
  psm_to_service_interface_map_.emplace(psm, service_interface);

  service_interface->RegisterService(
      [this](l2cap::Psm psm, l2cap::SecurityPolicy security_policy,
             l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete,
             l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open) {
@@ -416,24 +410,40 @@ void L2cap::impl::UnregisterService(l2cap::Psm psm) {
  psm_to_service_interface_map_.erase(psm);
}

void L2cap::impl::CreateConnection(l2cap::Psm psm, hci::Address address, std::promise<uint16_t> completed) {
  LOG_INFO("Creating connection to psm:%hd device:%s", psm, address.ToString().c_str());
  {
    std::unique_lock<std::mutex> lock(mutex_);
    psm_to_connect_completed_queue_[psm].push(std::move(completed));
  }
void L2cap::impl::CreateConnection(l2cap::Psm psm, hci::Address address, ConnectionOpenCallback on_open,
                                   std::promise<uint16_t> completed) {
  LOG_DEBUG("Initiating classic connection to psm:%hd device:%s", psm, address.ToString().c_str());
  auto pending_connection = std::make_shared<PendingConnection>(&connection_interface_manager_, psm, address,
                                                                std::move(on_open), std::move(completed));
  // TODO(cmanton) hash psm/address pair into unordered map for pending_connection
  // This is ok for now
  psm_to_pending_connection_map_[psm] = pending_connection;

  bool rc = dynamic_channel_manager_->ConnectChannel(
      address, psm, common::Bind(&L2cap::impl::OnConnectionOpenNever, common::Unretained(this)),
      common::Bind(&L2cap::impl::OnConnectionFailureNever, common::Unretained(this)), handler_);
  ASSERT_LOG(rc == true, "Failed to create classic connection channel");
      address, psm, common::Bind(&PendingConnection::OnConnectionOpen, common::Unretained(pending_connection.get())),
      common::BindOnce(&PendingConnection::OnConnectionFailure, common::Unretained(pending_connection.get())),
      handler_);
  ASSERT_LOG(rc == true, "Failed to create classic connection");
}

void L2cap::impl::CloseConnection(ConnectionInterfaceDescriptor cid) {
  connection_interface_manager_.RemoveConnection(cid);
}

bool L2cap::impl::Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet) {
  return connection_interface_manager_.Write(cid, std::move(packet));
void L2cap::impl::SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid, ReadDataReadyCallback on_data_ready) {
  connection_interface_manager_.SetReadDataReadyCallback(cid, on_data_ready);
}

void L2cap::impl::SetConnectionClosedCallback(ConnectionInterfaceDescriptor cid, ConnectionClosedCallback on_closed) {
  connection_interface_manager_.SetConnectionClosedCallback(cid, std::move(on_closed));
}

void L2cap::impl::Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet) {
  connection_interface_manager_.Write(cid, std::move(packet));
}

void L2cap::impl::SendLoopbackResponse(std::function<void()> function) {
  function();
}

void L2cap::RegisterService(uint16_t raw_psm, ConnectionOpenCallback on_open, std::promise<void> completed) {
@@ -444,51 +454,54 @@ void L2cap::RegisterService(uint16_t raw_psm, ConnectionOpenCallback on_open, st

void L2cap::UnregisterService(uint16_t raw_psm) {
  l2cap::Psm psm{raw_psm};
  pimpl_->UnregisterService(psm);
  GetHandler()->Post(common::Bind(&L2cap::impl::UnregisterService, common::Unretained(pimpl_.get()), psm));
}

void L2cap::CreateConnection(uint16_t raw_psm, const std::string address_string, std::promise<uint16_t> completed) {
void L2cap::CreateConnection(uint16_t raw_psm, const std::string address_string, ConnectionOpenCallback on_open,
                             std::promise<uint16_t> completed) {
  l2cap::Psm psm{raw_psm};
  hci::Address address;
  hci::Address::FromString(address_string, address);

  GetHandler()->Post(common::BindOnce(&L2cap::impl::CreateConnection, common::Unretained(pimpl_.get()), psm, address,
                                      std::move(completed)));
                                      on_open, std::move(completed)));
}

void L2cap::CloseConnection(uint16_t raw_cid) {
  ConnectionInterfaceDescriptor cid(raw_cid);
  return pimpl_->CloseConnection(cid);
  GetHandler()->Post(common::Bind(&L2cap::impl::CloseConnection, common::Unretained(pimpl_.get()), cid));
}

void L2cap::SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) {
  pimpl_->connection_interface_manager_.SetReadDataReadyCallback(static_cast<ConnectionInterfaceDescriptor>(cid),
                                                                 on_data_ready);
void L2cap::SetReadDataReadyCallback(uint16_t raw_cid, ReadDataReadyCallback on_data_ready) {
  ConnectionInterfaceDescriptor cid(raw_cid);
  GetHandler()->Post(
      common::Bind(&L2cap::impl::SetReadDataReadyCallback, common::Unretained(pimpl_.get()), cid, on_data_ready));
}

void L2cap::SetConnectionClosedCallback(uint16_t cid, ConnectionClosedCallback on_closed) {
  pimpl_->connection_interface_manager_.SetConnectionClosedCallback(static_cast<ConnectionInterfaceDescriptor>(cid),
                                                                    on_closed);
void L2cap::SetConnectionClosedCallback(uint16_t raw_cid, ConnectionClosedCallback on_closed) {
  ConnectionInterfaceDescriptor cid(raw_cid);
  GetHandler()->Post(common::Bind(&L2cap::impl::SetConnectionClosedCallback, common::Unretained(pimpl_.get()), cid,
                                  std::move(on_closed)));
}

bool L2cap::Write(uint16_t cid, const uint8_t* data, size_t len) {
void L2cap::Write(uint16_t raw_cid, const uint8_t* data, size_t len) {
  ConnectionInterfaceDescriptor cid(raw_cid);
  auto packet = MakeUniquePacket(data, len);
  return pimpl_->Write(static_cast<ConnectionInterfaceDescriptor>(cid), std::move(packet));
  GetHandler()->Post(common::BindOnce(&L2cap::impl::Write, common::Unretained(pimpl_.get()), cid, std::move(packet)));
}

bool L2cap::WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) {
void L2cap::WriteFlushable(uint16_t raw_cid, const uint8_t* data, size_t len) {
  LOG_WARN("UNIMPLEMENTED Write flushable");
  return false;
  return Write(raw_cid, data, len);
}

bool L2cap::WriteNonFlushable(uint16_t cid, const uint8_t* data, size_t len) {
void L2cap::WriteNonFlushable(uint16_t raw_cid, const uint8_t* data, size_t len) {
  LOG_WARN("UNIMPLEMENTED Write non flushable");
  return false;
  return Write(raw_cid, data, len);
}

bool L2cap::IsCongested(ConnectionInterfaceDescriptor cid) {
  LOG_WARN("UNIMPLEMENTED Congestion check on channels or links");
  return false;
void L2cap::SendLoopbackResponse(std::function<void()> function) {
  GetHandler()->Post(common::BindOnce(&L2cap::impl::SendLoopbackResponse, common::Unretained(pimpl_.get()), function));
}

/**
+6 −5
Original line number Diff line number Diff line
@@ -32,17 +32,18 @@ class L2cap : public bluetooth::Module, public bluetooth::shim::IL2cap {
  void RegisterService(uint16_t psm, ConnectionOpenCallback on_open, std::promise<void> completed) override;
  void UnregisterService(uint16_t psm) override;

  void CreateConnection(uint16_t psm, const std::string address, std::promise<uint16_t> completed) override;
  void CreateConnection(uint16_t psm, const std::string address_string, ConnectionOpenCallback on_open,
                        std::promise<uint16_t> completed) override;
  void CloseConnection(uint16_t cid) override;

  void SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) override;
  void SetConnectionClosedCallback(uint16_t cid, ConnectionClosedCallback on_closed) override;

  bool Write(uint16_t cid, const uint8_t* data, size_t len) override;
  bool WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) override;
  bool WriteNonFlushable(uint16_t cid, const uint8_t* data, size_t len) override;
  void Write(uint16_t cid, const uint8_t* data, size_t len) override;
  void WriteFlushable(uint16_t cid, const uint8_t* data, size_t len) override;
  void WriteNonFlushable(uint16_t cid, const uint8_t* data, size_t len) override;

  bool IsCongested(uint16_t cid) override;
  void SendLoopbackResponse(std::function<void()>) override;

  L2cap() = default;
  ~L2cap() = default;
Loading