2012-08-10 21:01:42

by Jefferson Delfes

[permalink] [raw]
Subject: [RFC 0/5] Broadcaster/Observer MGMT API

After some discussions on BlueZ meeting, it was decided to have a MGMT API for
Broadcaster and Observer roles.

The normal flow for Broadcaster is set controller data for any data needed and
set broadcaster on. For now, kernel will try to pack as much data as possible
for Adv. In future, we may implement a rotation logic to send all data set by
userspace.
Use unset controller data with respective data_type to remove any data that
matches this data_type.
After adding or removing controller data, to update Adv data, you need to set
broadcaster off and after set broadcaster on, so adv. data can be updated on
the controller.

To start observer, just set observer to on. Any data will come from device
found event.

We have patches for userspace that will hit BlueZ ML next week.

Jefferson Delfes (5):
Bluetooth: Add new commands HCI for LE and BR/EDR
Bluetooth: Add set controller data MGMT command
Bluetooth: Add unset controller data MGMT command
Bluetooth: Add set broadcaster MGMT command
Bluetooth: Add set observer MGMT command

include/net/bluetooth/hci.h | 30 +++++++
include/net/bluetooth/hci_core.h | 15 ++++
include/net/bluetooth/mgmt.h | 23 ++++++
net/bluetooth/hci_core.c | 48 +++++++++++
net/bluetooth/mgmt.c | 167 +++++++++++++++++++++++++++++++++++++++
5 files changed, 283 insertions(+)

--
1.7.11.4



2012-08-29 17:42:23

by Aloisio Almeida

[permalink] [raw]
Subject: Re: [RFC 4/5] Bluetooth: Add set broadcaster MGMT command

Hi Johan,

It was decided to have broadcaster/observer in BR/EDR also. I think it
was decided in the Bluez meeting, right?

For now we're thinking in use this on BR/EDR only controllers. Dual
mode controllers would use LE for broadcasting.

I'm working on adding this feature right now. Further I'll send the v2.

Aloisio

On Tue, Aug 14, 2012 at 6:13 AM, Johan Hedberg <[email protected]> wrote:
> Hi Jefferson,
>
> On Fri, Aug 10, 2012, Jefferson Delfes wrote:
>> --- a/net/bluetooth/mgmt.c
>> +++ b/net/bluetooth/mgmt.c
>> @@ -379,6 +379,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
>> settings |= MGMT_SETTING_FAST_CONNECTABLE;
>> settings |= MGMT_SETTING_DISCOVERABLE;
>> settings |= MGMT_SETTING_PAIRABLE;
>> + settings |= MGMT_SETTING_BROADCASTER;
>
> Shouldn't this be behind the same conditional as MGMT_SETTING_LE? I.e.
> only when hdev->features indicates LE support.
>
> Johan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2012-08-14 09:13:17

by Johan Hedberg

[permalink] [raw]
Subject: Re: [RFC 4/5] Bluetooth: Add set broadcaster MGMT command

Hi Jefferson,

On Fri, Aug 10, 2012, Jefferson Delfes wrote:
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -379,6 +379,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
> settings |= MGMT_SETTING_FAST_CONNECTABLE;
> settings |= MGMT_SETTING_DISCOVERABLE;
> settings |= MGMT_SETTING_PAIRABLE;
> + settings |= MGMT_SETTING_BROADCASTER;

Shouldn't this be behind the same conditional as MGMT_SETTING_LE? I.e.
only when hdev->features indicates LE support.

Johan

2012-08-10 21:01:47

by Jefferson Delfes

[permalink] [raw]
Subject: [RFC 5/5] Bluetooth: Add set observer MGMT command

This command will enable or disable observer mode. In that mode,
discovery will be started, so any broadcast will be received in device
found event.

Signed-off-by: Jefferson Delfes <[email protected]>
---
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/mgmt.h | 3 +++
net/bluetooth/mgmt.c | 43 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 47 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 80f585a..17ea1ad 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -119,6 +119,7 @@ enum {
HCI_PENDING_CLASS,
HCI_PERIODIC_INQ,
HCI_BROADCASTER,
+ HCI_OBSERVER,
};

/* HCI ioctl defines */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 2e85012..69525f9 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -93,6 +93,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
#define MGMT_SETTING_BROADCASTER 0x00000400
+#define MGMT_SETTING_OBSERVER 0x00000800

