summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorClaudio Takahasi <claudio.takahasi@openbossa.org>2011-02-11 19:28:55 -0200
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-16 16:33:24 -0300
commitde73115a7d67e1b81dbde2285a7657f3e3867703 (patch)
tree1bc55503b0fdce681fa038fb0c5af09df723b5cc /net
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')
-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 ce781a43f1d..e0e7b82cff0 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
return 0;
}
+static int inline l2cap_check_conn_param(u16 min, u16 max, u16 latency,
+ u16 to_multiplier)
+{
+ u16 max_latency;
+
+ if (min > max || min < 6 || max > 3200)
+ return -EINVAL;
+
+ if (to_multiplier < 10 || to_multiplier > 3200)
+ return -EINVAL;
+
+ if (max >= to_multiplier * 8)
+ return -EINVAL;
+
+ max_latency = (to_multiplier * 8 / max) - 1;
+ if (latency > 499 || latency > max_latency)
+ return -EINVAL;
+
+ return 0;
+}
+
+static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+ struct hci_conn *hcon = conn->hcon;
+ struct l2cap_conn_param_update_req *req;
+ struct l2cap_conn_param_update_rsp rsp;
+ u16 min, max, latency, to_multiplier, cmd_len;
+
+ if (!(hcon->link_mode & HCI_LM_MASTER))
+ return -EINVAL;
+
+ cmd_len = __le16_to_cpu(cmd->len);
+ if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
+ return -EPROTO;
+
+ req = (struct l2cap_conn_param_update_req *) data;
+ min = __le16_to_cpu(req->min);
+ max = __le16_to_cpu(req->max);
+ latency = __le16_to_cpu(req->latency);
+ to_multiplier = __le16_to_cpu(req->to_multiplier);
+
+ BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
+ min, max, latency, to_multiplier);
+
+ memset(&rsp, 0, sizeof(rsp));
+ if (l2cap_check_conn_param(min, max, latency, to_multiplier))
+ rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
+ else
+ rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+
+ l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
+ sizeof(rsp), &rsp);
+
+ return 0;
+}
+
static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
{
@@ -2567,7 +2624,7 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
return 0;
case L2CAP_CONN_PARAM_UPDATE_REQ:
- return -EINVAL;
+ return l2cap_conn_param_update_req(conn, cmd, data);
case L2CAP_CONN_PARAM_UPDATE_RSP:
return 0;