Bluetooth: Added support for HFP 1.6 Wide Band Speech
Signed-off-by: Kun Han Kim <kunhank@codeaurora.org>
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 9fda323..aa6aeb9 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -160,11 +160,25 @@
#define ESCO_2EV5 0x0100
#define ESCO_3EV5 0x0200
+#define ESCO_WBS (ESCO_EV3 | (EDR_ESCO_MASK ^ ESCO_2EV3))
+
#define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
#define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5)
#define ALL_ESCO_MASK (SCO_ESCO_MASK | ESCO_EV3 | ESCO_EV4 | ESCO_EV5 | \
EDR_ESCO_MASK)
+/* Air Coding Format */
+#define ACF_CVSD 0x0000;
+#define ACF_ULAW 0x0001;
+#define ACF_ALAW 0x0002;
+#define ACF_TRANS 0x0003;
+
+/* Retransmission Effort */
+#define RE_NO_RETRANS 0x00;
+#define RE_POWER_CONSUMP 0x01;
+#define RE_LINK_QUALITY 0x02;
+#define RE_DONT_CARE 0xFF;
+
/* ACL flags */
#define ACL_START_NO_FLUSH 0x00
#define ACL_CONT 0x01
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 41af2dd..f6eb639 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -171,6 +171,8 @@
__u32 amp_max_flush_to;
__u32 amp_be_flush_to;
+ __s8 is_wbs;
+
unsigned long quirks;
atomic_t cmd_cnt;
diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
index 6d1857a..160e3f0 100644
--- a/include/net/bluetooth/sco.h
+++ b/include/net/bluetooth/sco.h
@@ -1,6 +1,7 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2011, Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -38,6 +39,7 @@
sa_family_t sco_family;
bdaddr_t sco_bdaddr;
__u16 sco_pkt_type;
+ __s8 is_wbs;
};
/* SCO socket options */
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index bcc65ff..7ee9ff0 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -181,13 +181,23 @@
conn->attempt++;
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(0x000A);
- cp.voice_setting = cpu_to_le16(hdev->voice_setting);
- cp.retrans_effort = 0x01;
+ if (conn->hdev->is_wbs) {
+ /* Transparent Data */
+ uint16_t voice_setting = hdev->voice_setting | ACF_TRANS;
+ cp.max_latency = cpu_to_le16(0x000D);
+ cp.pkt_type = cpu_to_le16(ESCO_WBS);
+ cp.voice_setting = cpu_to_le16(voice_setting);
+ /* Retransmission Effort */
+ cp.retrans_effort = RE_LINK_QUALITY;
+ } else {
+ cp.max_latency = cpu_to_le16(0x000A);
+ cp.pkt_type = cpu_to_le16(conn->pkt_type);
+ cp.voice_setting = cpu_to_le16(hdev->voice_setting);
+ cp.retrans_effort = RE_POWER_CONSUMP;
+ }
hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0c731f9..43ad520 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2739,7 +2739,9 @@
case 0x1a: /* Unsupported Remote Feature */
case 0x1f: /* Unspecified error */
if (conn->out && conn->attempt < 2) {
- conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
+ if (!conn->hdev->is_wbs)
+ conn->pkt_type =
+ (hdev->esco_type & SCO_ESCO_MASK) |
(hdev->esco_type & EDR_ESCO_MASK);
hci_setup_sync(conn, conn->link->handle);
goto unlock;
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index e692b9d..3b1e54c 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -1,6 +1,7 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2011, Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -173,7 +174,7 @@
return err;
}
-static int sco_connect(struct sock *sk)
+static int sco_connect(struct sock *sk, __s8 is_wbs)
{
bdaddr_t *src = &bt_sk(sk)->src;
bdaddr_t *dst = &bt_sk(sk)->dst;
@@ -191,13 +192,19 @@
hci_dev_lock_bh(hdev);
- if (lmp_esco_capable(hdev) && !disable_esco)
+ hdev->is_wbs = is_wbs;
+
+ if (lmp_esco_capable(hdev) && !disable_esco) {
type = ESCO_LINK;
- else {
+ } else if (is_wbs) {
+ return -ENAVAIL;
+ } else {
type = SCO_LINK;
pkt_type &= SCO_ESCO_MASK;
}
+ BT_DBG("type: %d, pkt_type: 0x%x", type, pkt_type);
+
hcon = hci_connect(hdev, type, pkt_type, dst,
BT_SECURITY_LOW, HCI_AT_NO_BONDING);
if (IS_ERR(hcon)) {
@@ -205,6 +212,13 @@
goto done;
}
+ if (is_wbs && (hcon->type != ESCO_LINK)) {
+ BT_ERR("WBS [ hcon->type: 0x%x, hcon->pkt_type: 0x%x ]",
+ hcon->type, hcon->pkt_type);
+ err = -EREMOTEIO;
+ goto done;
+ }
+
conn = sco_conn_add(hcon, 0);
if (!conn) {
hci_conn_put(hcon);
@@ -527,7 +541,7 @@
bacpy(&bt_sk(sk)->dst, &sa.sco_bdaddr);
sco_pi(sk)->pkt_type = sa.sco_pkt_type;
- err = sco_connect(sk);
+ err = sco_connect(sk, sa.is_wbs);
if (err)
goto done;