Bluetooth: Introduce "New Connection Parameter" Event
authorAndre Guedes <andre.guedes@openbossa.org>
Tue, 1 Jul 2014 21:10:11 +0000 (18:10 -0300)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 3 Jul 2014 15:42:55 +0000 (17:42 +0200)
This patch introduces a new Mgmt event called "New Connection Parameter".
This event indicates to userspace the connection parameters values the
remote device requested.

The user may store these values and load them into kernel. This way, next
time a connection is established to that device, the kernel will use those
parameters values instead of the default ones.

This event is sent when the remote device requests new connection
parameters through connection parameter update procedure. This event is
not sent for slave connections.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci_core.h
include/net/bluetooth/mgmt.h
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/mgmt.c

index 3404f9bd2da02ac6ead2c68cf6edfa332d565c06..01fbbe20defbb9b11069d384347538a6c831e622 100644 (file)
@@ -1329,6 +1329,9 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent);
 void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk);
 void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
                   bool persistent);
+void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
+                        u8 bdaddr_type, u16 min_interval, u16 max_interval,
+                        u16 latency, u16 timeout);
 void mgmt_reenable_advertising(struct hci_dev *hdev);
 void mgmt_smp_complete(struct hci_conn *conn, bool complete);
 
index 2d88f361a016afbededddbb31a634f7a1d45c649..3c0f29614d1b4f85df6156986046629b8ce03c5c 100644 (file)
@@ -615,3 +615,13 @@ struct mgmt_ev_device_added {
 struct mgmt_ev_device_removed {
        struct mgmt_addr_info addr;
 } __packed;
+
+#define MGMT_EV_NEW_CONN_PARAM         0x001c
+struct mgmt_ev_new_conn_param {
+       struct mgmt_addr_info addr;
+       __u8 store_hint;
+       __le16 min_interval;
+       __le16 max_interval;
+       __le16 latency;
+       __le16 timeout;
+} __packed;
index 544e2ef85d8273265320140de9882c42103696ac..b9d16e0ed6610bdbd1b2fa38f31b063b8f8041a5 100644 (file)
@@ -4417,6 +4417,10 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
                return send_conn_param_neg_reply(hdev, handle,
                                                 HCI_ERROR_INVALID_LL_PARAMS);
 
+       if (test_bit(HCI_CONN_MASTER, &hcon->flags))
+               mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type, min, max,
+                                   latency, timeout);
+
        cp.handle = ev->handle;
        cp.interval_min = ev->interval_min;
        cp.interval_max = ev->interval_max;
index e203a5fdf8748f4ad8b5a0eb60ef98c9c0d92f6c..058b3b2b59b55d38294c3f6b92eb5ebec0a3933e 100644 (file)
@@ -5249,8 +5249,12 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
        l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
                       sizeof(rsp), &rsp);
 
-       if (!err)
+       if (!err) {
+               mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
+                                   min, max, latency, to_multiplier);
+
                hci_le_conn_update(hcon, min, max, latency, to_multiplier);
+       }
 
        return 0;
 }
index ba5e215a7561a23ac08b4708d1b4b09cfb58c861..93cfefa260d5414e5aabdf5c1ff59bc46b9bf014 100644 (file)
@@ -116,6 +116,7 @@ static const u16 mgmt_events[] = {
        MGMT_EV_NEW_CSRK,
        MGMT_EV_DEVICE_ADDED,
        MGMT_EV_DEVICE_REMOVED,
+       MGMT_EV_NEW_CONN_PARAM,
 };
 
 #define CACHE_TIMEOUT  msecs_to_jiffies(2 * 1000)
@@ -5690,6 +5691,24 @@ void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
        mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
 }
 
+void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
+                        u8 bdaddr_type, u16 min_interval, u16 max_interval,
+                        u16 latency, u16 timeout)
+{
+       struct mgmt_ev_new_conn_param ev;
+
+       memset(&ev, 0, sizeof(ev));
+       bacpy(&ev.addr.bdaddr, bdaddr);
+       ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
+       ev.store_hint = 0x00;
+       ev.min_interval = cpu_to_le16(min_interval);
+       ev.max_interval = cpu_to_le16(max_interval);
+       ev.latency = cpu_to_le16(latency);
+       ev.timeout = cpu_to_le16(timeout);
+
+       mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
+}
+
 static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
                                  u8 data_len)
 {