Skip to content

Commit 80e1320

Browse files
alstrzebonskipdunaj
authored andcommitted
doc: applications: nrf_desktop: Add HID report providers doc
Adds documentation related to recently introduced HID report providers architecture. Modifies already present documentation according to introduced changes. Updates event propagation tables. Jira: NCSDK-34702 Signed-off-by: Aleksander Strzebonski <[email protected]>
1 parent 9497c45 commit 80e1320

File tree

8 files changed

+807
-269
lines changed

8 files changed

+807
-269
lines changed

applications/nrf_desktop/doc/event_propagation.rst

Lines changed: 203 additions & 133 deletions
Large diffs are not rendered by default.

applications/nrf_desktop/doc/event_rel_modules.rst

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,31 @@ Sink modules for ble_peer_event
3939
* :ref:`nrf_desktop_ble_state`
4040

4141

42+
.. _nrf_desktop_button_event_sources:
43+
44+
Source modules for button_event
45+
===============================
46+
47+
* :ref:`nrf_desktop_buttons`
48+
* :ref:`nrf_desktop_buttons_sim`
49+
* :ref:`nrf_desktop_fn_keys`
50+
51+
.. _nrf_desktop_button_event_sinks:
52+
53+
Sink modules for button_event
54+
=============================
55+
56+
* :ref:`nrf_desktop_buttons_sim`
57+
* :ref:`nrf_desktop_fn_keys`
58+
* :ref:`nrf_desktop_motion`
59+
* :ref:`nrf_desktop_passkey`
60+
* :ref:`nrf_desktop_click_detector`
61+
* :ref:`nrf_desktop_hid_provider_consumer_ctrl`
62+
* :ref:`nrf_desktop_hid_provider_keyboard`
63+
* :ref:`nrf_desktop_hid_provider_mouse`
64+
* :ref:`nrf_desktop_hid_provider_system_ctrl`
65+
66+
4267
.. _nrf_desktop_config_event_sources:
4368

4469
Source modules for config_event
@@ -80,7 +105,10 @@ Source modules for hid_report_event
80105
===================================
81106

82107
* :ref:`nrf_desktop_hid_forward`
83-
* :ref:`nrf_desktop_hid_state`
108+
* :ref:`nrf_desktop_hid_provider_consumer_ctrl`
109+
* :ref:`nrf_desktop_hid_provider_keyboard`
110+
* :ref:`nrf_desktop_hid_provider_mouse`
111+
* :ref:`nrf_desktop_hid_provider_system_ctrl`
84112
* :ref:`nrf_desktop_hids`
85113
* :ref:`nrf_desktop_usb_state`
86114

