aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-04-29 12:35:33 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-06-22 19:23:47 -0400
commitc5623556fc61804713b1569b4f748e36956bc6e8 (patch)
tree9324958d959cdbbccf9b801523871725292095e7 /net
parentb887664d882ee4f6a67e0bf05e5f141d32fcc067 (diff)
Bluetooth: Handle LE L2CAP signalling in its own function
The LE L2CAP signalling channel follows its own rules and will continue to evolve independently from the BR/EDR signalling channel. Therefore, it makes sense to have a clear split from BR/EDR by having a dedicated function for handling LE signalling commands. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_core.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4be6a264b475..ab9961118181 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5292,6 +5292,51 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5292 } 5292 }
5293} 5293}
5294 5294
5295static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5296 struct sk_buff *skb)
5297{
5298 u8 *data = skb->data;
5299 int len = skb->len;
5300 struct l2cap_cmd_hdr cmd;
5301 int err;
5302
5303 l2cap_raw_recv(conn, skb);
5304
5305 while (len >= L2CAP_CMD_HDR_SIZE) {
5306 u16 cmd_len;
5307 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
5308 data += L2CAP_CMD_HDR_SIZE;
5309 len -= L2CAP_CMD_HDR_SIZE;
5310
5311 cmd_len = le16_to_cpu(cmd.len);
5312
5313 BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
5314 cmd.ident);
5315
5316 if (cmd_len > len || !cmd.ident) {
5317 BT_DBG("corrupted command");
5318 break;
5319 }
5320
5321 err = l2cap_le_sig_cmd(conn, &cmd, data);
5322 if (err) {
5323 struct l2cap_cmd_rej_unk rej;
5324
5325 BT_ERR("Wrong link type (%d)", err);
5326
5327 /* FIXME: Map err to a valid reason */
5328 rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
5329 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
5330 sizeof(rej), &rej);
5331 }
5332
5333 data += cmd_len;
5334 len -= cmd_len;
5335 }
5336
5337 kfree_skb(skb);
5338}
5339
5295static inline void l2cap_sig_channel(struct l2cap_conn *conn, 5340static inline void l2cap_sig_channel(struct l2cap_conn *conn,
5296 struct sk_buff *skb) 5341 struct sk_buff *skb)
5297{ 5342{
@@ -5318,11 +5363,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
5318 break; 5363 break;
5319 } 5364 }
5320 5365
5321 if (conn->hcon->type == LE_LINK) 5366 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
5322 err = l2cap_le_sig_cmd(conn, &cmd, data);
5323 else
5324 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
5325
5326 if (err) { 5367 if (err) {
5327 struct l2cap_cmd_rej_unk rej; 5368 struct l2cap_cmd_rej_unk rej;
5328 5369
@@ -6395,6 +6436,8 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
6395 6436
6396 switch (cid) { 6437 switch (cid) {
6397 case L2CAP_CID_LE_SIGNALING: 6438 case L2CAP_CID_LE_SIGNALING:
6439 l2cap_le_sig_channel(conn, skb);
6440 break;
6398 case L2CAP_CID_SIGNALING: 6441 case L2CAP_CID_SIGNALING:
6399 l2cap_sig_channel(conn, skb); 6442 l2cap_sig_channel(conn, skb);
6400 break; 6443 break;