Skip to content

Commit 81edee2

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 b6b0de2 commit 81edee2

6 files changed

Lines changed: 805 additions & 20 deletions

File tree

doc/nrf/links.txt

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

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

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

include/bluetooth/services/hids.h

Lines changed: 142 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ 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+
#define BT_HIDS_SCI_INFORMATION_MAX_GROUPS BT_CONN_LE_MAX_CONN_INTERVAL_GROUPS
49+
50+
/** Max length of encoded HID SCI Information based on the HIDS specification:
51+
* Minimum supported conn interval (1 B) + Num groups (1 B) +
52+
* Num groups * (Group Min (2 B) + Group Max (2 B) + Group Stride (2 B)).
53+
*/
54+
#define BT_HIDS_SCI_INFORMATION_MAX_LEN (1 + 1 + BT_HIDS_SCI_INFORMATION_MAX_GROUPS * (2 + 2 + 2))
55+
#define BT_HIDS_SCI_INFORMATION_MIN_LEN 2
56+
57+
/** The transport interval which the device must support to be compliant
58+
* with the HID over GATT Profile specification (chapter 7.4).
59+
*/
60+
#define BT_HIDS_MAX_MINIMAL_TRANSPORT_INTERVAL_US 1250
61+
4762
/**
4863
* @brief Declare a HIDS instance.
4964
*
@@ -116,15 +131,37 @@ enum bt_hids_flags {
116131
BT_HIDS_REMOTE_WAKE = BIT(0),
117132
/** Device advertises when bonded but not connected. */
118133
BT_HIDS_NORMALLY_CONNECTABLE = BIT(1),
134+
/** Device is capable of supporting the HID SCI feature */
135+
BT_HIDS_SCI_SUPPORTED = BIT(2),
136+
/** Device is capable of supporting the HID SCI Low Power mode feature */
137+
BT_HIDS_SCI_LOW_POWER_MODE_SUPPORTED = BIT(3),
119138
};
120139

