cp.conn_interval_max = cpu_to_le16(max);
cp.conn_latency = cpu_to_le16(latency);
cp.supervision_timeout = cpu_to_le16(to_multiplier);
- cp.min_ce_len = cpu_to_le16(0x0000);
- cp.max_ce_len = cpu_to_le16(0x0000);
+
+#ifdef TIZEN_BT
+ cp.min_ce_len = cpu_to_le16(0x0009);
+ cp.max_ce_len = cpu_to_le16(0x0009);
+
+ BT_INFO("[%s(%d)] Sent to Remote - Min Connection Interval: %u (in slots), Max Connection Interval: %u (in slots)", __FUNCTION__, __LINE__, min, max);
+#else
+ cp.min_ce_len = cpu_to_le16(0x0000);
+ cp.max_ce_len = cpu_to_le16(0x0000);
+#endif
hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
if (hcon->out)
smp_conn_security(hcon, hcon->pending_sec_level);
+#ifndef TIZEN_BT
/* For LE peripheral connections, make sure the connection interval
* is in the range of the minimum and maximum interval that has
* been configured for this connection. If not, then trigger
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
}
+#else
+/*
+* Too small supervision timeout causes sudden link loss,
+* when remote device has multiple links and it cannot manage those
+* properly.
+*
+* To protect such a case, it needs to widen supervision timeout
+*/
+ if (hcon->role == HCI_ROLE_SLAVE &&
+ hcon->le_supv_timeout < hdev->le_supv_timeout) {
+ if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC &&
+ hcon->features[0][0] & HCI_LE_CONN_PARAM_REQ_PROC) {
+ BT_DBG("use hci_le_conn_update");
+ hci_le_conn_update(hcon,
+ hcon->le_conn_min_interval,
+ hcon->le_conn_max_interval,
+ hcon->le_conn_latency,
+ hdev->le_supv_timeout);
+ } else {
+ BT_DBG("use l2cap conn_update");
+ l2cap_update_connection_param(conn,
+ hcon->le_conn_min_interval,
+ hcon->le_conn_max_interval,
+ hcon->le_conn_latency,
+ hdev->le_supv_timeout);
+ }
+ }
+
+#endif
}
static void l2cap_conn_ready(struct l2cap_conn *conn)
return 0;
}
+#ifdef TIZEN_BT
+int l2cap_update_connection_param(struct l2cap_conn *conn, u16 min, u16 max,
+ u16 latency, u16 to_multiplier)
+{
+ struct l2cap_conn_param_update_req req;
+
+ req.min = cpu_to_le16(min);
+ req.max = cpu_to_le16(max);
+ req.latency = cpu_to_le16(latency);
+ req.to_multiplier = cpu_to_le16(to_multiplier);
+
+ BT_INFO("[%s(%d)] Sent to Remote - Min Connection Interval: %u (in slots), Max Connection Interval: %u (in slots)", __FUNCTION__, __LINE__, min, max);
+ l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONN_PARAM_UPDATE_REQ,
+ sizeof(req), &req);
+
+ return 0;
+}
+#endif
+
static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
struct l2cap_cmd_hdr *cmd,
u16 cmd_len, u8 *data)
break;
+#ifdef TIZEN_BT
+ case BT_LE_CONN_PARAM: {
+ struct hci_dev *hdev;
+ struct le_conn_param param;
+ int err;
+
+ if (bt_copy_from_sockptr(¶m, sizeof(param), optval, optlen)) {
+ err = -EFAULT;
+ break;
+ }
+
+ err = hci_check_conn_params(param.min, param.max,
+ param.latency, param.to_multiplier);
+ if (err < 0)
+ break;
+
+ conn = chan->conn;
+ hdev = conn->hcon->hdev;
+ if (conn->hcon->out ||
+ (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC &&
+ conn->hcon->features[0][0] & HCI_LE_CONN_PARAM_REQ_PROC)) {
+ BT_DBG("use hci_le_conn_update");
+ err = hci_le_conn_update(conn->hcon, param.min,
+ param.max, param.latency,
+ param.to_multiplier);
+ break;
+ }
+ BT_DBG("use l2cap conn_update");
+ err = l2cap_update_connection_param(conn, param.min,
+ param.max, param.latency, param.to_multiplier);
+ break;
+ }
+#endif
+
default:
err = -ENOPROTOOPT;
break;