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

Commit e4447aef authored by Jayden Kim's avatar Jayden Kim
Browse files

Determine local mtu for offload LE socket

The local MTU is selected as the minimum of:
  - The socket hal's offload capabilities
  - The application's requested maximum RX packet size

However, the MTU must be at least the minimum required by the L2CAP LE specification.

Bug: 342012881
Bug: 367419086
Test: m -j
Change-Id: Ia6360280b0527cb1218701d99a4ca424e38d83c9
parent 5c298722
Loading
Loading
Loading
Loading
+37 −3
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@
#include "gd/os/rand.h"
#include "include/hardware/bluetooth.h"
#include "internal_include/bt_target.h"
#include "lpp/lpp_offload_interface.h"
#include "main/shim/entry.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
#include "stack/include/bt_hdr.h"
@@ -868,12 +870,38 @@ static void btsock_l2cap_server_listen(l2cap_socket* sock) {
                         sock->rx_mtu, std::move(cfg), btsock_l2cap_cbk, sock->id);
}

/*
 * Determine the local MTU for the offloaded L2CAP connection.
 *
 * The local MTU is selected as the minimum of:
 *   - The socket hal's offload capabilities (socket_cap.leCocCapabilities.mtu)
 *   - The application's requested maximum RX packet size (app_max_rx_packet_size)
 *
 * However, the MTU must be at least the minimum required by the L2CAP LE
 * specification (L2CAP_SDU_LENGTH_LE_MIN).
 */

static bool btsock_l2cap_get_offload_mtu(uint16_t* rx_mtu, uint16_t app_max_rx_packet_size) {
  hal::SocketCapabilities socket_cap =
          bluetooth::shim::GetLppOffloadManager()->GetSocketCapabilities();
  if (!socket_cap.le_coc_capabilities.number_of_supported_sockets) {
    return false;
  }
  /* Socket HAL client has already verified that the MTU is in a valid range. */
  uint16_t mtu = static_cast<uint16_t>(socket_cap.le_coc_capabilities.mtu);
  mtu = std::min(mtu, app_max_rx_packet_size);
  if (mtu < L2CAP_SDU_LENGTH_LE_MIN) {
    mtu = L2CAP_SDU_LENGTH_LE_MIN;
  }
  *rx_mtu = mtu;
  return true;
}

static bt_status_t btsock_l2cap_listen_or_connect(const char* name, const RawAddress* addr,
                                                  int channel, int* sock_fd, int flags, char listen,
                                                  int app_uid, btsock_data_path_t data_path,
                                                  const char* socket_name, uint64_t hub_id,
                                                  uint64_t endpoint_id,
                                                  int /* max_rx_packet_size */) {
                                                  uint64_t endpoint_id, int max_rx_packet_size) {
  if (!is_inited()) {
    return BT_STATUS_NOT_READY;
  }
@@ -911,7 +939,13 @@ static bt_status_t btsock_l2cap_listen_or_connect(const char* name, const RawAdd
  sock->channel = channel;
  sock->app_uid = app_uid;
  sock->is_le_coc = is_le_coc;
  if (data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) {
    if (!btsock_l2cap_get_offload_mtu(&sock->rx_mtu, static_cast<uint16_t>(max_rx_packet_size))) {
      return BT_STATUS_UNSUPPORTED;
    }
  } else {
    sock->rx_mtu = is_le_coc ? L2CAP_SDU_LENGTH_LE_MAX : L2CAP_SDU_LENGTH_MAX;
  }
  sock->data_path = data_path;
  if (socket_name) {
    strncpy(sock->socket_name, socket_name, sizeof(sock->socket_name) - 1);
+1 −0
Original line number Diff line number Diff line
@@ -487,6 +487,7 @@ inline std::string l2cap_cfg_result_text(const tL2CAP_CFG_RESULT& result) {
 */
#define L2CAP_SDU_LENGTH_MAX (8080 + 26 - (L2CAP_MIN_OFFSET + 6))
constexpr uint16_t L2CAP_SDU_LENGTH_LE_MAX = 0xffff;
constexpr uint16_t L2CAP_SDU_LENGTH_LE_MIN = 23;

/* SAR bits in the control word
 */
+2 −3
Original line number Diff line number Diff line
@@ -777,9 +777,8 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      p_ccb->p_rcb = p_rcb;
      p_ccb->remote_cid = rcid;

      p_ccb->local_conn_cfg.mtu = L2CAP_SDU_LENGTH_LE_MAX;
      p_ccb->local_conn_cfg.mps =
              bluetooth::shim::GetController()->GetLeBufferSize().le_data_packet_length_;
      p_ccb->local_conn_cfg.mtu = p_rcb->coc_cfg.mtu;
      p_ccb->local_conn_cfg.mps = p_rcb->coc_cfg.mps;
      p_ccb->local_conn_cfg.credits = p_rcb->coc_cfg.credits;

      p_ccb->remote_credit_count = p_rcb->coc_cfg.credits;