Skip to content

Commit

Permalink
doc: kernel: drivers: Update with DEVICE_API macros
Browse files Browse the repository at this point in the history
Update the device driver API documentation with the new DEVICE_API
macro definitions and how to use them.

Signed-off-by: Pieter De Gendt <[email protected]>
  • Loading branch information
pdgendt authored and kartben committed Nov 27, 2024
1 parent f29203d commit d6b1de1
Showing 1 changed file with 21 additions and 16 deletions.
37 changes: 21 additions & 16 deletions doc/kernel/drivers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,24 @@ The following APIs for device drivers are provided by :file:`device.h`. The APIs
are intended for use in device drivers only and should not be used in
applications.

:c:func:`DEVICE_DEFINE()`
:c:macro:`DEVICE_DEFINE()`
Create device object and related data structures including setting it
up for boot-time initialization.

:c:func:`DEVICE_NAME_GET()`
:c:macro:`DEVICE_NAME_GET()`
Converts a device identifier to the global identifier for a device
object.

:c:func:`DEVICE_GET()`
:c:macro:`DEVICE_GET()`
Obtain a pointer to a device object by name.

:c:func:`DEVICE_DECLARE()`
:c:macro:`DEVICE_DECLARE()`
Declare a device object. Use this when you need a forward reference
to a device that has not yet been defined.

:c:macro:`DEVICE_API()`
Wrap a driver API declaration to assign it to its respective linker section.

.. _device_struct:

Driver Data Structures
Expand All @@ -97,8 +100,8 @@ split into read-only and runtime-mutable parts. At a high level we have:
struct device {
const char *name;
const void *config;
const void *api;
void * const data;
const void *api;
void * const data;
};
The ``config`` member is for read-only configuration data set at build time. For
Expand All @@ -122,36 +125,38 @@ Most drivers will be implementing a device-independent subsystem API.
Applications can simply program to that generic API, and application
code is not specific to any particular driver implementation.

If all driver API instances are assigned to their respective API linker section
use :c:macro:`DEVICE_API_IS()` to verify the API's type.

A subsystem API definition typically looks like this:

.. code-block:: C
typedef int (*subsystem_do_this_t)(const struct device *dev, int foo, int bar);
typedef void (*subsystem_do_that_t)(const struct device *dev, void *baz);
struct subsystem_api {
__subsystem struct subsystem_driver_api {
subsystem_do_this_t do_this;
subsystem_do_that_t do_that;
};
static inline int subsystem_do_this(const struct device *dev, int foo, int bar)
{
struct subsystem_api *api;
__ASSERT_NO_MSG(DEVICE_API_IS(subsystem, dev));
api = (struct subsystem_api *)dev->api;
return api->do_this(dev, foo, bar);
return DEVICE_API_GET(subsystem, dev)->do_this(dev, foo, bar);
}
static inline void subsystem_do_that(const struct device *dev, void *baz)
{
struct subsystem_api *api;
__ASSERT_NO_MSG(DEVICE_API_IS(subsystem, dev));
api = (struct subsystem_api *)dev->api;
api->do_that(dev, baz);
DEVICE_API_GET(subsystem, dev)->do_that(dev, baz);
}
A driver implementing a particular subsystem will define the real implementation
of these APIs, and populate an instance of subsystem_api structure:
of these APIs, and populate an instance of subsystem_driver_api structure using
the :c:macro:`DEVICE_API()` wrapper:

.. code-block:: C
Expand All @@ -165,9 +170,9 @@ of these APIs, and populate an instance of subsystem_api structure:
...
}
static struct subsystem_api my_driver_api_funcs = {
static DEVICE_API(subsystem, my_driver_api_funcs) = {
.do_this = my_driver_do_this,
.do_that = my_driver_do_that
.do_that = my_driver_do_that,
};
The driver would then pass ``my_driver_api_funcs`` as the ``api`` argument to
Expand Down

0 comments on commit d6b1de1

Please sign in to comment.