1.. _design_guidelines:
2
3API Design Guidelines
4#####################
5
6Zephyr development and evolution is a group effort, and to simplify
7maintenance and enhancements there are some general policies that should
8be followed when developing a new capability or interface.
9
10Using Callbacks
11***************
12
13Many APIs involve passing a callback as a parameter or as a member of a
14configuration structure.  The following policies should be followed when
15specifying the signature of a callback:
16
17* The first parameter should be a pointer to the object most closely
18  associated with the callback.  In the case of device drivers this
19  would be ``const struct device *dev``.  For library functions it may be a
20  pointer to another object that was referenced when the callback was
21  provided.
22
23* The next parameter(s) should be additional information specific to the
24  callback invocation, such as a channel identifier, new status value,
25  and/or a message pointer followed by the message length.
26
27* The final parameter should be a ``void *user_data`` pointer carrying
28  context that allows a shared callback function to locate additional
29  material necessary to process the callback.
30
31An exception to providing ``user_data`` as the last parameter may be
32allowed when the callback itself was provided through a structure that
33will be embedded in another structure.  An example of such a case is
34:c:struct:`gpio_callback`, normally defined within a data structure
35specific to the code that also defines the callback function.  In those
36cases further context can accessed by the callback indirectly by
37:c:macro:`CONTAINER_OF`.
38
39Examples
40========
41
42* The requirements of :c:type:`k_timer_expiry_t` invoked when a system
43  timer alarm fires are satisfied by::
44
45    void handle_timeout(struct k_timer *timer)
46    { ... }
47
48  The assumption here, as with :c:struct:`gpio_callback`, is that the
49  timer is embedded in a structure reachable from
50  :c:macro:`CONTAINER_OF` that can provide additional context to the
51  callback.
52
53* The requirements of :c:type:`counter_alarm_callback_t` invoked when a
54  counter device alarm fires are satisfied by::
55
56    void handle_alarm(const struct device *dev,
57                      uint8_t chan_id,
58		      uint32_t ticks,
59		      void *user_data)
60    { ... }
61
62  This provides more complete useful information, including which
63  counter channel timed-out and the counter value at which the timeout
64  occurred, as well as user context which may or may not be the
65  :c:struct:`counter_alarm_cfg` used to register the callback, depending
66  on user needs.
67
68Conditional Data and APIs
69*************************
70
71APIs and libraries may provide features that are expensive in RAM or
72code size but are optional in the sense that some applications can be
73implemented without them.  Examples of such feature include
74:kconfig:option:`capturing a timestamp <CONFIG_CAN_RX_TIMESTAMP>` or
75:kconfig:option:`providing an alternative interface <CONFIG_SPI_ASYNC>`.  The
76developer in coordination with the community must determine whether
77enabling the features is to be controllable through a Kconfig option.
78
79In the case where a feature is determined to be optional the following
80practices should be followed.
81
82* Any data that is accessed only when the feature is enabled should be
83  conditionally included via ``#ifdef CONFIG_MYFEATURE`` in the
84  structure or union declaration.  This reduces memory use for
85  applications that don't need the capability.
86* Function declarations that are available only when the option is
87  enabled should be provided unconditionally.  Add a note in the
88  description that the function is available only when the specified
89  feature is enabled, referencing the required Kconfig symbol by name.
90  In the cases where the function is used but not enabled the definition
91  of the function shall be excluded from compilation, so references to
92  the unsupported API will result in a link-time error.
93* Where code specific to the feature is isolated in a source file that
94  has no other content that file should be conditionally included in
95  ``CMakeLists.txt``::
96
97    zephyr_sources_ifdef(CONFIG_MYFEATURE foo_funcs.c)
98* Where code specific to the feature is part of a source file that has
99  other content the feature-specific code should be conditionally
100  processed using ``#ifdef CONFIG_MYFEATURE``.
101
102The Kconfig flag used to enable the feature should be added to the
103``PREDEFINED`` variable in :file:`doc/zephyr.doxyfile.in` to ensure the
104conditional API and functions appear in generated documentation.
105
106Return Codes
107************
108
109Implementations of an API, for example an API for accessing a peripheral might
110implement only a subset of the functions that is required for minimal operation.
111A distinction is needed between APIs that are not supported and those that are
112not implemented or optional:
113
114- APIs that are supported but not implemented shall return ``-ENOSYS``.
115
116- Optional APIs that are not supported by the hardware should be implemented and
117  the return code in this case shall be ``-ENOTSUP``.
118
119- When an API is implemented, but the particular combination of options
120  requested in the call cannot be satisfied by the implementation the call shall
121  return ``-ENOTSUP``. (For example, a request for a level-triggered GPIO interrupt on
122  hardware that supports only edge-triggered interrupts)
123