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

Commit 29d72cab authored by Venkata Jagadeesh Garaga's avatar Venkata Jagadeesh Garaga Committed by William Escande
Browse files

SDP: Serialize sdp connections from profiles/BT APP

This SDP enhancement serialize the sdp reqs and also
same uses same sdp channel when sdp layer receives
multiple sdp req from profiles for same remote.

Thus avoid multiple IOT issues, where IOT remote
goes to bad state when DUT sends more than one
sdp at same time.

Merged-In: Ia7ac9d7254963607f8c9a873d547179c5ebd141d
Change-Id: Ia7ac9d7254963607f8c9a873d547179c5ebd141d
CRs-Fixed: 2104397
Bug: 246022810
Test: atest net_test_stack_sdp
Tag: #feature
(cherry picked from commit cf8c68cf)
parent f185b5b5
Loading
Loading
Loading
Loading
+37 −2
Original line number Diff line number Diff line
@@ -257,6 +257,16 @@ static void sdp_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) {
    return;
  }

  if (ack_needed) {
    sdpu_process_pend_ccb(p_ccb->connection_id, false);
  } else {
    SDP_TRACE_WARNING(
        "SDP - Rcvd L2CAP disc, "
        "ACL disc clear pend sdp ccb: 0x%x",
        l2cap_cid);
    sdpu_clear_pend_ccb(p_ccb->connection_id);
  }

  SDP_TRACE_EVENT("SDP - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
  /* Tell the user if there is a callback */
  if (p_ccb->p_cb)
@@ -345,7 +355,17 @@ tCONN_CB* sdp_conn_originate(const RawAddress& p_bd_addr) {
   */
  p_ccb->con_state = SDP_STATE_CONN_SETUP;

  // Look for any active sdp connection on the remote device
  cid = sdpu_get_active_ccb_cid(p_bd_addr);

  if (cid == 0) {
    p_ccb->con_state = SDP_STATE_CONN_SETUP;
    cid = L2CA_ConnectReq2(BT_PSM_SDP, p_bd_addr, BTM_SEC_NONE);
  } else {
    p_ccb->con_state = SDP_STATE_CONN_PEND;
    SDP_TRACE_WARNING("SDP already active for peer %s. cid=%#0x",
                      p_bd_addr.ToString().c_str(), cid);
  }

  /* Check if L2CAP started the connection process */
  if (cid == 0) {
@@ -372,8 +392,20 @@ void sdp_disconnect(tCONN_CB* p_ccb, tSDP_REASON reason) {

  /* Check if we have a connection ID */
  if (p_ccb->connection_id != 0) {
    L2CA_DisconnectReq(p_ccb->connection_id);
    p_ccb->disconnect_reason = reason;
    if (SDP_SUCCESS == reason &&
        (true == sdpu_process_pend_ccb(p_ccb->connection_id, true))) {
      /* Tell the user if he has a callback */
      if (p_ccb->p_cb)
        (*p_ccb->p_cb)(static_cast<tSDP_STATUS>(p_ccb->disconnect_reason));
      else if (p_ccb->p_cb2)
        (*p_ccb->p_cb2)(static_cast<tSDP_STATUS>(p_ccb->disconnect_reason),
                        p_ccb->user_data);
      sdpu_release_ccb(p_ccb);
      return;
    } else {
      L2CA_DisconnectReq(p_ccb->connection_id);
    }
  }

  /* If at setup state, we may not get callback ind from L2CAP */
@@ -412,6 +444,7 @@ static void sdp_disconnect_cfm(uint16_t l2cap_cid,

  SDP_TRACE_EVENT("SDP - Rcvd L2CAP disc cfm, CID: 0x%x", l2cap_cid);

  sdpu_process_pend_ccb(p_ccb->connection_id, false);
  /* Tell the user if there is a callback */
  if (p_ccb->p_cb)
    (*p_ccb->p_cb)(static_cast<tSDP_STATUS>(p_ccb->disconnect_reason));
@@ -439,6 +472,8 @@ void sdp_conn_timer_timeout(void* data) {
                  p_ccb->connection_id);

  L2CA_DisconnectReq(p_ccb->connection_id);
  sdpu_clear_pend_ccb(p_ccb->connection_id);

  /* Tell the user if there is a callback */
  if (p_ccb->p_cb)
    (*p_ccb->p_cb)(SDP_CONN_FAILED);
+128 −1
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include "stack/include/avrc_api.h"
#include "stack/include/avrc_defs.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/btm_api_types.h"
#include "stack/include/sdp_api.h"
#include "stack/include/sdpdefs.h"
#include "stack/include/stack_metrics_logging.h"
@@ -320,9 +321,12 @@ tCONN_CB* sdpu_find_ccb_by_cid(uint16_t cid) {

  /* Look through each connection control block */
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->connection_id == cid))
    if ((p_ccb->con_state != SDP_STATE_IDLE) &&
        (p_ccb->con_state != SDP_STATE_CONN_PEND) &&
        (p_ccb->connection_id == cid)) {
      return (p_ccb);
    }
  }

  /* If here, not found */
  return (NULL);
@@ -402,6 +406,129 @@ void sdpu_release_ccb(tCONN_CB* p_ccb) {
  osi_free_and_reset((void**)&p_ccb->rsp_list);
}

/*******************************************************************************
 *
 * Function         sdpu_get_active_ccb_cid
 *
 * Description      This function checks if any sdp connecting is there for
 *                  same remote and returns cid if its available
 *
 *                  RawAddress : Remote address
 *
 * Returns          returns cid if any active sdp connection, else 0.
 *
 ******************************************************************************/
uint16_t sdpu_get_active_ccb_cid(const RawAddress& remote_bd_addr) {
  uint16_t xx;
  tCONN_CB* p_ccb;

  // Look through each connection control block for active sdp on given remote
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state == SDP_STATE_CONN_SETUP) ||
        (p_ccb->con_state == SDP_STATE_CFG_SETUP) ||
        (p_ccb->con_state == SDP_STATE_CONNECTED)) {
      if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG &&
          p_ccb->device_address == remote_bd_addr) {
        return p_ccb->connection_id;
      }
    }
  }

  // No active sdp channel for this remote
  return 0;
}

