[Bluetooth] Support concurrent connect requests
Most Bluetooth chips don't support concurrent connect requests, because this would involve a multiple baseband page with only one radio. In the case an upper layer like L2CAP requests a concurrent connect these chips return the error "Command Disallowed" for the second request. If this happens it the responsibility of the Bluetooth core to queue the request and try again after the previous connect attempt has been completed. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
committed by
David S. Miller
parent
e9c4bec63e
commit
4c67bc74f0
@ -48,7 +48,7 @@
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "2.10"
|
||||
#define VERSION "2.11"
|
||||
|
||||
/* Bluetooth sockets */
|
||||
#define BT_MAX_PROTO 8
|
||||
|
@ -51,7 +51,7 @@
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
static void hci_acl_connect(struct hci_conn *conn)
|
||||
void hci_acl_connect(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
struct inquiry_entry *ie;
|
||||
@ -63,6 +63,8 @@ static void hci_acl_connect(struct hci_conn *conn)
|
||||
conn->out = 1;
|
||||
conn->link_mode = HCI_LM_MASTER;
|
||||
|
||||
conn->attempt++;
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
cp.pscan_rep_mode = 0x02;
|
||||
@ -80,7 +82,7 @@ static void hci_acl_connect(struct hci_conn *conn)
|
||||
cp.role_switch = 0x01;
|
||||
else
|
||||
cp.role_switch = 0x00;
|
||||
|
||||
|
||||
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
|
@ -414,9 +414,12 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
|
||||
|
||||
if (status) {
|
||||
if (conn && conn->state == BT_CONNECT) {
|
||||
conn->state = BT_CLOSED;
|
||||
hci_proto_connect_cfm(conn, status);
|
||||
hci_conn_del(conn);
|
||||
if (status != 0x0c || conn->attempt > 2) {
|
||||
conn->state = BT_CLOSED;
|
||||
hci_proto_connect_cfm(conn, status);
|
||||
hci_conn_del(conn);
|
||||
} else
|
||||
conn->state = BT_CONNECT2;
|
||||
}
|
||||
} else {
|
||||
if (!conn) {
|
||||
@ -728,7 +731,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
|
||||
static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
|
||||
struct hci_conn *conn;
|
||||
struct hci_conn *conn, *pend;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
@ -801,6 +804,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
|
||||
if (ev->status)
|
||||
hci_conn_del(conn);
|
||||
|
||||
pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
|
||||
if (pend)
|
||||
hci_acl_connect(pend);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user