summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSudha Bheemanna <b.sudha@samsung.com>2016-08-24 15:02:56 +0530
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-09-21 01:40:24 -0700
commit3a54c89e9cfb5302362caa02f3f6a268c0eeaed6 (patch)
tree36d998b81fc3d7d6213ef9e49f2b95a6c3031fee
parent59ef0291f8a7b96a1c47c62a30c2ce63950dd573 (diff)
downloadlinux-exynos-3a54c89e9cfb5302362caa02f3f6a268c0eeaed6.tar.gz
linux-exynos-3a54c89e9cfb5302362caa02f3f6a268c0eeaed6.tar.bz2
linux-exynos-3a54c89e9cfb5302362caa02f3f6a268c0eeaed6.zip
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 <b.sudha@samsung.com> Signed-off-by: DoHyun Pyun <dh79.pyun@samsung.com>
-rw-r--r--include/net/bluetooth/mgmt_tizen.h17
-rw-r--r--net/bluetooth/mgmt.c241
2 files changed, 258 insertions, 0 deletions
diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h
index 04bd25573e64..6dc8e36eebda 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 378bfd3263ab..d9806e1f560f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -5708,6 +5708,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)
@@ -7489,6 +7727,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