Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Bluetooth: MGMT: Make MGMT_OP_LOAD_CONN_PARAM update existing connection

This makes MGMT_OP_LOAD_CONN_PARAM update existing connection by
dectecting the request is just for one connection, parameters already
exists and there is a connection.

Since this is a new behavior the revision is also updated to enable
userspace to detect it.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

+69 -2
+3
include/net/bluetooth/hci_sync.h
··· 138 138 int hci_resume_sync(struct hci_dev *hdev); 139 139 140 140 struct hci_conn; 141 + struct hci_conn_params; 141 142 142 143 int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason); 143 144 ··· 157 156 int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn); 158 157 159 158 int hci_cancel_connect_sync(struct hci_dev *hdev, struct hci_conn *conn); 159 + int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn, 160 + struct hci_conn_params *params);
+18
net/bluetooth/hci_sync.c
··· 6724 6724 6725 6725 return -ENOENT; 6726 6726 } 6727 + 6728 + int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn, 6729 + struct hci_conn_params *params) 6730 + { 6731 + struct hci_cp_le_conn_update cp; 6732 + 6733 + memset(&cp, 0, sizeof(cp)); 6734 + cp.handle = cpu_to_le16(conn->handle); 6735 + cp.conn_interval_min = cpu_to_le16(params->conn_min_interval); 6736 + cp.conn_interval_max = cpu_to_le16(params->conn_max_interval); 6737 + cp.conn_latency = cpu_to_le16(params->conn_latency); 6738 + cp.supervision_timeout = cpu_to_le16(params->supervision_timeout); 6739 + cp.min_ce_len = cpu_to_le16(0x0000); 6740 + cp.max_ce_len = cpu_to_le16(0x0000); 6741 + 6742 + return __hci_cmd_sync_status(hdev, HCI_OP_LE_CONN_UPDATE, 6743 + sizeof(cp), &cp, HCI_CMD_TIMEOUT); 6744 + }
+48 -2
net/bluetooth/mgmt.c
··· 42 42 #include "aosp.h" 43 43 44 44 #define MGMT_VERSION 1 45 - #define MGMT_REVISION 22 45 + #define MGMT_REVISION 23 46 46 47 47 static const u16 mgmt_commands[] = { 48 48 MGMT_OP_READ_INDEX_LIST, ··· 7813 7813 return err; 7814 7814 } 7815 7815 7816 + static int conn_update_sync(struct hci_dev *hdev, void *data) 7817 + { 7818 + struct hci_conn_params *params = data; 7819 + struct hci_conn *conn; 7820 + 7821 + conn = hci_conn_hash_lookup_le(hdev, &params->addr, params->addr_type); 7822 + if (!conn) 7823 + return -ECANCELED; 7824 + 7825 + return hci_le_conn_update_sync(hdev, conn, params); 7826 + } 7827 + 7816 7828 static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, 7817 7829 u16 len) 7818 7830 { ··· 7858 7846 7859 7847 hci_dev_lock(hdev); 7860 7848 7861 - hci_conn_params_clear_disabled(hdev); 7849 + if (param_count > 1) 7850 + hci_conn_params_clear_disabled(hdev); 7862 7851 7863 7852 for (i = 0; i < param_count; i++) { 7864 7853 struct mgmt_conn_param *param = &cp->params[i]; 7865 7854 struct hci_conn_params *hci_param; 7866 7855 u16 min, max, latency, timeout; 7867 7856 u8 addr_type; 7857 + bool update; 7868 7858 7869 7859 bt_dev_dbg(hdev, "Adding %pMR (type %u)", &param->addr.bdaddr, 7870 7860 param->addr.type); ··· 7893 7879 continue; 7894 7880 } 7895 7881 7882 + /* Detect when the loading is for an existing parameter then 7883 + * attempt to trigger the connection update procedure. 7884 + */ 7885 + if (!i && param_count == 1) { 7886 + hci_param = hci_conn_params_lookup(hdev, 7887 + &param->addr.bdaddr, 7888 + addr_type); 7889 + if (hci_param) 7890 + update = true; 7891 + else 7892 + hci_conn_params_clear_disabled(hdev); 7893 + } 7894 + 7896 7895 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr, 7897 7896 addr_type); 7898 7897 if (!hci_param) { ··· 7917 7890 hci_param->conn_max_interval = max; 7918 7891 hci_param->conn_latency = latency; 7919 7892 hci_param->supervision_timeout = timeout; 7893 + 7894 + /* Check if we need to trigger a connection update */ 7895 + if (update) { 7896 + struct hci_conn *conn; 7897 + 7898 + /* Lookup for existing connection as central and check 7899 + * if parameters match and if they don't then trigger 7900 + * a connection update. 7901 + */ 7902 + conn = hci_conn_hash_lookup_le(hdev, &hci_param->addr, 7903 + addr_type); 7904 + if (conn && conn->role == HCI_ROLE_MASTER && 7905 + (conn->le_conn_min_interval != min || 7906 + conn->le_conn_max_interval != max || 7907 + conn->le_conn_latency != latency || 7908 + conn->le_supv_timeout != timeout)) 7909 + hci_cmd_sync_queue(hdev, conn_update_sync, 7910 + hci_param, NULL); 7911 + } 7920 7912 } 7921 7913 7922 7914 hci_dev_unlock(hdev);