aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_conn.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2010-07-26 10:06:00 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-07-27 15:29:04 -0400
commite73439d8c0e4c522c843b8bb98c0eb5700da6b05 (patch)
tree0ca070acc02700061380bd40315e39684b3e59fa /net/bluetooth/hci_conn.c
parent800f65bba8d2030b3fef62850e203f9f176625a8 (diff)
Bluetooth: Defer SCO setup if mode change is pending
Certain headsets such as the Motorola H350 will reject SCO and eSCO connection requests while the ACL is transitioning from sniff mode to active mode. Add synchronization so that SCO and eSCO connection requests will wait until the ACL has fully transitioned to active mode. < HCI Command: Exit Sniff Mode (0x02|0x0004) plen 2 handle 12 > HCI Event: Command Status (0x0f) plen 4 Exit Sniff Mode (0x02|0x0004) status 0x00 ncmd 1 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 12 voice setting 0x0040 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 > HCI Event: Number of Completed Packets (0x13) plen 5 handle 12 packets 1 > HCI Event: Mode Change (0x14) plen 6 status 0x00 handle 12 mode 0x00 interval 0 Mode: Active > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x10 handle 14 bdaddr 00:1A:0E:50:28:A4 type SCO Error: Connection Accept Timeout Exceeded Signed-off-by: Ron Shaffer <rshaffer@codeaurora.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r--net/bluetooth/hci_conn.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index e9fef83449f8..0b1e460fe440 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -155,6 +155,27 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
155 hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp); 155 hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
156} 156}
157 157
158/* Device _must_ be locked */
159void hci_sco_setup(struct hci_conn *conn, __u8 status)
160{
161 struct hci_conn *sco = conn->link;
162
163 BT_DBG("%p", conn);
164
165 if (!sco)
166 return;
167
168 if (!status) {
169 if (lmp_esco_capable(conn->hdev))
170 hci_setup_sync(sco, conn->handle);
171 else
172 hci_add_sco(sco, conn->handle);
173 } else {
174 hci_proto_connect_cfm(sco, status);
175 hci_conn_del(sco);
176 }
177}
178
158static void hci_conn_timeout(unsigned long arg) 179static void hci_conn_timeout(unsigned long arg)
159{ 180{
160 struct hci_conn *conn = (void *) arg; 181 struct hci_conn *conn = (void *) arg;
@@ -385,10 +406,13 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
385 acl->power_save = 1; 406 acl->power_save = 1;
386 hci_conn_enter_active_mode(acl); 407 hci_conn_enter_active_mode(acl);
387 408
388 if (lmp_esco_capable(hdev)) 409 if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
389 hci_setup_sync(sco, acl->handle); 410 /* defer SCO setup until mode change completed */
390 else 411 set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
391 hci_add_sco(sco, acl->handle); 412 return sco;
413 }
414
415 hci_sco_setup(acl, 0x00);
392 } 416 }
393 417
394 return sco; 418 return sco;