Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[cascardo/linux.git] / net / bluetooth / hci_conn.c
index c0e56a5..f081712 100644 (file)
 #include <net/bluetooth/a2mp.h>
 #include <net/bluetooth/smp.h>
 
+struct sco_param {
+       u16 pkt_type;
+       u16 max_latency;
+};
+
+static const struct sco_param sco_param_cvsd[] = {
+       { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a }, /* S3 */
+       { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007 }, /* S2 */
+       { EDR_ESCO_MASK | ESCO_EV3,   0x0007 }, /* S1 */
+       { EDR_ESCO_MASK | ESCO_HV3,   0xffff }, /* D1 */
+       { EDR_ESCO_MASK | ESCO_HV1,   0xffff }, /* D0 */
+};
+
+static const struct sco_param sco_param_wideband[] = {
+       { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d }, /* T2 */
+       { EDR_ESCO_MASK | ESCO_EV3,   0x0008 }, /* T1 */
+};
+
 static void hci_le_create_connection(struct hci_conn *conn)
 {
        struct hci_dev *hdev = conn->hdev;
@@ -172,10 +190,11 @@ static void hci_add_sco(struct hci_conn *conn, __u16 handle)
        hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
 }
 
-void hci_setup_sync(struct hci_conn *conn, __u16 handle)
+bool hci_setup_sync(struct hci_conn *conn, __u16 handle)
 {
        struct hci_dev *hdev = conn->hdev;
        struct hci_cp_setup_sync_conn cp;
+       const struct sco_param *param;
 
        BT_DBG("hcon %p", conn);
 
@@ -192,19 +211,28 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
 
        switch (conn->setting & SCO_AIRMODE_MASK) {
        case SCO_AIRMODE_TRANSP:
-               cp.pkt_type = __constant_cpu_to_le16(EDR_ESCO_MASK &
-                                                    ~ESCO_2EV3);
-               cp.max_latency = __constant_cpu_to_le16(0x000d);
+               if (conn->attempt > ARRAY_SIZE(sco_param_wideband))
+                       return false;
                cp.retrans_effort = 0x02;
+               param = &sco_param_wideband[conn->attempt - 1];
                break;
        case SCO_AIRMODE_CVSD:
-               cp.pkt_type = cpu_to_le16(conn->pkt_type);
-               cp.max_latency = __constant_cpu_to_le16(0xffff);
-               cp.retrans_effort = 0xff;
+               if (conn->attempt > ARRAY_SIZE(sco_param_cvsd))
+                       return false;
+               cp.retrans_effort = 0x01;
+               param = &sco_param_cvsd[conn->attempt - 1];
                break;
+       default:
+               return false;
        }
 
-       hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
+       cp.pkt_type = __cpu_to_le16(param->pkt_type);
+       cp.max_latency = __cpu_to_le16(param->max_latency);
+
+       if (hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp) < 0)
+               return false;
+
+       return true;
 }
 
 void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,