Skip to content

Commit 4c67bc7

Browse files
holtmannDavid S. Miller
authored andcommitted
[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 <[email protected]>
1 parent e9c4bec commit 4c67bc7

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ struct hci_conn {
153153
__u8 mode;
154154
__u8 type;
155155
__u8 out;
156+
__u8 attempt;
156157
__u8 dev_class[3];
157158
__u8 features[8];
158159
__u16 interval;
@@ -289,6 +290,22 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
289290
return NULL;
290291
}
291292

293+
static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
294+
__u8 type, __u16 state)
295+
{
296+
struct hci_conn_hash *h = &hdev->conn_hash;
297+
struct list_head *p;
298+
struct hci_conn *c;
299+
300+
list_for_each(p, &h->list) {
301+
c = list_entry(p, struct hci_conn, list);
302+
if (c->type == type && c->state == state)
303+
return c;
304+
}
305+
return NULL;
306+
}
307+
308+
void hci_acl_connect(struct hci_conn *conn);
292309
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
293310
void hci_add_sco(struct hci_conn *conn, __u16 handle);
294311

net/bluetooth/af_bluetooth.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
#define BT_DBG(D...)
4949
#endif
5050

51-
#define VERSION "2.10"
51+
#define VERSION "2.11"
5252

5353
/* Bluetooth sockets */
5454
#define BT_MAX_PROTO 8

net/bluetooth/hci_conn.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
#define BT_DBG(D...)
5252
#endif
5353

54-
static void hci_acl_connect(struct hci_conn *conn)
54+
void hci_acl_connect(struct hci_conn *conn)
5555
{
5656
struct hci_dev *hdev = conn->hdev;
5757
struct inquiry_entry *ie;
@@ -63,6 +63,8 @@ static void hci_acl_connect(struct hci_conn *conn)
6363
conn->out = 1;
6464
conn->link_mode = HCI_LM_MASTER;
6565

66+
conn->attempt++;
67+
6668
memset(&cp, 0, sizeof(cp));
6769
bacpy(&cp.bdaddr, &conn->dst);
6870
cp.pscan_rep_mode = 0x02;
@@ -80,7 +82,7 @@ static void hci_acl_connect(struct hci_conn *conn)
8082
cp.role_switch = 0x01;
8183
else
8284
cp.role_switch = 0x00;
83-
85+
8486
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
8587
}
8688

net/bluetooth/hci_event.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -414,9 +414,12 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
414414

415415
if (status) {
416416
if (conn && conn->state == BT_CONNECT) {
417-
conn->state = BT_CLOSED;
418-
hci_proto_connect_cfm(conn, status);
419-
hci_conn_del(conn);
417+
if (status != 0x0c || conn->attempt > 2) {
418+
conn->state = BT_CLOSED;
419+
hci_proto_connect_cfm(conn, status);
420+
hci_conn_del(conn);
421+
} else
422+
conn->state = BT_CONNECT2;
420423
}
421424
} else {
422425
if (!conn) {
@@ -728,7 +731,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
728731
static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
729732
{
730733
struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
731-
struct hci_conn *conn;
734+
struct hci_conn *conn, *pend;
732735

733736
BT_DBG("%s", hdev->name);
734737

@@ -801,6 +804,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
801804
if (ev->status)
802805
hci_conn_del(conn);
803806

807+
pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
808+
if (pend)
809+
hci_acl_connect(pend);
810+
804811
hci_dev_unlock(hdev);
805812
}
806813

0 commit comments

Comments
 (0)