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