#define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0
@@ -370,6 +371,8 @@ struct mgmt_cp_unset_controller_data {

#define MGMT_OP_SET_BROADCASTER 0x002B

+#define MGMT_OP_SET_OBSERVER 0x002C
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ae4910a..845ce2d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -380,6 +380,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
settings |= MGMT_SETTING_DISCOVERABLE;
settings |= MGMT_SETTING_PAIRABLE;
settings |= MGMT_SETTING_BROADCASTER;
+ settings |= MGMT_SETTING_OBSERVER;

if (lmp_ssp_capable(hdev))
settings |= MGMT_SETTING_SSP;
@@ -423,6 +424,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (test_bit(HCI_BROADCASTER, &hdev->dev_flags))
settings |= MGMT_SETTING_BROADCASTER;

+ if (test_bit(HCI_OBSERVER, &hdev->dev_flags))
+ settings |= MGMT_SETTING_OBSERVER;
+
if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
settings |= MGMT_SETTING_LINK_SECURITY;

@@ -2805,6 +2809,44 @@ failed:
return err;
}

+static int set_observer_le(struct hci_dev *hdev, u8 enable)
+{
+ struct hci_cp_le_set_scan_enable cmd;
+
+ cmd.enable = enable;
+ cmd.filter_dup = 0;
+ return hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cmd), &cmd);
+}
+
+static int set_observer(struct sock *sk, struct hci_dev *hdev, void *data,
+ u16 len)
+{
+ struct mgmt_mode *cp = data;
+ int err;
+
+ BT_DBG("%s val:%i", hdev->name, cp->val);
+
+ if (cp->val)
+ set_bit(HCI_OBSERVER, &hdev->dev_flags);
+ else
+ clear_bit(HCI_OBSERVER, &hdev->dev_flags);
+
+ hci_dev_lock(hdev);
+
+ if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ set_observer_le(hdev, cp->val);
+
+ err = send_settings_rsp(sk, MGMT_OP_SET_OBSERVER, hdev);
+ if (err < 0)
+ goto failed;
+
+ err = new_settings(hdev, sk);
+
+failed:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
static const struct mgmt_handler {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len);
@@ -2855,6 +2897,7 @@ static const struct mgmt_handler {
{ set_controller_data, true, MGMT_SET_CONTROLLER_DATA_SIZE },
{ unset_controller_data, false, MGMT_UNSET_CONTROLLER_DATA_SIZE },
{ set_broadcaster, false, MGMT_SETTING_SIZE },
+ { set_observer, false, MGMT_SETTING_SIZE },
};


--
1.7.11.4


2012-08-10 21:01:46

by Jefferson Delfes

[permalink] [raw]
Subject: [RFC 4/5] Bluetooth: Add set broadcaster MGMT command

This command will enable or disable broadcaster mode. Data can be added
with set_controller_data command. If there are more data that can be
broadcasted, it will be ignored for while.

Signed-off-by: Jefferson Delfes <[email protected]>
---
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/mgmt.h | 3 ++
net/bluetooth/mgmt.c | 75 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index e4d4717..80f585a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -118,6 +118,7 @@ enum {
HCI_LINK_SECURITY,
HCI_PENDING_CLASS,
HCI_PERIODIC_INQ,
+ HCI_BROADCASTER,
};

/* HCI ioctl defines */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index eda2755..2e85012 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -92,6 +92,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_BREDR 0x00000080
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
+#define MGMT_SETTING_BROADCASTER 0x00000400

#define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0
@@ -367,6 +368,8 @@ struct mgmt_cp_unset_controller_data {
} __packed;
#define MGMT_UNSET_CONTROLLER_DATA_SIZE 1

+#define MGMT_OP_SET_BROADCASTER 0x002B
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 51d0e2f..ae4910a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -379,6 +379,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
settings |= MGMT_SETTING_FAST_CONNECTABLE;
settings |= MGMT_SETTING_DISCOVERABLE;
settings |= MGMT_SETTING_PAIRABLE;
+ settings |= MGMT_SETTING_BROADCASTER;

if (lmp_ssp_capable(hdev))
settings |= MGMT_SETTING_SSP;
@@ -419,6 +420,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
settings |= MGMT_SETTING_LE;

+ if (test_bit(HCI_BROADCASTER, &hdev->dev_flags))
+ settings |= MGMT_SETTING_BROADCASTER;
+
if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
settings |= MGMT_SETTING_LINK_SECURITY;

@@ -2731,6 +2735,76 @@ static int unset_controller_data(struct sock *sk, struct hci_dev *hdev,
NULL, 0);
}

