summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorSudha Bheemanna <b.sudha@samsung.com>2016-09-08 12:37:45 +0530
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:53:15 +0900
commitccfffda9305969ccbf32f18e6c8ba696d632d51b (patch)
tree1a3780a22d6d2c6985b2fd1c38f1099a9af2bdec /net
parent9eedcb2b6671f73072428184f496af2e8963f425 (diff)
Bluetooth: Set the link for SCO connection
This patch sets the link policy for SCO/eSCO connection. Change-Id: I71caef5a3887f73a10329b6886c8cf52b80e8d37 Signed-off-by: Sudha Bheemanna <b.sudha@samsung.com> [add link policy setting in sco connection] Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_event.c29
-rw-r--r--net/bluetooth/sco.c33
2 files changed, 62 insertions, 0 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c2a445101e93..697a140b4302 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -136,6 +136,10 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
struct hci_rp_write_link_policy *rp = (void *) skb->data;
struct hci_conn *conn;
void *sent;
+#ifdef TIZEN_BT
+ struct hci_cp_write_link_policy cp;
+ struct hci_conn *sco_conn;
+#endif
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
@@ -152,6 +156,17 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
if (conn)
conn->link_policy = get_unaligned_le16(sent + 2);
+#ifdef TIZEN_BT
+ sco_conn = hci_conn_hash_lookup_sco(hdev);
+ if (sco_conn && bacmp(&sco_conn->dst, &conn->dst) == 0 &&
+ conn->link_policy & HCI_LP_SNIFF) {
+ BT_ERR("SNIFF is not allowed during sco connection");
+ cp.handle = __cpu_to_le16(conn->handle);
+ cp.policy = __cpu_to_le16(conn->link_policy & ~HCI_LP_SNIFF);
+ hci_send_cmd(hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp);
+ }
+#endif
+
hci_dev_unlock(hdev);
}
@@ -2461,6 +2476,20 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (ie)
memcpy(ie->data.dev_class, ev->dev_class, 3);
+#ifdef TIZEN_BT
+ if ((ev->link_type == SCO_LINK || ev->link_type == ESCO_LINK) &&
+ hci_conn_hash_lookup_sco(hdev)) {
+ struct hci_cp_reject_conn_req cp;
+
+ bacpy(&cp.bdaddr, &ev->bdaddr);
+ cp.reason = HCI_ERROR_REJ_LIMITED_RESOURCES;
+ hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ,
+ sizeof(cp), &cp);
+ hci_dev_unlock(hdev);
+ return;
+ }
+#endif
+
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
&ev->bdaddr);
if (!conn) {
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 805282b2225f..b20345885c82 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -1081,6 +1081,29 @@ static void sco_conn_ready(struct sco_conn *conn)
}
#ifdef TIZEN_BT
+/* Link policy */
+static int hci_write_acl_link_policy(struct hci_conn *hcon, uint16_t policy)
+{
+ struct hci_conn *hcon_acl;
+ struct hci_cp_write_link_policy cp;
+
+ BT_DBG("Write link Policy %d", policy);
+
+ hcon_acl = hci_conn_hash_lookup_ba(hcon->hdev, ACL_LINK, &hcon->dst);
+ if (!hcon_acl) {
+ BT_ERR("ACL does not alive");
+ return -1;
+ }
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = __cpu_to_le16(hcon_acl->handle);
+ cp.policy = __cpu_to_le16(policy);
+
+ hci_send_cmd(hcon_acl->hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp);
+
+ return 0;
+}
+
/* WBC/NBC feature */
void sco_connect_set_gw_nbc(struct hci_dev *hdev)
{
@@ -1282,6 +1305,11 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
conn = sco_conn_add(hcon);
if (conn)
sco_conn_ready(conn);
+
+#ifdef TIZEN_BT
+ /* Link policy */
+ hci_write_acl_link_policy(hcon, HCI_LP_RSWITCH);
+#endif
} else
sco_conn_del(hcon, bt_to_errno(status));
}
@@ -1293,6 +1321,11 @@ static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
BT_DBG("hcon %p reason %d", hcon, reason);
+#ifdef TIZEN_BT
+ /* Link policy */
+ hci_write_acl_link_policy(hcon, HCI_LP_SNIFF | HCI_LP_RSWITCH);
+#endif
+
sco_conn_del(hcon, bt_to_errno(reason));
}