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

Commit 0f85e35d authored by Chris Manton's avatar Chris Manton
Browse files

Move l2cu_get_next_buffer_to_send

From: stack/l2cap/l2c_utils
Into: stack/l2cap/l2c_link

Towards proper interfaces

Bug: 163134718
Tag: #refactor
Test: compile & verify basic functions working

Change-Id: I8e0ef282d5bae9a0deb0e465b326d7889d67d5e8
parent 908191be
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -611,8 +611,6 @@ extern void l2cu_create_conn_br_edr(tL2C_LCB* p_lcb);
extern bool l2cu_create_conn_le(tL2C_LCB* p_lcb);
extern bool l2cu_create_conn_le(tL2C_LCB* p_lcb, uint8_t initiating_phys);
extern void l2cu_create_conn_after_switch(tL2C_LCB* p_lcb);
extern BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
                                            tL2C_TX_COMPLETE_CB_INFO* p_cbi);
extern void l2cu_adjust_out_mps(tL2C_CCB* p_ccb);

/* Functions provided by l2c_link.cc
+112 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@

static void l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf,
                                   tL2C_TX_COMPLETE_CB_INFO* p_cbi);
static BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
                                            tL2C_TX_COMPLETE_CB_INFO* p_cbi);

/*******************************************************************************
 *
@@ -1384,3 +1386,113 @@ tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) {

  return p_serve_ccb;
}

/******************************************************************************
 *
 * Function         l2cu_get_next_buffer_to_send
 *
 * Description      get the next buffer to send on a link. It also adjusts the
 *                  CCB queue to do a basic priority and round-robin scheduling.
 *
 * Returns          pointer to buffer or NULL
 *
 ******************************************************************************/
BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
                                     tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
  tL2C_CCB* p_ccb;
  BT_HDR* p_buf;

/* Highest priority are fixed channels */
  int xx;

  p_cbi->cb = NULL;

  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
    p_ccb = p_lcb->p_fixed_ccbs[xx];
    if (p_ccb == NULL) continue;

    /* eL2CAP option in use */
    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
      if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;

      /* No more checks needed if sending from the reatransmit queue */
      if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
        if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;

        /* If in eRTM mode, check for window closure */
        if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
            (l2c_fcr_is_flow_controlled(p_ccb)))
          continue;
      }

      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
      if (p_buf != NULL) {
        l2cu_check_channel_congestion(p_ccb);
        l2cu_set_acl_hci_header(p_buf, p_ccb);
        return (p_buf);
      }
    } else {
      if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
        p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
        if (NULL == p_buf) {
          L2CAP_TRACE_ERROR("%s: No data to be sent", __func__);
          return (NULL);
        }

        /* Prepare callback info for TX completion */
        p_cbi->cb = l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb;
        p_cbi->local_cid = p_ccb->local_cid;
        p_cbi->num_sdu = 1;

        l2cu_check_channel_congestion(p_ccb);
        l2cu_set_acl_hci_header(p_buf, p_ccb);
        return (p_buf);
      }
    }
  }

  /* get next serving channel in round-robin */
  p_ccb = l2cu_get_next_channel_in_rr(p_lcb);

  /* Return if no buffer */
  if (p_ccb == NULL) return (NULL);

  if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
    /* Check credits */
    if (p_ccb->peer_conn_cfg.credits == 0) {
      L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__);
      return NULL;
    }

    bool last_piece_of_sdu = false;
    p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, &last_piece_of_sdu);
    p_ccb->peer_conn_cfg.credits--;

    if (last_piece_of_sdu) {
      // TODO: send callback up the stack. Investigate setting p_cbi->cb to
      // notify after controller ack send.
    }

  } else {
    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
      if (p_buf == NULL) return (NULL);
    } else {
      p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
      if (NULL == p_buf) {
        L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
        return (NULL);
      }
    }
  }

  if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb &&
      (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE))
    (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);

  l2cu_check_channel_congestion(p_ccb);

  l2cu_set_acl_hci_header(p_buf, p_ccb);

  return (p_buf);
}
+0 −110
Original line number Diff line number Diff line
@@ -2921,116 +2921,6 @@ void l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
  if (p_cbi->cb != NULL) p_cbi->cb(p_cbi->local_cid, p_cbi->num_sdu);
}

/******************************************************************************
 *
 * Function         l2cu_get_next_buffer_to_send
 *
 * Description      get the next buffer to send on a link. It also adjusts the
 *                  CCB queue to do a basic priority and round-robin scheduling.
 *
 * Returns          pointer to buffer or NULL
 *
 ******************************************************************************/
BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
                                     tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
  tL2C_CCB* p_ccb;
  BT_HDR* p_buf;

/* Highest priority are fixed channels */
  int xx;

  p_cbi->cb = NULL;

  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
    p_ccb = p_lcb->p_fixed_ccbs[xx];
    if (p_ccb == NULL) continue;

    /* eL2CAP option in use */
    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
      if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;

      /* No more checks needed if sending from the reatransmit queue */
      if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
        if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;

        /* If in eRTM mode, check for window closure */
        if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
            (l2c_fcr_is_flow_controlled(p_ccb)))
          continue;
      }

      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
      if (p_buf != NULL) {
        l2cu_check_channel_congestion(p_ccb);
        l2cu_set_acl_hci_header(p_buf, p_ccb);
        return (p_buf);
      }
    } else {
      if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
        p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
        if (NULL == p_buf) {
          L2CAP_TRACE_ERROR("%s: No data to be sent", __func__);
          return (NULL);
        }

        /* Prepare callback info for TX completion */
        p_cbi->cb = l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb;
        p_cbi->local_cid = p_ccb->local_cid;
        p_cbi->num_sdu = 1;

        l2cu_check_channel_congestion(p_ccb);
        l2cu_set_acl_hci_header(p_buf, p_ccb);
        return (p_buf);
      }
    }
  }

  /* get next serving channel in round-robin */
  p_ccb = l2cu_get_next_channel_in_rr(p_lcb);

  /* Return if no buffer */
  if (p_ccb == NULL) return (NULL);

  if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
    /* Check credits */
    if (p_ccb->peer_conn_cfg.credits == 0) {
      L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__);
      return NULL;
    }

    bool last_piece_of_sdu = false;
    p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, &last_piece_of_sdu);
    p_ccb->peer_conn_cfg.credits--;

    if (last_piece_of_sdu) {
      // TODO: send callback up the stack. Investigate setting p_cbi->cb to
      // notify after controller ack send.
    }

  } else {
    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
      if (p_buf == NULL) return (NULL);
    } else {
      p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
      if (NULL == p_buf) {
        L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
        return (NULL);
      }
    }
  }

  if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb &&
      (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE))
    (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);

  l2cu_check_channel_congestion(p_ccb);

  l2cu_set_acl_hci_header(p_buf, p_ccb);

  return (p_buf);
}

/******************************************************************************
 *
 * Function         l2cu_set_acl_hci_header