+static int set_broadcaster_le(struct hci_dev *hdev, u8 enable)
+{
+ BT_DBG("%s enable:%i", hdev->name, enable);
+
+ if (enable) {
+ struct hci_cp_le_set_adv_params params;
+ struct hci_cp_le_set_adv_data data;
+ struct controller_data *d;
+
+ params.interval_min = __constant_cpu_to_le16(0x0800);
+ params.interval_max = __constant_cpu_to_le16(0x0800);
+ params.type = ADV_NONCONN_IND;
+ params.own_address_type = ADDR_LE_DEV_PUBLIC;
+ params.direct_address_type = ADDR_LE_DEV_PUBLIC;
+ memset(&params.direct_address, 0,
+ sizeof(params.direct_address));
+ params.channel_map = ADV_USE_ALL_CHANNELS;
+ params.filter_policy = 0x00;
+ hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_PARAMS, sizeof(params),
+ &params);
+
+ data.data_len = 0;
+ memset(&data.data, 0, sizeof(data.data));
+ list_for_each_entry(d, &hdev->controller_data, list) {
+ if (data.data_len + d->data_length + 2 >
+ HCI_MAX_ADV_LENGTH)
+ break;
+
+ data.data[data.data_len] = d->data_length + 1;
+ data.data[data.data_len + 1] = d->data_type;
+ memcpy(&data.data[data.data_len + 2], d->data,
+ d->data_length);
+ data.data_len += d->data_length + 2;
+ }
+ hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(data), &data);
+ }
+
+ return hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
+ &enable);
+}
+
+static int set_broadcaster(struct sock *sk, struct hci_dev *hdev, void *data,
+ u16 len)
+{
+ struct mgmt_mode *cp = data;
+ int err;
+
+ BT_DBG("%s val:%i", hdev->name, cp->val);
+
+ if (cp->val)
+ set_bit(HCI_BROADCASTER, &hdev->dev_flags);
+ else
+ clear_bit(HCI_BROADCASTER, &hdev->dev_flags);
+
+ hci_dev_lock(hdev);
+
+ if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ set_broadcaster_le(hdev, cp->val);
+
+ err = send_settings_rsp(sk, MGMT_OP_SET_BROADCASTER, hdev);
+ if (err < 0)
+ goto failed;
+
+ err = new_settings(hdev, sk);
+
+failed:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
static const struct mgmt_handler {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len);
@@ -2780,6 +2854,7 @@ static const struct mgmt_handler {
{ set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
{ set_controller_data, true, MGMT_SET_CONTROLLER_DATA_SIZE },
{ unset_controller_data, false, MGMT_UNSET_CONTROLLER_DATA_SIZE },
+ { set_broadcaster, false, MGMT_SETTING_SIZE },
};


--
1.7.11.4


2012-08-10 21:01:45

by Jefferson Delfes

[permalink] [raw]
Subject: [RFC 3/5] Bluetooth: Add unset controller data MGMT command

This command will remove controller data from EIR and/or AD.

Signed-off-by: Jefferson Delfes <[email protected]>
---
include/net/bluetooth/hci_core.h | 1 +
include/net/bluetooth/mgmt.h | 6 ++++++
net/bluetooth/hci_core.c | 16 ++++++++++++++++
net/bluetooth/mgmt.c | 16 ++++++++++++++++
4 files changed, 39 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3a61227..5e6b477 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -728,6 +728,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
int hci_controller_data_add(struct hci_dev *hdev, u8 flags, u8 data_type,
u8 data_length, u8 *data);
int hci_controller_data_clear(struct hci_dev *hdev);
+int hci_controller_data_remove(struct hci_dev *hdev, u8 data_type);

#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))

diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 1afa399..eda2755 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -361,6 +361,12 @@ struct mgmt_cp_set_controller_data {
} __packed;
#define MGMT_SET_CONTROLLER_DATA_SIZE 3

+#define MGMT_OP_UNSET_CONTROLLER_DATA 0x002A
+struct mgmt_cp_unset_controller_data {
+ __u8 data_type;
+} __packed;
+#define MGMT_UNSET_CONTROLLER_DATA_SIZE 1
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2e38a1b..80280fa 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1471,6 +1471,22 @@ int hci_controller_data_clear(struct hci_dev *hdev)
return 0;
}

+int hci_controller_data_remove(struct hci_dev *hdev, u8 data_type)
+{
+ struct controller_data *match, *n;
+ int matches = 0;
+
+ list_for_each_entry_safe(match, n, &hdev->controller_data, list) {
+ if (data_type == match->data_type) {
+ list_del(&match->list);
+ kfree(match);
+ matches++;
+ }
+ }
+
+ return matches;
+}
+
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct bdaddr_list *b;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 9e9702a..51d0e2f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2716,6 +2716,21 @@ static int set_controller_data(struct sock *sk, struct hci_dev *hdev,
0);
}

