aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2006-10-15 11:30:56 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-10-16 02:14:30 -0400
commit4c67bc74f016b0d360b8573e18969c0ff7926974 (patch)
treed5eec3da59b642f48e7fcc2034b6d90b5fa54e01
parente9c4bec63eac001651d6d30239dd4175cc3698ef (diff)
[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>
-rw-r--r--include/net/bluetooth/hci_core.h17
-rw-r--r--net/bluetooth/af_bluetooth.c2
-rw-r--r--net/bluetooth/hci_conn.c6
-rw-r--r--net/bluetooth/hci_event.c15
4 files changed, 33 insertions, 7 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index df22efcfcc0b..c0fc39620f36 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -153,6 +153,7 @@ struct hci_conn {
153 __u8 mode; 153 __u8 mode;
154 __u8 type; 154 __u8 type;
155 __u8 out; 155 __u8 out;
156 __u8 attempt;
156 __u8 dev_class[3]; 157 __u8 dev_class[3];
157 __u8 features[8]; 158 __u8 features[8];
158 __u16 interval; 159 __u16 interval;
@@ -289,6 +290,22 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
289 return NULL; 290 return NULL;
290} 291}
291 292
293static 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
308void hci_acl_connect(struct hci_conn *conn);
292void hci_acl_disconn(struct hci_conn *conn, __u8 reason); 309void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
293void hci_add_sco(struct hci_conn *conn, __u16 handle); 310void hci_add_sco(struct hci_conn *conn, __u16 handle);
294 311
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 305a099b7477..a91fee4f2705 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -48,7 +48,7 @@
48#define BT_DBG(D...) 48#define BT_DBG(D...)
49#endif 49#endif
50 50
51#define VERSION "2.10" 51#define VERSION "2.11"
52 52
53/* Bluetooth sockets */ 53/* Bluetooth sockets */
54#define BT_MAX_PROTO 8 54#define BT_MAX_PROTO 8
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 90e3a285a17e..6cd5711fa28a 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -51,7 +51,7 @@
51#define BT_DBG(D...) 51#define BT_DBG(D...)
52#endif 52#endif
53 53
54static void hci_acl_connect(struct hci_conn *conn) 54void hci_acl_connect(struct hci_conn *conn)
55{ 55{
56 struct hci_dev *hdev = conn->hdev; 56 struct hci_dev *hdev = conn->hdev;
57 struct inquiry_entry *ie; 57 struct inquiry_entry *ie;
@@ -63,6 +63,8 @@ static void hci_acl_connect(struct hci_conn *conn)
63 conn->out = 1; 63 conn->out = 1;
64 conn->link_mode = HCI_LM_MASTER; 64 conn->link_mode = HCI_LM_MASTER;
65 65
66 conn->attempt++;
67
66 memset(&cp, 0, sizeof(cp)); 68 memset(&cp, 0, sizeof(cp));
67 bacpy(&cp.bdaddr, &conn->dst); 69 bacpy(&cp.bdaddr, &conn->dst);
68 cp.pscan_rep_mode = 0x02; 70 cp.pscan_rep_mode = 0x02;
@@ -80,7 +82,7 @@ static void hci_acl_connect(struct hci_conn *conn)
80 cp.role_switch = 0x01; 82 cp.role_switch = 0x01;
81 else 83 else
82 cp.role_switch = 0x00; 84 cp.role_switch = 0x00;
83 85
84 hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp); 86 hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
85} 87}
86 88
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d43d0c890975..65f094845719 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -414,9 +414,12 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
414 414
415 if (status) { 415 if (status) {
416 if (conn && conn->state == BT_CONNECT) { 416 if (conn && conn->state == BT_CONNECT) {
417 conn->state = BT_CLOSED; 417 if (status != 0x0c || conn->attempt > 2) {
418 hci_proto_connect_cfm(conn, status); 418 conn->state = BT_CLOSED;
419 hci_conn_del(conn); 419 hci_proto_connect_cfm(conn, status);
420 hci_conn_del(conn);
421 } else
422 conn->state = BT_CONNECT2;
420 } 423 }
421 } else { 424 } else {
422 if (!conn) { 425 if (!conn) {
@@ -728,7 +731,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
728static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 731static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
729{ 732{
730 struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data; 733 struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
731 struct hci_conn *conn; 734 struct hci_conn *conn, *pend;
732 735
733 BT_DBG("%s", hdev->name); 736 BT_DBG("%s", hdev->name);
734 737
@@ -801,6 +804,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
801 if (ev->status) 804 if (ev->status)
802 hci_conn_del(conn); 805 hci_conn_del(conn);
803 806
807 pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
808 if (pend)
809 hci_acl_connect(pend);
810
804 hci_dev_unlock(hdev); 811 hci_dev_unlock(hdev);
805} 812}
806 813