Skip to content

Commit db2f946

Browse files
committed
bluetooth: hids: Add support for HID SCI
Add support for HID Shorter Connection Intervals on the HID device side. Signed-off-by: Artur Hadasz <artur.hadasz@nordicsemi.no>
1 parent a89a099 commit db2f946

6 files changed

Lines changed: 834 additions & 19 deletions

File tree

doc/nrf/links.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1285,7 +1285,7 @@
12851285

12861286
.. _`Join Bluetooth SIG`: https://www.bluetooth.com/develop-with-bluetooth/join/
12871287

1288-
.. _`HID Service Specification`: https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=245140
1288+
.. _`HID Service Specification`: https://files.bluetooth.com/download/hid-service-specification/
12891289
.. _`Battery Service Specification`: https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=245138
12901290
.. _`Bluetooth Low Energy RF PHY Test Specification`: https://www.bluetooth.org/docman/handlers/DownloadDoc.ashx?doc_id=225827
12911291
.. _`Bond Management Service Specification`: https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=293524

include/bluetooth/services/hids.h

Lines changed: 145 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@ extern "C" {
4444
/** Length of encoded HID Information. */
4545
#define BT_HIDS_INFORMATION_LEN 4
4646

47+
/** Maximum number of connection interval groups in HID SCI Information. */
48+
#if defined(CONFIG_BT_HIDS_SCI_INFORMATION_MAX_GROUPS_COUNT)
49+
#define BT_HIDS_SCI_INFORMATION_MAX_GROUPS CONFIG_BT_HIDS_SCI_INFORMATION_MAX_GROUPS_COUNT
50+
#else
51+
#define BT_HIDS_SCI_INFORMATION_MAX_GROUPS BT_CONN_LE_MAX_CONN_INTERVAL_GROUPS
52+
#endif
53+
/** Max length of encoded HID SCI Information based on the HIDS specification:
54+
* Minimum supported conn interval (1 B) + Num groups (1 B) +
55+
* Num groups * (Group Min (2 B) + Group Max (2 B) + Group Stride (2 B)).
56+
*/
57+
#define BT_HIDS_SCI_INFORMATION_MAX_LEN (1 + 1 + BT_HIDS_SCI_INFORMATION_MAX_GROUPS * (2 + 2 + 2))
58+
#define BT_HIDS_SCI_INFORMATION_MIN_LEN 2
59+
60+
/** The transport interval which the device must support to be compliant
61+
* with the HID over GATT Profile specification (chapter 7.4).
62+
*/
63+
#define BT_HIDS_MAX_MINIMAL_TRANSPORT_INTERVAL_US 1250
64+
4765
/**
4866
* @brief Declare a HIDS instance.
4967
*
@@ -116,15 +134,37 @@ enum bt_hids_flags {
116134
BT_HIDS_REMOTE_WAKE = BIT(0),
117135
/** Device advertises when bonded but not connected. */
118136
BT_HIDS_NORMALLY_CONNECTABLE = BIT(1),
137+
/** Device is capable of supporting the HID SCI feature */
138+
BT_HIDS_SCI_SUPPORTED = BIT(2),
139+
/** Device is capable of supporting the HID SCI Low Power mode feature */
140+
BT_HIDS_SCI_LOW_POWER_MODE_SUPPORTED = BIT(3),
119141
};
120142

