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

Bluetooth: Add management command for setting LE scan parameters

The scan interval and window parameters are used for LE passive
background scanning and connection establishment. This allows
userspace to change the values.

These two values should be kept in sync with whatever is used for
the scan parameters service on remote devices. And it puts the
controlling daemon (for example bluetoothd) in charge of setting
the values.

Main use case would be to switch between two sets of values. One
for foreground applications and one for background applications.

At this moment, the values are only used for manual connection
establishment, but soon that should be extended to background
scanning and automatic connection establishment.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>

authored by

Marcel Holtmann and committed by
Johan Hedberg
14b49b9a bef64738

+45
+7
include/net/bluetooth/mgmt.h
··· 362 362 } __packed; 363 363 #define MGMT_SET_STATIC_ADDRESS_SIZE 6 364 364 365 + #define MGMT_OP_SET_SCAN_PARAMS 0x002C 366 + struct mgmt_cp_set_scan_params { 367 + __le16 interval; 368 + __le16 window; 369 + } __packed; 370 + #define MGMT_SET_SCAN_PARAMS_SIZE 4 371 + 365 372 #define MGMT_EV_CMD_COMPLETE 0x0001 366 373 struct mgmt_ev_cmd_complete { 367 374 __le16 opcode;
+38
net/bluetooth/mgmt.c
··· 3374 3374 return err; 3375 3375 } 3376 3376 3377 + static int set_scan_params(struct sock *sk, struct hci_dev *hdev, 3378 + void *data, u16 len) 3379 + { 3380 + struct mgmt_cp_set_scan_params *cp = data; 3381 + __u16 interval, window; 3382 + int err; 3383 + 3384 + BT_DBG("%s", hdev->name); 3385 + 3386 + if (!lmp_le_capable(hdev)) 3387 + return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 3388 + MGMT_STATUS_NOT_SUPPORTED); 3389 + 3390 + interval = __le16_to_cpu(cp->interval); 3391 + 3392 + if (interval < 0x0004 || interval > 0x4000) 3393 + return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 3394 + MGMT_STATUS_INVALID_PARAMS); 3395 + 3396 + window = __le16_to_cpu(cp->window); 3397 + 3398 + if (window < 0x0004 || window > 0x4000) 3399 + return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 3400 + MGMT_STATUS_INVALID_PARAMS); 3401 + 3402 + hci_dev_lock(hdev); 3403 + 3404 + hdev->le_scan_interval = interval; 3405 + hdev->le_scan_window = window; 3406 + 3407 + err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0); 3408 + 3409 + hci_dev_unlock(hdev); 3410 + 3411 + return err; 3412 + } 3413 + 3377 3414 static void fast_connectable_complete(struct hci_dev *hdev, u8 status) 3378 3415 { 3379 3416 struct pending_cmd *cmd; ··· 3747 3710 { set_advertising, false, MGMT_SETTING_SIZE }, 3748 3711 { set_bredr, false, MGMT_SETTING_SIZE }, 3749 3712 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE }, 3713 + { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, 3750 3714 }; 3751 3715 3752 3716