aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.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_event.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_event.c')
-rw-r--r--net/bluetooth/hci_event.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 2069c3b05fda..bfef5bae0b3a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -785,9 +785,13 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
785 hci_dev_lock(hdev); 785 hci_dev_lock(hdev);
786 786
787 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 787 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
788 if (conn) 788 if (conn) {
789 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 789 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
790 790
791 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
792 hci_sco_setup(conn, status);
793 }
794
791 hci_dev_unlock(hdev); 795 hci_dev_unlock(hdev);
792} 796}
793 797
@@ -808,9 +812,13 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
808 hci_dev_lock(hdev); 812 hci_dev_lock(hdev);
809 813
810 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 814 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
811 if (conn) 815 if (conn) {
812 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 816 clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
813 817
818 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
819 hci_sco_setup(conn, status);
820 }
821
814 hci_dev_unlock(hdev); 822 hci_dev_unlock(hdev);
815} 823}
816 824
@@ -915,20 +923,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
915 } else 923 } else
916 conn->state = BT_CLOSED; 924 conn->state = BT_CLOSED;
917 925
918 if (conn->type == ACL_LINK) { 926 if (conn->type == ACL_LINK)
919 struct hci_conn *sco = conn->link; 927 hci_sco_setup(conn, ev->status);
920 if (sco) {
921 if (!ev->status) {
922 if (lmp_esco_capable(hdev))
923 hci_setup_sync(sco, conn->handle);
924 else
925 hci_add_sco(sco, conn->handle);
926 } else {
927 hci_proto_connect_cfm(sco, ev->status);
928 hci_conn_del(sco);
929 }
930 }
931 }
932 928
933 if (ev->status) { 929 if (ev->status) {
934 hci_proto_connect_cfm(conn, ev->status); 930 hci_proto_connect_cfm(conn, ev->status);
@@ -1481,6 +1477,9 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
1481 else 1477 else
1482 conn->power_save = 0; 1478 conn->power_save = 0;
1483 } 1479 }
1480
1481 if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
1482 hci_sco_setup(conn, ev->status);
1484 } 1483 }
1485 1484
1486 hci_dev_unlock(hdev); 1485 hci_dev_unlock(hdev);