diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 2 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 142 |
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 | ||
2500 | static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | 2504 | static 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 | |||
2562 | static 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 | |||
2581 | static 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; |