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

Commit d338a642 authored by Sanket Agarwal's avatar Sanket Agarwal
Browse files

Implement multiple control blocks for HF Client in BTA/BTIF

Test: Manual test for multiple incoming/outgoing HF connections

Bug: b/30984220
Change-Id: If66cad7c9bbc92051ebb7efb2b352c10e7514af3
parent e630f985
Loading
Loading
Loading
Loading
+51 −61
Original line number Diff line number Diff line
@@ -63,12 +63,12 @@ void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA* p_data) {
  }

  /* Take the link out of sniff and set L2C idle time to 0 */
  bta_dm_pm_active(client_cb->scb.peer_addr);
  L2CA_SetIdleTimeoutByBdAddr(client_cb->scb.peer_addr, 0, BT_TRANSPORT_BR_EDR);
  bta_dm_pm_active(client_cb->peer_addr);
  L2CA_SetIdleTimeoutByBdAddr(client_cb->peer_addr, 0, BT_TRANSPORT_BR_EDR);

  /* if SCO is open close SCO and wait on RFCOMM close */
  if (client_cb->scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) {
    client_cb->scb.sco_close_rfc = true;
  if (client_cb->sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) {
    client_cb->sco_close_rfc = true;
  } else {
    bta_hf_client_rfc_do_close(p_data);
  }
@@ -98,8 +98,8 @@ void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA* p_data) {

  /* store parameters */
  if (p_data) {
    bdcpy(client_cb->scb.peer_addr, p_data->api_open.bd_addr);
    client_cb->scb.cli_sec_mask = p_data->api_open.sec_mask;
    bdcpy(client_cb->peer_addr, p_data->api_open.bd_addr);
    client_cb->cli_sec_mask = p_data->api_open.sec_mask;
  }

  /* Check if RFCOMM has any incoming connection to avoid collision. */
@@ -108,15 +108,12 @@ void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA* p_data) {
    /* Let the incoming connection goes through.                        */
    /* Issue collision for now.                                         */
    /* We will decide what to do when we find incoming connection later.*/
    bta_hf_client_collision_cback(0, BTA_ID_HS, 0, client_cb->scb.peer_addr);
    bta_hf_client_collision_cback(0, BTA_ID_HS, 0, client_cb->peer_addr);
    return;
  }

  /* close server */
  bta_hf_client_close_server(client_cb);

  /* set role */
  client_cb->scb.role = BTA_HF_CLIENT_INT;
  client_cb->role = BTA_HF_CLIENT_INT;

  /* do service search */
  bta_hf_client_do_disc(client_cb);
@@ -140,8 +137,8 @@ static void bta_hf_client_cback_open(tBTA_HF_CLIENT_CB* client_cb,

  /* call app callback with open event */
  evt.open.status = status;
  bdcpy(evt.open.bd_addr, client_cb->scb.peer_addr);
  (*client_cb->p_cback)(BTA_HF_CLIENT_OPEN_EVT, &evt);
  bdcpy(evt.open.bd_addr, client_cb->peer_addr);
  bta_hf_client_app_callback(BTA_HF_CLIENT_OPEN_EVT, &evt);
}

