* [PATCH v2 1/7] Bluetooth: Add clarifying comment to bt_sock_wait_state()
2013-09-25 10:26 [PATCH v2 0/7] Bluetooth: Cleanups and LE advertising support johan.hedberg
@ 2013-09-25 10:26 ` johan.hedberg
2013-09-25 10:26 ` [PATCH v2 2/7] Bluetooth: Clean up socket locking in l2cap_sock_recvmsg johan.hedberg
` (5 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: johan.hedberg @ 2013-09-25 10:26 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
The bt_sock_wait_state requires the sk lock to be held (through
lock_sock) so document it clearly in the code.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/af_bluetooth.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index c600631..e6e1278 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -490,6 +490,7 @@ int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
EXPORT_SYMBOL(bt_sock_ioctl);
+/* This function expects the sk lock to be held when called */
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
{
DECLARE_WAITQUEUE(wait, current);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 2/7] Bluetooth: Clean up socket locking in l2cap_sock_recvmsg
2013-09-25 10:26 [PATCH v2 0/7] Bluetooth: Cleanups and LE advertising support johan.hedberg
2013-09-25 10:26 ` [PATCH v2 1/7] Bluetooth: Add clarifying comment to bt_sock_wait_state() johan.hedberg
@ 2013-09-25 10:26 ` johan.hedberg
2013-09-25 10:30 ` Marcel Holtmann
2013-09-25 10:26 ` [PATCH v2 3/7] Bluetooth: Fix busy return for mgmt_set_powered in some cases johan.hedberg
` (4 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: johan.hedberg @ 2013-09-25 10:26 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch cleans up the locking login in l2cap_sock_recvmsg by pairing
up each lock_sock call with a release_sock call. The function already
has a "done" label that handles releasing the socket and returning from
the function so the fix is rather simple.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/l2cap_sock.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index ad95b42..c85537c 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -805,8 +805,8 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
pi->chan->state = BT_CONFIG;
__l2cap_connect_rsp_defer(pi->chan);
- release_sock(sk);
- return 0;
+ err = 0;
+ goto done;
}
release_sock(sk);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 3/7] Bluetooth: Fix busy return for mgmt_set_powered in some cases
2013-09-25 10:26 [PATCH v2 0/7] Bluetooth: Cleanups and LE advertising support johan.hedberg
2013-09-25 10:26 ` [PATCH v2 1/7] Bluetooth: Add clarifying comment to bt_sock_wait_state() johan.hedberg
2013-09-25 10:26 ` [PATCH v2 2/7] Bluetooth: Clean up socket locking in l2cap_sock_recvmsg johan.hedberg
@ 2013-09-25 10:26 ` johan.hedberg
2013-09-25 10:26 ` [PATCH v2 4/7] Bluetooth: Move mgmt response convenience functions to a better location johan.hedberg
` (3 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: johan.hedberg @ 2013-09-25 10:26 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
We should return a "busy" error always when there is another
mgmt_set_powered operation in progress. Previously when powering on
while the auto off timer was still set the code could have let two or
more pending power on commands to be queued. This patch fixes the issue
by moving the check for duplicate commands to an earlier point in the
set_powered handler.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/mgmt.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3070e77..85bfa21 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -807,6 +807,12 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev);
+ if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
+ MGMT_STATUS_BUSY);
+ goto failed;
+ }
+
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
cancel_delayed_work(&hdev->power_off);
@@ -823,12 +829,6 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed;
}
- if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
- err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
- MGMT_STATUS_BUSY);
- goto failed;
- }
-
cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 4/7] Bluetooth: Move mgmt response convenience functions to a better location
2013-09-25 10:26 [PATCH v2 0/7] Bluetooth: Cleanups and LE advertising support johan.hedberg
` (2 preceding siblings ...)
2013-09-25 10:26 ` [PATCH v2 3/7] Bluetooth: Fix busy return for mgmt_set_powered in some cases johan.hedberg
@ 2013-09-25 10:26 ` johan.hedberg
2013-09-25 10:26 ` [PATCH v2 5/7] Bluetooth: Use async request for LE enable/disable johan.hedberg
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: johan.hedberg @ 2013-09-25 10:26 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
The settings_rsp and cmd_status_rsp functions can be useful for all mgmt
command handlers when asynchronous request callbacks are used. They will
e.g. be used by subsequent patches to change set_le to use an async
request as well as a new set_advertising command. Therefore, move them
higher up in the mgmt.c file to avoid unnecessary forward declarations
or mixing this trivial change with other patches.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/mgmt.c | 60 ++++++++++++++++++++++++++--------------------------
1 file changed, 30 insertions(+), 30 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 85bfa21..61d4b19 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -886,6 +886,36 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip)
return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
}
+struct cmd_lookup {
+ struct sock *sk;
+ struct hci_dev *hdev;
+ u8 mgmt_status;
+};
+
+static void settings_rsp(struct pending_cmd *cmd, void *data)
+{
+ struct cmd_lookup *match = data;
+
+ send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
+
+ list_del(&cmd->list);
+
+ if (match->sk == NULL) {
+ match->sk = cmd->sk;
+ sock_hold(match->sk);
+ }
+
+ mgmt_pending_free(cmd);
+}
+
+static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
+{
+ u8 *status = data;
+
+ cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
+ mgmt_pending_remove(cmd);
+}
+
static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
@@ -3374,14 +3404,6 @@ done:
return err;
}
-static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
-{
- u8 *status = data;
-
- cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
- mgmt_pending_remove(cmd);
-}
-
int mgmt_index_added(struct hci_dev *hdev)
{
if (!mgmt_valid_hdev(hdev))
@@ -3402,28 +3424,6 @@ int mgmt_index_removed(struct hci_dev *hdev)
return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
}
-struct cmd_lookup {
- struct sock *sk;
- struct hci_dev *hdev;
- u8 mgmt_status;
-};
-
-static void settings_rsp(struct pending_cmd *cmd, void *data)
-{
- struct cmd_lookup *match = data;
-
- send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
-
- list_del(&cmd->list);
-
- if (match->sk == NULL) {
- match->sk = cmd->sk;
- sock_hold(match->sk);
- }
-
- mgmt_pending_free(cmd);
-}
-
static void set_bredr_scan(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 5/7] Bluetooth: Use async request for LE enable/disable
2013-09-25 10:26 [PATCH v2 0/7] Bluetooth: Cleanups and LE advertising support johan.hedberg
` (3 preceding siblings ...)
2013-09-25 10:26 ` [PATCH v2 4/7] Bluetooth: Move mgmt response convenience functions to a better location johan.hedberg
@ 2013-09-25 10:26 ` johan.hedberg
2013-09-25 10:26 ` [PATCH v2 6/7] Bluetooth: Add new mgmt setting for LE advertising johan.hedberg
2013-09-25 10:26 ` [PATCH v2 7/7] Bluetooth: Add new mgmt_set_advertising command johan.hedberg
6 siblings, 0 replies; 11+ messages in thread
From: johan.hedberg @ 2013-09-25 10:26 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch updates the code to use an asynchronous request for handling
the enabling and disabling of LE support. This refactoring is necessary
as a preparation for adding advertising support, since when LE is
disabled we should also disable advertising, and the cleanest way to do
this is to perform the two respective HCI commands in the same
asynchronous request.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/hci_core.h | 1 -
net/bluetooth/hci_event.c | 11 +++----
net/bluetooth/mgmt.c | 67 ++++++++++++++++------------------------
3 files changed, 32 insertions(+), 47 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3ede820..26cc9f7 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1168,7 +1168,6 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
u8 *randomizer, u8 status);
-int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
u8 ssp, u8 *eir, u16 eir_len);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 94aab73..48db81f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -994,20 +994,19 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
return;
if (!status) {
- if (sent->le)
+ if (sent->le) {
hdev->features[1][0] |= LMP_HOST_LE;
- else
+ set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
+ } else {
hdev->features[1][0] &= ~LMP_HOST_LE;
+ clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
+ }
if (sent->simul)
hdev->features[1][0] |= LMP_HOST_LE_BREDR;
else
hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
}
-
- if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
- !test_bit(HCI_INIT, &hdev->flags))
- mgmt_le_enable_complete(hdev, sent->le, status);
}
static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 61d4b19..4c3984e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1354,11 +1354,32 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
return send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
}
+static void le_enable_complete(struct hci_dev *hdev, u8 status)
+{
+ struct cmd_lookup match = { NULL, hdev };
+
+ if (status) {
+ u8 mgmt_err = mgmt_status(status);
+
+ mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
+ &mgmt_err);
+ return;
+ }
+
+ mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
+
+ new_settings(hdev, match.sk);
+
+ if (match.sk)
+ sock_put(match.sk);
+}
+
static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_mode *cp = data;
struct hci_cp_write_le_host_supported hci_cp;
struct pending_cmd *cmd;
+ struct hci_request req;
int err;
u8 val, enabled;
@@ -1419,8 +1440,12 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_cp.simul = lmp_le_br_capable(hdev);
}
- err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
- &hci_cp);
+ hci_req_init(&req, hdev);
+
+ hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
+ &hci_cp);
+
+ err = hci_req_run(&req, le_enable_complete);
if (err < 0)
mgmt_pending_remove(cmd);
@@ -4141,44 +4166,6 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
return err;
}
-int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
-{
- struct cmd_lookup match = { NULL, hdev };
- bool changed = false;
- int err = 0;
-
- if (status) {
- u8 mgmt_err = mgmt_status(status);
-
- if (enable && test_and_clear_bit(HCI_LE_ENABLED,
- &hdev->dev_flags))
- err = new_settings(hdev, NULL);
-
- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
- &mgmt_err);
-
- return err;
- }
-
- if (enable) {
- if (!test_and_set_bit(HCI_LE_ENABLED, &hdev->dev_flags))
- changed = true;
- } else {
- if (test_and_clear_bit(HCI_LE_ENABLED, &hdev->dev_flags))
- changed = true;
- }
-
- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
-
- if (changed)
- err = new_settings(hdev, match.sk);
-
- if (match.sk)
- sock_put(match.sk);
-
- return err;
-}
-
int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
ssp, u8 *eir, u16 eir_len)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 6/7] Bluetooth: Add new mgmt setting for LE advertising
2013-09-25 10:26 [PATCH v2 0/7] Bluetooth: Cleanups and LE advertising support johan.hedberg
` (4 preceding siblings ...)
2013-09-25 10:26 ` [PATCH v2 5/7] Bluetooth: Use async request for LE enable/disable johan.hedberg
@ 2013-09-25 10:26 ` johan.hedberg
2013-09-25 10:26 ` [PATCH v2 7/7] Bluetooth: Add new mgmt_set_advertising command johan.hedberg
6 siblings, 0 replies; 11+ messages in thread
From: johan.hedberg @ 2013-09-25 10:26 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds a new mgmt setting for LE advertising and hooks up the
necessary places in the mgmt code to operate on the HCI_LE_PERIPHERAL
flag (which corresponds to this setting). This patch does not yet add
any new command for enabling the setting - that is left for a subsequent
patch.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/mgmt.h | 1 +
net/bluetooth/hci_event.c | 1 +
net/bluetooth/mgmt.c | 21 ++++++++++++++++++++-
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 9944c3e..6cc72b6 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_BREDR 0x00000080
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
+#define MGMT_SETTING_ADVERTISING 0x00000400
#define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 48db81f..917c7c8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1000,6 +1000,7 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
} else {
hdev->features[1][0] &= ~LMP_HOST_LE;
clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
+ clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
}
if (sent->simul)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4c3984e..9a2faa3 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -384,8 +384,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
if (enable_hs)
settings |= MGMT_SETTING_HS;
- if (lmp_le_capable(hdev))
+ if (lmp_le_capable(hdev)) {
settings |= MGMT_SETTING_LE;
+ settings |= MGMT_SETTING_ADVERTISING;
+ }
return settings;
}
@@ -424,6 +426,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
settings |= MGMT_SETTING_HS;
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
+ settings |= MGMT_SETTING_ADVERTISING;
+
return settings;
}
@@ -1411,6 +1416,11 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
changed = true;
}
+ if (!val && test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
+ clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+ changed = true;
+ }
+
err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
if (err < 0)
goto unlock;
@@ -1442,6 +1452,9 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_req_init(&req, hdev);
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags) && !val)
+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val);
+
hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
&hci_cp);
@@ -3517,6 +3530,12 @@ static int powered_update_hci(struct hci_dev *hdev)
sizeof(cp), &cp);
}
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
+ u8 adv = 0x01;
+
+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv);
+ }
+
link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v2 7/7] Bluetooth: Add new mgmt_set_advertising command
2013-09-25 10:26 [PATCH v2 0/7] Bluetooth: Cleanups and LE advertising support johan.hedberg
` (5 preceding siblings ...)
2013-09-25 10:26 ` [PATCH v2 6/7] Bluetooth: Add new mgmt setting for LE advertising johan.hedberg
@ 2013-09-25 10:26 ` johan.hedberg
2013-09-25 10:31 ` Marcel Holtmann
2013-09-25 17:30 ` Gustavo Padovan
6 siblings, 2 replies; 11+ messages in thread
From: johan.hedberg @ 2013-09-25 10:26 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds a new mgmt command for enabling and disabling
LE advertising. The command depends on the LE setting being enabled
first and will return a "rejected" response otherwise. The patch also
adds safeguards so that there will ever only be one set_le or
set_advertising command pending per adapter.
The response handling and new_settings event sending is done in an
asynchronous request callback, meaning raw HCI access from user space to
enable advertising (e.g. hciconfig leadv) will not trigger the
new_settings event. This is intentional since trying to support mixed
raw HCI and mgmt access would mean adding extra state tracking or new
helper functions, essentially negating the benefit of using the
asynchronous request framework. The HCI_LE_ENABLED and HCI_LE_PERIPHERAL
flags however are updated correctly even with raw HCI access so this
will not completely break subsequent access over mgmt.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/mgmt.h | 2 +
net/bluetooth/mgmt.c | 97 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 6cc72b6..421d763 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -352,6 +352,8 @@ struct mgmt_cp_set_device_id {
} __packed;
#define MGMT_SET_DEVICE_ID_SIZE 8
+#define MGMT_OP_SET_ADVERTISING 0x0029
+
#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 9a2faa3..1b5b10f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -76,6 +76,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_BLOCK_DEVICE,
MGMT_OP_UNBLOCK_DEVICE,
MGMT_OP_SET_DEVICE_ID,
+ MGMT_OP_SET_ADVERTISING,
};
static const u16 mgmt_events[] = {
@@ -1431,7 +1432,8 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
goto unlock;
}
- if (mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
+ if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
+ mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_BUSY);
goto unlock;
@@ -3136,6 +3138,98 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
return err;
}
+static void set_advertising_complete(struct hci_dev *hdev, u8 status)
+{
+ struct cmd_lookup match = { NULL, hdev };
+
+ if (status) {
+ u8 mgmt_err = mgmt_status(status);
+
+ mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
+ cmd_status_rsp, &mgmt_err);
+ return;
+ }
+
+ mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
+ &match);
+
+ new_settings(hdev, match.sk);
+
+ if (match.sk)
+ sock_put(match.sk);
+}
+
+static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+{
+ struct mgmt_mode *cp = data;
+ struct pending_cmd *cmd;
+ struct hci_request req;
+ u8 val, enabled;
+ int err;
+
+ BT_DBG("request for %s", hdev->name);
+
+ if (!lmp_le_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_NOT_SUPPORTED);
+
+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_REJECTED);
+
+ if (cp->val != 0x00 && cp->val != 0x01)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ hci_dev_lock(hdev);
+
+ val = !!cp->val;
+ enabled = test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+
+ if (!hdev_is_powered(hdev) || val == enabled) {
+ bool changed = false;
+
+ if (val != test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
+ change_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+ changed = true;
+ }
+
+ err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
+ if (err < 0)
+ goto unlock;
+
+ if (changed)
+ err = new_settings(hdev, sk);
+
+ goto unlock;
+ }
+
+ if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
+ mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_BUSY);
+ goto unlock;
+ }
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
+ if (!cmd) {
+ err = -ENOMEM;
+ goto unlock;
+ }
+
+ hci_req_init(&req, hdev);
+
+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val);
+
+ err = hci_req_run(&req, set_advertising_complete);
+ if (err < 0)
+ mgmt_pending_remove(cmd);
+
+unlock:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
{
struct pending_cmd *cmd;
@@ -3347,6 +3441,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_advertising, false, MGMT_SETTING_SIZE },
};
--
1.8.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v2 7/7] Bluetooth: Add new mgmt_set_advertising command
2013-09-25 10:26 ` [PATCH v2 7/7] Bluetooth: Add new mgmt_set_advertising command johan.hedberg
@ 2013-09-25 10:31 ` Marcel Holtmann
2013-09-25 17:30 ` Gustavo Padovan
1 sibling, 0 replies; 11+ messages in thread
From: Marcel Holtmann @ 2013-09-25 10:31 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
Hi Johan,
> This patch adds a new mgmt command for enabling and disabling
> LE advertising. The command depends on the LE setting being enabled
> first and will return a "rejected" response otherwise. The patch also
> adds safeguards so that there will ever only be one set_le or
> set_advertising command pending per adapter.
>
> The response handling and new_settings event sending is done in an
> asynchronous request callback, meaning raw HCI access from user space to
> enable advertising (e.g. hciconfig leadv) will not trigger the
> new_settings event. This is intentional since trying to support mixed
> raw HCI and mgmt access would mean adding extra state tracking or new
> helper functions, essentially negating the benefit of using the
> asynchronous request framework. The HCI_LE_ENABLED and HCI_LE_PERIPHERAL
> flags however are updated correctly even with raw HCI access so this
> will not completely break subsequent access over mgmt.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/mgmt.h | 2 +
> net/bluetooth/mgmt.c | 97 +++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 98 insertions(+), 1 deletion(-)
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Regards
Marcel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 7/7] Bluetooth: Add new mgmt_set_advertising command
2013-09-25 10:26 ` [PATCH v2 7/7] Bluetooth: Add new mgmt_set_advertising command johan.hedberg
2013-09-25 10:31 ` Marcel Holtmann
@ 2013-09-25 17:30 ` Gustavo Padovan
1 sibling, 0 replies; 11+ messages in thread
From: Gustavo Padovan @ 2013-09-25 17:30 UTC (permalink / raw)
To: johan.hedberg; +Cc: linux-bluetooth
Hi Johan,
2013-09-25 johan.hedberg@gmail.com <johan.hedberg@gmail.com>:
> From: Johan Hedberg <johan.hedberg@intel.com>
>
> This patch adds a new mgmt command for enabling and disabling
> LE advertising. The command depends on the LE setting being enabled
> first and will return a "rejected" response otherwise. The patch also
> adds safeguards so that there will ever only be one set_le or
> set_advertising command pending per adapter.
>
> The response handling and new_settings event sending is done in an
> asynchronous request callback, meaning raw HCI access from user space to
> enable advertising (e.g. hciconfig leadv) will not trigger the
> new_settings event. This is intentional since trying to support mixed
> raw HCI and mgmt access would mean adding extra state tracking or new
> helper functions, essentially negating the benefit of using the
> asynchronous request framework. The HCI_LE_ENABLED and HCI_LE_PERIPHERAL
> flags however are updated correctly even with raw HCI access so this
> will not completely break subsequent access over mgmt.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/mgmt.h | 2 +
> net/bluetooth/mgmt.c | 97 +++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 98 insertions(+), 1 deletion(-)
All patches have been applied to bluetooth-next. Thanks.
Gustavo
^ permalink raw reply [flat|nested] 11+ messages in thread