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

Commit d73ef572 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Limit data accepted by GAP_ConnWriteData to just one SDU

This limit is already enforced in BluetoothSocket.java, which is
dividing data into pieces no bigger than MTU.

This is first step towards making it accept BT_HDR with data, in order
to make LE sockets work with zero copies.

Test: transfer file using OPP
Bug: 68359837
Change-Id: I67bfd4ab5c2dc6aa8210058a742c57e1ccf845a0
parent 73c1ecb7
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -1163,10 +1163,9 @@ void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, uint8_t* p_data,
  evt_data.handle = handle;
  evt_data.req_id = req_id;
  evt_data.cong = p_cb->cong;
  evt_data.len = 0;
  evt_data.len = len;
  bta_jv_pm_conn_busy(p_cb->p_pm_cb);
  if (!evt_data.cong &&
      BT_PASS == GAP_ConnWriteData(handle, p_data, len, &evt_data.len)) {
  if (!evt_data.cong && BT_PASS == GAP_ConnWriteData(handle, p_data, len)) {
    evt_data.status = BTA_JV_SUCCESS;
  }

+2 −1
Original line number Diff line number Diff line
@@ -507,7 +507,8 @@ tBTA_JV_STATUS BTA_JvL2capReady(uint32_t handle, uint32_t* p_data_size) {
 *                  When the operation is complete, tBTA_JV_L2CAP_CBACK is
 *                  called with BTA_JV_L2CAP_WRITE_EVT. Works for
 *                  PSM-based connections. This function takes ownership of
 *                  p_data, and will osi_free it.
 *                  p_data, and will osi_free it. Data length must be smaller
 *                  than remote maximum SDU size.
 *
 * Returns          BTA_JV_SUCCESS, if the request is being processed.
 *                  BTA_JV_FAILURE, otherwise.
+39 −58
Original line number Diff line number Diff line
@@ -472,6 +472,25 @@ uint16_t GAP_ConnBTRead(uint16_t gap_handle, BT_HDR** pp_buf) {
  }
}

/* Try to write the queued data to l2ca. Return true on success, or if queue is
 * congested. False if error occured when writing. */
static bool gap_try_write_queued_data(tGAP_CCB* p_ccb) {
  if (p_ccb->is_congested) return true;

  /* Send the buffer through L2CAP */
  BT_HDR* p_buf;
  while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) {
    uint8_t status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf);

    if (status == L2CAP_DW_CONGESTED) {
      p_ccb->is_congested = true;
      return true;
    } else if (status != L2CAP_DW_SUCCESS)
      return false;
  }
  return true;
}

/*******************************************************************************
 *
 * Function         GAP_ConnWriteData
@@ -481,8 +500,7 @@ uint16_t GAP_ConnBTRead(uint16_t gap_handle, BT_HDR** pp_buf) {
 *
 * Parameters:      handle      - Handle of the connection returned in the Open
 *                  p_data      - Data area
 *                  max_len     - Byte count requested
 *                  p_len       - Byte count received
 *                  data_len    - Data length, must be smaller thand remote MTU
 *
 * Returns          BT_PASS                 - data read
 *                  GAP_ERR_BAD_HANDLE      - invalid handle
@@ -491,52 +509,31 @@ uint16_t GAP_ConnBTRead(uint16_t gap_handle, BT_HDR** pp_buf) {
 *
 ******************************************************************************/
uint16_t GAP_ConnWriteData(uint16_t gap_handle, uint8_t* p_data,
                           uint16_t max_len, uint16_t* p_len) {
                           uint16_t data_len) {
  tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
  BT_HDR* p_buf;

  *p_len = 0;

  if (!p_ccb) return (GAP_ERR_BAD_HANDLE);

  if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) return (GAP_ERR_BAD_STATE);

  while (max_len) {
    uint16_t data_len = std::min(p_ccb->rem_mtu_size, max_len);
  if (data_len > p_ccb->rem_mtu_size) return GAP_ERR_ILL_PARM;

  size_t bufsize = BT_HDR_SIZE + L2CAP_MIN_OFFSET + data_len;
  if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
    bufsize += 2; /* 2 byte FCS at end on PDU */

    p_buf = (BT_HDR*)osi_malloc(bufsize);
  BT_HDR* p_buf = (BT_HDR*)osi_malloc(bufsize);
  p_buf->offset = L2CAP_MIN_OFFSET;
  p_buf->len = data_len;
  p_buf->event = BT_EVT_TO_BTU_SP_DATA;

  memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);

    *p_len += p_buf->len;
    max_len -= p_buf->len;
    p_data += p_buf->len;

  DVLOG(1) << StringPrintf("GAP_WriteData %d bytes", p_buf->len);

  fixed_queue_enqueue(p_ccb->tx_queue, p_buf);
  }

  if (p_ccb->is_congested) {
    return (BT_PASS);
  }

  /* Send the buffer through L2CAP */
  while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) {
    uint8_t status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf);

    if (status == L2CAP_DW_CONGESTED) {
      p_ccb->is_congested = true;
      break;
    } else if (status != L2CAP_DW_SUCCESS)
      return (GAP_ERR_BAD_STATE);
  }
  if (!gap_try_write_queued_data(p_ccb)) return GAP_ERR_BAD_STATE;

  return (BT_PASS);
}
@@ -1008,35 +1005,19 @@ static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) {
 *
 ******************************************************************************/
static void gap_congestion_ind(uint16_t lcid, bool is_congested) {
  tGAP_CCB* p_ccb;
  uint16_t event;
  BT_HDR* p_buf;
  uint8_t status;

  DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
                  is_congested, lcid);

  /* Find CCB based on CID */
  p_ccb = gap_find_ccb_by_cid(lcid);
  if (p_ccb == NULL) return;
  tGAP_CCB* p_ccb = gap_find_ccb_by_cid(lcid); /* Find CCB based on CID */
  if (!p_ccb) return;

  p_ccb->is_congested = is_congested;

  event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED;
  p_ccb->p_callback(p_ccb->gap_handle, event);
  p_ccb->p_callback(p_ccb->gap_handle, (is_congested)
                                           ? GAP_EVT_CONN_CONGESTED
                                           : GAP_EVT_CONN_UNCONGESTED);

  if (!is_congested) {
    while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) !=
           NULL) {
      status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf);

      if (status == L2CAP_DW_CONGESTED) {
        p_ccb->is_congested = true;
        break;
      } else if (status != L2CAP_DW_SUCCESS)
        break;
    }
  }
  gap_try_write_queued_data(p_ccb);
}

/*******************************************************************************
+1 −1
Original line number Diff line number Diff line
@@ -240,7 +240,7 @@ extern uint16_t GAP_ConnBTRead(uint16_t gap_handle, BT_HDR** pp_buf);
 *
 ******************************************************************************/
extern uint16_t GAP_ConnWriteData(uint16_t gap_handle, uint8_t* p_data,
                                  uint16_t max_len, uint16_t* p_len);
                                  uint16_t max_len);

/*******************************************************************************
 *