aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorClaudio Takahasi <claudio.takahasi@openbossa.org>2011-02-11 16:28:54 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-16 14:33:23 -0500
commit3300d9a930a79508032e3e03ac2bde3a22dd048d (patch)
treef5a3c285b282a6bc6e9e814bcbe5220f6acc7132 /net
parent03c2d0e89409b59c1ec9d9511533cedc0b7aaa69 (diff)
Bluetooth: Add LE signaling commands handling
This patch splits the L2CAP command handling function in order to have a clear separation between the commands related to BR/EDR and LE. Commands and responses in the LE signaling channel are not being handled yet, command reject is sent to all received requests. Bluetooth Core Specification, Volume 3, Part A, section 4 defines the signaling packets formats and allowed commands/responses over the LE signaling channel. Signed-off-by: Claudio Takahasi <claudio.takahasi@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_core.c142
1 files changed, 90 insertions, 52 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3079175065d4..ce781a43f1d5 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1428,7 +1428,11 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1428 1428
1429 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); 1429 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1430 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); 1430 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
1431 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); 1431
1432 if (conn->hcon->type == LE_LINK)
1433 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1434 else
1435 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
1432 1436
1433 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); 1437 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1434 cmd->code = code; 1438 cmd->code = code;
@@ -2497,12 +2501,90 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
2497 return 0; 2501 return 0;
2498} 2502}
2499 2503
2500static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) 2504static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2505 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2506{
2507 int err = 0;
2508
2509 switch (cmd->code) {
2510 case L2CAP_COMMAND_REJ:
2511 l2cap_command_rej(conn, cmd, data);
2512 break;
2513
2514 case L2CAP_CONN_REQ:
2515 err = l2cap_connect_req(conn, cmd, data);
2516 break;
2517
2518 case L2CAP_CONN_RSP:
2519 err = l2cap_connect_rsp(conn, cmd, data);
2520 break;
2521
2522 case L2CAP_CONF_REQ:
2523 err = l2cap_config_req(conn, cmd, cmd_len, data);
2524 break;
2525
2526 case L2CAP_CONF_RSP:
2527 err = l2cap_config_rsp(conn, cmd, data);
2528 break;
2529
2530 case L2CAP_DISCONN_REQ:
2531 err = l2cap_disconnect_req(conn, cmd, data);
2532 break;
2533
2534 case L2CAP_DISCONN_RSP:
2535 err = l2cap_disconnect_rsp(conn, cmd, data);
2536 break;
2537
2538 case L2CAP_ECHO_REQ:
2539 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2540 break;
2541
2542 case L2CAP_ECHO_RSP:
2543 break;
2544
2545 case L2CAP_INFO_REQ:
2546 err = l2cap_information_req(conn, cmd, data);
2547 break;
2548
2549 case L2CAP_INFO_RSP:
2550 err = l2cap_information_rsp(conn, cmd, data);
2551 break;
2552
2553 default:
2554 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2555 err = -EINVAL;
2556 break;
2557 }
2558
2559 return err;
2560}
2561
2562static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2563 struct l2cap_cmd_hdr *cmd, u8 *data)
2564{
2565 switch (cmd->code) {
2566 case L2CAP_COMMAND_REJ:
2567 return 0;
2568
2569 case L2CAP_CONN_PARAM_UPDATE_REQ:
2570 return -EINVAL;
2571
2572 case L2CAP_CONN_PARAM_UPDATE_RSP:
2573 return 0;
2574
2575 default:
2576 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2577 return -EINVAL;
2578 }
2579}
2580
2581static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2582 struct sk_buff *skb)
2501{ 2583{
2502 u8 *data = skb->data; 2584 u8 *data = skb->data;
2503 int len = skb->len; 2585 int len = skb->len;
2504 struct l2cap_cmd_hdr cmd; 2586 struct l2cap_cmd_hdr cmd;
2505 int err = 0; 2587 int err;
2506 2588
2507 l2cap_raw_recv(conn, skb); 2589 l2cap_raw_recv(conn, skb);
2508 2590
@@ -2521,55 +2603,10 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *sk
2521 break; 2603 break;
2522 } 2604 }
2523 2605
2524 switch (cmd.code) { 2606 if (conn->hcon->type == LE_LINK)
2525 case L2CAP_COMMAND_REJ: 2607 err = l2cap_le_sig_cmd(conn, &cmd, data);
2526 l2cap_command_rej(conn, &cmd, data); 2608 else
2527 break; 2609 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
2528
2529 case L2CAP_CONN_REQ:
2530 err = l2cap_connect_req(conn, &cmd, data);
2531 break;
2532
2533 case L2CAP_CONN_RSP:
2534 err = l2cap_connect_rsp(conn, &cmd, data);
2535 break;
2536
2537 case L2CAP_CONF_REQ:
2538 err = l2cap_config_req(conn, &cmd, cmd_len, data);
2539 break;
2540
2541 case L2CAP_CONF_RSP:
2542 err = l2cap_config_rsp(conn, &cmd, data);
2543 break;
2544
2545 case L2CAP_DISCONN_REQ:
2546 err = l2cap_disconnect_req(conn, &cmd, data);
2547 break;
2548
2549 case L2CAP_DISCONN_RSP:
2550 err = l2cap_disconnect_rsp(conn, &cmd, data);
2551 break;
2552
2553 case L2CAP_ECHO_REQ:
2554 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
2555 break;
2556
2557 case L2CAP_ECHO_RSP:
2558 break;
2559
2560 case L2CAP_INFO_REQ:
2561 err = l2cap_information_req(conn, &cmd, data);
2562 break;
2563
2564 case L2CAP_INFO_RSP:
2565 err = l2cap_information_rsp(conn, &cmd, data);
2566 break;
2567
2568 default:
2569 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
2570 err = -EINVAL;
2571 break;
2572 }
2573 2610
2574 if (err) { 2611 if (err) {
2575 struct l2cap_cmd_rej rej; 2612 struct l2cap_cmd_rej rej;
@@ -3566,6 +3603,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3566 BT_DBG("len %d, cid 0x%4.4x", len, cid); 3603 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3567 3604
3568 switch (cid) { 3605 switch (cid) {
3606 case L2CAP_CID_LE_SIGNALING:
3569 case L2CAP_CID_SIGNALING: 3607 case L2CAP_CID_SIGNALING:
3570 l2cap_sig_channel(conn, skb); 3608 l2cap_sig_channel(conn, skb);
3571 break; 3609 break;