aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorClaudio Takahasi <claudio.takahasi@openbossa.org>2011-02-11 16:28:55 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-16 14:33:24 -0500
commitde73115a7d67e1b81dbde2285a7657f3e3867703 (patch)
tree1bc55503b0fdce681fa038fb0c5af09df723b5cc /net/bluetooth
parent3300d9a930a79508032e3e03ac2bde3a22dd048d (diff)
Bluetooth: Add connection parameter update response
Implements L2CAP Connection Parameter Update Response defined in the Bluetooth Core Specification, Volume 3, Part A, section 4.21. Address the LE Connection Parameter Procedure initiated by the slave. Connection Interval Minimum and Maximum have the same range: 6 to 3200. Time = N * 1.25ms. Minimum shall be less or equal to Maximum. The Slave Latency field shall have a value in the range of 0 to ((connSupervisionTimeout / connIntervalMax) - 1). Latency field shall be less than 500. connSupervisionTimeout = Timeout Multiplier * 10 ms. Multiplier field shall have a value in the range of 10 to 3200. Signed-off-by: Claudio Takahasi <claudio.takahasi@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
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;