@@ -179,6 +207,10 @@ Sink modules for module_state_event
179207
* :ref:`nrf_desktop_fn_keys`
180208
* :ref:`nrf_desktop_hfclk_lock`
181209
* :ref:`nrf_desktop_hid_forward`
210+
* :ref:`nrf_desktop_hid_provider_consumer_ctrl`
211+
* :ref:`nrf_desktop_hid_provider_keyboard`
212+
* :ref:`nrf_desktop_hid_provider_mouse`
213+
* :ref:`nrf_desktop_hid_provider_system_ctrl`
182214
* :ref:`nrf_desktop_hid_state`
183215
* :ref:`nrf_desktop_info`
184216
* :ref:`nrf_desktop_led_state`
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
.. _nrf_desktop_hid_provider_consumer_ctrl:
2+
3+
HID provider consumer control module
4+
####################################
5+
6+
.. contents::
7+
:local:
8+
:depth: 2
9+
10+
The HID provider consumer control module is responsible for providing consumer control HID reports.
11+
The module listens to the :c:struct:`button_event` event and communicates with the :ref:`nrf_desktop_hid_state`.
12+
It provides new consumer control HID reports when requested by the :ref:`nrf_desktop_hid_state`.
13+
It also notifies the :ref:`nrf_desktop_hid_state` when new data is available.
14+
15+
Module events
16+
*************
17+
18+
.. include:: event_propagation.rst
19+
:start-after: table_hid_provider_consumer_ctrl_start
20+
:end-before: table_hid_provider_consumer_ctrl_end
21+
22+
.. note::
23+
|nrf_desktop_module_event_note|
24+
25+
Configuration
26+
*************
27+
28+
You can enable the module using the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_CONSUMER_CTRL <config_desktop_app_options>` Kconfig option.
29+
This option is enabled by default if the device supports HID consumer control reports.
30+
You can substitute the module with a custom HID consumer control report provider implementation.
31+
Enable the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_CONSUMER_CTRL_ALT <config_desktop_app_options>` Kconfig option to use a custom HID consumer control report provider.
32+
Make sure to introduce the custom HID consumer control report provider if you enable this option.
33+
34+
HID keymap
35+
==========
36+
37+
The module uses the :ref:`nrf_desktop_hid_keymap` to map an application-specific key ID to a HID report ID and HID usage ID pair.
38+
The module selects the :ref:`CONFIG_DESKTOP_HID_KEYMAP <config_desktop_app_options>` Kconfig option to enable the utility.
39+
Make sure to configure the HID keymap utility.
40+
See the utility's documentation for details.
41+
42+
Queuing keypresses
43+
==================
44+
45+
The module selects the :ref:`CONFIG_DESKTOP_HID_EVENTQ <config_desktop_app_options>` Kconfig option to enable the :ref:`nrf_desktop_hid_eventq`.
46+
The utility is used to temporarily queue key state changes (presses and releases) before the connection with the HID host is established.
47+
When a key state changes (it is pressed or released) before the connection is established, an element containing this key's usage ID is pushed onto the queue.
48+
49+
Queue size
50+
----------
51+
52+
With the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_CONSUMER_CTRL_EVENT_QUEUE_SIZE <config_desktop_app_options>` Kconfig option, you can set the number of elements on the queue where the keys are stored before the connection is established.
53+
For backwards compatibility, you can set the default value for this option using the deprecated :ref:`CONFIG_DESKTOP_HID_EVENT_QUEUE_SIZE <config_desktop_app_options>` Kconfig option.
54+
If there is no space in the queue to enqueue a new key state change, the oldest element is released.
55+
56+
Report expiration
57+
-----------------
58+
59+
With the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_CONSUMER_CTRL_KEYPRESS_EXPIRATION <config_desktop_app_options>` Kconfig option, you can set the amount of time after which a queued key will be considered expired.
60+
For backwards compatibility, you can set the default value for this option using the deprecated :ref:`CONFIG_DESKTOP_HID_REPORT_EXPIRATION <config_desktop_app_options>` Kconfig option.
61+
The higher the value, the longer the period from which the nRF Desktop application will recall pressed keys when the connection with HID host is established.
62+
63+
Handling keys state
64+
===================
65+
66+
The module selects the :ref:`CONFIG_DESKTOP_KEYS_STATE <config_desktop_app_options>` Kconfig option to enable the :ref:`nrf_desktop_keys_state`.
67+
The utility is used to track the state of active keys after the connection with the HID host is established.
68+
69+
Implementation details
70+
**********************
71+
72+
On initialization, the module announces its presence by sending the :c:struct:`hid_report_provider_event` event with an appropriate report ID and implementation of callbacks from the HID report provider API (:c:struct:`hid_report_provider_api`).
73+
The :ref:`nrf_desktop_hid_state` receives the event and fills it with its own implementation of callbacks from the HID state API (:c:struct:`hid_state_api`).
74+
After that process, the modules can communicate by callbacks.
75+
The module also subscribes to the :c:struct:`button_event` event to get information about the button presses.
76+
The module sends :c:struct:`hid_report_event` events to an appropriate subscriber when it is requested by the :ref:`nrf_desktop_hid_state`.
77+
78+
.. note::
79+
The HID report formatting function must work according to the HID report descriptor (``hid_report_desc``).
80+
The source file containing the descriptor is provided by the :ref:`CONFIG_DESKTOP_HID_REPORT_DESC <config_desktop_app_options>` Kconfig option.
81+
82+
Linking input data with the right HID report
83+
============================================
84+
85+
Out of all available input data types, the module collects button events.
86+
The button events are stored in the :c:struct:`report_data` structure.
87+
The ``button_event`` is the source of this type of data.
88+
89+
To indicate a change to this input data, the module overwrites the value that is already stored.
90+
91+
Since keys on the board can be associated with a HID usage ID and thus be part of different HID reports, the first step is to identify if the key belongs to a HID report that is provided by this module.
92+
This is done by obtaining the key mapping from the :ref:`nrf_desktop_hid_keymap`.
93+
94+
Once the mapping is obtained, the application checks if the report to which the usage belongs is connected:
95+
96+
* If the report is connected and the :ref:`nrf_desktop_hid_eventq` instance is empty, the module stores the report and calls the ``trigger_report_send`` callback from the :c:struct:`hid_state_api` to notify the :ref:`nrf_desktop_hid_state` about the new data.
97+
* If the report is not connected or the :ref:`nrf_desktop_hid_eventq` instance is not empty, the value is enqueued in the :ref:`nrf_desktop_hid_eventq` instance.
98+
99+
The difference between these operations is that a storing value onto the queue (second case) preserves the order of input events.
100+
See the following section for more information about storing data before the connection.
101+
102+
Storing input data before the connection
103+
========================================
104+
105+
The button data is stored before the connection.
106+
107+
The reason for this operation is to allow to track key presses that happen right after the device is woken up, but before it can connect to the HID host.
108+
109+
When the device is disconnected and the input event with the button data is received, the data is stored onto the :ref:`nrf_desktop_hid_eventq` instance, a member of the :c:struct:`report_data` structure.
110+
This queue preserves an order in which input data events are received.
111+
112+
Storing limitations
113+
-------------------
114+
115+
You can limit the number of events that can be inserted into the queue using the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_CONSUMER_CTRL_EVENT_QUEUE_SIZE <config_desktop_app_options>` Kconfig option.
116+
117+
Discarding events
118+
------------------
119+
120+
When there is no space for a new input event, the module tries to free space by discarding the oldest event in the queue.
121+
Events stored in the queue are automatically discarded after the period defined by the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_CONSUMER_CTRL_KEYPRESS_EXPIRATION <config_desktop_app_options>` option.
122+
123+
When discarding an event from the queue, the module checks if the key associated with the event is pressed.
124+
This is to avoid missing key releases for earlier key presses when the keys from the queue are replayed to the host.
125+
If a key release is missed, the host could stay with a key that is permanently pressed.
126+
The discarding mechanism ensures that the host will always receive the correct key sequence.
127+
128+
.. note::
129+
The module can only discard an event if the event does not overlap any button that was pressed but not released, or if the button itself is pressed.
130+
The event is released only when the following conditions are met:
131+
132+
* The associated key is not pressed anymore.
133+
* Every key that was pressed after the associated key had been pressed is also released.
134+
135+
If there is no space to store the input event in the queue and no old event can be discarded, the entire content of the queue is dropped to ensure the sanity.
136+
137+
Once the connection is established, the elements of the queue are replayed one after the other to the host, in a sequence of consecutive HID reports.
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
.. _nrf_desktop_hid_provider_keyboard:
2+
3+
HID provider keyboard module
4+
############################
5+
6+
.. contents::
7+
:local:
8+
:depth: 2
9+
10+
The HID provider keyboard module is responsible for providing keyboard HID reports.
11+
The module listens to the :c:struct:`button_event` event and communicates with the :ref:`nrf_desktop_hid_state`.
12+
It provides new keyboard HID reports when requested by the :ref:`nrf_desktop_hid_state`.
13+
It also notifies the :ref:`nrf_desktop_hid_state` when new data is available.
14+
15+
Module events
16+
*************
17+
18+
.. include:: event_propagation.rst
19+
:start-after: table_hid_provider_keyboard_start
20+
:end-before: table_hid_provider_keyboard_end
21+
22+
.. note::
23+
|nrf_desktop_module_event_note|
24+
25+
Configuration
26+
*************
27+
28+
You can enable the module using the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_KEYBOARD <config_desktop_app_options>` Kconfig option.
29+
This option is enabled by default if the device supports HID keyboard reports.
30+
You can substitute the module with a custom HID keyboard report provider implementation.
31+
Enable the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_KEYBOARD_ALT <config_desktop_app_options>` Kconfig option to use a custom HID keyboard report provider.
32+
Make sure to introduce the custom HID keyboard report provider if you enable this option.
33+
34+
HID keymap
35+
==========
36+
37+
The module uses the :ref:`nrf_desktop_hid_keymap` to map an application-specific key ID to a HID report ID and HID usage ID pair.
38+
The module selects the :ref:`CONFIG_DESKTOP_HID_KEYMAP <config_desktop_app_options>` Kconfig option to enable the utility.
39+
Make sure to configure the HID keymap utility.
40+
See the utility's documentation for details.
41+
42+
Queuing keypresses
43+
==================
44+
45+
The module selects the :ref:`CONFIG_DESKTOP_HID_EVENTQ <config_desktop_app_options>` Kconfig option to enable the :ref:`nrf_desktop_hid_eventq`.
46+
The utility is used to temporarily queue key state changes (presses and releases) before the connection with the HID host is established.
47+
When a key state changes (it is pressed or released) before the connection is established, an element containing this key's usage ID is pushed onto the queue.
48+
49+
Queue size
50+
----------
51+
52+
With the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_KEYBOARD_EVENT_QUEUE_SIZE <config_desktop_app_options>` Kconfig option, you can set the number of elements on the queue where the keys are stored before the connection is established.
53+
For backwards compatibility, you can set the default value for this option using the deprecated :ref:`CONFIG_DESKTOP_HID_EVENT_QUEUE_SIZE <config_desktop_app_options>` Kconfig option.
54+
If there is no space in the queue to enqueue a new key state change, the oldest element is released.
55+
56+
Report expiration
57+
-----------------
58+
59+
With the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_KEYBOARD_KEYPRESS_EXPIRATION <config_desktop_app_options>` Kconfig option, you can set the amount of time after which a queued key will be considered expired.
60+
For backwards compatibility, you can set the default value for this option using the deprecated :ref:`CONFIG_DESKTOP_HID_REPORT_EXPIRATION <config_desktop_app_options>` Kconfig option.
61+
The higher the value, the longer the period from which the nRF Desktop application will recall pressed keys when the connection with HID host is established.
62+
63+
Handling keys state
64+
===================
65+
66+
The module selects the :ref:`CONFIG_DESKTOP_KEYS_STATE <config_desktop_app_options>` Kconfig option to enable the :ref:`nrf_desktop_keys_state`.
67+
The utility is used to track the state of active keys after the connection with the HID host is established.
68+
69+
Implementation details
70+
**********************
71+
72+
On initialization, the module announces its presence by sending the :c:struct:`hid_report_provider_event` event with an appropriate report ID and implementation of callbacks from HID report provider API (:c:struct:`hid_report_provider_api`).
73+
Separate :c:struct:`hid_report_provider_event` events are sent for each report ID.
74+
The module supports keyboard reports from the report and boot protocols.
75+
You can enable the boot protocol support using the :ref:`CONFIG_DESKTOP_HID_BOOT_INTERFACE_KEYBOARD <config_desktop_app_options>` Kconfig option.
76+
The :ref:`nrf_desktop_hid_state` receives the events and fills them with its own implementation of callbacks from the HID state API (:c:struct:`hid_state_api`).
77+
After that process, the modules can communicate by callbacks.
78+
The module also subscribes to the :c:struct:`button_event` event to get information about the button presses.
79+
The module sends :c:struct:`hid_report_event` events to an appropriate subscriber when it is requested by the :ref:`nrf_desktop_hid_state`.
80+
81+
.. note::
82+
The HID report formatting function must work according to the HID report descriptor (``hid_report_desc``).
83+
The source file containing the descriptor is provided by the :ref:`CONFIG_DESKTOP_HID_REPORT_DESC <config_desktop_app_options>` Kconfig option.
84+
85+
Linking input data with the right HID report
86+
============================================
87+
88+
Out of all available input data types, the module collects button events.
89+
The button events are stored in the :c:struct:`report_data` structure.
90+
The ``button_event`` is the source of this type of data.
91+
92+
To indicate a change to this input data, the module overwrites the value that is already stored.
93+
94+
Since keys on the board can be associated with a HID usage ID and thus be part of different HID reports, the first step is to identify if the key belongs to a HID report that is provided by this module.
95+
This is done by obtaining the key mapping from the :ref:`nrf_desktop_hid_keymap`.
96+
97+
Once the mapping is obtained, the application checks if the report to which the usage belongs is connected:
98+
99+
* If the report is connected and the :ref:`nrf_desktop_hid_eventq` instance is empty, the module stores the report and calls the ``trigger_report_send`` callback from the :c:struct:`hid_state_api` to notify the :ref:`nrf_desktop_hid_state` about the new data.
100+
* If the report is not connected or the :ref:`nrf_desktop_hid_eventq` instance is not empty, the value is enqueued in the :ref:`nrf_desktop_hid_eventq` instance.
101+
102+
The difference between these operations is that storing a value onto the queue (second case) preserves the order of input events.
103+
See the following section for more information about storing data before the connection.
104+
105+
Storing input data before the connection
106+
========================================
107+
108+
The button data is stored before the connection.
109+
110+
The reason for this operation is to allow to track key presses that happen right after the device is woken up, but before it can connect to the HID host.
111+
112+
When the device is disconnected and the input event with the button data is received, the data is stored onto the :ref:`nrf_desktop_hid_eventq` instance, a member of the :c:struct:`report_data` structure.
113+
This queue preserves an order in which input data events are received.
114+
115+
Storing limitations
116+
-------------------
117+
118+
You can limit the number of events that can be inserted into the queue using the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_KEYBOARD_EVENT_QUEUE_SIZE <config_desktop_app_options>` Kconfig option.
119+
120+
Discarding events
121+
------------------
122+
123+
When there is no space for a new input event, the module tries to free space by discarding the oldest event in the queue.
124+
Events stored in the queue are automatically discarded after the period defined by the :ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_KEYBOARD_KEYPRESS_EXPIRATION <config_desktop_app_options>` option.
125+
126+
When discarding an event from the queue, the module checks if the key associated with the event is pressed.
127+
This is to avoid missing key releases for earlier key presses when the keys from the queue are replayed to the host.
128+
If a key release is missed, the host could stay with a key that is permanently pressed.
129+
The discarding mechanism ensures that the host will always receive the correct key sequence.
130+
131+
.. note::
132+
The module can only discard an event if the event does not overlap any button that was pressed but not released, or if the button itself is pressed.
133+
The event is released only when the following conditions are met:
134+
135+
* The associated key is not pressed anymore.
136+
* Every key that was pressed after the associated key had been pressed is also released.
137+
138+
If there is no space to store the input event in the queue and no old event can be discarded, the entire content of the queue is dropped to ensure the sanity.
139+
140+
Once the connection is established, the elements of the queue are replayed one after the other to the host, in a sequence of consecutive HID reports.

0 commit comments

Comments
 (0)