Line data Source code
1 1 : /*
2 : * Copyright (c) 2018 Linaro Limited
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @brief Public LED driver APIs
10 : */
11 :
12 : #ifndef ZEPHYR_INCLUDE_DRIVERS_LED_H_
13 : #define ZEPHYR_INCLUDE_DRIVERS_LED_H_
14 :
15 : /**
16 : * @brief LED Interface
17 : * @defgroup led_interface LED Interface
18 : * @since 1.12
19 : * @version 1.0.0
20 : * @ingroup io_interfaces
21 : * @{
22 : */
23 :
24 : #include <errno.h>
25 :
26 : #include <zephyr/types.h>
27 : #include <zephyr/device.h>
28 :
29 : #ifdef __cplusplus
30 : extern "C" {
31 : #endif
32 :
33 : /**
34 : * @brief LED information structure
35 : *
36 : * This structure gathers useful information about LED controller.
37 : */
38 1 : struct led_info {
39 : /** LED label */
40 1 : const char *label;
41 : /** Index of the LED on the controller */
42 1 : uint32_t index;
43 : /** Number of colors per LED */
44 1 : uint8_t num_colors;
45 : /** Mapping of the LED colors */
46 1 : const uint8_t *color_mapping;
47 : };
48 :
49 : /**
50 : * @typedef led_api_blink()
51 : * @brief Callback API for blinking an LED
52 : *
53 : * @see led_blink() for argument descriptions.
54 : */
55 1 : typedef int (*led_api_blink)(const struct device *dev, uint32_t led,
56 : uint32_t delay_on, uint32_t delay_off);
57 :
58 : /**
59 : * @typedef led_api_get_info()
60 : * @brief Optional API callback to get LED information
61 : *
62 : * @see led_get_info() for argument descriptions.
63 : */
64 1 : typedef int (*led_api_get_info)(const struct device *dev, uint32_t led,
65 : const struct led_info **info);
66 :
67 : /**
68 : * @typedef led_api_set_brightness()
69 : * @brief Callback API for setting brightness of an LED
70 : *
71 : * @see led_set_brightness() for argument descriptions.
72 : */
73 1 : typedef int (*led_api_set_brightness)(const struct device *dev, uint32_t led,
74 : uint8_t value);
75 : /**
76 : * @typedef led_api_set_color()
77 : * @brief Optional API callback to set the colors of a LED.
78 : *
79 : * @see led_set_color() for argument descriptions.
80 : */
81 1 : typedef int (*led_api_set_color)(const struct device *dev, uint32_t led,
82 : uint8_t num_colors, const uint8_t *color);
83 :
84 : /**
85 : * @typedef led_api_on()
86 : * @brief Callback API for turning on an LED
87 : *
88 : * @see led_on() for argument descriptions.
89 : */
90 1 : typedef int (*led_api_on)(const struct device *dev, uint32_t led);
91 :
92 : /**
93 : * @typedef led_api_off()
94 : * @brief Callback API for turning off an LED
95 : *
96 : * @see led_off() for argument descriptions.
97 : */
98 1 : typedef int (*led_api_off)(const struct device *dev, uint32_t led);
99 :
100 : /**
101 : * @typedef led_api_write_channels()
102 : * @brief Callback API for writing a strip of LED channels
103 : *
104 : * @see led_api_write_channels() for arguments descriptions.
105 : */
106 1 : typedef int (*led_api_write_channels)(const struct device *dev,
107 : uint32_t start_channel,
108 : uint32_t num_channels,
109 : const uint8_t *buf);
110 :
111 : /**
112 : * @brief LED driver API
113 : */
114 1 : __subsystem struct led_driver_api {
115 : /* Mandatory callbacks. */
116 0 : led_api_on on;
117 0 : led_api_off off;
118 : /* Optional callbacks. */
119 0 : led_api_blink blink;
120 0 : led_api_get_info get_info;
121 0 : led_api_set_brightness set_brightness;
122 0 : led_api_set_color set_color;
123 0 : led_api_write_channels write_channels;
124 : };
125 :
126 : /**
127 : * @brief Blink an LED
128 : *
129 : * This optional routine starts blinking a LED forever with the given time
130 : * period.
131 : *
132 : * @param dev LED device
133 : * @param led LED number
134 : * @param delay_on Time period (in milliseconds) an LED should be ON
135 : * @param delay_off Time period (in milliseconds) an LED should be OFF
136 : * @return 0 on success, negative on error
137 : */
138 1 : __syscall int led_blink(const struct device *dev, uint32_t led,
139 : uint32_t delay_on, uint32_t delay_off);
140 :
141 : static inline int z_impl_led_blink(const struct device *dev, uint32_t led,
142 : uint32_t delay_on, uint32_t delay_off)
143 : {
144 : const struct led_driver_api *api =
145 : (const struct led_driver_api *)dev->api;
146 :
147 : if (api->blink == NULL) {
148 : return -ENOSYS;
149 : }
150 : return api->blink(dev, led, delay_on, delay_off);
151 : }
152 :
153 : /**
154 : * @brief Get LED information
155 : *
156 : * This optional routine provides information about a LED.
157 : *
158 : * @param dev LED device
159 : * @param led LED number
160 : * @param info Pointer to a pointer filled with LED information
161 : * @return 0 on success, negative on error
162 : */
163 1 : __syscall int led_get_info(const struct device *dev, uint32_t led,
164 : const struct led_info **info);
165 :
166 : static inline int z_impl_led_get_info(const struct device *dev, uint32_t led,
167 : const struct led_info **info)
168 : {
169 : const struct led_driver_api *api =
170 : (const struct led_driver_api *)dev->api;
171 :
172 : if (api->get_info == NULL) {
173 : *info = NULL;
174 : return -ENOSYS;
175 : }
176 : return api->get_info(dev, led, info);
177 : }
178 :
179 : /**
180 : * @brief Set LED brightness
181 : *
182 : * This optional routine sets the brightness of a LED to the given value.
183 : * Calling this function after led_blink() won't affect blinking.
184 : *
185 : * LEDs which can only be turned on or off may provide this function.
186 : * These should simply turn the LED on if @p value is nonzero, and off
187 : * if @p value is zero.
188 : *
189 : * @param dev LED device
190 : * @param led LED number
191 : * @param value Brightness value to set in percent
192 : * @return 0 on success, negative on error
193 : */
194 1 : __syscall int led_set_brightness(const struct device *dev, uint32_t led,
195 : uint8_t value);
196 :
197 : static inline int z_impl_led_set_brightness(const struct device *dev,
198 : uint32_t led,
199 : uint8_t value)
200 : {
201 : const struct led_driver_api *api =
202 : (const struct led_driver_api *)dev->api;
203 :
204 : if (api->set_brightness == NULL) {
205 : return -ENOSYS;
206 : }
207 : return api->set_brightness(dev, led, value);
208 : }
209 :
210 : /**
211 : * @brief Write/update a strip of LED channels
212 : *
213 : * This optional routine writes a strip of LED channels to the given array of
214 : * levels. Therefore it can be used to configure several LEDs at the same time.
215 : *
216 : * Calling this function after led_blink() won't affect blinking.
217 : *
218 : * @param dev LED device
219 : * @param start_channel Absolute number (i.e. not relative to a LED) of the
220 : * first channel to update.
221 : * @param num_channels The number of channels to write/update.
222 : * @param buf array of values to configure the channels with. num_channels
223 : * entries must be provided.
224 : * @return 0 on success, negative on error
225 : */
226 1 : __syscall int led_write_channels(const struct device *dev,
227 : uint32_t start_channel,
228 : uint32_t num_channels, const uint8_t *buf);
229 :
230 : static inline int
231 : z_impl_led_write_channels(const struct device *dev, uint32_t start_channel,
232 : uint32_t num_channels, const uint8_t *buf)
233 : {
234 : const struct led_driver_api *api =
235 : (const struct led_driver_api *)dev->api;
236 :
237 : if (api->write_channels == NULL) {
238 : return -ENOSYS;
239 : }
240 : return api->write_channels(dev, start_channel, num_channels, buf);
241 : }
242 :
243 : /**
244 : * @brief Set a single LED channel
245 : *
246 : * This optional routine sets a single LED channel to the given value.
247 : *
248 : * Calling this function after led_blink() won't affect blinking.
249 : *
250 : * @param dev LED device
251 : * @param channel Absolute channel number (i.e. not relative to a LED)
252 : * @param value Value to configure the channel with
253 : * @return 0 on success, negative on error
254 : */
255 1 : __syscall int led_set_channel(const struct device *dev,
256 : uint32_t channel, uint8_t value);
257 :
258 : static inline int z_impl_led_set_channel(const struct device *dev,
259 : uint32_t channel, uint8_t value)
260 : {
261 : return z_impl_led_write_channels(dev, channel, 1, &value);
262 : }
263 :
264 : /**
265 : * @brief Set LED color
266 : *
267 : * This routine configures all the color channels of a LED with the given
268 : * color array.
269 : *
270 : * Calling this function after led_blink() won't affect blinking.
271 : *
272 : * @param dev LED device
273 : * @param led LED number
274 : * @param num_colors Number of colors in the array.
275 : * @param color Array of colors. It must be ordered following the color
276 : * mapping of the LED controller. See the color_mapping member
277 : * in struct led_info.
278 : * @return 0 on success, negative on error
279 : */
280 1 : __syscall int led_set_color(const struct device *dev, uint32_t led,
281 : uint8_t num_colors, const uint8_t *color);
282 :
283 : static inline int z_impl_led_set_color(const struct device *dev, uint32_t led,
284 : uint8_t num_colors, const uint8_t *color)
285 : {
286 : const struct led_driver_api *api =
287 : (const struct led_driver_api *)dev->api;
288 :
289 : if (api->set_color == NULL) {
290 : return -ENOSYS;
291 : }
292 : return api->set_color(dev, led, num_colors, color);
293 : }
294 :
295 : /**
296 : * @brief Turn on an LED
297 : *
298 : * This routine turns on an LED
299 : *
300 : * @param dev LED device
301 : * @param led LED number
302 : * @return 0 on success, negative on error
303 : */
304 1 : __syscall int led_on(const struct device *dev, uint32_t led);
305 :
306 : static inline int z_impl_led_on(const struct device *dev, uint32_t led)
307 : {
308 : const struct led_driver_api *api =
309 : (const struct led_driver_api *)dev->api;
310 :
311 : return api->on(dev, led);
312 : }
313 :
314 : /**
315 : * @brief Turn off an LED
316 : *
317 : * This routine turns off an LED
318 : *
319 : * @param dev LED device
320 : * @param led LED number
321 : * @return 0 on success, negative on error
322 : */
323 1 : __syscall int led_off(const struct device *dev, uint32_t led);
324 :
325 : static inline int z_impl_led_off(const struct device *dev, uint32_t led)
326 : {
327 : const struct led_driver_api *api =
328 : (const struct led_driver_api *)dev->api;
329 :
330 : return api->off(dev, led);
331 : }
332 :
333 : /*
334 : * LED DT helpers.
335 : */
336 :
337 : /**
338 : * @brief Container for an LED information specified in devicetree.
339 : *
340 : * This type contains a pointer to and LED device and an LED index.
341 : *
342 : * @see LED_DT_SPEC_GET
343 : * @see LED_DT_SPEC_GET_OR
344 : */
345 1 : struct led_dt_spec {
346 : /** LED device instance. */
347 1 : const struct device *dev;
348 : /** Index of the LED on the controller. */
349 1 : uint32_t index;
350 : };
351 :
352 : /**
353 : * @brief Set LED brightness from a led_dt_spec.
354 : *
355 : * @param spec LED device specification from devicetree.
356 : * @param value Brightness value to set in percent.
357 : * @return 0 on success, negative on error.
358 : *
359 : * @see led_set_brightness()
360 : */
361 1 : static inline int led_set_brightness_dt(const struct led_dt_spec *spec,
362 : uint8_t value)
363 : {
364 : return led_set_brightness(spec->dev, spec->index, value);
365 : }
366 :
367 : /**
368 : * @brief Turn on an LED from a struct led_dt_spec.
369 : *
370 : * @param spec LED device specification from devicetree.
371 : * @return 0 on success, negative on error.
372 : *
373 : * @see led_on()
374 : */
375 1 : static inline int led_on_dt(const struct led_dt_spec *spec)
376 : {
377 : return led_on(spec->dev, spec->index);
378 : }
379 :
380 : /**
381 : * @brief Turn off an LED from a struct led_dt_spec.
382 : *
383 : * @param spec LED device specification from devicetree.
384 : * @return 0 on success, negative on error.
385 : *
386 : * @see led_off()
387 : */
388 1 : static inline int led_off_dt(const struct led_dt_spec *spec)
389 : {
390 : return led_off(spec->dev, spec->index);
391 : }
392 :
393 : /**
394 : * @brief Validate that the LED device is ready.
395 : *
396 : * @param spec LED specification from devicetree.
397 : *
398 : * @retval true If the LED device is ready for use.
399 : * @retval false If the LED device is not ready for use.
400 : */
401 1 : static inline bool led_is_ready_dt(const struct led_dt_spec *spec)
402 : {
403 : return device_is_ready(spec->dev);
404 : }
405 :
406 : /**
407 : * @brief Static initializer for a struct led_dt_spec
408 : *
409 : * This returns a static initializer for a struct led_dt_spec given a devicetree
410 : * node identifier.
411 : *
412 : * Example devicetree fragment:
413 : *
414 : * @code{.dts}
415 : * leds {
416 : * compatible = "gpio-leds";
417 : * led0: led_0 {
418 : * ...
419 : * };
420 : * };
421 : * @endcode
422 : *
423 : * Example usage:
424 : *
425 : * @code{.c}
426 : * const struct led_dt_spec spec = LED_DT_SPEC_GET(DT_NODELABEL(led0));
427 : *
428 : * // Initializes 'spec' to:
429 : * // {
430 : * // .dev = DEVICE_DT_GET(DT_PARENT(led0)),
431 : * // .index = 0,
432 : * // }
433 : * @endcode
434 : *
435 : * The device (dev) must still be checked for readiness, e.g. using
436 : * device_is_ready().
437 : *
438 : * @param node_id Devicetree node identifier.
439 : *
440 : * @return Static initializer for a struct led_dt_spec for the property.
441 : */
442 1 : #define LED_DT_SPEC_GET(node_id) \
443 : { \
444 : .dev = DEVICE_DT_GET(DT_PARENT(node_id)), \
445 : .index = DT_NODE_CHILD_IDX(node_id), \
446 : }
447 :
448 : /**
449 : * @brief Like LED_DT_SPEC_GET(), with a fallback value if the node does not exist.
450 : *
451 : * @param node_id Devicetree node identifier.
452 : *
453 : * @return Static initializer for a struct led_dt_spec for the property.
454 : *
455 : * @see LED_DT_SPEC_GET
456 : */
457 1 : #define LED_DT_SPEC_GET_OR(node_id, default_value) \
458 : COND_CODE_1(DT_NODE_EXISTS(node_id), \
459 : (LED_DT_SPEC_GET(node_id)), \
460 : (default_value))
461 :
462 : /**
463 : * @}
464 : */
465 :
466 : #ifdef __cplusplus
467 : }
468 : #endif
469 :
470 : #include <zephyr/syscalls/led.h>
471 :
472 : #endif /* ZEPHYR_INCLUDE_DRIVERS_LED_H_ */
|