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