[Bluetooth] Make use of the default link policy settings
[pandora-kernel.git] / net / bluetooth / hci_conn.c
index 797a30b..6175ce8 100644 (file)
@@ -59,11 +59,14 @@ void hci_acl_connect(struct hci_conn *conn)
        BT_DBG("%p", conn);
 
        conn->state = BT_CONNECT;
-       conn->out   = 1;
+       conn->out = 1;
+
        conn->link_mode = HCI_LM_MASTER;
 
        conn->attempt++;
 
+       conn->link_policy = hdev->link_policy;
+
        memset(&cp, 0, sizeof(cp));
        bacpy(&cp.bdaddr, &conn->dst);
        cp.pscan_rep_mode = 0x02;
@@ -76,11 +79,11 @@ void hci_acl_connect(struct hci_conn *conn)
                memcpy(conn->dev_class, ie->data.dev_class, 3);
        }
 
-       cp.pkt_type = cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK);
+       cp.pkt_type = cpu_to_le16(conn->pkt_type);
        if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
-               cp.role_switch  = 0x01;
+               cp.role_switch = 0x01;
        else
-               cp.role_switch  = 0x00;
+               cp.role_switch = 0x00;
 
        hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
 }
@@ -122,11 +125,33 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
        conn->out = 1;
 
        cp.handle   = cpu_to_le16(handle);
-       cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
+       cp.pkt_type = cpu_to_le16(conn->pkt_type);
 
        hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
 }
 
+void hci_setup_sync(struct hci_conn *conn, __u16 handle)
+{
+       struct hci_dev *hdev = conn->hdev;
+       struct hci_cp_setup_sync_conn cp;
+
+       BT_DBG("%p", conn);
+
+       conn->state = BT_CONNECT;
+       conn->out = 1;
+
+       cp.handle   = cpu_to_le16(handle);
+       cp.pkt_type = cpu_to_le16(conn->pkt_type);
+
+       cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
+       cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
+       cp.max_latency    = cpu_to_le16(0xffff);
+       cp.voice_setting  = cpu_to_le16(hdev->voice_setting);
+       cp.retrans_effort = 0xff;
+
+       hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
+}
+
 static void hci_conn_timeout(unsigned long arg)
 {
        struct hci_conn *conn = (void *) arg;
@@ -141,7 +166,10 @@ static void hci_conn_timeout(unsigned long arg)
 
        switch (conn->state) {
        case BT_CONNECT:
-               hci_acl_connect_cancel(conn);
+               if (conn->type == ACL_LINK)
+                       hci_acl_connect_cancel(conn);
+               else
+                       hci_acl_disconn(conn, 0x13);
                break;
        case BT_CONNECTED:
                hci_acl_disconn(conn, 0x13);
@@ -174,22 +202,32 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
                return NULL;
 
        bacpy(&conn->dst, dst);
-       conn->hdev   = hdev;
-       conn->type   = type;
-       conn->mode   = HCI_CM_ACTIVE;
-       conn->state  = BT_OPEN;
+       conn->hdev  = hdev;
+       conn->type  = type;
+       conn->mode  = HCI_CM_ACTIVE;
+       conn->state = BT_OPEN;
 
        conn->power_save = 1;
 
-       skb_queue_head_init(&conn->data_q);
+       switch (type) {
+       case ACL_LINK:
+               conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
+               break;
+       case SCO_LINK:
+               if (lmp_esco_capable(hdev))
+                       conn->pkt_type = hdev->esco_type & SCO_ESCO_MASK;
+               else
+                       conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
+               break;
+       case ESCO_LINK:
+               conn->pkt_type = hdev->esco_type;
+               break;
+       }
 
-       init_timer(&conn->disc_timer);
-       conn->disc_timer.function = hci_conn_timeout;
-       conn->disc_timer.data = (unsigned long) conn;
+       skb_queue_head_init(&conn->data_q);
 
-       init_timer(&conn->idle_timer);
-       conn->idle_timer.function = hci_conn_idle;
-       conn->idle_timer.data = (unsigned long) conn;
+       setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
+       setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
 
        atomic_set(&conn->refcnt, 0);
 
@@ -234,21 +272,12 @@ int hci_conn_del(struct hci_conn *conn)
        }
 
        tasklet_disable(&hdev->tx_task);
-
-       hci_conn_del_sysfs(conn);
-
        hci_conn_hash_del(hdev, conn);
        if (hdev->notify)
                hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
-
        tasklet_enable(&hdev->tx_task);
-
        skb_queue_purge(&conn->data_q);
-
-       hci_dev_put(hdev);
-
-       /* will free via device release */
-       put_device(&conn->dev);
+       hci_conn_del_sysfs(conn);
 
        return 0;
 }
@@ -328,8 +357,12 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
        hci_conn_hold(sco);
 
        if (acl->state == BT_CONNECTED &&
-                       (sco->state == BT_OPEN || sco->state == BT_CLOSED))
-               hci_add_sco(sco, acl->handle);
+                       (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
+               if (lmp_esco_capable(hdev))
+                       hci_setup_sync(sco, acl->handle);
+               else
+                       hci_add_sco(sco, acl->handle);
+       }
 
        return sco;
 }