@@ -68,21 +68,24 @@ The following APIs for device drivers are provided by :file:`device.h`. The APIs
6868are intended for use in device drivers only and should not be used in
6969applications.
7070
71- :c:func : `DEVICE_DEFINE() `
71+ :c:macro : `DEVICE_DEFINE() `
7272 Create device object and related data structures including setting it
7373 up for boot-time initialization.
7474
75- :c:func : `DEVICE_NAME_GET() `
75+ :c:macro : `DEVICE_NAME_GET() `
7676 Converts a device identifier to the global identifier for a device
7777 object.
7878
79- :c:func : `DEVICE_GET() `
79+ :c:macro : `DEVICE_GET() `
8080 Obtain a pointer to a device object by name.
8181
82- :c:func : `DEVICE_DECLARE() `
82+ :c:macro : `DEVICE_DECLARE() `
8383 Declare a device object. Use this when you need a forward reference
8484 to a device that has not yet been defined.
8585
86+ :c:macro: `DEVICE_API() `
87+ Wrap a driver API declaration to assign it to its respective linker section.
88+
8689.. _device_struct :
8790
8891Driver Data Structures
@@ -97,8 +100,8 @@ split into read-only and runtime-mutable parts. At a high level we have:
97100 struct device {
98101 const char *name;
99102 const void *config;
100- const void *api;
101- void * const data;
103+ const void *api;
104+ void * const data;
102105 };
103106
104107 The ``config `` member is for read-only configuration data set at build time. For
@@ -122,36 +125,38 @@ Most drivers will be implementing a device-independent subsystem API.
122125Applications can simply program to that generic API, and application
123126code is not specific to any particular driver implementation.
124127
128+ If all driver API instances are assigned to their respective API linker section
129+ use :c:macro: `DEVICE_API_IS() ` to verify the API's type.
130+
125131A subsystem API definition typically looks like this:
126132
127133.. code-block :: C
128134
129135 typedef int (*subsystem_do_this_t)(const struct device *dev, int foo, int bar);
130136 typedef void (*subsystem_do_that_t)(const struct device *dev, void *baz);
131137
132- struct subsystem_api {
138+ __subsystem struct subsystem_driver_api {
133139 subsystem_do_this_t do_this;
134140 subsystem_do_that_t do_that;
135141 };
136142
137143 static inline int subsystem_do_this(const struct device *dev, int foo, int bar)
138144 {
139- struct subsystem_api *api ;
145+ __ASSERT_NO_MSG(DEVICE_API_IS(subsystem, dev)) ;
140146
141- api = (struct subsystem_api *)dev->api;
142- return api->do_this(dev, foo, bar);
147+ return DEVICE_API_GET(subsystem, dev)->do_this(dev, foo, bar);
143148 }
144149
145150 static inline void subsystem_do_that(const struct device *dev, void *baz)
146151 {
147- struct subsystem_api *api ;
152+ __ASSERT_NO_MSG(DEVICE_API_IS(subsystem, dev)) ;
148153
149- api = (struct subsystem_api *)dev->api;
150- api->do_that(dev, baz);
154+ DEVICE_API_GET(subsystem, dev)->do_that(dev, baz);
151155 }
152156
153157 A driver implementing a particular subsystem will define the real implementation
154- of these APIs, and populate an instance of subsystem_api structure:
158+ of these APIs, and populate an instance of subsystem_driver_api structure using
159+ the :c:macro: `DEVICE_API() ` wrapper:
155160
156161.. code-block :: C
157162
@@ -165,9 +170,9 @@ of these APIs, and populate an instance of subsystem_api structure:
165170 ...
166171 }
167172
168- static struct subsystem_api my_driver_api_funcs = {
173+ static DEVICE_API(subsystem, my_driver_api_funcs) = {
169174 .do_this = my_driver_do_this,
170- .do_that = my_driver_do_that
175+ .do_that = my_driver_do_that,
171176 };
172177
173178 The driver would then pass ``my_driver_api_funcs `` as the ``api `` argument to
0 commit comments