Bluetooth: Implement deferred sco socket setup
In order to authenticate and configure an incoming SCO connection, the BT_DEFER_SETUP option was added. This option is intended to defer reply to Connect Request on SCO sockets. When a connection is requested, the listening socket is unblocked but the effective connection setup happens only on first recv. Any send between accept and recv fails with -ENOTCONN. Signed-off-by: Frédéric Dalleau <frederic.dalleau@linux.intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
This commit is contained in:

committed by
Gustavo Padovan

parent
b96e9c671b
commit
20714bfef8
@@ -2047,15 +2047,53 @@ unlock:
|
||||
hci_conn_check_pending(hdev);
|
||||
}
|
||||
|
||||
void hci_conn_accept(struct hci_conn *conn, int mask)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
conn->state = BT_CONFIG;
|
||||
|
||||
if (!lmp_esco_capable(hdev)) {
|
||||
struct hci_cp_accept_conn_req cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
|
||||
if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
|
||||
cp.role = 0x00; /* Become master */
|
||||
else
|
||||
cp.role = 0x01; /* Remain slave */
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
|
||||
} else /* lmp_esco_capable(hdev)) */ {
|
||||
struct hci_cp_accept_sync_conn_req cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
cp.pkt_type = cpu_to_le16(conn->pkt_type);
|
||||
|
||||
cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
|
||||
cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
|
||||
cp.max_latency = __constant_cpu_to_le16(0xffff);
|
||||
cp.content_format = cpu_to_le16(hdev->voice_setting);
|
||||
cp.retrans_effort = 0xff;
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_conn_request *ev = (void *) skb->data;
|
||||
int mask = hdev->link_mode;
|
||||
__u8 flags = 0;
|
||||
|
||||
BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
|
||||
ev->link_type);
|
||||
|
||||
mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
|
||||
mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
|
||||
&flags);
|
||||
|
||||
if ((mask & HCI_LM_ACCEPT) &&
|
||||
!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
|
||||
@@ -2081,12 +2119,13 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
memcpy(conn->dev_class, ev->dev_class, 3);
|
||||
conn->state = BT_CONNECT;
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
|
||||
if (ev->link_type == ACL_LINK ||
|
||||
(!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
|
||||
struct hci_cp_accept_conn_req cp;
|
||||
conn->state = BT_CONNECT;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
|
||||
@@ -2097,8 +2136,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
|
||||
&cp);
|
||||
} else {
|
||||
} else if (!(flags & HCI_PROTO_DEFER)) {
|
||||
struct hci_cp_accept_sync_conn_req cp;
|
||||
conn->state = BT_CONNECT;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
cp.pkt_type = cpu_to_le16(conn->pkt_type);
|
||||
@@ -2111,6 +2151,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
|
||||
sizeof(cp), &cp);
|
||||
} else {
|
||||
conn->state = BT_CONNECT2;
|
||||
hci_proto_connect_cfm(conn, 0);
|
||||
hci_conn_put(conn);
|
||||
}
|
||||
} else {
|
||||
/* Connection rejected */
|
||||
|
Reference in New Issue
Block a user