Merge "bluetooth: Add support for LE conn param" into msm-3.4
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index eb89f4b..3526e29 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1334,6 +1334,15 @@
__u8 data[0];
} __packed;
+#define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03
+struct hci_ev_le_conn_update_complete {
+ __u8 status;
+ __le16 handle;
+ __le16 interval;
+ __le16 latency;
+ __le16 supervision_timeout;
+} __packed;
+
#define HCI_EV_LE_LTK_REQ 0x05
struct hci_ev_le_ltk_req {
__le16 handle;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 47b856c..22428c1 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1033,6 +1033,8 @@
int mgmt_connectable(u16 index, u8 connectable);
int mgmt_new_key(u16 index, struct link_key *key, u8 bonded);
int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le);
+int mgmt_le_conn_params(u16 index, bdaddr_t *bdaddr, u16 interval,
+ u16 latency, u16 timeout);
int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
int mgmt_disconnect_failed(u16 index);
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index e34c425..3048339 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -379,3 +379,11 @@
bdaddr_t bdaddr;
__s8 rssi;
} __packed;
+
+#define MGMT_EV_LE_CONN_PARAMS 0xF000
+struct mgmt_ev_le_conn_params {
+ bdaddr_t bdaddr;
+ __u16 interval;
+ __u16 latency;
+ __u16 timeout;
+} __packed;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index eb5a0cc..f83c108 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3191,6 +3191,10 @@
conn->state = BT_CONNECTED;
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
mgmt_connected(hdev->id, &ev->bdaddr, 1);
+ mgmt_le_conn_params(hdev->id, &ev->bdaddr,
+ __le16_to_cpu(ev->interval),
+ __le16_to_cpu(ev->latency),
+ __le16_to_cpu(ev->supervision_timeout));
hci_conn_hold(conn);
hci_conn_hold_device(conn);
@@ -3202,6 +3206,37 @@
hci_dev_unlock(hdev);
}
+static inline void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
+ BT_DBG("%s status %d", hdev->name, ev->status);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_handle(hdev,
+ __le16_to_cpu(ev->handle));
+ if (conn == NULL) {
+ BT_ERR("Unknown connection update");
+ goto unlock;
+ }
+
+ if (ev->status) {
+ BT_ERR("Connection update unsuccessful");
+ goto unlock;
+ }
+
+ mgmt_le_conn_params(hdev->id, &conn->dst,
+ __le16_to_cpu(ev->interval),
+ __le16_to_cpu(ev->latency),
+ __le16_to_cpu(ev->supervision_timeout));
+
+unlock:
+ hci_dev_unlock(hdev);
+}
+
static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
@@ -3271,6 +3306,10 @@
hci_le_conn_complete_evt(hdev, skb);
break;
+ case HCI_EV_LE_CONN_UPDATE_COMPLETE:
+ hci_le_conn_update_complete_evt(hdev, skb);
+ break;
+
case HCI_EV_LE_LTK_REQ:
hci_le_ltk_request_evt(hdev, skb);
break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index dce8491..72234c1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2633,6 +2633,20 @@
return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
}
+int mgmt_le_conn_params(u16 index, bdaddr_t *bdaddr, u16 interval,
+ u16 latency, u16 timeout)
+{
+ struct mgmt_ev_le_conn_params ev;
+
+ bacpy(&ev.bdaddr, bdaddr);
+ ev.interval = interval;
+ ev.latency = latency;
+ ev.timeout = timeout;
+
+ return mgmt_event(MGMT_EV_LE_CONN_PARAMS, index, &ev, sizeof(ev),
+ NULL);
+}
+
static void disconnect_rsp(struct pending_cmd *cmd, void *data)
{
struct mgmt_cp_disconnect *cp = cmd->param;