From: Anuj Jain Date: Fri, 6 Jan 2023 09:59:24 +0000 (+0530) Subject: Bluetooth: Add LE connection parameter update X-Git-Tag: accepted/tizen/unified/20250514.114144~16 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9c78b1716ffd2bf5c2e5bddf7386367144215cfe;p=platform%2Fkernel%2Flinux-riscv.git Bluetooth: Add LE connection parameter update Add support for BT_LE_CONN_PARAM in l2cap socket. Change-Id: I02136d555761d20c4ad16b34631bd16595ca52a9 Signed-off-by: Anuj Jain Signed-off-by: Wootak Jung Signed-off-by: Jaehoon Chung --- diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 0d372cf22ada..836e8badd6a9 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -41,6 +41,16 @@ /*To enable Tizen specific fixes */ #define TIZEN_BT +#ifdef TIZEN_BT +#define BT_LE_CONN_PARAM 14 +struct le_conn_param { + __u16 min; + __u16 max; + __u16 latency; + __u16 to_multiplier; +}; +#endif + /* Bluetooth versions */ #define BLUETOOTH_VER_1_1 1 #define BLUETOOTH_VER_1_2 2 diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 04262945d511..8574b4cd6787 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -975,6 +975,9 @@ int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user); #ifdef TIZEN_BT +int l2cap_update_connection_param(struct l2cap_conn *conn, u16 min, u16 max, + u16 latency, u16 to_multiplier); + #ifdef CONFIG_BT_6LOWPAN /* IPSP : initialize/deinitialize 6lowpan */ void bt_6lowpan_enable(void); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e3ace1b6dcf7..c41aedebdf36 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -525,8 +525,16 @@ u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, 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); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e9762b2a51f4..7c5dd9ed8f77 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1602,6 +1602,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) 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 @@ -1620,6 +1621,35 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) 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) @@ -4605,6 +4635,25 @@ static inline int l2cap_information_rsp(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) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index aaaaf9733b58..27aacc9f1eb1 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1089,6 +1089,40 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, 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;