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

Bluetooth: implement read/set default system parameters mgmt

This patch implements the read default system parameters and the set
default system parameters mgmt commands.

Signed-off-by: Alain Michaud <alainm@chromium.org>
Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Alain Michaud and committed by
Marcel Holtmann
17896406 10873f99

+273 -1
+1 -1
net/bluetooth/Makefile
··· 14 14 15 15 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ 16 16 hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \ 17 - ecdh_helper.o hci_request.o mgmt_util.o 17 + ecdh_helper.o hci_request.o mgmt_util.o mgmt_config.o 18 18 19 19 bluetooth-$(CONFIG_BT_BREDR) += sco.o 20 20 bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
+8
net/bluetooth/mgmt.c
··· 36 36 #include "hci_request.h" 37 37 #include "smp.h" 38 38 #include "mgmt_util.h" 39 + #include "mgmt_config.h" 39 40 40 41 #define MGMT_VERSION 1 41 42 #define MGMT_REVISION 17 ··· 112 111 MGMT_OP_READ_SECURITY_INFO, 113 112 MGMT_OP_READ_EXP_FEATURES_INFO, 114 113 MGMT_OP_SET_EXP_FEATURE, 114 + MGMT_OP_READ_DEF_SYSTEM_CONFIG, 115 + MGMT_OP_SET_DEF_SYSTEM_CONFIG, 115 116 }; 116 117 117 118 static const u16 mgmt_events[] = { ··· 165 162 MGMT_OP_READ_EXT_INFO, 166 163 MGMT_OP_READ_SECURITY_INFO, 167 164 MGMT_OP_READ_EXP_FEATURES_INFO, 165 + MGMT_OP_READ_DEF_SYSTEM_CONFIG, 168 166 }; 169 167 170 168 static const u16 mgmt_untrusted_events[] = { ··· 7301 7297 { set_exp_feature, MGMT_SET_EXP_FEATURE_SIZE, 7302 7298 HCI_MGMT_VAR_LEN | 7303 7299 HCI_MGMT_HDEV_OPTIONAL }, 7300 + { read_def_system_config, MGMT_READ_DEF_SYSTEM_CONFIG_SIZE, 7301 + HCI_MGMT_UNTRUSTED }, 7302 + { set_def_system_config, MGMT_SET_DEF_SYSTEM_CONFIG_SIZE, 7303 + HCI_MGMT_VAR_LEN }, 7304 7304 }; 7305 7305 7306 7306 void mgmt_index_added(struct hci_dev *hdev)
+253
net/bluetooth/mgmt_config.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * Copyright (C) 2020 Google Corporation 5 + */ 6 + 7 + #include <net/bluetooth/bluetooth.h> 8 + #include <net/bluetooth/hci_core.h> 9 + #include <net/bluetooth/mgmt.h> 10 + 11 + #include "mgmt_util.h" 12 + #include "mgmt_config.h" 13 + 14 + #define HDEV_PARAM_U16(_param_code_, _param_name_) \ 15 + { \ 16 + { cpu_to_le16(_param_code_), sizeof(__u16) }, \ 17 + { cpu_to_le16(hdev->_param_name_) } \ 18 + } 19 + 20 + int read_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data, 21 + u16 data_len) 22 + { 23 + struct { 24 + struct mgmt_tlv entry; 25 + union { 26 + /* This is a simplification for now since all values 27 + * are 16 bits. In the future, this code may need 28 + * refactoring to account for variable length values 29 + * and properly calculate the required buffer size. 30 + */ 31 + __le16 value; 32 + }; 33 + } __packed params[] = { 34 + /* Please see mgmt-api.txt for documentation of these values */ 35 + HDEV_PARAM_U16(0x0000, def_page_scan_type), 36 + HDEV_PARAM_U16(0x0001, def_page_scan_int), 37 + HDEV_PARAM_U16(0x0002, def_page_scan_window), 38 + HDEV_PARAM_U16(0x0003, def_inq_scan_type), 39 + HDEV_PARAM_U16(0x0004, def_inq_scan_int), 40 + HDEV_PARAM_U16(0x0005, def_inq_scan_window), 41 + HDEV_PARAM_U16(0x0006, def_br_lsto), 42 + HDEV_PARAM_U16(0x0007, def_page_timeout), 43 + HDEV_PARAM_U16(0x0008, sniff_min_interval), 44 + HDEV_PARAM_U16(0x0009, sniff_max_interval), 45 + HDEV_PARAM_U16(0x000a, le_adv_min_interval), 46 + HDEV_PARAM_U16(0x000b, le_adv_max_interval), 47 + HDEV_PARAM_U16(0x000c, def_multi_adv_rotation_duration), 48 + HDEV_PARAM_U16(0x000d, le_scan_interval), 49 + HDEV_PARAM_U16(0x000e, le_scan_window), 50 + HDEV_PARAM_U16(0x000f, le_scan_int_suspend), 51 + HDEV_PARAM_U16(0x0010, le_scan_window_suspend), 52 + HDEV_PARAM_U16(0x0011, le_scan_int_discovery), 53 + HDEV_PARAM_U16(0x0012, le_scan_window_discovery), 54 + HDEV_PARAM_U16(0x0013, le_scan_int_adv_monitor), 55 + HDEV_PARAM_U16(0x0014, le_scan_window_adv_monitor), 56 + HDEV_PARAM_U16(0x0015, le_scan_int_connect), 57 + HDEV_PARAM_U16(0x0016, le_scan_window_connect), 58 + HDEV_PARAM_U16(0x0017, le_conn_min_interval), 59 + HDEV_PARAM_U16(0x0018, le_conn_max_interval), 60 + HDEV_PARAM_U16(0x0019, le_conn_latency), 61 + HDEV_PARAM_U16(0x001a, le_supv_timeout), 62 + }; 63 + struct mgmt_rp_read_def_system_config *rp = (void *)params; 64 + 65 + bt_dev_dbg(hdev, "sock %p", sk); 66 + 67 + return mgmt_cmd_complete(sk, hdev->id, 68 + MGMT_OP_READ_DEF_SYSTEM_CONFIG, 69 + 0, rp, sizeof(params)); 70 + } 71 + 72 + #define TO_TLV(x) ((struct mgmt_tlv *)(x)) 73 + #define TLV_GET_LE16(tlv) le16_to_cpu(*((__le16 *)(TO_TLV(tlv)->value))) 74 + 75 + int set_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data, 76 + u16 data_len) 77 + { 78 + u16 buffer_left = data_len; 79 + u8 *buffer = data; 80 + 81 + if (buffer_left < sizeof(struct mgmt_tlv)) { 82 + return mgmt_cmd_status(sk, hdev->id, 83 + MGMT_OP_SET_DEF_SYSTEM_CONFIG, 84 + MGMT_STATUS_INVALID_PARAMS); 85 + } 86 + 87 + /* First pass to validate the tlv */ 88 + while (buffer_left >= sizeof(struct mgmt_tlv)) { 89 + const u8 len = TO_TLV(buffer)->length; 90 + const u16 exp_len = sizeof(struct mgmt_tlv) + 91 + len; 92 + const u16 type = le16_to_cpu(TO_TLV(buffer)->type); 93 + 94 + if (buffer_left < exp_len) { 95 + bt_dev_warn(hdev, "invalid len left %d, exp >= %d", 96 + buffer_left, exp_len); 97 + 98 + return mgmt_cmd_status(sk, hdev->id, 99 + MGMT_OP_SET_DEF_SYSTEM_CONFIG, 100 + MGMT_STATUS_INVALID_PARAMS); 101 + } 102 + 103 + /* Please see mgmt-api.txt for documentation of these values */ 104 + switch (type) { 105 + case 0x0000: 106 + case 0x0001: 107 + case 0x0002: 108 + case 0x0003: 109 + case 0x0004: 110 + case 0x0005: 111 + case 0x0006: 112 + case 0x0007: 113 + case 0x0008: 114 + case 0x0009: 115 + case 0x000a: 116 + case 0x000b: 117 + case 0x000c: 118 + case 0x000d: 119 + case 0x000e: 120 + case 0x000f: 121 + case 0x0010: 122 + case 0x0011: 123 + case 0x0012: 124 + case 0x0013: 125 + case 0x0014: 126 + case 0x0015: 127 + case 0x0016: 128 + case 0x0017: 129 + case 0x0018: 130 + case 0x0019: 131 + case 0x001a: 132 + if (len != sizeof(u16)) { 133 + bt_dev_warn(hdev, "invalid length %d, exp %zu for type %d", 134 + len, sizeof(u16), type); 135 + 136 + return mgmt_cmd_status(sk, hdev->id, 137 + MGMT_OP_SET_DEF_SYSTEM_CONFIG, 138 + MGMT_STATUS_INVALID_PARAMS); 139 + } 140 + break; 141 + default: 142 + bt_dev_warn(hdev, "unsupported parameter %u", type); 143 + break; 144 + } 145 + 146 + buffer_left -= exp_len; 147 + buffer += exp_len; 148 + } 149 + 150 + buffer_left = data_len; 151 + buffer = data; 152 + while (buffer_left >= sizeof(struct mgmt_tlv)) { 153 + const u8 len = TO_TLV(buffer)->length; 154 + const u16 exp_len = sizeof(struct mgmt_tlv) + 155 + len; 156 + const u16 type = le16_to_cpu(TO_TLV(buffer)->type); 157 + 158 + switch (type) { 159 + case 0x0000: 160 + hdev->def_page_scan_type = TLV_GET_LE16(buffer); 161 + break; 162 + case 0x0001: 163 + hdev->def_page_scan_int = TLV_GET_LE16(buffer); 164 + break; 165 + case 0x0002: 166 + hdev->def_page_scan_window = TLV_GET_LE16(buffer); 167 + break; 168 + case 0x0003: 169 + hdev->def_inq_scan_type = TLV_GET_LE16(buffer); 170 + break; 171 + case 0x0004: 172 + hdev->def_inq_scan_int = TLV_GET_LE16(buffer); 173 + break; 174 + case 0x0005: 175 + hdev->def_inq_scan_window = TLV_GET_LE16(buffer); 176 + break; 177 + case 0x0006: 178 + hdev->def_br_lsto = TLV_GET_LE16(buffer); 179 + break; 180 + case 0x0007: 181 + hdev->def_page_timeout = TLV_GET_LE16(buffer); 182 + break; 183 + case 0x0008: 184 + hdev->sniff_min_interval = TLV_GET_LE16(buffer); 185 + break; 186 + case 0x0009: 187 + hdev->sniff_max_interval = TLV_GET_LE16(buffer); 188 + break; 189 + case 0x000a: 190 + hdev->le_adv_min_interval = TLV_GET_LE16(buffer); 191 + break; 192 + case 0x000b: 193 + hdev->le_adv_max_interval = TLV_GET_LE16(buffer); 194 + break; 195 + case 0x000c: 196 + hdev->def_multi_adv_rotation_duration = 197 + TLV_GET_LE16(buffer); 198 + break; 199 + case 0x000d: 200 + hdev->le_scan_interval = TLV_GET_LE16(buffer); 201 + break; 202 + case 0x000e: 203 + hdev->le_scan_window = TLV_GET_LE16(buffer); 204 + break; 205 + case 0x000f: 206 + hdev->le_scan_int_suspend = TLV_GET_LE16(buffer); 207 + break; 208 + case 0x0010: 209 + hdev->le_scan_window_suspend = TLV_GET_LE16(buffer); 210 + break; 211 + case 0x0011: 212 + hdev->le_scan_int_discovery = TLV_GET_LE16(buffer); 213 + break; 214 + case 0x00012: 215 + hdev->le_scan_window_discovery = TLV_GET_LE16(buffer); 216 + break; 217 + case 0x00013: 218 + hdev->le_scan_int_adv_monitor = TLV_GET_LE16(buffer); 219 + break; 220 + case 0x00014: 221 + hdev->le_scan_window_adv_monitor = TLV_GET_LE16(buffer); 222 + break; 223 + case 0x00015: 224 + hdev->le_scan_int_connect = TLV_GET_LE16(buffer); 225 + break; 226 + case 0x00016: 227 + hdev->le_scan_window_connect = TLV_GET_LE16(buffer); 228 + break; 229 + case 0x00017: 230 + hdev->le_conn_min_interval = TLV_GET_LE16(buffer); 231 + break; 232 + case 0x00018: 233 + hdev->le_conn_max_interval = TLV_GET_LE16(buffer); 234 + break; 235 + case 0x00019: 236 + hdev->le_conn_latency = TLV_GET_LE16(buffer); 237 + break; 238 + case 0x0001a: 239 + hdev->le_supv_timeout = TLV_GET_LE16(buffer); 240 + break; 241 + default: 242 + bt_dev_warn(hdev, "unsupported parameter %u", type); 243 + break; 244 + } 245 + 246 + buffer_left -= exp_len; 247 + buffer += exp_len; 248 + } 249 + 250 + return mgmt_cmd_status(sk, hdev->id, 251 + MGMT_OP_SET_DEF_SYSTEM_CONFIG, 252 + MGMT_STATUS_SUCCESS); 253 + }
+11
net/bluetooth/mgmt_config.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * Copyright (C) 2020 Google Corporation 5 + */ 6 + 7 + int read_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data, 8 + u16 data_len); 9 + 10 + int set_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data, 11 + u16 data_len);