aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-03-13 01:30:58 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2015-03-13 06:07:54 -0400
commitcc91cb042ce5dab66fedeb94260b18f193ed33d9 (patch)
treee21de1be11a57c1baedc10c8257b98c2686e60bb /net/bluetooth
parent983f9814c0199c26a58cbfe98f071e3bfa968839 (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.c39
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