Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / bluetooth / sco.c
index 2c80553505107540f75c1d4521f8a61e900b61cd..373d81e6e8f0af0a6cc33bbdf0d7c6e905726db5 100644 (file)
@@ -83,7 +83,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
        if (conn)
                return conn;
 
-       conn = kzalloc(sizeof(struct sco_conn), GFP_ATOMIC);
+       conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
        if (!conn)
                return NULL;
 
@@ -185,7 +185,7 @@ static int sco_connect(struct sock *sk)
 
        conn = sco_conn_add(hcon);
        if (!conn) {
-               hci_conn_put(hcon);
+               hci_conn_drop(hcon);
                err = -ENOMEM;
                goto done;
        }
@@ -353,7 +353,7 @@ static void __sco_sock_close(struct sock *sk)
                if (sco_pi(sk)->conn->hcon) {
                        sk->sk_state = BT_DISCONN;
                        sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
-                       hci_conn_put(sco_pi(sk)->conn->hcon);
+                       hci_conn_drop(sco_pi(sk)->conn->hcon);
                        sco_pi(sk)->conn->hcon = NULL;
                } else
                        sco_chan_del(sk, ECONNRESET);
@@ -481,8 +481,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
 {
        struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
        struct sock *sk = sock->sk;
-       int err = 0;
-
+       int err;
 
        BT_DBG("sk %p", sk);
 
@@ -653,6 +652,42 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        return err;
 }
 
+static void sco_conn_defer_accept(struct hci_conn *conn, int mask)
+{
+       struct hci_dev *hdev = conn->hdev;
+
+       BT_DBG("conn %p", conn);
+
+       conn->state = BT_CONFIG;
+
+       if (!lmp_esco_capable(hdev)) {
+               struct hci_cp_accept_conn_req cp;
+
+               bacpy(&cp.bdaddr, &conn->dst);
+
+               if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+                       cp.role = 0x00; /* Become master */
+               else
+                       cp.role = 0x01; /* Remain slave */
+
+               hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+       } else {
+               struct hci_cp_accept_sync_conn_req cp;
+
+               bacpy(&cp.bdaddr, &conn->dst);
+               cp.pkt_type = cpu_to_le16(conn->pkt_type);
+
+               cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
+               cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
+               cp.max_latency    = __constant_cpu_to_le16(0xffff);
+               cp.content_format = cpu_to_le16(hdev->voice_setting);
+               cp.retrans_effort = 0xff;
+
+               hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
+                            sizeof(cp), &cp);
+       }
+}
+
 static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                            struct msghdr *msg, size_t len, int flags)
 {
@@ -663,7 +698,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (sk->sk_state == BT_CONNECT2 &&
            test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
-               hci_conn_accept(pi->conn->hcon, 0);
+               sco_conn_defer_accept(pi->conn->hcon, 0);
                sk->sk_state = BT_CONFIG;
                msg->msg_namelen = 0;
 
@@ -883,7 +918,7 @@ static void sco_chan_del(struct sock *sk, int err)
                sco_conn_unlock(conn);
 
                if (conn->hcon)
-                       hci_conn_put(conn->hcon);
+                       hci_conn_drop(conn->hcon);
        }
 
        sk->sk_state = BT_CLOSED;