diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2015-03-13 01:30:58 -0400 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2015-03-13 06:07:54 -0400 |
commit | cc91cb042ce5dab66fedeb94260b18f193ed33d9 (patch) | |
tree | e21de1be11a57c1baedc10c8257b98c2686e60bb /net/bluetooth | |
parent | 983f9814c0199c26a58cbfe98f071e3bfa968839 (diff) |
Bluetooth: Add support connectable advertising setting
The patch adds a second advertising setting that allows switching of the
controller into connectable mode independent of the global connectable
setting.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/mgmt.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 025f29bf1f1a..0761f2e0fefa 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1110,7 +1110,10 @@ static void enable_advertising(struct hci_request *req) | |||
1110 | */ | 1110 | */ |
1111 | clear_bit(HCI_LE_ADV, &hdev->dev_flags); | 1111 | clear_bit(HCI_LE_ADV, &hdev->dev_flags); |
1112 | 1112 | ||
1113 | connectable = get_connectable(hdev); | 1113 | if (test_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags)) |
1114 | connectable = true; | ||
1115 | else | ||
1116 | connectable = get_connectable(hdev); | ||
1114 | 1117 | ||
1115 | /* Set require_privacy to true only when non-connectable | 1118 | /* Set require_privacy to true only when non-connectable |
1116 | * advertising is used. In that case it is fine to use a | 1119 | * advertising is used. In that case it is fine to use a |
@@ -4430,7 +4433,7 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4430 | struct mgmt_mode *cp = data; | 4433 | struct mgmt_mode *cp = data; |
4431 | struct mgmt_pending_cmd *cmd; | 4434 | struct mgmt_pending_cmd *cmd; |
4432 | struct hci_request req; | 4435 | struct hci_request req; |
4433 | u8 val, enabled, status; | 4436 | u8 val, status; |
4434 | int err; | 4437 | int err; |
4435 | 4438 | ||
4436 | BT_DBG("request for %s", hdev->name); | 4439 | BT_DBG("request for %s", hdev->name); |
@@ -4440,29 +4443,42 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4440 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, | 4443 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, |
4441 | status); | 4444 | status); |
4442 | 4445 | ||
4443 | if (cp->val != 0x00 && cp->val != 0x01) | 4446 | if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) |
4444 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, | 4447 | return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, |
4445 | MGMT_STATUS_INVALID_PARAMS); | 4448 | MGMT_STATUS_INVALID_PARAMS); |
4446 | 4449 | ||
4447 | hci_dev_lock(hdev); | 4450 | hci_dev_lock(hdev); |
4448 | 4451 | ||
4449 | val = !!cp->val; | 4452 | val = !!cp->val; |
4450 | enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
4451 | 4453 | ||
4452 | /* The following conditions are ones which mean that we should | 4454 | /* The following conditions are ones which mean that we should |
4453 | * not do any HCI communication but directly send a mgmt | 4455 | * not do any HCI communication but directly send a mgmt |
4454 | * response to user space (after toggling the flag if | 4456 | * response to user space (after toggling the flag if |
4455 | * necessary). | 4457 | * necessary). |
4456 | */ | 4458 | */ |
4457 | if (!hdev_is_powered(hdev) || val == enabled || | 4459 | if (!hdev_is_powered(hdev) || |
4460 | (val == test_bit(HCI_ADVERTISING, &hdev->dev_flags) && | ||
4461 | (cp->val == 0x02) == test_bit(HCI_ADVERTISING_CONNECTABLE, | ||
4462 | &hdev->dev_flags)) || | ||
4458 | hci_conn_num(hdev, LE_LINK) > 0 || | 4463 | hci_conn_num(hdev, LE_LINK) > 0 || |
4459 | (test_bit(HCI_LE_SCAN, &hdev->dev_flags) && | 4464 | (test_bit(HCI_LE_SCAN, &hdev->dev_flags) && |
4460 | hdev->le_scan_type == LE_SCAN_ACTIVE)) { | 4465 | hdev->le_scan_type == LE_SCAN_ACTIVE)) { |
4461 | bool changed = false; | 4466 | bool changed; |
4462 | 4467 | ||
4463 | if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { | 4468 | if (cp->val) { |
4464 | change_bit(HCI_ADVERTISING, &hdev->dev_flags); | 4469 | changed = !test_and_set_bit(HCI_ADVERTISING, |
4465 | changed = true; | 4470 | &hdev->dev_flags); |
4471 | if (cp->val == 0x02) | ||
4472 | set_bit(HCI_ADVERTISING_CONNECTABLE, | ||
4473 | &hdev->dev_flags); | ||
4474 | else | ||
4475 | clear_bit(HCI_ADVERTISING_CONNECTABLE, | ||
4476 | &hdev->dev_flags); | ||
4477 | } else { | ||
4478 | changed = test_and_clear_bit(HCI_ADVERTISING, | ||
4479 | &hdev->dev_flags); | ||
4480 | clear_bit(HCI_ADVERTISING_CONNECTABLE, | ||
4481 | &hdev->dev_flags); | ||
4466 | } | 4482 | } |
4467 | 4483 | ||
4468 | err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev); | 4484 | err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev); |
@@ -4490,6 +4506,11 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | |||
4490 | 4506 | ||
4491 | hci_req_init(&req, hdev); | 4507 | hci_req_init(&req, hdev); |
4492 | 4508 | ||
4509 | if (cp->val == 0x02) | ||
4510 | set_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags); | ||
4511 | else | ||
4512 | clear_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags); | ||
4513 | |||
4493 | if (val) | 4514 | if (val) |
4494 | enable_advertising(&req); | 4515 | enable_advertising(&req); |
4495 | else | 4516 | else |