]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/bluetooth/hci_conn.c
Merge branch 'for-linus' of git://codeaurora.org/quic/kernel/davidb/linux-msm
[karo-tx-linux.git] / net / bluetooth / hci_conn.c
index 800b6b9fbbaefe15c90406e7631acd4e25b172b3..6b90a41917347826f2a81fea590124a54af1f9bd 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>
 
@@ -39,7 +39,7 @@
 #include <net/sock.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
@@ -66,7 +66,8 @@ void hci_acl_connect(struct hci_conn *conn)
        bacpy(&cp.bdaddr, &conn->dst);
        cp.pscan_rep_mode = 0x02;
 
-       if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
+       ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
+       if (ie) {
                if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
                        cp.pscan_rep_mode = ie->data.pscan_rep_mode;
                        cp.pscan_mode     = ie->data.pscan_mode;
@@ -155,6 +156,27 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
        hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
 }
 
+/* Device _must_ be locked */
+void hci_sco_setup(struct hci_conn *conn, __u8 status)
+{
+       struct hci_conn *sco = conn->link;
+
+       BT_DBG("%p", conn);
+
+       if (!sco)
+               return;
+
+       if (!status) {
+               if (lmp_esco_capable(conn->hdev))
+                       hci_setup_sync(sco, conn->handle);
+               else
+                       hci_add_sco(sco, conn->handle);
+       } else {
+               hci_proto_connect_cfm(sco, status);
+               hci_conn_del(sco);
+       }
+}
+
 static void hci_conn_timeout(unsigned long arg)
 {
        struct hci_conn *conn = (void *) arg;
@@ -347,8 +369,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
 
        BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
-       if (!(acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst))) {
-               if (!(acl = hci_conn_add(hdev, ACL_LINK, dst)))
+       acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+       if (!acl) {
+               acl = hci_conn_add(hdev, ACL_LINK, dst);
+               if (!acl)
                        return NULL;
        }
 
@@ -368,8 +392,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
        if (type == ACL_LINK)
                return acl;
 
-       if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) {
-               if (!(sco = hci_conn_add(hdev, type, dst))) {
+       sco = hci_conn_hash_lookup_ba(hdev, type, dst);
+       if (!sco) {
+               sco = hci_conn_add(hdev, type, dst);
+               if (!sco) {
                        hci_conn_put(acl);
                        return NULL;
                }
@@ -385,10 +411,13 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
                acl->power_save = 1;
                hci_conn_enter_active_mode(acl);
 
-               if (lmp_esco_capable(hdev))
-                       hci_setup_sync(sco, acl->handle);
-               else
-                       hci_add_sco(sco, acl->handle);
+               if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
+                       /* defer SCO setup until mode change completed */
+                       set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
+                       return sco;
+               }
+
+               hci_sco_setup(acl, 0x00);
        }
 
        return sco;
@@ -623,10 +652,12 @@ int hci_get_conn_list(void __user *arg)
 
        size = sizeof(req) + req.conn_num * sizeof(*ci);
 
-       if (!(cl = kmalloc(size, GFP_KERNEL)))
+       cl = kmalloc(size, GFP_KERNEL);
+       if (!cl)
                return -ENOMEM;
 
-       if (!(hdev = hci_dev_get(req.dev_id))) {
+       hdev = hci_dev_get(req.dev_id);
+       if (!hdev) {
                kfree(cl);
                return -ENODEV;
        }