Bluetooth: Defer SCO setup if mode change is pending
[pandora-kernel.git] / net / bluetooth / hci_event.c
index 592da5c..bfef5ba 100644 (file)
@@ -1,6 +1,6 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
-   Copyright (C) 2000-2001 Qualcomm Incorporated
+   Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -584,7 +584,7 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
                                conn->out = 1;
                                conn->link_mode |= HCI_LM_MASTER;
                        } else
-                               BT_ERR("No memmory for new connection");
+                               BT_ERR("No memory for new connection");
                }
        }
 
@@ -785,9 +785,13 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
        hci_dev_lock(hdev);
 
        conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
-       if (conn)
+       if (conn) {
                clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
 
+               if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+                       hci_sco_setup(conn, status);
+       }
+
        hci_dev_unlock(hdev);
 }
 
@@ -808,9 +812,13 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
        hci_dev_lock(hdev);
 
        conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
-       if (conn)
+       if (conn) {
                clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
 
+               if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+                       hci_sco_setup(conn, status);
+       }
+
        hci_dev_unlock(hdev);
 }
 
@@ -915,20 +923,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
        } else
                conn->state = BT_CLOSED;
 
-       if (conn->type == ACL_LINK) {
-               struct hci_conn *sco = conn->link;
-               if (sco) {
-                       if (!ev->status) {
-                               if (lmp_esco_capable(hdev))
-                                       hci_setup_sync(sco, conn->handle);
-                               else
-                                       hci_add_sco(sco, conn->handle);
-                       } else {
-                               hci_proto_connect_cfm(sco, ev->status);
-                               hci_conn_del(sco);
-                       }
-               }
-       }
+       if (conn->type == ACL_LINK)
+               hci_sco_setup(conn, ev->status);
 
        if (ev->status) {
                hci_proto_connect_cfm(conn, ev->status);
@@ -952,7 +948,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
 
        mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
 
-       if (mask & HCI_LM_ACCEPT) {
+       if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
                /* Connection accepted */
                struct inquiry_entry *ie;
                struct hci_conn *conn;
@@ -965,7 +961,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
                conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
                if (!conn) {
                        if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
-                               BT_ERR("No memmory for new connection");
+                               BT_ERR("No memory for new connection");
                                hci_dev_unlock(hdev);
                                return;
                        }
@@ -1049,6 +1045,8 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
        if (conn) {
                if (!ev->status)
                        conn->link_mode |= HCI_LM_AUTH;
+               else
+                       conn->sec_level = BT_SECURITY_LOW;
 
                clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
 
@@ -1479,6 +1477,9 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
                        else
                                conn->power_save = 0;
                }
+
+               if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+                       hci_sco_setup(conn, ev->status);
        }
 
        hci_dev_unlock(hdev);
@@ -1698,6 +1699,7 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu
                hci_conn_add_sysfs(conn);
                break;
 
+       case 0x11:      /* Unsupported Feature or Parameter Value */
        case 0x1c:      /* SCO interval rejected */
        case 0x1a:      /* Unsupported Remote Feature */
        case 0x1f:      /* Unspecified error */