From 841a6664f213f76a9bc1bfd07a466d3dbe281a88 Mon Sep 17 00:00:00 2001 From: Arman Uguray Date: Mon, 23 Mar 2015 15:57:09 -0700 Subject: Bluetooth: Add definitions for Add/Remove Advertising API This patch adds definitions for the Add Advertising and Remove Advertising MGMT commands and events. Signed-off-by: Arman Uguray Signed-off-by: Marcel Holtmann --- include/net/bluetooth/mgmt.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index a1a68671bf88..68abd4b0c25d 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -539,6 +539,30 @@ struct mgmt_rp_read_adv_features { __u8 instance[0]; } __packed; +#define MGMT_OP_ADD_ADVERTISING 0x003E +struct mgmt_cp_add_advertising { + __u8 instance; + __le32 flags; + __le16 duration; + __le16 timeout; + __u8 adv_data_len; + __u8 scan_rsp_len; + __u8 data[0]; +} __packed; +#define MGMT_ADD_ADVERTISING_SIZE 11 +struct mgmt_rp_add_advertising { + __u8 instance; +} __packed; + +#define MGMT_OP_REMOVE_ADVERTISING 0x003F +struct mgmt_cp_remove_advertising { + __u8 instance; +} __packed; +#define MGMT_REMOVE_ADVERTISING_SIZE 1 +struct mgmt_rp_remove_advertising { + __u8 instance; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -742,3 +766,13 @@ struct mgmt_ev_local_oob_data_updated { __le16 eir_len; __u8 eir[0]; } __packed; + +#define MGMT_EV_ADVERTISING_ADDED 0x0023 +struct mgmt_ev_advertising_added { + __u8 instance; +} __packed; + +#define MGMT_EV_ADVERTISING_REMOVED 0x0024 +struct mgmt_ev_advertising_removed { + __u8 instance; +} __packed; -- cgit v1.2.3-59-g8ed1b From 4453b006538d02ada8294a195bb2dc2ada498436 Mon Sep 17 00:00:00 2001 From: Arman Uguray Date: Mon, 23 Mar 2015 15:57:10 -0700 Subject: Bluetooth: Introduce HCI_ADVERTISING_INSTANCE setting and add AD flags This patch introduces the HCI_ADVERTISING_INSTANCE setting, which is set when an at least one advertising instance has been added using the "Add Advertising" mgmt command. This patch also adds a macro definition for the EIR_APPEARANCE field type. Signed-off-by: Arman Uguray Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 06e7eee31ce4..3acecf35420b 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -227,6 +227,7 @@ enum { HCI_LE_ENABLED, HCI_ADVERTISING, HCI_ADVERTISING_CONNECTABLE, + HCI_ADVERTISING_INSTANCE, HCI_CONNECTABLE, HCI_DISCOVERABLE, HCI_LIMITED_DISCOVERABLE, @@ -465,6 +466,7 @@ enum { #define EIR_SSP_HASH_C 0x0E /* Simple Pairing Hash C */ #define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */ #define EIR_DEVICE_ID 0x10 /* device ID */ +#define EIR_APPEARANCE 0x19 /* Device appearance */ #define EIR_LE_BDADDR 0x1B /* LE Bluetooth device address */ #define EIR_LE_ROLE 0x1C /* LE role */ #define EIR_LE_SC_CONFIRM 0x22 /* LE SC Confirmation Value */ -- cgit v1.2.3-59-g8ed1b From 203fea0178d7e165dbe834d1bdd9d243018fd5bf Mon Sep 17 00:00:00 2001 From: Arman Uguray Date: Mon, 23 Mar 2015 15:57:11 -0700 Subject: Bluetooth: Add data structure for advertising instance This patch introduces a new data structure to represent advertising instances that were added using the "Add Advertising" mgmt command. Initially an hci_dev structure will support only one of these instances at a time, so the current instance is simply stored as a direct member of hci_dev. Signed-off-by: Arman Uguray Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 16 ++++++++++++++++ net/bluetooth/hci_core.c | 1 + 2 files changed, 17 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b65c53de6a69..3a6d4e3d68fe 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -155,6 +155,15 @@ struct oob_data { u8 rand256[16]; }; +struct adv_info { + __u8 instance; + __u32 flags; + __u16 adv_data_len; + __u8 adv_data[HCI_MAX_AD_LENGTH]; + __u16 scan_rsp_len; + __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; +}; + #define HCI_MAX_SHORT_NAME_LENGTH 10 /* Default LE RPA expiry time, 15 minutes */ @@ -364,6 +373,8 @@ struct hci_dev { __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; __u8 scan_rsp_data_len; + struct adv_info adv_instance; + __u8 irk[16]; __u32 rpa_timeout; struct delayed_work rpa_expired; @@ -550,6 +561,11 @@ static inline void hci_discovery_filter_clear(struct hci_dev *hdev) hdev->discovery.scan_duration = 0; } +static inline void adv_info_init(struct hci_dev *hdev) +{ + memset(&hdev->adv_instance, 0, sizeof(struct adv_info)); +} + bool hci_discovery_active(struct hci_dev *hdev); void hci_discovery_set_state(struct hci_dev *hdev, int state); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 17f52a195ba8..e6bfeb7b4415 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3126,6 +3126,7 @@ struct hci_dev *hci_alloc_dev(void) hci_init_sysfs(hdev); discovery_init(hdev); + adv_info_init(hdev); return hdev; } -- cgit v1.2.3-59-g8ed1b From 912098a6308e37208b8dcc46c57c66d0778a854b Mon Sep 17 00:00:00 2001 From: Arman Uguray Date: Mon, 23 Mar 2015 15:57:15 -0700 Subject: Bluetooth: Add support for adv instance timeout This patch implements support for the timeout parameter of the Add Advertising command. Signed-off-by: Arman Uguray Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 2 + net/bluetooth/mgmt.c | 101 +++++++++++++++++++++++++++++++-------- 2 files changed, 83 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3a6d4e3d68fe..540c07feece7 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -156,8 +156,10 @@ struct oob_data { }; struct adv_info { + struct delayed_work timeout_exp; __u8 instance; __u32 flags; + __u16 timeout; __u16 adv_data_len; __u8 adv_data[HCI_MAX_AD_LENGTH]; __u16 scan_rsp_len; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 762ca9be9806..eda52397a648 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1336,6 +1336,49 @@ static bool hci_stop_discovery(struct hci_request *req) return false; } +static void advertising_added(struct sock *sk, struct hci_dev *hdev, + u8 instance) +{ + struct mgmt_ev_advertising_added ev; + + ev.instance = instance; + + mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk); +} + +static void advertising_removed(struct sock *sk, struct hci_dev *hdev, + u8 instance) +{ + struct mgmt_ev_advertising_removed ev; + + ev.instance = instance; + + mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk); +} + +static void clear_adv_instance(struct hci_dev *hdev) +{ + struct hci_request req; + + if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) + return; + + if (hdev->adv_instance.timeout) + cancel_delayed_work(&hdev->adv_instance.timeout_exp); + + memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance)); + advertising_removed(NULL, hdev, 1); + hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE); + + if (!hdev_is_powered(hdev) || + hci_dev_test_flag(hdev, HCI_ADVERTISING)) + return; + + hci_req_init(&req, hdev); + disable_advertising(&req); + hci_req_run(&req, NULL); +} + static int clean_up_hci_state(struct hci_dev *hdev) { struct hci_request req; @@ -1351,6 +1394,9 @@ static int clean_up_hci_state(struct hci_dev *hdev) hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); } + if (hdev->adv_instance.timeout) + clear_adv_instance(hdev); + if (hci_dev_test_flag(hdev, HCI_LE_ADV)) disable_advertising(&req); @@ -6468,26 +6514,6 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data, return true; } -static void advertising_added(struct sock *sk, struct hci_dev *hdev, - u8 instance) -{ - struct mgmt_ev_advertising_added ev; - - ev.instance = instance; - - mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk); -} - -static void advertising_removed(struct sock *sk, struct hci_dev *hdev, - u8 instance) -{ - struct mgmt_ev_advertising_removed ev; - - ev.instance = instance; - - mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk); -} - static void add_advertising_complete(struct hci_dev *hdev, u8 status, u16 opcode) { @@ -6524,6 +6550,18 @@ unlock: hci_dev_unlock(hdev); } +static void adv_timeout_expired(struct work_struct *work) +{ + struct hci_dev *hdev = container_of(work, struct hci_dev, + adv_instance.timeout_exp.work); + + hdev->adv_instance.timeout = 0; + + hci_dev_lock(hdev); + clear_adv_instance(hdev); + hci_dev_unlock(hdev); +} + static int add_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u16 data_len) { @@ -6531,6 +6569,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, struct mgmt_rp_add_advertising rp; u32 flags; u8 status; + u16 timeout; int err; struct mgmt_pending_cmd *cmd; struct hci_request req; @@ -6543,6 +6582,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, status); flags = __le32_to_cpu(cp->flags); + timeout = __le16_to_cpu(cp->timeout); /* The current implementation only supports adding one instance and * doesn't support flags. @@ -6553,6 +6593,12 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, hci_dev_lock(hdev); + if (timeout && !hdev_is_powered(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, + MGMT_STATUS_REJECTED); + goto unlock; + } + if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) || pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) || pending_find(MGMT_OP_SET_LE, hdev)) { @@ -6569,6 +6615,8 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, goto unlock; } + INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired); + hdev->adv_instance.flags = flags; hdev->adv_instance.adv_data_len = cp->adv_data_len; hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len; @@ -6580,6 +6628,16 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, memcpy(hdev->adv_instance.scan_rsp_data, cp->data + cp->adv_data_len, cp->scan_rsp_len); + if (hdev->adv_instance.timeout) + cancel_delayed_work(&hdev->adv_instance.timeout_exp); + + hdev->adv_instance.timeout = timeout; + + if (timeout) + queue_delayed_work(hdev->workqueue, + &hdev->adv_instance.timeout_exp, + msecs_to_jiffies(timeout * 1000)); + if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE)) advertising_added(sk, hdev, 1); @@ -6682,6 +6740,9 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev, goto unlock; } + if (hdev->adv_instance.timeout) + cancel_delayed_work(&hdev->adv_instance.timeout_exp); + memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance)); advertising_removed(sk, hdev, 1); -- cgit v1.2.3-59-g8ed1b From 495099962138732c28449d07f3b1988836659851 Mon Sep 17 00:00:00 2001 From: Arman Uguray Date: Wed, 25 Mar 2015 18:53:39 -0700 Subject: Bluetooth: Add macros for advertising instance flags This patch adds macro definitions for possible advertising instance flags that can be passed to the "Add Advertising" command. Signed-off-by: Arman Uguray Signed-off-by: Marcel Holtmann --- include/net/bluetooth/mgmt.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 68abd4b0c25d..b831242d48a4 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -554,6 +554,14 @@ struct mgmt_rp_add_advertising { __u8 instance; } __packed; +#define MGMT_ADV_FLAG_CONNECTABLE BIT(0) +#define MGMT_ADV_FLAG_DISCOV BIT(1) +#define MGMT_ADV_FLAG_LIMITED_DISCOV BIT(2) +#define MGMT_ADV_FLAG_MANAGED_FLAGS BIT(3) +#define MGMT_ADV_FLAG_TX_POWER BIT(4) +#define MGMT_ADV_FLAG_APPEARANCE BIT(5) +#define MGMT_ADV_FLAG_LOCAL_NAME BIT(6) + #define MGMT_OP_REMOVE_ADVERTISING 0x003F struct mgmt_cp_remove_advertising { __u8 instance; -- cgit v1.2.3-59-g8ed1b