+static int unset_controller_data(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ struct mgmt_cp_unset_controller_data *cp = data;
+
+ BT_DBG("%s type:0x%02x", hdev->name, cp->data_type);
+
+ hci_dev_lock(hdev);
+ hci_controller_data_remove(hdev, cp->data_type);
+ hci_dev_unlock(hdev);
+
+ return cmd_complete(sk, hdev->id, MGMT_OP_UNSET_CONTROLLER_DATA, 0,
+ NULL, 0);
+}
+
static const struct mgmt_handler {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len);
@@ -2764,6 +2779,7 @@ static const struct mgmt_handler {
{ unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
{ set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
{ set_controller_data, true, MGMT_SET_CONTROLLER_DATA_SIZE },
+ { unset_controller_data, false, MGMT_UNSET_CONTROLLER_DATA_SIZE },
};


--
1.7.11.4


2012-08-10 21:01:44

by Jefferson Delfes

[permalink] [raw]
Subject: [RFC 2/5] Bluetooth: Add set controller data MGMT command

This command will be used to sets EIR data for BR/EDR and/or AD for LE.

Signed-off-by: Jefferson Delfes <[email protected]>
---
include/net/bluetooth/hci_core.h | 14 ++++++++++++++
include/net/bluetooth/mgmt.h | 11 +++++++++++
net/bluetooth/hci_core.c | 32 ++++++++++++++++++++++++++++++++
net/bluetooth/mgmt.c | 33 +++++++++++++++++++++++++++++++++
4 files changed, 90 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 41d9439..3a61227 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -122,6 +122,14 @@ struct le_scan_params {
int timeout;
};

+struct controller_data {
+ struct list_head list;
+ u8 flags;
+ u8 data_type;
+ u8 data_length;
+ u8 data[0];
+};
+
#define HCI_MAX_SHORT_NAME_LENGTH 10

#define NUM_REASSEMBLY 4
@@ -269,6 +277,8 @@ struct hci_dev {
struct work_struct le_scan;
struct le_scan_params le_scan_params;

+ struct list_head controller_data;
+
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
@@ -715,6 +725,10 @@ void hci_conn_init_sysfs(struct hci_conn *conn);
void hci_conn_add_sysfs(struct hci_conn *conn);
void hci_conn_del_sysfs(struct hci_conn *conn);

+int hci_controller_data_add(struct hci_dev *hdev, u8 flags, u8 data_type,
+ u8 data_length, u8 *data);
+int hci_controller_data_clear(struct hci_dev *hdev);
+
#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))

/* ----- LMP capabilities ----- */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 4348ee8..1afa399 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -350,6 +350,17 @@ struct mgmt_cp_set_device_id {
} __packed;
#define MGMT_SET_DEVICE_ID_SIZE 8

+#define MGMT_DATA_HIGH_PRIORITY BIT(0)
+
+#define MGMT_OP_SET_CONTROLLER_DATA 0x0029
+struct mgmt_cp_set_controller_data {
+ __u8 flags;
+ __u8 data_type;
+ __u8 data_length;
+ __u8 data[0];
+} __packed;
+#define MGMT_SET_CONTROLLER_DATA_SIZE 3
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index fa974a1..2e38a1b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1441,6 +1441,36 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
return 0;
}

+int hci_controller_data_add(struct hci_dev *hdev, u8 flags, u8 data_type,
+ u8 data_length, u8 *data)
+{
+ struct controller_data *c_data;
+
+ c_data = kmalloc(sizeof(*c_data) + data_length, GFP_KERNEL);
+ if (!c_data)
+ return -ENOMEM;
+
+ c_data->flags = flags;
+ c_data->data_type = data_type;
+ c_data->data_length = data_length;
+ memcpy(c_data->data, data, data_length);
+
+ list_add(&c_data->list, &hdev->controller_data);
+ return 0;
+}
+
+int hci_controller_data_clear(struct hci_dev *hdev)
+{
+ struct controller_data *c_data, *n;
+
+ list_for_each_entry_safe(c_data, n, &hdev->controller_data, list) {
+ list_del(&c_data->list);
+ kfree(c_data);
+ }
+
+ return 0;
+}
+
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct bdaddr_list *b;
@@ -1652,6 +1682,7 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->link_keys);
INIT_LIST_HEAD(&hdev->long_term_keys);
INIT_LIST_HEAD(&hdev->remote_oob_data);
+ INIT_LIST_HEAD(&hdev->controller_data);

INIT_WORK(&hdev->rx_work, hci_rx_work);
INIT_WORK(&hdev->cmd_work, hci_cmd_work);
@@ -1817,6 +1848,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_link_keys_clear(hdev);
hci_smp_ltks_clear(hdev);
hci_remote_oob_data_clear(hdev);
+ hci_controller_data_clear(hdev);
hci_dev_unlock(hdev);

hci_dev_put(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a3329cb..9e9702a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2684,6 +2684,38 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
return 0;
}

+static int set_controller_data(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ struct mgmt_cp_set_controller_data *cp = data;
+
+ BT_DBG("%s", hdev->name);
+
+ if (cp->flags > MGMT_DATA_HIGH_PRIORITY)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ if (cp->data_type != EIR_SERVICE_DATA &&
+ cp->data_type != EIR_MANUFACTURER_DATA)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ if (cp->data_length > HCI_MAX_EIR_LENGTH - 2)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ BT_DBG("flags:0x%02x type:0x%02x length:%i", cp->flags, cp->data_type,
+ cp->data_length);
+
+ hci_dev_lock(hdev);
+ hci_controller_data_add(hdev, cp->flags, cp->data_type, cp->data_length,
+ cp->data);
+ hci_dev_unlock(hdev);
+
+ return cmd_complete(sk, hdev->id, MGMT_OP_SET_CONTROLLER_DATA, 0, NULL,
+ 0);
+}
+
static const struct mgmt_handler {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len);
@@ -2731,6 +2763,7 @@ static const struct mgmt_handler {
{ block_device, false, MGMT_BLOCK_DEVICE_SIZE },
{ unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
{ set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
+ { set_controller_data, true, MGMT_SET_CONTROLLER_DATA_SIZE },
};


--
1.7.11.4


2012-08-10 21:01:43

by Jefferson Delfes

[permalink] [raw]
Subject: [RFC 1/5] Bluetooth: Add new commands HCI for LE and BR/EDR

Add some commands to control Advertising data.

Signed-off-by: Jefferson Delfes <[email protected]>
---
include/net/bluetooth/hci.h | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 23cf413..e4d4717 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -326,6 +326,8 @@ 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_SERVICE_DATA 0x16 /* Service Data */
+#define EIR_MANUFACTURER_DATA 0xFF /* Manufacturer Specific Data */

/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
@@ -891,6 +893,32 @@ struct hci_rp_le_read_buffer_size {
__u8 le_max_pkt;
} __packed;

+#define ADV_USE_ALL_CHANNELS 0x07
+
+#define HCI_OP_LE_SET_ADV_PARAMS 0x2006
+struct hci_cp_le_set_adv_params {
+ __le16 interval_min;
+ __le16 interval_max;
+ __u8 type;
+ __u8 own_address_type;
+ __u8 direct_address_type;
+ __u8 direct_address[6];
+ __u8 channel_map;
+ __u8 filter_policy;
+} __packed;
+
+#define HCI_MAX_ADV_LENGTH 31
+
+#define HCI_OP_LE_SET_ADV_DATA 0x2008
+struct hci_cp_le_set_adv_data {
+ __u8 data_len;
+ __u8 data[HCI_MAX_ADV_LENGTH];
+} __packed;
+
+#define HCI_OP_LE_SET_ADV_ENABLE 0x200a
+ #define ADVERTISING_DISABLE 0x00
+ #define ADVERTISING_ENABLE 0x01
+
#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct hci_cp_le_set_scan_param {
__u8 type;
--
1.7.11.4