Add the capability to set flags on devices being added via add_device. The first flag being used is the wakeable flag which allows the device to wake the system from suspend. Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@xxxxxxxxxxxx> --- include/net/bluetooth/mgmt.h | 5 ++++- net/bluetooth/mgmt.c | 42 +++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index f41cd87550dc..e9db9b1a4436 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -445,8 +445,11 @@ struct mgmt_rp_get_clock_info { struct mgmt_cp_add_device { struct mgmt_addr_info addr; __u8 action; + __u8 flags_mask; + __u8 flags_value; } __packed; -#define MGMT_ADD_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1) +#define MGMT_ADD_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 3) +#define DEVICE_FLAG_WAKEABLE (1 << 0) #define MGMT_OP_REMOVE_DEVICE 0x0034 struct mgmt_cp_remove_device { diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 6552003a170e..ae241f541713 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -5759,6 +5759,25 @@ static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, return 0; } +static int hci_conn_params_set_flags(struct hci_dev *hdev, bdaddr_t *addr, + u8 addr_type, u8 flags_mask, + u8 flags_value) +{ + struct hci_conn_params *params = + hci_conn_params_add(hdev, addr, addr_type); + + if (!params) + return -EIO; + + if (flags_mask & DEVICE_FLAG_WAKEABLE) + params->wakeable = flags_mask & DEVICE_FLAG_WAKEABLE; + + bt_dev_dbg(hdev, "addr %pMR (type %u) flag mask %u, values %u", addr, + addr_type, flags_mask, flags_value); + + return 0; +} + static void device_added(struct sock *sk, struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, u8 action) { @@ -5805,11 +5824,23 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr, cp->addr.type); - if (err) + if (err && err != -EEXIST) goto unlock; hci_req_update_scan(hdev); + /* Modify wake capable property if set. */ + if (cp->flags_mask & DEVICE_FLAG_WAKEABLE) { + if (cp->flags_value & DEVICE_FLAG_WAKEABLE) + hci_bdaddr_list_add(&hdev->wakeable, + &cp->addr.bdaddr, + cp->addr.type); + else + hci_bdaddr_list_del(&hdev->wakeable, + &cp->addr.bdaddr, + cp->addr.type); + } + goto added; } @@ -5845,6 +5876,15 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, goto unlock; } + /* Set or clear flags that were configured for this device */ + if (hci_conn_params_set_flags(hdev, &cp->addr.bdaddr, addr_type, + cp->flags_mask, cp->flags_value)) { + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, + MGMT_STATUS_FAILED, &cp->addr, + sizeof(cp->addr)); + goto unlock; + } + hci_update_background_scan(hdev); added: -- 2.25.1.696.g5e7596f4ac-goog