diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2013-04-19 11:35:21 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-04-23 19:20:12 -0400 |
commit | c73eee9172bf061202c75ad4d16506a7efd04d1c (patch) | |
tree | 6141b15c1eeddd09cf1a7324cc6974f75cd41189 | |
parent | 07dc93dd14957dc1faba08f0aadd27b082e35ba2 (diff) |
Bluetooth: Fix sending write_le_host_supporte for LE-only controllers
The Bluetooth Core Specification (4.0) defines the Write LE Host
Supported HCI command as only available for controllers supporting
BR/EDR. This is further reflected in the Read Local Extended Features
HCI command also not being available for LE-only controllers. In other
words, host-side LE support is implicit for single-mode LE controllers
and doesn't have explicit HCI-level enablement.
This patch ensures that the LE setting is always exposed as enabled
through mgmt and returns a "rejected" response if user space tries to
toggle the setting. The patch also ensures that Write LE Host Supported
is never sent for LE-only controllers.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r-- | net/bluetooth/hci_core.c | 10 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 8 |
2 files changed, 17 insertions, 1 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 215db0801a65..b04ac355f118 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -377,6 +377,8 @@ static void bredr_setup(struct hci_request *req) | |||
377 | 377 | ||
378 | static void le_setup(struct hci_request *req) | 378 | static void le_setup(struct hci_request *req) |
379 | { | 379 | { |
380 | struct hci_dev *hdev = req->hdev; | ||
381 | |||
380 | /* Read LE Buffer Size */ | 382 | /* Read LE Buffer Size */ |
381 | hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | 383 | hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); |
382 | 384 | ||
@@ -391,6 +393,10 @@ static void le_setup(struct hci_request *req) | |||
391 | 393 | ||
392 | /* Read LE Supported States */ | 394 | /* Read LE Supported States */ |
393 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | 395 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); |
396 | |||
397 | /* LE-only controllers have LE implicitly enabled */ | ||
398 | if (!lmp_bredr_capable(hdev)) | ||
399 | set_bit(HCI_LE_ENABLED, &hdev->dev_flags); | ||
394 | } | 400 | } |
395 | 401 | ||
396 | static u8 hci_get_inquiry_mode(struct hci_dev *hdev) | 402 | static u8 hci_get_inquiry_mode(struct hci_dev *hdev) |
@@ -574,6 +580,10 @@ static void hci_set_le_support(struct hci_request *req) | |||
574 | struct hci_dev *hdev = req->hdev; | 580 | struct hci_dev *hdev = req->hdev; |
575 | struct hci_cp_write_le_host_supported cp; | 581 | struct hci_cp_write_le_host_supported cp; |
576 | 582 | ||
583 | /* LE-only devices do not support explicit enablement */ | ||
584 | if (!lmp_bredr_capable(hdev)) | ||
585 | return; | ||
586 | |||
577 | memset(&cp, 0, sizeof(cp)); | 587 | memset(&cp, 0, sizeof(cp)); |
578 | 588 | ||
579 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 589 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 4c830c62ef74..35fef22703e9 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1351,6 +1351,11 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1351 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, | 1351 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, |
1352 | MGMT_STATUS_INVALID_PARAMS); | 1352 | MGMT_STATUS_INVALID_PARAMS); |
1353 | 1353 | ||
1354 | /* LE-only devices do not allow toggling LE on/off */ | ||
1355 | if (!lmp_bredr_capable(hdev)) | ||
1356 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, | ||
1357 | MGMT_STATUS_REJECTED); | ||
1358 | |||
1354 | hci_dev_lock(hdev); | 1359 | hci_dev_lock(hdev); |
1355 | 1360 | ||
1356 | val = !!cp->val; | 1361 | val = !!cp->val; |
@@ -3347,7 +3352,8 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
3347 | hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp); | 3352 | hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp); |
3348 | } | 3353 | } |
3349 | 3354 | ||
3350 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 3355 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && |
3356 | lmp_bredr_capable(hdev)) { | ||
3351 | struct hci_cp_write_le_host_supported cp; | 3357 | struct hci_cp_write_le_host_supported cp; |
3352 | 3358 | ||
3353 | cp.le = 1; | 3359 | cp.le = 1; |