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_U32(_param_name_) \ 15 struct {\ 16 struct mgmt_tlv_hdr entry; \ 17 __le32 value; \ 18 } __packed _param_name_ 19 20 #define HDEV_PARAM_U16(_param_name_) \ 21 struct {\ 22 struct mgmt_tlv_hdr entry; \ 23 __le16 value; \ 24 } __packed _param_name_ 25 26 #define HDEV_PARAM_U8(_param_name_) \ 27 struct {\ 28 struct mgmt_tlv_hdr entry; \ 29 __u8 value; \ 30 } __packed _param_name_ 31 32 #define TLV_SET_U16(_param_code_, _param_name_) \ 33 { \ 34 { cpu_to_le16(_param_code_), sizeof(__u16) }, \ 35 cpu_to_le16(hdev->_param_name_) \ 36 } 37 38 #define TLV_SET_U32(_param_code_, _param_name_) \ 39 { \ 40 { cpu_to_le16(_param_code_), sizeof(__u32) }, \ 41 cpu_to_le32(hdev->_param_name_) \ 42 } 43 44 #define TLV_SET_U8(_param_code_, _param_name_) \ 45 { \ 46 { cpu_to_le16(_param_code_), sizeof(__u8) }, \ 47 hdev->_param_name_ \ 48 } 49 50 #define TLV_SET_U16_JIFFIES_TO_MSECS(_param_code_, _param_name_) \ 51 { \ 52 { cpu_to_le16(_param_code_), sizeof(__u16) }, \ 53 cpu_to_le16(jiffies_to_msecs(hdev->_param_name_)) \ 54 } 55 56 int read_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data, 57 u16 data_len) 58 { 59 int ret; 60 struct mgmt_rp_read_def_system_config { 61 /* Please see mgmt-api.txt for documentation of these values */ 62 HDEV_PARAM_U16(def_page_scan_type); 63 HDEV_PARAM_U16(def_page_scan_int); 64 HDEV_PARAM_U16(def_page_scan_window); 65 HDEV_PARAM_U16(def_inq_scan_type); 66 HDEV_PARAM_U16(def_inq_scan_int); 67 HDEV_PARAM_U16(def_inq_scan_window); 68 HDEV_PARAM_U16(def_br_lsto); 69 HDEV_PARAM_U16(def_page_timeout); 70 HDEV_PARAM_U16(sniff_min_interval); 71 HDEV_PARAM_U16(sniff_max_interval); 72 HDEV_PARAM_U16(le_adv_min_interval); 73 HDEV_PARAM_U16(le_adv_max_interval); 74 HDEV_PARAM_U16(def_multi_adv_rotation_duration); 75 HDEV_PARAM_U16(le_scan_interval); 76 HDEV_PARAM_U16(le_scan_window); 77 HDEV_PARAM_U16(le_scan_int_suspend); 78 HDEV_PARAM_U16(le_scan_window_suspend); 79 HDEV_PARAM_U16(le_scan_int_discovery); 80 HDEV_PARAM_U16(le_scan_window_discovery); 81 HDEV_PARAM_U16(le_scan_int_adv_monitor); 82 HDEV_PARAM_U16(le_scan_window_adv_monitor); 83 HDEV_PARAM_U16(le_scan_int_connect); 84 HDEV_PARAM_U16(le_scan_window_connect); 85 HDEV_PARAM_U16(le_conn_min_interval); 86 HDEV_PARAM_U16(le_conn_max_interval); 87 HDEV_PARAM_U16(le_conn_latency); 88 HDEV_PARAM_U16(le_supv_timeout); 89 HDEV_PARAM_U16(def_le_autoconnect_timeout); 90 HDEV_PARAM_U16(advmon_allowlist_duration); 91 HDEV_PARAM_U16(advmon_no_filter_duration); 92 HDEV_PARAM_U8(enable_advmon_interleave_scan); 93 HDEV_PARAM_U32(idle_timeout); 94 } __packed rp = { 95 TLV_SET_U16(0x0000, def_page_scan_type), 96 TLV_SET_U16(0x0001, def_page_scan_int), 97 TLV_SET_U16(0x0002, def_page_scan_window), 98 TLV_SET_U16(0x0003, def_inq_scan_type), 99 TLV_SET_U16(0x0004, def_inq_scan_int), 100 TLV_SET_U16(0x0005, def_inq_scan_window), 101 TLV_SET_U16(0x0006, def_br_lsto), 102 TLV_SET_U16(0x0007, def_page_timeout), 103 TLV_SET_U16(0x0008, sniff_min_interval), 104 TLV_SET_U16(0x0009, sniff_max_interval), 105 TLV_SET_U16(0x000a, le_adv_min_interval), 106 TLV_SET_U16(0x000b, le_adv_max_interval), 107 TLV_SET_U16(0x000c, def_multi_adv_rotation_duration), 108 TLV_SET_U16(0x000d, le_scan_interval), 109 TLV_SET_U16(0x000e, le_scan_window), 110 TLV_SET_U16(0x000f, le_scan_int_suspend), 111 TLV_SET_U16(0x0010, le_scan_window_suspend), 112 TLV_SET_U16(0x0011, le_scan_int_discovery), 113 TLV_SET_U16(0x0012, le_scan_window_discovery), 114 TLV_SET_U16(0x0013, le_scan_int_adv_monitor), 115 TLV_SET_U16(0x0014, le_scan_window_adv_monitor), 116 TLV_SET_U16(0x0015, le_scan_int_connect), 117 TLV_SET_U16(0x0016, le_scan_window_connect), 118 TLV_SET_U16(0x0017, le_conn_min_interval), 119 TLV_SET_U16(0x0018, le_conn_max_interval), 120 TLV_SET_U16(0x0019, le_conn_latency), 121 TLV_SET_U16(0x001a, le_supv_timeout), 122 TLV_SET_U16_JIFFIES_TO_MSECS(0x001b, 123 def_le_autoconnect_timeout), 124 TLV_SET_U16(0x001d, advmon_allowlist_duration), 125 TLV_SET_U16(0x001e, advmon_no_filter_duration), 126 TLV_SET_U8(0x001f, enable_advmon_interleave_scan), 127 TLV_SET_U32(0x0020, idle_timeout), 128 }; 129 130 bt_dev_dbg(hdev, "sock %p", sk); 131 132 ret = mgmt_cmd_complete(sk, hdev->id, 133 MGMT_OP_READ_DEF_SYSTEM_CONFIG, 134 0, &rp, sizeof(rp)); 135 return ret; 136 } 137 138 #define TO_TLV(x) ((struct mgmt_tlv *)(x)) 139 #define TLV_GET_LE32(tlv) le32_to_cpu(*((__le32 *)(TO_TLV(tlv)->value))) 140 #define TLV_GET_LE16(tlv) le16_to_cpu(*((__le16 *)(TO_TLV(tlv)->value))) 141 #define TLV_GET_U8(tlv) (*((__u8 *)(TO_TLV(tlv)->value))) 142 143 int set_def_system_config(struct sock *sk, struct hci_dev *hdev, void *data, 144 u16 data_len) 145 { 146 u16 buffer_left = data_len; 147 u8 *buffer = data; 148 149 if (buffer_left < sizeof(struct mgmt_tlv)) { 150 return mgmt_cmd_status(sk, hdev->id, 151 MGMT_OP_SET_DEF_SYSTEM_CONFIG, 152 MGMT_STATUS_INVALID_PARAMS); 153 } 154 155 /* First pass to validate the tlv */ 156 while (buffer_left >= sizeof(struct mgmt_tlv)) { 157 const u8 len = TO_TLV(buffer)->length; 158 size_t exp_type_len; 159 const u16 exp_len = sizeof(struct mgmt_tlv) + 160 len; 161 const u16 type = le16_to_cpu(TO_TLV(buffer)->type); 162 163 if (buffer_left < exp_len) { 164 bt_dev_warn(hdev, "invalid len left %u, exp >= %u", 165 buffer_left, exp_len); 166 167 return mgmt_cmd_status(sk, hdev->id, 168 MGMT_OP_SET_DEF_SYSTEM_CONFIG, 169 MGMT_STATUS_INVALID_PARAMS); 170 } 171 172 /* Please see mgmt-api.txt for documentation of these values */ 173 switch (type) { 174 case 0x0000: 175 case 0x0001: 176 case 0x0002: 177 case 0x0003: 178 case 0x0004: 179 case 0x0005: 180 case 0x0006: 181 case 0x0007: 182 case 0x0008: 183 case 0x0009: 184 case 0x000a: 185 case 0x000b: 186 case 0x000c: 187 case 0x000d: 188 case 0x000e: 189 case 0x000f: 190 case 0x0010: 191 case 0x0011: 192 case 0x0012: 193 case 0x0013: 194 case 0x0014: 195 case 0x0015: 196 case 0x0016: 197 case 0x0017: 198 case 0x0018: 199 case 0x0019: 200 case 0x001a: 201 case 0x001b: 202 case 0x001d: 203 case 0x001e: 204 exp_type_len = sizeof(u16); 205 break; 206 case 0x001f: 207 exp_type_len = sizeof(u8); 208 break; 209 case 0x0020: 210 exp_type_len = sizeof(u32); 211 break; 212 default: 213 exp_type_len = 0; 214 bt_dev_warn(hdev, "unsupported parameter %u", type); 215 break; 216 } 217 218 if (exp_type_len && len != exp_type_len) { 219 bt_dev_warn(hdev, "invalid length %d, exp %zu for type %u", 220 len, exp_type_len, type); 221 222 return mgmt_cmd_status(sk, hdev->id, 223 MGMT_OP_SET_DEF_SYSTEM_CONFIG, 224 MGMT_STATUS_INVALID_PARAMS); 225 } 226 227 buffer_left -= exp_len; 228 buffer += exp_len; 229 } 230 231 buffer_left = data_len; 232 buffer = data; 233 while (buffer_left >= sizeof(struct mgmt_tlv)) { 234 const u8 len = TO_TLV(buffer)->length; 235 const u16 exp_len = sizeof(struct mgmt_tlv) + 236 len; 237 const u16 type = le16_to_cpu(TO_TLV(buffer)->type); 238 239 switch (type) { 240 case 0x0000: 241 hdev->def_page_scan_type = TLV_GET_LE16(buffer); 242 break; 243 case 0x0001: 244 hdev->def_page_scan_int = TLV_GET_LE16(buffer); 245 break; 246 case 0x0002: 247 hdev->def_page_scan_window = TLV_GET_LE16(buffer); 248 break; 249 case 0x0003: 250 hdev->def_inq_scan_type = TLV_GET_LE16(buffer); 251 break; 252 case 0x0004: 253 hdev->def_inq_scan_int = TLV_GET_LE16(buffer); 254 break; 255 case 0x0005: 256 hdev->def_inq_scan_window = TLV_GET_LE16(buffer); 257 break; 258 case 0x0006: 259 hdev->def_br_lsto = TLV_GET_LE16(buffer); 260 break; 261 case 0x0007: 262 hdev->def_page_timeout = TLV_GET_LE16(buffer); 263 break; 264 case 0x0008: 265 hdev->sniff_min_interval = TLV_GET_LE16(buffer); 266 break; 267 case 0x0009: 268 hdev->sniff_max_interval = TLV_GET_LE16(buffer); 269 break; 270 case 0x000a: 271 hdev->le_adv_min_interval = TLV_GET_LE16(buffer); 272 break; 273 case 0x000b: 274 hdev->le_adv_max_interval = TLV_GET_LE16(buffer); 275 break; 276 case 0x000c: 277 hdev->def_multi_adv_rotation_duration = 278 TLV_GET_LE16(buffer); 279 break; 280 case 0x000d: 281 hdev->le_scan_interval = TLV_GET_LE16(buffer); 282 break; 283 case 0x000e: 284 hdev->le_scan_window = TLV_GET_LE16(buffer); 285 break; 286 case 0x000f: 287 hdev->le_scan_int_suspend = TLV_GET_LE16(buffer); 288 break; 289 case 0x0010: 290 hdev->le_scan_window_suspend = TLV_GET_LE16(buffer); 291 break; 292 case 0x0011: 293 hdev->le_scan_int_discovery = TLV_GET_LE16(buffer); 294 break; 295 case 0x00012: 296 hdev->le_scan_window_discovery = TLV_GET_LE16(buffer); 297 break; 298 case 0x00013: 299 hdev->le_scan_int_adv_monitor = TLV_GET_LE16(buffer); 300 break; 301 case 0x00014: 302 hdev->le_scan_window_adv_monitor = TLV_GET_LE16(buffer); 303 break; 304 case 0x00015: 305 hdev->le_scan_int_connect = TLV_GET_LE16(buffer); 306 break; 307 case 0x00016: 308 hdev->le_scan_window_connect = TLV_GET_LE16(buffer); 309 break; 310 case 0x00017: 311 hdev->le_conn_min_interval = TLV_GET_LE16(buffer); 312 break; 313 case 0x00018: 314 hdev->le_conn_max_interval = TLV_GET_LE16(buffer); 315 break; 316 case 0x00019: 317 hdev->le_conn_latency = TLV_GET_LE16(buffer); 318 break; 319 case 0x0001a: 320 hdev->le_supv_timeout = TLV_GET_LE16(buffer); 321 break; 322 case 0x0001b: 323 hdev->def_le_autoconnect_timeout = 324 msecs_to_jiffies(TLV_GET_LE16(buffer)); 325 break; 326 case 0x0001d: 327 hdev->advmon_allowlist_duration = TLV_GET_LE16(buffer); 328 break; 329 case 0x0001e: 330 hdev->advmon_no_filter_duration = TLV_GET_LE16(buffer); 331 break; 332 case 0x0001f: 333 hdev->enable_advmon_interleave_scan = TLV_GET_U8(buffer); 334 break; 335 case 0x00020: 336 hdev->idle_timeout = TLV_GET_LE32(buffer); 337 break; 338 default: 339 bt_dev_warn(hdev, "unsupported parameter %u", type); 340 break; 341 } 342 343 buffer_left -= exp_len; 344 buffer += exp_len; 345 } 346 347 return mgmt_cmd_complete(sk, hdev->id, 348 MGMT_OP_SET_DEF_SYSTEM_CONFIG, 0, NULL, 0); 349 } 350 351 int read_def_runtime_config(struct sock *sk, struct hci_dev *hdev, void *data, 352 u16 data_len) 353 { 354 bt_dev_dbg(hdev, "sock %p", sk); 355 356 return mgmt_cmd_complete(sk, hdev->id, 357 MGMT_OP_READ_DEF_RUNTIME_CONFIG, 0, NULL, 0); 358 } 359 360 int set_def_runtime_config(struct sock *sk, struct hci_dev *hdev, void *data, 361 u16 data_len) 362 { 363 bt_dev_dbg(hdev, "sock %p", sk); 364 365 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEF_SYSTEM_CONFIG, 366 MGMT_STATUS_INVALID_PARAMS); 367 } 368