Bluetooth: HFP HF: SCO: Handle SCO Disconnect

This patch handles the SCO disconnection part also unref the connected
corresponding ACL conn.

Change-Id: Ic2de68560cfd7d847e6011578c4424e24800d2ac
Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
This commit is contained in:
Sathish Narasimman 2017-02-15 15:18:13 +05:30 committed by Johan Hedberg
commit dcf9a97b18
3 changed files with 45 additions and 1 deletions

View file

@ -191,6 +191,13 @@ static struct bt_conn *conn_new(void)
}
#if defined(CONFIG_BLUETOOTH_BREDR)
void bt_sco_cleanup(struct bt_conn *sco_conn)
{
bt_conn_unref(sco_conn->sco.acl);
sco_conn->sco.acl = NULL;
bt_conn_unref(sco_conn);
}
static struct bt_conn *sco_conn_new(void)
{
struct bt_conn *sco_conn = NULL;
@ -1239,6 +1246,11 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
notify_connected(conn);
break;
case BT_CONN_DISCONNECTED:
if (conn->type == BT_CONN_TYPE_SCO) {
/* TODO: Notify sco disconnected */
bt_conn_unref(conn);
break;
}
/* Notify disconnection and queue a dummy buffer to wake
* up and stop the tx thread for states where it was
* running.
@ -1322,6 +1334,24 @@ struct bt_conn *bt_conn_lookup_handle(uint16_t handle)
}
}
#if defined(CONFIG_BLUETOOTH_BREDR)
for (i = 0; i < ARRAY_SIZE(sco_conns); i++) {
if (!atomic_get(&sco_conns[i].ref)) {
continue;
}
/* We only care about connections with a valid handle */
if (sco_conns[i].state != BT_CONN_CONNECTED &&
sco_conns[i].state != BT_CONN_DISCONNECT) {
continue;
}
if (sco_conns[i].handle == handle) {
return bt_conn_ref(&sco_conns[i]);
}
}
#endif
return NULL;
}

View file

@ -127,6 +127,9 @@ struct bt_conn *bt_conn_add_br(const bt_addr_t *peer);
/* Add a new SCO connection */
struct bt_conn *bt_conn_add_sco(const bt_addr_t *peer, int link_type);
/* Cleanup SCO references */
void bt_sco_cleanup(struct bt_conn *sco_conn);
/* Look up an existing sco connection by BT address */
struct bt_conn *bt_conn_lookup_addr_sco(const bt_addr_t *peer);

View file

@ -567,6 +567,10 @@ static void hci_disconn_complete(struct net_buf *buf)
if (conn->type != BT_CONN_TYPE_LE) {
#if defined(CONFIG_BLUETOOTH_BREDR)
if (conn->type == BT_CONN_TYPE_SCO) {
bt_sco_cleanup(conn);
return;
}
/*
* If only for one connection session bond was set, clear keys
* database row for this connection.
@ -1058,7 +1062,14 @@ static void bt_esco_conn_req(struct bt_hci_evt_conn_request *evt)
return;
}
accept_sco_conn(&evt->bdaddr, sco_conn);
if (accept_sco_conn(&evt->bdaddr, sco_conn)) {
BT_ERR("Error accepting connection from %s",
bt_addr_str(&evt->bdaddr));
reject_conn(&evt->bdaddr, BT_HCI_ERR_UNSPECIFIED);
bt_sco_cleanup(sco_conn);
return;
}
sco_conn->role = BT_HCI_ROLE_SLAVE;
bt_conn_set_state(sco_conn, BT_CONN_CONNECT);
bt_conn_unref(sco_conn);