aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap_core.c59
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
2504static 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
2525static 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
2504static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, 2561static 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;