/*******************************************************************************
@@ -164,7 +161,7 @@ void bta_hf_client_rfc_open(tBTA_HF_CLIENT_DATA* p_data) {
    return;
  }

  bta_sys_conn_open(BTA_ID_HS, 1, client_cb->scb.peer_addr);
  bta_sys_conn_open(BTA_ID_HS, 1, client_cb->peer_addr);

  bta_hf_client_cback_open(client_cb, BTA_HF_CLIENT_SUCCESS);

@@ -197,32 +194,32 @@ void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA* p_data) {
  int status;

  /* set role */
  client_cb->scb.role = BTA_HF_CLIENT_ACP;
  client_cb->role = BTA_HF_CLIENT_ACP;

  APPL_TRACE_DEBUG("%s: serv_handle %d", __func__, client_cb->scb.serv_handle);
  APPL_TRACE_DEBUG("%s: conn_handle %d", __func__, client_cb->conn_handle);

  /* get bd addr of peer */
  if (PORT_SUCCESS != (status = PORT_CheckConnection(client_cb->scb.serv_handle,
  if (PORT_SUCCESS != (status = PORT_CheckConnection(client_cb->conn_handle,
                                                     dev_addr, &lcid))) {
    APPL_TRACE_DEBUG("%s: error PORT_CheckConnection returned status %d",
                     __func__, status);
  }

  /* Collision Handling */
  if (alarm_is_scheduled(client_cb->scb.collision_timer)) {
    alarm_cancel(client_cb->scb.collision_timer);
  if (alarm_is_scheduled(client_cb->collision_timer)) {
    alarm_cancel(client_cb->collision_timer);

    if (bdcmp(dev_addr, client_cb->scb.peer_addr) == 0) {
    if (bdcmp(dev_addr, client_cb->peer_addr) == 0) {
      /* If incoming and outgoing device are same, nothing more to do. */
      /* Outgoing conn will be aborted because we have successful incoming conn.
       */
    } else {
      /* Resume outgoing connection. */
      bta_hf_client_resume_open();
      bta_hf_client_resume_open(client_cb);
    }
  }

  bdcpy(client_cb->scb.peer_addr, dev_addr);
  bdcpy(client_cb->peer_addr, dev_addr);

  /* do service discovery to get features */
  bta_hf_client_do_disc(client_cb);
@@ -251,19 +248,15 @@ void bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA* p_data) {
  }

  /* reinitialize stuff */
  // client_cb->scb.conn_handle = 0;
  client_cb->scb.peer_features = 0;
  client_cb->scb.chld_features = 0;
  client_cb->scb.role = BTA_HF_CLIENT_ACP;
  client_cb->scb.svc_conn = false;
  client_cb->scb.send_at_reply = false;
  client_cb->scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
  client_cb->peer_features = 0;
  client_cb->chld_features = 0;
  client_cb->role = BTA_HF_CLIENT_ACP;
  client_cb->svc_conn = false;
  client_cb->send_at_reply = false;
  client_cb->negotiated_codec = BTM_SCO_CODEC_CVSD;

  bta_hf_client_at_reset(client_cb);

  /* reopen server */
  bta_hf_client_start_server(client_cb);

  /* call open cback w. failure */
  bta_hf_client_cback_open(client_cb, BTA_HF_CLIENT_FAIL_RFCOMM);
}
@@ -287,11 +280,6 @@ void bta_hf_client_disc_fail(tBTA_HF_CLIENT_DATA* p_data) {
    return;
  }

  /* reopen server */
  bta_hf_client_start_server(client_cb);

  /* reinitialize stuff */

  /* call open cback w. failure */
  bta_hf_client_cback_open(client_cb, BTA_HF_CLIENT_FAIL_SDP);
}
@@ -339,38 +327,39 @@ void bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA* p_data) {
  }

  /* reinitialize stuff */
  client_cb->scb.peer_features = 0;
  client_cb->scb.chld_features = 0;
  client_cb->scb.role = BTA_HF_CLIENT_ACP;
  client_cb->scb.svc_conn = false;
  client_cb->scb.send_at_reply = false;
  client_cb->scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
  client_cb->peer_features = 0;
  client_cb->chld_features = 0;
  client_cb->role = BTA_HF_CLIENT_ACP;
  client_cb->svc_conn = false;
  client_cb->send_at_reply = false;
  client_cb->negotiated_codec = BTM_SCO_CODEC_CVSD;

  bta_hf_client_at_reset(client_cb);

  bta_sys_conn_close(BTA_ID_HS, 1, client_cb->scb.peer_addr);
  bta_sys_conn_close(BTA_ID_HS, 1, client_cb->peer_addr);

  /* call close cback */
  (*client_cb->p_cback)(BTA_HF_CLIENT_CLOSE_EVT, NULL);
  tBTA_HF_CLIENT evt;
  memset(&evt, 0, sizeof(evt));
  bdcpy(evt.conn.bd_addr, client_cb->peer_addr);
  bta_hf_client_app_callback(BTA_HF_CLIENT_CLOSE_EVT, &evt);

  /* if not deregistering reopen server */
  if (client_cb->scb.deregister == false) {
  if (bta_hf_client_cb_arr.deregister == false) {
    /* Clear peer bd_addr so instance can be reused */
    bdcpy(client_cb->scb.peer_addr, bd_addr_null);

    /* start server as it might got closed on open*/
    bta_hf_client_start_server(client_cb);
    bdcpy(client_cb->peer_addr, bd_addr_null);

    /* Make sure SCO is shutdown */
    bta_hf_client_sco_shutdown(client_cb);

    bta_sys_sco_unuse(BTA_ID_HS, 1, client_cb->scb.peer_addr);
    bta_sys_sco_unuse(BTA_ID_HS, 1, client_cb->peer_addr);
  }
  /* else close port and deallocate scb */
  else {
    bta_hf_client_close_server(client_cb);
    bta_hf_client_scb_init();
    (*client_cb->p_cback)(BTA_HF_CLIENT_DISABLE_EVT, NULL);
    tBTA_HF_CLIENT evt;
    memset(&evt, 0, sizeof(evt));
    bdcpy(evt.reg.bd_addr, client_cb->peer_addr);
    bta_hf_client_app_callback(BTA_HF_CLIENT_DISABLE_EVT, &evt);
  }
}

@@ -465,8 +454,8 @@ void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA* p_data) {
  char buf[BTA_HF_CLIENT_RFC_READ_MAX];
  memset(buf, 0, sizeof(buf));
  /* read data from rfcomm; if bad status, we're done */
  while (PORT_ReadData(client_cb->scb.conn_handle, buf,
                       BTA_HF_CLIENT_RFC_READ_MAX, &len) == PORT_SUCCESS) {
  while (PORT_ReadData(client_cb->conn_handle, buf, BTA_HF_CLIENT_RFC_READ_MAX,
                       &len) == PORT_SUCCESS) {
    /* if no data, we're done */
    if (len == 0) {
      break;
@@ -504,14 +493,15 @@ void bta_hf_client_svc_conn_open(tBTA_HF_CLIENT_DATA* p_data) {

  memset(&evt, 0, sizeof(evt));

  if (!client_cb->scb.svc_conn) {
  if (!client_cb->svc_conn) {
    /* set state variable */
    client_cb->scb.svc_conn = true;
    client_cb->svc_conn = true;

    /* call callback */
    evt.conn.peer_feat = client_cb->scb.peer_features;
    evt.conn.chld_feat = client_cb->scb.chld_features;
    bdcpy(evt.conn.bd_addr, client_cb->peer_addr);
    evt.conn.peer_feat = client_cb->peer_features;
    evt.conn.chld_feat = client_cb->chld_features;

    (*client_cb->p_cback)(BTA_HF_CLIENT_CONN_EVT, &evt);
    bta_hf_client_app_callback(BTA_HF_CLIENT_CONN_EVT, &evt);
  }
}
+13 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ void BTA_HfClientDisable(void) { bta_hf_client_api_disable(); }
 *
 ******************************************************************************/
void BTA_HfClientOpen(BD_ADDR bd_addr, tBTA_SEC sec_mask, uint16_t* p_handle) {
  APPL_TRACE_DEBUG("%s", __func__);
  tBTA_HF_CLIENT_API_OPEN* p_buf =
      (tBTA_HF_CLIENT_API_OPEN*)osi_malloc(sizeof(tBTA_HF_CLIENT_API_OPEN));

@@ -184,3 +185,15 @@ void BTA_HfClientSendAT(uint16_t handle, tBTA_HF_CLIENT_AT_CMD_TYPE at,

  bta_sys_sendmsg(p_buf);
}

/*******************************************************************************
 *
 * Function         BTA_HfClientDumpStatistics
 *
 * Description      Dump statistics about the various control blocks
 *                  and other relevant connection statistics
 *
 * Returns          Void
 *
 ******************************************************************************/
void BTA_HfClientDumpStatistics(int fd) { bta_hf_client_dump_statistics(fd); }
+98 −97

File changed.

Preview size limit exceeded, changes collapsed.

+40 −30
Original line number Diff line number Diff line
@@ -41,6 +41,9 @@
#define BTA_HF_CLIENT_COLLISION_TIMER_MS 2411
#endif

/* Maximum number of HF devices supported simultaneously */
#define HF_CLIENT_MAX_DEVICES 10

enum {
  /* these events are handled by the state machine */
  BTA_HF_CLIENT_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HS),
@@ -142,17 +145,27 @@ typedef union {
/* First handle for the control block */
#define BTA_HF_CLIENT_CB_FIRST_HANDLE 1

/* type for each service device control block */
/* sco states */
enum {
  BTA_HF_CLIENT_SCO_SHUTDOWN_ST, /* no listening, no connection */
  BTA_HF_CLIENT_SCO_LISTEN_ST,   /* listening */
  BTA_HF_CLIENT_SCO_OPENING_ST,  /* connection opening */
  BTA_HF_CLIENT_SCO_OPEN_CL_ST,  /* opening connection being closed */
  BTA_HF_CLIENT_SCO_OPEN_ST,     /* open */
  BTA_HF_CLIENT_SCO_CLOSING_ST,  /* closing */
  BTA_HF_CLIENT_SCO_CLOSE_OP_ST, /* closing sco being opened */
  BTA_HF_CLIENT_SCO_SHUTTING_ST  /* sco shutting down */
};

/* type for HF control block */
typedef struct {
  // Fields useful for particular control block.
  uint8_t handle;               /* Handle of the control block to be
                                   used by upper layer */
  uint16_t serv_handle;         /* RFCOMM server handle */
  BD_ADDR peer_addr;            /* peer bd address */
  tSDP_DISCOVERY_DB* p_disc_db; /* pointer to discovery database */
  uint16_t conn_handle;         /* RFCOMM handle of connected service */
  tBTA_SEC serv_sec_mask;       /* server security mask */
  tBTA_SEC cli_sec_mask;        /* client security mask */
  tBTA_HF_CLIENT_FEAT features; /* features registered by application */
  tBTA_HF_CLIENT_PEER_FEAT peer_features; /* peer device features */
  tBTA_HF_CLIENT_CHLD_FEAT chld_features; /* call handling features */
  uint16_t peer_version;                  /* profile version of peer device */
@@ -162,36 +175,30 @@ typedef struct {
  uint8_t sco_state;                      /* SCO state variable */
  bool sco_close_rfc; /* true if also close RFCOMM after SCO */
  bool retry_with_sco_only;
  bool deregister;    /* true if service shutting down */
  tBTM_SCO_CODEC_TYPE negotiated_codec; /* negotiated codec */
  bool svc_conn;      /* set to true when service level connection is up */
  bool send_at_reply; /* set to true to notify framework about AT results */
  tBTA_HF_CLIENT_AT_CB at_cb;           /* AT Parser control block */
  uint8_t state;                        /* state machine state */
  bool is_allocated; /* if the control block is already allocated */
  tBTM_SCO_CODEC_TYPE negotiated_codec; /* negotiated codec */
  alarm_t* collision_timer;             /* Collision timer */
} tBTA_HF_CLIENT_SCB;

/* sco states */
enum {
  BTA_HF_CLIENT_SCO_SHUTDOWN_ST, /* no listening, no connection */
  BTA_HF_CLIENT_SCO_LISTEN_ST,   /* listening */
  BTA_HF_CLIENT_SCO_OPENING_ST,  /* connection opening */
  BTA_HF_CLIENT_SCO_OPEN_CL_ST,  /* opening connection being closed */
  BTA_HF_CLIENT_SCO_OPEN_ST,     /* open */
  BTA_HF_CLIENT_SCO_CLOSING_ST,  /* closing */
  BTA_HF_CLIENT_SCO_CLOSE_OP_ST, /* closing sco being opened */
  BTA_HF_CLIENT_SCO_SHUTTING_ST  /* sco shutting down */
};
} tBTA_HF_CLIENT_CB;

/* type for AG control block */
typedef struct {
  tBTA_HF_CLIENT_SCB scb; /* service control block */
  // Common fields, should be taken out.
  uint32_t sdp_handle;
  uint8_t scn;
  tBTA_HF_CLIENT_CBACK* p_cback; /* application callback */
  bool msbc_enabled;
} tBTA_HF_CLIENT_CB;
  tBTA_HF_CLIENT_FEAT features;  /* features registered by application */
  tBTA_SEC serv_sec_mask;        /* server security mask */
  uint16_t serv_handle;          /* RFCOMM server handle */
  bool deregister;               /* true if service shutting down */

  // Maximum number of control blocks supported by the BTA layer.
  tBTA_HF_CLIENT_CB cb[HF_CLIENT_MAX_DEVICES];
} tBTA_HF_CLIENT_CB_ARR;

extern tBTA_HF_CLIENT_CB_ARR bta_hf_client_cb_arr;

/*****************************************************************************
 *  Function prototypes
@@ -199,40 +206,42 @@ typedef struct {

/* main functions */
extern tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_handle(uint16_t handle);
extern tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_bda(BD_ADDR bd_addr);
extern tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_rfc_handle(uint16_t handle);
extern tBTA_HF_CLIENT_CB* bta_hf_client_find_cb_by_sco_handle(uint16_t handle);
extern void bta_hf_client_scb_init(void);
extern bool bta_hf_client_hdl_event(BT_HDR* p_msg);
extern void bta_hf_client_sm_execute(uint16_t event,
                                     tBTA_HF_CLIENT_DATA* p_data);
extern void bta_hf_client_slc_seq(tBTA_HF_CLIENT_CB* client_cb, bool error);
extern bool bta_hf_client_allocate_handle(uint16_t* handle);
extern void bta_hf_client_app_callback(uint16_t event, tBTA_HF_CLIENT* data);
extern void bta_hf_client_collision_cback(tBTA_SYS_CONN_STATUS status,
                                          uint8_t id, uint8_t app_id,
                                          BD_ADDR peer_addr);
extern void bta_hf_client_resume_open();
extern void bta_hf_client_resume_open(tBTA_HF_CLIENT_CB* client_cb);
extern tBTA_STATUS bta_hf_client_api_enable(tBTA_HF_CLIENT_CBACK* p_cback,
                                            tBTA_SEC sec_mask,
                                            tBTA_HF_CLIENT_FEAT features,
                                            const char* p_service_name);

extern void bta_hf_client_api_disable(void);
extern void bta_hf_client_dump_statistics(int fd);

/* SDP functions */
extern bool bta_hf_client_add_record(char* p_service_name, uint8_t scn,
                                     tBTA_HF_CLIENT_FEAT features,
                                     uint32_t sdp_handle);
extern void bta_hf_client_create_record(tBTA_HF_CLIENT_CB* client_cb,
extern void bta_hf_client_create_record(tBTA_HF_CLIENT_CB_ARR* client_cb,
                                        const char* p_data);
extern void bta_hf_client_del_record(tBTA_HF_CLIENT_CB* client_cb);
extern void bta_hf_client_del_record(tBTA_HF_CLIENT_CB_ARR* client_cb);
extern bool bta_hf_client_sdp_find_attr(tBTA_HF_CLIENT_CB* client_cb);
extern void bta_hf_client_do_disc(tBTA_HF_CLIENT_CB* client_cb);
extern void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA* p_data);

/* RFCOMM functions */
extern void bta_hf_client_setup_port(uint16_t handle);
extern void bta_hf_client_start_server(tBTA_HF_CLIENT_CB* client_cb);
extern void bta_hf_client_close_server(tBTA_HF_CLIENT_CB* client_cb);
extern void bta_hf_client_start_server();
extern void bta_hf_client_close_server();
extern void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA* p_data);
extern void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA* p_data);

@@ -249,7 +258,8 @@ extern void bta_hf_client_cback_sco(tBTA_HF_CLIENT_CB* client_cb,
/* AT command functions */
extern void bta_hf_client_at_parse(tBTA_HF_CLIENT_CB* client_cb, char* buf,
                                   unsigned int len);
extern void bta_hf_client_send_at_brsf(tBTA_HF_CLIENT_CB* client_cb);
extern void bta_hf_client_send_at_brsf(tBTA_HF_CLIENT_CB* client_cb,
                                       tBTA_HF_CLIENT_FEAT features);
extern void bta_hf_client_send_at_bac(tBTA_HF_CLIENT_CB* client_cb);
extern void bta_hf_client_send_at_cind(tBTA_HF_CLIENT_CB* client_cb,
                                       bool status);
+333 −261

File changed.

Preview size limit exceeded, changes collapsed.

Loading