summaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-04-29 15:31:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-29 15:31:57 -0400
commit17a2911f3395d66694fcbd2e8970015904d9b034 (patch)
treec93e40197d4614b5183f86f0335c5c7abcee31aa /net/bluetooth
parent94dace10142790ddeb0a3a7b8b33d9540d30c79f (diff)
parenta8a48e60a468084ef6ec23c78e8903c9e0ba7a4c (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c29
-rw-r--r--net/bluetooth/l2cap_core.c7
-rw-r--r--net/bluetooth/mgmt.c8
3 files changed, 32 insertions, 12 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index ce82265f561..33843c5c493 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -79,7 +79,8 @@ static void hci_req_cancel(struct hci_dev *hdev, int err)
}
}
-struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 event)
+static struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
+ u8 event)
{
struct hci_ev_cmd_complete *ev;
struct hci_event_hdr *hdr;
@@ -134,7 +135,7 @@ failed:
}
struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
- void *param, u8 event, u32 timeout)
+ const void *param, u8 event, u32 timeout)
{
DECLARE_WAITQUEUE(wait, current);
struct hci_request req;
@@ -188,7 +189,7 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
EXPORT_SYMBOL(__hci_cmd_sync_ev);
struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
- void *param, u32 timeout)
+ const void *param, u32 timeout)
{
return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout);
}
@@ -377,6 +378,8 @@ static void bredr_setup(struct hci_request *req)
static void le_setup(struct hci_request *req)
{
+ struct hci_dev *hdev = req->hdev;
+
/* Read LE Buffer Size */
hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
@@ -391,6 +394,10 @@ static void le_setup(struct hci_request *req)
/* Read LE Supported States */
hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
+
+ /* LE-only controllers have LE implicitly enabled */
+ if (!lmp_bredr_capable(hdev))
+ set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
}
static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
@@ -574,6 +581,10 @@ static void hci_set_le_support(struct hci_request *req)
struct hci_dev *hdev = req->hdev;
struct hci_cp_write_le_host_supported cp;
+ /* LE-only devices do not support explicit enablement */
+ if (!lmp_bredr_capable(hdev))
+ return;
+
memset(&cp, 0, sizeof(cp));
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
@@ -2602,7 +2613,7 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
}
static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
- u32 plen, void *param)
+ u32 plen, const void *param)
{
int len = HCI_COMMAND_HDR_SIZE + plen;
struct hci_command_hdr *hdr;
@@ -2628,7 +2639,8 @@ static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
}
/* Send HCI command */
-int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
+int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
+ const void *param)
{
struct sk_buff *skb;
@@ -2652,8 +2664,8 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
}
/* Queue a command to an asynchronous HCI request */
-void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
- u8 event)
+void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
+ const void *param, u8 event)
{
struct hci_dev *hdev = req->hdev;
struct sk_buff *skb;
@@ -2682,7 +2694,8 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
skb_queue_tail(&req->cmd_q, skb);
}
-void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
+void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
+ const void *param)
{
hci_req_add_ev(req, opcode, plen, param, 0);
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index eae1d9f90b6..a76d1ac0321 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6314,12 +6314,13 @@ drop:
kfree_skb(skb);
}
-static void l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
+static void l2cap_att_channel(struct l2cap_conn *conn,
struct sk_buff *skb)
{
struct l2cap_chan *chan;
- chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
+ chan = l2cap_global_chan_by_scid(0, L2CAP_CID_LE_DATA,
+ conn->src, conn->dst);
if (!chan)
goto drop;
@@ -6368,7 +6369,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
break;
case L2CAP_CID_LE_DATA:
- l2cap_att_channel(conn, cid, skb);
+ l2cap_att_channel(conn, skb);
break;
case L2CAP_CID_SMP:
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4c830c62ef7..35fef22703e 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)
return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_INVALID_PARAMS);
+ /* LE-only devices do not allow toggling LE on/off */
+ if (!lmp_bredr_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
+ MGMT_STATUS_REJECTED);
+
hci_dev_lock(hdev);
val = !!cp->val;
@@ -3347,7 +3352,8 @@ static int powered_update_hci(struct hci_dev *hdev)
hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
}
- if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+ if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
+ lmp_bredr_capable(hdev)) {
struct hci_cp_write_le_host_supported cp;
cp.le = 1;