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