From cb7d0762bd6445d39383f043e9c6c6329860c200 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Wed, 24 Aug 2016 15:02:56 +0530 Subject: [PATCH] Bluetooth: Functions to modify WhiteList This patch provides MGMT commands to manage the white list which includes, adding, removing and clearing the devices from white list. Change-Id: If71107129d3a090ae81448a8122b76accd4f5522 Signed-off-by: Sudha Bheemanna Signed-off-by: DoHyun Pyun Signed-off-by: Amit Purwar --- include/net/bluetooth/mgmt_tizen.h | 17 +++ net/bluetooth/mgmt.c | 241 +++++++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+) diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h index 04bd255..6dc8e36 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -46,4 +46,21 @@ struct mgmt_cp_set_scan_rsp_data { #define MGMT_SET_SCAN_RSP_DATA_SIZE HCI_MAX_AD_LENGTH #define MGMT_SET_SCAN_RSP_MIN_APP_DATA_SIZE 1 +#define MGMT_OP_ADD_DEV_WHITE_LIST (TIZEN_OP_CODE_BASE + 0x04) +struct mgmt_cp_add_dev_white_list { + __u8 bdaddr_type; + bdaddr_t bdaddr; +} __packed; +#define MGMT_ADD_DEV_WHITE_LIST_SIZE 7 + +#define MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST (TIZEN_OP_CODE_BASE + 0x05) +struct mgmt_cp_remove_dev_from_white_list { + __u8 bdaddr_type; + bdaddr_t bdaddr; +} __packed; +#define MGMT_REMOVE_DEV_FROM_WHITE_LIST_SIZE 7 + +#define MGMT_OP_CLEAR_DEV_WHITE_LIST (TIZEN_OP_CODE_BASE + 0x06) +#define MGMT_OP_CLEAR_DEV_WHITE_LIST_SIZE 0 + #endif /* __MGMT_TIZEN_H */ diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8164fc6..c953154 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4931,6 +4931,244 @@ unlocked: return err; } + +/* Adv White List feature */ +static void add_white_list_complete(struct hci_dev *hdev, u8 status, u16 opcode) +{ + struct mgmt_cp_add_dev_white_list *cp; + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_ADD_DEV_WHITE_LIST, hdev); + if (!cmd) + goto unlock; + + cp = cmd->param; + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_ADD_DEV_WHITE_LIST, + mgmt_status(status)); + else + mgmt_cmd_complete(cmd->sk, hdev->id, + MGMT_OP_ADD_DEV_WHITE_LIST, 0, cp, sizeof(*cp)); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +static int add_white_list(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_pending_cmd *cmd; + struct mgmt_cp_add_dev_white_list *cp = data; + struct hci_request req; + int err; + + BT_DBG("%s", hdev->name); + + if (!lmp_le_capable(hdev)) + return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_DEV_WHITE_LIST, + MGMT_STATUS_NOT_SUPPORTED); + + if (!hdev_is_powered(hdev)) + return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_DEV_WHITE_LIST, + MGMT_STATUS_REJECTED); + + hci_dev_lock(hdev); + + if (pending_find(MGMT_OP_ADD_DEV_WHITE_LIST, hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_DEV_WHITE_LIST, + MGMT_STATUS_BUSY); + goto unlocked; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEV_WHITE_LIST, hdev, data, len); + if (!cmd) { + err = -ENOMEM; + goto unlocked; + } + + hci_req_init(&req, hdev); + + hci_req_add(&req, HCI_OP_LE_ADD_TO_WHITE_LIST, sizeof(*cp), cp); + + err = hci_req_run(&req, add_white_list_complete); + if (err < 0) { + mgmt_pending_remove(cmd); + goto unlocked; + } + +unlocked: + hci_dev_unlock(hdev); + + return err; +} + +static void remove_from_white_list_complete(struct hci_dev *hdev, + u8 status, u16 opcode) +{ + struct mgmt_cp_remove_dev_from_white_list *cp; + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST, hdev); + if (!cmd) + goto unlock; + + cp = cmd->param; + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, + MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST, + mgmt_status(status)); + else + mgmt_cmd_complete(cmd->sk, hdev->id, + MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST, 0, + cp, sizeof(*cp)); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +static int remove_from_white_list(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_pending_cmd *cmd; + struct mgmt_cp_remove_dev_from_white_list *cp = data; + struct hci_request req; + int err; + + BT_DBG("%s", hdev->name); + + if (!lmp_le_capable(hdev)) + return mgmt_cmd_status(sk, hdev->id, + MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST, + MGMT_STATUS_NOT_SUPPORTED); + + if (!hdev_is_powered(hdev)) + return mgmt_cmd_status(sk, hdev->id, + MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST, + MGMT_STATUS_REJECTED); + + hci_dev_lock(hdev); + + if (pending_find(MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST, hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST, + MGMT_STATUS_BUSY); + goto unlocked; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEV_FROM_WHITE_LIST, + hdev, data, len); + if (!cmd) { + err = -ENOMEM; + goto unlocked; + } + + hci_req_init(&req, hdev); + + hci_req_add(&req, HCI_OP_LE_DEL_FROM_WHITE_LIST, sizeof(*cp), cp); + + err = hci_req_run(&req, remove_from_white_list_complete); + if (err < 0) { + mgmt_pending_remove(cmd); + goto unlocked; + } + +unlocked: + hci_dev_unlock(hdev); + + return err; +} + +static void clear_white_list_complete(struct hci_dev *hdev, u8 status, + u16 opcode) +{ + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_CLEAR_DEV_WHITE_LIST, hdev); + if (!cmd) + goto unlock; + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_CLEAR_DEV_WHITE_LIST, + mgmt_status(status)); + else + mgmt_cmd_complete(cmd->sk, hdev->id, + MGMT_OP_CLEAR_DEV_WHITE_LIST, + 0, NULL, 0); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +static int clear_white_list(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_pending_cmd *cmd; + struct hci_request req; + int err; + + BT_DBG("%s", hdev->name); + + if (!lmp_le_capable(hdev)) + return mgmt_cmd_status(sk, hdev->id, + MGMT_OP_CLEAR_DEV_WHITE_LIST, + MGMT_STATUS_NOT_SUPPORTED); + + if (!hdev_is_powered(hdev)) + return mgmt_cmd_status(sk, hdev->id, + MGMT_OP_CLEAR_DEV_WHITE_LIST, + MGMT_STATUS_REJECTED); + + hci_dev_lock(hdev); + + if (pending_find(MGMT_OP_CLEAR_DEV_WHITE_LIST, hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_CLEAR_DEV_WHITE_LIST, + MGMT_STATUS_BUSY); + goto unlocked; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_CLEAR_DEV_WHITE_LIST, + hdev, NULL, 0); + if (!cmd) { + err = -ENOMEM; + goto unlocked; + } + + hci_req_init(&req, hdev); + + hci_req_add(&req, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL); + + err = hci_req_run(&req, clear_white_list_complete); + if (err < 0) { + mgmt_pending_remove(cmd); + goto unlocked; + } + +unlocked: + hci_dev_unlock(hdev); + + return err; +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) @@ -6772,6 +7010,9 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { HCI_MGMT_VAR_LEN }, { set_scan_rsp_data, MGMT_SET_SCAN_RSP_MIN_APP_DATA_SIZE, HCI_MGMT_VAR_LEN }, + { add_white_list, MGMT_ADD_DEV_WHITE_LIST_SIZE }, + { remove_from_white_list, MGMT_REMOVE_DEV_FROM_WHITE_LIST_SIZE }, + { clear_white_list, MGMT_OP_CLEAR_DEV_WHITE_LIST_SIZE }, }; #endif -- 2.7.4