diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index ce781a43f1d5..e0e7b82cff02 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -2501,6 +2501,63 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm | |||
2501 | return 0; | 2501 | return 0; |
2502 | } | 2502 | } |
2503 | 2503 | ||
2504 | static int inline l2cap_check_conn_param(u16 min, u16 max, u16 latency, | ||
2505 | u16 to_multiplier) | ||
2506 | { | ||
2507 | u16 max_latency; | ||
2508 | |||
2509 | if (min > max || min < 6 || max > 3200) | ||
2510 | return -EINVAL; | ||
2511 | |||
2512 | if (to_multiplier < 10 || to_multiplier > 3200) | ||
2513 | return -EINVAL; | ||
2514 | |||
2515 | if (max >= to_multiplier * 8) | ||
2516 | return -EINVAL; | ||
2517 | |||
2518 | max_latency = (to_multiplier * 8 / max) - 1; | ||
2519 | if (latency > 499 || latency > max_latency) | ||
2520 | return -EINVAL; | ||
2521 | |||
2522 | return 0; | ||
2523 | } | ||
2524 | |||
2525 | static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | ||
2526 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
2527 | { | ||
2528 | struct hci_conn *hcon = conn->hcon; | ||
2529 | struct l2cap_conn_param_update_req *req; | ||
2530 | struct l2cap_conn_param_update_rsp rsp; | ||
2531 | u16 min, max, latency, to_multiplier, cmd_len; | ||
2532 | |||
2533 | if (!(hcon->link_mode & HCI_LM_MASTER)) | ||
2534 | return -EINVAL; | ||
2535 | |||
2536 | cmd_len = __le16_to_cpu(cmd->len); | ||
2537 | if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) | ||
2538 | return -EPROTO; | ||
2539 | |||
2540 | req = (struct l2cap_conn_param_update_req *) data; | ||
2541 | min = __le16_to_cpu(req->min); | ||
2542 | max = __le16_to_cpu(req->max); | ||
2543 | latency = __le16_to_cpu(req->latency); | ||
2544 | to_multiplier = __le16_to_cpu(req->to_multiplier); | ||
2545 | |||
2546 | BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", | ||
2547 | min, max, latency, to_multiplier); | ||
2548 | |||
2549 | memset(&rsp, 0, sizeof(rsp)); | ||
2550 | if (l2cap_check_conn_param(min, max, latency, to_multiplier)) | ||
2551 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); | ||
2552 | else | ||
2553 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); | ||
2554 | |||
2555 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, | ||
2556 | sizeof(rsp), &rsp); | ||
2557 | |||
2558 | return 0; | ||
2559 | } | ||
2560 | |||
2504 | static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | 2561 | static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, |
2505 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) | 2562 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) |
2506 | { | 2563 | { |
@@ -2567,7 +2624,7 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, | |||
2567 | return 0; | 2624 | return 0; |
2568 | 2625 | ||
2569 | case L2CAP_CONN_PARAM_UPDATE_REQ: | 2626 | case L2CAP_CONN_PARAM_UPDATE_REQ: |
2570 | return -EINVAL; | 2627 | return l2cap_conn_param_update_req(conn, cmd, data); |
2571 | 2628 | ||
2572 | case L2CAP_CONN_PARAM_UPDATE_RSP: | 2629 | case L2CAP_CONN_PARAM_UPDATE_RSP: |
2573 | return 0; | 2630 | return 0; |