/*******************************************************************************
 *
 * Function         sdpu_process_pend_ccb
 *
 * Description      This function process if any sdp ccb pending for connection
 *
 *                  uint16_t : Remote CID
 *                  bool: if true will reuse current channel else will create a
 *                         new L2CAP connection
 *
 * Returns          returns true if any pending ccb, else false.
 *
 ******************************************************************************/
bool sdpu_process_pend_ccb(uint16_t cid, bool use_cur_chnl) {
  uint16_t xx;
  tCONN_CB* p_ccb;

  if (use_cur_chnl) {
    // Look through each connection control block for active sdp on given remote
    for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
      if ((p_ccb->con_state == SDP_STATE_CONN_PEND) &&
          (p_ccb->connection_id == cid) &&
          (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)) {
        p_ccb->con_state = SDP_STATE_CONNECTED;
        sdp_disc_connected(p_ccb);
        return true;
      }
    }
    // No pending SDP channel for this remote
    return false;
  }

  uint16_t new_cid = 0;
  bool new_conn = false;
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state == SDP_STATE_CONN_PEND) &&
        (p_ccb->connection_id == cid) &&
        (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)) {
      if (!new_conn) {
        p_ccb->con_state = SDP_STATE_CONN_SETUP;
        new_cid =
            L2CA_ConnectReq2(BT_PSM_SDP, p_ccb->device_address, BTM_SEC_NONE);
        new_conn = true;
      }
      // Check if L2CAP started the connection process
      if (new_cid != 0) {
        p_ccb->connection_id = new_cid;
      } else {
        // Tell the user if he has a callback
        if (p_ccb->p_cb)
          (*p_ccb->p_cb)(SDP_CONN_FAILED);
        else if (p_ccb->p_cb2)
          (*p_ccb->p_cb2)(SDP_CONN_FAILED, p_ccb->user_data);
        sdpu_release_ccb(p_ccb);
      }
    }
  }
  return new_conn && new_cid != 0;
}

/*******************************************************************************
 *
 * Function         sdpu_clear_pend_ccb
 *
 * Description      This function releases if any sdp ccb pending for connection
 *
 *                  uint16_t : Remote CID
 *
 * Returns          returns none.
 *
 ******************************************************************************/
void sdpu_clear_pend_ccb(uint16_t cid) {
  uint16_t xx;
  tCONN_CB* p_ccb;

  // Look through each connection control block for active sdp on given remote
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state == SDP_STATE_CONN_PEND) &&
        (p_ccb->connection_id == cid) &&
        (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)) {
      // Tell the user if he has a callback
      if (p_ccb->p_cb)
        (*p_ccb->p_cb)(SDP_CONN_FAILED);
      else if (p_ccb->p_cb2)
        (*p_ccb->p_cb2)(SDP_CONN_FAILED, p_ccb->user_data);
      sdpu_release_ccb(p_ccb);
    }
  }
  return;
}

/*******************************************************************************
 *
 * Function         sdpu_build_attrib_seq
+4 −0
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ typedef struct {
#define SDP_STATE_CONN_SETUP 1
#define SDP_STATE_CFG_SETUP 2
#define SDP_STATE_CONNECTED 3
#define SDP_STATE_CONN_PEND 4
  uint8_t con_state;

#define SDP_FLAGS_IS_ORIG 0x01
@@ -236,6 +237,9 @@ extern bool sdpu_is_service_id_avrc_target(const tSDP_ATTRIBUTE* p_attr);
extern bool spdu_is_avrcp_version_valid(const uint16_t version);
extern void sdpu_set_avrc_target_version(const tSDP_ATTRIBUTE* p_attr,
                                         const RawAddress* bdaddr);
extern uint16_t sdpu_get_active_ccb_cid(const RawAddress& remote_bd_addr);
extern bool sdpu_process_pend_ccb(uint16_t cid, bool use_cur_chnl);
extern void sdpu_clear_pend_ccb(uint16_t cid);

/* Functions provided by sdp_db.cc
 */