aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/l2cap.h2
-rw-r--r--net/bluetooth/l2cap_core.c142
2 files changed, 92 insertions, 52 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 41b3bc56f13f..06f245dcf6b2 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -89,6 +89,8 @@ struct l2cap_conninfo {
89#define L2CAP_ECHO_RSP 0x09 89#define L2CAP_ECHO_RSP 0x09
90#define L2CAP_INFO_REQ 0x0a 90#define L2CAP_INFO_REQ 0x0a
91#define L2CAP_INFO_RSP 0x0b 91#define L2CAP_INFO_RSP 0x0b
92#define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
93#define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
92 94
93/* L2CAP feature mask */ 95/* L2CAP feature mask */
94#define L2CAP_FEAT_FLOWCTL 0x00000001 96#define L2CAP_FEAT_FLOWCTL 0x00000001
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;