121-
/** @brief HID Control Point settings. */
122-
enum bt_hids_control_point {
140+
/**
141+
* @brief HID Control Point settings.
142+
*
143+
* @deprecated Use @ref bt_hids_cp_evt instead
144+
*/
145+
__deprecated enum bt_hids_control_point {
123146
/** Suspend value for Control Point. */
124147
BT_HIDS_CONTROL_POINT_SUSPEND = 0x00,
125148

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

130167
/** HID Service Protocol Mode events. */
@@ -137,10 +174,18 @@ enum bt_hids_pm_evt {
137174

138175
/** HID Service Control Point events. */
139176
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,
177+
/** Suspend command. */
178+
BT_HIDS_CP_EVT_HOST_SUSP = 0x00,
179+
/** Exit suspend command. */
180+
BT_HIDS_CP_EVT_HOST_EXIT_SUSP = 0x01,
181+
/** SCI Default mode request. */
182+
BT_HIDS_CP_EVT_HOST_SCI_DEFAULT_REQ = 0x02,
183+
/** SCI Fast mode request. */
184+
BT_HIDS_CP_EVT_HOST_SCI_FAST_REQ = 0x03,
185+
/** SCI Low Power mode request. */
186+
BT_HIDS_CP_EVT_HOST_SCI_LOW_POWER_REQ = 0x04,
187+
/** SCI Full Range mode request. */
188+
BT_HIDS_CP_EVT_HOST_SCI_FULL_RANGE_REQ = 0x05,
144189
};
145190

146191
/** HID notification events. */
@@ -377,12 +422,22 @@ struct bt_hids_pm_data {
377422
};
378423

379424
/** @brief HID Control Point event handler.
425+
*
426+
* @deprecated Use @ref bt_hids_conn_cp_evt_handler_t instead
380427
*
381428
* @param evt Event indicating that the Control Point value has changed.
382429
* (see @ref bt_hids_cp_evt).
383430
*/
384431
typedef void (*bt_hids_cp_evt_handler_t) (enum bt_hids_cp_evt evt);
385432

433+
/** @brief HID Control Point event handler.
434+
*
435+
* @param evt Event indicating that the Control Point value has changed.
436+
* (see @ref bt_hids_cp_evt).
437+
* @param conn Pointer to Connection Object.
438+
*/
439+
typedef void (*bt_hids_conn_cp_evt_handler_t) (enum bt_hids_cp_evt evt, struct bt_conn *conn);
440+
386441
/** @brief Control Point.
387442
*/
388443
struct bt_hids_cp {
@@ -391,8 +446,24 @@ struct bt_hids_cp {
391446

392447
/** Callback with new Control Point state.*/
393448
bt_hids_cp_evt_handler_t evt_handler;
449+
450+
/** Callback with new Control Point state.*/
451+
bt_hids_conn_cp_evt_handler_t conn_evt_handler;
394452
};
395453

454+
#if defined(CONFIG_BT_HIDS_SCI)
455+
/** @brief SCI mode.
456+
*/
457+
struct bt_hids_sci_mode_data {
458+
/** CCC descriptor. */
459+
struct bt_gatt_ccc_managed_user_data ccc;
460+
461+
/** Index in the service attribute array. */
462+
uint8_t att_ind;
463+
};
464+
465+
#endif /* CONFIG_BT_HIDS_SCI */
466+
396467
/** @brief HID initialization.
397468
*/
398469
struct bt_hids_init_param {
@@ -414,9 +485,15 @@ struct bt_hids_init_param {
414485
/** Callback for Protocol Mode characteristic. */
415486
bt_hids_pm_evt_handler_t pm_evt_handler;
416487

417-
/** Callback for Control Point characteristic. */
488+
/** Callback for Control Point event.
489+
*
490+
* @deprecated Use @ref conn_cp_evt_handler instead
491+
*/
418492
bt_hids_cp_evt_handler_t cp_evt_handler;
419493

494+
/** Callback for Control Point event. */
495+
bt_hids_conn_cp_evt_handler_t conn_cp_evt_handler;
496+
420497
/** Callback for Boot Mouse Input Report. */
421498
bt_hids_notify_handler_t boot_mouse_notif_handler;
422499

@@ -466,6 +543,10 @@ struct bt_hids {
466543
/** Control Point. */
467544
struct bt_hids_cp cp;
468545

546+
#if defined(CONFIG_BT_HIDS_SCI)
547+
/** SCI mode data. */
548+
struct bt_hids_sci_mode_data sci_mode_data;
549+
#endif
469550
/** Buffer with encoded HID Information. */
470551
uint8_t info[BT_HIDS_INFORMATION_LEN];
471552

@@ -502,6 +583,14 @@ struct bt_hids_conn_data {
502583

503584
/** Pointer to Feature Reports Context data. */
504585
uint8_t *feat_rep_ctx;
586+
587+
#if defined(CONFIG_BT_HIDS_SCI)
588+
/** Pending SCI mode value. */
589+
uint8_t pending_sci_mode;
590+
591+
/** SCI mode value. */
592+
uint8_t sci_mode;
593+
#endif
505594
};
506595

507596

@@ -631,6 +720,51 @@ int bt_hids_boot_kb_inp_rep_send(struct bt_hids *hids_obj, struct bt_conn *conn,
631720
uint8_t const *rep, uint16_t len,
632721
bt_gatt_complete_func_t cb);
633722

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

635769
#ifdef __cplusplus
636770
}

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: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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_AUTO_CONNECTION_PARAMS_REQUEST
20+
bool "Automatically update connection parameters on CP SCI mode request event"
21+
help
22+
If this option is enabled, the HIDS library will automatically request
23+
the connection parameters for the new SCI mode when a Control Point
24+
write event containing an SCI mode request is received.
25+
Otherwise, bt_hids_sci_mode_change_request must be called by the application.
26+
Note: The application still has to call bt_hids_sci_conn_rate_changed when
27+
it receives the conn_rate_changed event from the Bluetooth stack
28+
to apply the new SCI mode.
29+
30+
# The default values below are based on the recommended values from
31+
# the HID over GATT Profile specification (chapter 7.4.1), except
32+
# supervision timeout defaults: smallest HCI-legal value (10 = 100 ms,
33+
# Core Vol 4 Part E) that still satisfies Link Layer §4.5.2 for each
34+
# mode's default interval_max, subrate_max, and max_latency.
35+
36+
# Default mode
37+
MODE = DEFAULT
38+
MODE_PRETTY = Default
39+
sci_interval_min_default = 60
40+
sci_interval_max_default = 120
41+
sci_subrate_min_default = 1
42+
sci_subrate_max_default = 4
43+
sci_max_peripheral_latency_default = 0
44+
sci_continuation_number_default = 0
45+
sci_supervision_timeout_10ms_default = 13
46+
rsource "Kconfig.template.hids.sci_mode"
47+
48+
# Fast mode
49+
MODE = FAST
50+
MODE_PRETTY = Fast
51+
sci_interval_min_default = 10
52+
sci_interval_max_default = 40
53+
sci_subrate_min_default = 1
54+
sci_subrate_max_default = 4
55+
sci_max_peripheral_latency_default = 0
56+
sci_continuation_number_default = 3
57+
sci_supervision_timeout_10ms_default = 10
58+
rsource "Kconfig.template.hids.sci_mode"
59+
60+
if BT_HIDS_SCI_LOW_POWER_MODE
61+
62+
# Low power mode
63+
MODE = LOW_POWER
64+
MODE_PRETTY = Low_Power
65+
sci_interval_min_default = 60
66+
sci_interval_max_default = 120
67+
sci_subrate_min_default = 1
68+
sci_subrate_max_default = 4
69+
sci_max_peripheral_latency_default = 100
70+
sci_continuation_number_default = 0
71+
sci_supervision_timeout_10ms_default = 1213
72+
rsource "Kconfig.template.hids.sci_mode"
73+
74+
endif
75+
76+
# Full range mode
77+
MODE = FULL_RANGE
78+
MODE_PRETTY = Full_Range
79+
sci_interval_min_default = 10
80+
sci_interval_max_default = 120
81+
sci_subrate_min_default = 1
82+
sci_subrate_max_default = 4
83+
sci_max_peripheral_latency_default = 0
84+
sci_continuation_number_default = 1
85+
sci_supervision_timeout_10ms_default = 13
86+
rsource "Kconfig.template.hids.sci_mode"
87+
88+
endif

0 commit comments

Comments
 (0)