diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 05528e7760f98b..3deb160e04617c 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -349,6 +349,44 @@ config BT_MAX_PAIRED Maximum number of paired Bluetooth devices. The minimum (and default) number is 1. +config BT_GAP_PERIPHERAL_PREF_PARAMS + bool "Configure peripheral preferred connection parameters" + default y + depends on BT_PERIPHERAL + help + This allows to configure periphral preferred connection parameters. + Enabling this option results in adding PPCP characteristic in GAP + and sending request for connection parameters udpate after GAP + recommended 5 seconds of connection as peripheral. If disabled it is + up to application to set expected connection parameters. + +if BT_GAP_PERIPHERAL_PREF_PARAMS +config BT_PERIPHERAL_PREF_MIN_INT + int "Peripheral preferred minimum connection interval in 1.25ms units" + default 24 + range 6 3200 + +config BT_PERIPHERAL_PREF_MAX_INT + int "Peripheral preferred maximum connection interval in 1.25ms units" + default 40 + range 6 3200 + +config BT_PERIPHERAL_PREF_SLAVE_LATENCY + int "Peripheral preferred slave latency in Connection Intervals" + default 0 + range 0 499 + +config BT_PERIPHERAL_PREF_TIMEOUT + int "Peripheral preferred supervision timeout in 10ms units" + default 42 + range 10 3200 + help + It is up to user to provide valid timeout which pass required minimum + value: in milliseconds it shall be larger than + "(1+ Conn_Latency) * Conn_Interval_Max * 2" + where Conn_Interval_Max is given in milliseconds. +endif # BT_GAP_PERIPHERAL_PREF_PARAMS + endif # BT_CONN config BT_SCAN_WITH_IDENTITY diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 74c61d54d93260..6613443a809b4c 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -230,12 +230,32 @@ static void conn_le_update_timeout(struct k_work *work) return; } - param = BT_LE_CONN_PARAM(conn->le.interval_min, - conn->le.interval_max, - conn->le.latency, - conn->le.timeout); +#if defined (CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS) + /* if application set own params use those, otherwise use defaults */ + if (atomic_test_and_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET)) { + param = BT_LE_CONN_PARAM(conn->le.interval_min, + conn->le.interval_max, + conn->le.latency, + conn->le.timeout); + } else { + param = BT_LE_CONN_PARAM(CONFIG_BT_PERIPHERAL_PREF_MIN_INT, + CONFIG_BT_PERIPHERAL_PREF_MAX_INT, + CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY, + CONFIG_BT_PERIPHERAL_PREF_TIMEOUT); + } send_conn_le_param_update(conn, param); +#else + /* update only if application set own params */ + if (atomic_test_and_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET)) { + param = BT_LE_CONN_PARAM(conn->le.interval_min, + conn->le.interval_max, + conn->le.latency, + conn->le.timeout); + + send_conn_le_param_update(conn, param); + } +#endif atomic_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE); } @@ -1796,6 +1816,7 @@ int bt_conn_le_param_update(struct bt_conn *conn, conn->le.interval_max = param->interval_max; conn->le.latency = param->latency; conn->le.timeout = param->timeout; + atomic_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET); } return 0; diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index e7096b791e2fcb..887e163c67397e 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -28,6 +28,7 @@ enum { BT_CONN_AUTO_PHY_UPDATE, /* Auto-update PHY */ BT_CONN_AUTO_DATA_LEN, /* Auto data len change in progress */ BT_CONN_SLAVE_PARAM_UPDATE, /* If slave param update timer fired */ + BT_CONN_SLAVE_PARAM_SET, /* If slave param were set from app */ /* Total number of flags - must be at the end of the enum */ BT_CONN_NUM_FLAGS, diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 205ee7e51519af..d3bea364afe926 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -96,6 +96,27 @@ static ssize_t read_appearance(struct bt_conn *conn, sizeof(appearance)); } +#if defined (CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS) +static ssize_t read_ppcp(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, u16_t len, u16_t offset) +{ + struct __packed { + uint16_t min_int; + uint16_t max_int; + uint16_t latency; + uint16_t timeout; + } ppcp; + + ppcp.min_int = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_MIN_INT); + ppcp.max_int = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_MAX_INT); + ppcp.latency = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY); + ppcp.timeout = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_TIMEOUT); + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &ppcp, + sizeof(ppcp)); +} +#endif + #if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PRIVACY) static ssize_t read_central_addr_res(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, @@ -127,6 +148,10 @@ static struct bt_gatt_attr gap_attrs[] = { BT_GATT_CHRC_READ, BT_GATT_PERM_READ, read_central_addr_res, NULL, NULL), #endif /* CONFIG_BT_CENTRAL && CONFIG_BT_PRIVACY */ +#if defined(CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS) + BT_GATT_CHARACTERISTIC(BT_UUID_GAP_PPCP, BT_GATT_CHRC_READ, + BT_GATT_PERM_READ, read_ppcp, NULL, NULL), +#endif }; static struct bt_gatt_service gap_svc = BT_GATT_SERVICE(gap_attrs);