121-
/** @brief HID Control Point settings. */
122-
enum bt_hids_control_point {
143+
/**
144+
* @brief HID Control Point settings.
145+
*
146+
* @deprecated Use @ref bt_hids_cp_evt instead
147+
*/
148+
__deprecated enum bt_hids_control_point {
123149
/** Suspend value for Control Point. */
124150
BT_HIDS_CONTROL_POINT_SUSPEND = 0x00,
125151

126152
/** Exit suspend value for Control Point.*/
127-
BT_HIDS_CONTROL_POINT_EXIT_SUSPEND = 0x01
153+
BT_HIDS_CONTROL_POINT_EXIT_SUSPEND = 0x01,
154+
};
155+
156+
/** @brief HID SCI Mode values */
157+
enum bt_hids_sci_mode_value {
158+
/** SCI None mode. */
159+
BT_HIDS_SCI_MODE_NONE = 0x00,
160+
/** SCI Default mode. */
161+
BT_HIDS_SCI_MODE_DEFAULT = 0x02,
162+
/** SCI Fast mode. */
163+
BT_HIDS_SCI_MODE_FAST = 0x03,
164+
/** SCI Low Power mode. */
165+
BT_HIDS_SCI_MODE_LOW_POWER = 0x04,
166+
/** SCI Full Range mode. */
167+
BT_HIDS_SCI_MODE_FULL_RANGE = 0x05,
128168
};
129169

130170
/** HID Service Protocol Mode events. */
@@ -137,10 +177,18 @@ enum bt_hids_pm_evt {
137177

138178
/** HID Service Control Point events. */
139179
enum bt_hids_cp_evt {
140-
/** Suspend command received. */
141-
BT_HIDS_CP_EVT_HOST_SUSP,
142-
/** Exit suspend command received. */
143-
BT_HIDS_CP_EVT_HOST_EXIT_SUSP,
180+
/** Suspend command. */
181+
BT_HIDS_CP_EVT_HOST_SUSP = 0x00,
182+
/** Exit suspend command. */
183+
BT_HIDS_CP_EVT_HOST_EXIT_SUSP = 0x01,
184+
/** SCI Default mode request. */
185+
BT_HIDS_CP_EVT_HOST_SCI_DEFAULT_REQ = 0x02,
186+
/** SCI Fast mode request. */
187+
BT_HIDS_CP_EVT_HOST_SCI_FAST_REQ = 0x03,
188+
/** SCI Low Power mode request. */
189+
BT_HIDS_CP_EVT_HOST_SCI_LOW_POWER_REQ = 0x04,
190+
/** SCI Full Range mode request. */
191+
BT_HIDS_CP_EVT_HOST_SCI_FULL_RANGE_REQ = 0x05,
144192
};
145193

146194
/** HID notification events. */
@@ -377,12 +425,22 @@ struct bt_hids_pm_data {
377425
};
378426

379427
/** @brief HID Control Point event handler.
428+
*
429+
* @deprecated Use @ref bt_hids_conn_cp_evt_handler_t instead
380430
*
381431
* @param evt Event indicating that the Control Point value has changed.
382432
* (see @ref bt_hids_cp_evt).
383433
*/
384434
typedef void (*bt_hids_cp_evt_handler_t) (enum bt_hids_cp_evt evt);
385435

436+
/** @brief HID Control Point event handler.
437+
*
438+
* @param evt Event indicating that the Control Point value has changed.
439+
* (see @ref bt_hids_cp_evt).
440+
* @param conn Pointer to Connection Object.
441+
*/
442+
typedef void (*bt_hids_conn_cp_evt_handler_t) (enum bt_hids_cp_evt evt, struct bt_conn *conn);
443+
386444
/** @brief Control Point.
387445
*/
388446
struct bt_hids_cp {
@@ -391,8 +449,24 @@ struct bt_hids_cp {
391449

392450
/** Callback with new Control Point state.*/
393451
bt_hids_cp_evt_handler_t evt_handler;
452+
453+
/** Callback with new Control Point state.*/
454+
bt_hids_conn_cp_evt_handler_t conn_evt_handler;
394455
};
395456

457+
#if defined(CONFIG_BT_HIDS_SCI)
458+
/** @brief SCI mode.
459+
*/
460+
struct bt_hids_sci_mode_data {
461+
/** CCC descriptor. */
462+
struct bt_gatt_ccc_managed_user_data ccc;
463+
464+
/** Index in the service attribute array. */
465+
uint8_t att_ind;
466+
};
467+
468+
#endif /* CONFIG_BT_HIDS_SCI */
469+
396470
/** @brief HID initialization.
397471
*/
398472
struct bt_hids_init_param {
@@ -414,9 +488,15 @@ struct bt_hids_init_param {
414488
/** Callback for Protocol Mode characteristic. */
415489
bt_hids_pm_evt_handler_t pm_evt_handler;
416490

417-
/** Callback for Control Point characteristic. */
491+
/** Callback for Control Point event.
492+
*
493+
* @deprecated Use @ref conn_cp_evt_handler instead
494+
*/
418495
bt_hids_cp_evt_handler_t cp_evt_handler;
419496

497+
/** Callback for Control Point event. */
498+
bt_hids_conn_cp_evt_handler_t conn_cp_evt_handler;
499+
420500
/** Callback for Boot Mouse Input Report. */
421501
bt_hids_notify_handler_t boot_mouse_notif_handler;
422502

@@ -466,6 +546,10 @@ struct bt_hids {
466546
/** Control Point. */
467547
struct bt_hids_cp cp;
468548

549+
#if defined(CONFIG_BT_HIDS_SCI)
550+
/** SCI mode data. */
551+
struct bt_hids_sci_mode_data sci_mode_data;
552+
#endif
469553
/** Buffer with encoded HID Information. */
470554
uint8_t info[BT_HIDS_INFORMATION_LEN];
471555

@@ -502,6 +586,14 @@ struct bt_hids_conn_data {
502586

503587
/** Pointer to Feature Reports Context data. */
504588
uint8_t *feat_rep_ctx;
589+
590+
#if defined(CONFIG_BT_HIDS_SCI)
591+
/** Pending SCI mode value. */
592+
uint8_t pending_sci_mode;
593+
594+
/** SCI mode value. */
595+
uint8_t sci_mode;
596+
#endif
505597
};
506598

507599

@@ -631,6 +723,51 @@ int bt_hids_boot_kb_inp_rep_send(struct bt_hids *hids_obj, struct bt_conn *conn,
631723
uint8_t const *rep, uint16_t len,
632724
bt_gatt_complete_func_t cb);
633725

726+
/** @brief Request a new HID SCI mode.
727+
* This function will request connection parameters for the mode.
728+
* The user of the API must call @ref bt_hids_sci_conn_rate_changed to apply the new mode
729+
* when the connection rate change event is received from the Bluetooth stack
730+
* (conn_rate_changed callback).
731+
*
732+
* @note The function is not thread safe.
733+
*
734+
* @param conn Pointer to Connection Object.
735+
* @param mode New SCI mode.
736+
*
737+
* @return 0 If the operation was successful.
738+
* Otherwise, a (negative) error code is returned.
739+
*/
740+
int bt_hids_sci_mode_change_request(struct bt_conn *conn,
741+
enum bt_hids_sci_mode_value mode);
742+
743+
/** @brief Handle a SCI connection rate change.
744+
* This function will validate the new connection parameters
745+
* to the SCI mode pending from a previous call to @ref bt_hids_sci_mode_change_request
746+
* and apply the new mode on success.
747+
* If the connection parameters do not match the pending mode
748+
* the mode will be set to NONE.
749+
* If no pending mode is set, the current mode will be validated against the new
750+
* connection parameters.
751+
* The new SCI mode will be returned in the new_mode parameter.
752+
* Calling this function with status != BT_HCI_ERR_SUCCESS will clear the pending mode.
753+
*
754+
* @note The function is not thread safe.
755+
* @note As the HID SCI mode must be the same for all HID services,
756+
* this function does not require the bt_hids object parameter.
757+
* It will update the mode for all registered services.
758+
*
759+
* @param conn Pointer to Connection Object.
760+
* @param status Status of the connection rate change.
761+
* @param params Parameters of the connection rate change.
762+
* @param new_mode Output parameter for the new SCI mode.
763+
*
764+
* @return 0 if the mode was updated to the pending mode
765+
* -EPIPE if the mode defaulted to NONE due to parameters validation error.
766+
* Otherwise, a (negative) error code is returned.
767+
*/
768+
int bt_hids_sci_conn_rate_changed(struct bt_conn *conn, uint8_t status,
769+
const struct bt_conn_le_conn_rate_changed *params,
770+
enum bt_hids_sci_mode_value *new_mode);
634771

635772
#ifdef __cplusplus
636773
}

subsys/bluetooth/services/Kconfig.hids

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ config BT_HIDS_DEFAULT_PERM_RW_AUTHEN
6868

6969
endchoice
7070

71+
rsource "Kconfig.hids.sci"
72+
7173
module = BT_HIDS
7274
module-str = HIDS
7375
source "$(ZEPHYR_BASE)/subsys/logging/Kconfig.template.log_config"
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#
2+
# Copyright (c) 2026 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
menuconfig BT_HIDS_SCI
8+
bool "HID Shorter Connection Intervals (SCI) for HIDS service"
9+
depends on BT_SHORTER_CONNECTION_INTERVALS
10+
11+
if BT_HIDS_SCI
12+
13+
config BT_HIDS_SCI_LOW_POWER_MODE
14+
bool "HID SCI low power mode"
15+
default y
16+
help
17+
Enable HID Shorter Connection Intervals (SCI) low power mode.
18+
19+
config BT_HIDS_SCI_INFORMATION_MAX_GROUPS_COUNT
20+
int "Maximum number of connection interval groups in HID SCI Information"
21+
default 4
22+
range 1 41
23+
help
24+
Number of connection interval groups in HID SCI Information.
25+
Set this to the actual number of groups supported by the BLE controller.
26+
If a larger number of groups is reported by the BLE controller,
27+
this will result in reporting only the first
28+
CONFIG_BT_HIDS_SCI_INFORMATION_MAX_GROUPS_COUNT groups in the HID SCI Information.
29+
30+
config BT_HIDS_SCI_AUTO_CONNECTION_PARAMS_REQUEST
31+
bool "Automatically update connection parameters on CP SCI mode request event"
32+
help
33+
If this option is enabled, the HIDS library will automatically request
34+
the connection parameters for the new SCI mode when a Control Point
35+
write event containing an SCI mode request is received.
36+
Otherwise, bt_hids_sci_mode_change_request must be called by the application.
37+
Note: The application still has to call bt_hids_sci_conn_rate_changed when
38+
it receives the conn_rate_changed event from the Bluetooth stack
39+
to apply the new SCI mode.
40+
41+
# The default values below are based on the recommended values from
42+
# the HID over GATT Profile specification (chapter 7.4.1), except
43+
# supervision timeout defaults: smallest HCI-legal value (10 = 100 ms,
44+
# Core Vol 4 Part E) that still satisfies Link Layer §4.5.2 for each
45+
# mode's default interval_max, subrate_max, and max_latency.
46+
47+
# Default mode
48+
MODE = DEFAULT
49+
MODE_PRETTY = Default
50+
sci_interval_min_default = 60
51+
sci_interval_max_default = 120
52+
sci_subrate_min_default = 1
53+
sci_subrate_max_default = 4
54+
sci_max_peripheral_latency_default = 0
55+
sci_continuation_number_default = 0
56+
sci_supervision_timeout_10ms_default = 13
57+
rsource "Kconfig.template.hids.sci_mode"
58+
59+
# Fast mode
60+
MODE = FAST
61+
MODE_PRETTY = Fast
62+
sci_interval_min_default = 10
63+
sci_interval_max_default = 40
64+
sci_subrate_min_default = 1
65+
sci_subrate_max_default = 4
66+
sci_max_peripheral_latency_default = 0
67+
sci_continuation_number_default = 3
68+
sci_supervision_timeout_10ms_default = 10
69+
rsource "Kconfig.template.hids.sci_mode"
70+
71+
if BT_HIDS_SCI_LOW_POWER_MODE
72+
73+
# Low power mode
74+
MODE = LOW_POWER
75+
MODE_PRETTY = Low_Power
76+
sci_interval_min_default = 60
77+
sci_interval_max_default = 120
78+
sci_subrate_min_default = 1
79+
sci_subrate_max_default = 4
80+
sci_max_peripheral_latency_default = 100
81+
sci_continuation_number_default = 0
82+
sci_supervision_timeout_10ms_default = 1213
83+
rsource "Kconfig.template.hids.sci_mode"
84+
85+
endif
86+
87+
# Full range mode
88+
MODE = FULL_RANGE
89+
MODE_PRETTY = Full_Range
90+
sci_interval_min_default = 10
91+
sci_interval_max_default = 120
92+
sci_subrate_min_default = 1
93+
sci_subrate_max_default = 4
94+
sci_max_peripheral_latency_default = 0
95+
sci_continuation_number_default = 1
96+
sci_supervision_timeout_10ms_default = 13
97+
rsource "Kconfig.template.hids.sci_mode"
98+
99+
endif

0 commit comments

Comments
 (0)