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  * @ingroup io_interfaces
19  * @{
20  */
21 
22 #include <errno.h>
23 
24 #include <zephyr/types.h>
25 #include <zephyr/device.h>
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 /**
32  * @brief LED information structure
33  *
34  * This structure gathers useful information about LED controller.
35  *
36  * @param label LED label.
37  * @param num_colors Number of colors per LED.
38  * @param index Index of the LED on the controller.
39  * @param color_mapping Mapping of the LED colors.
40  */
41 struct led_info {
42 	const char *label;
43 	uint32_t index;
44 	uint8_t num_colors;
45 	const uint8_t *color_mapping;
46 };
47 
48 /**
49  * @typedef led_api_blink()
50  * @brief Callback API for blinking an LED
51  *
52  * @see led_blink() for argument descriptions.
53  */
54 typedef int (*led_api_blink)(const struct device *dev, uint32_t led,
55 			     uint32_t delay_on, uint32_t delay_off);
56 
57 /**
58  * @typedef led_api_get_info()
59  * @brief Optional API callback to get LED information
60  *
61  * @see led_get_info() for argument descriptions.
62  */
63 typedef int (*led_api_get_info)(const struct device *dev, uint32_t led,
64 				const struct led_info **info);
65 
66 /**
67  * @typedef led_api_set_brightness()
68  * @brief Callback API for setting brightness of an LED
69  *
70  * @see led_set_brightness() for argument descriptions.
71  */
72 typedef int (*led_api_set_brightness)(const struct device *dev, uint32_t led,
73 				      uint8_t value);
74 /**
75  * @typedef led_api_set_color()
76  * @brief Optional API callback to set the colors of a LED.
77  *
78  * @see led_set_color() for argument descriptions.
79  */
80 typedef int (*led_api_set_color)(const struct device *dev, uint32_t led,
81 				 uint8_t num_colors, const uint8_t *color);
82 
83 /**
84  * @typedef led_api_on()
85  * @brief Callback API for turning on an LED
86  *
87  * @see led_on() for argument descriptions.
88  */
89 typedef int (*led_api_on)(const struct device *dev, uint32_t led);
90 
91 /**
92  * @typedef led_api_off()
93  * @brief Callback API for turning off an LED
94  *
95  * @see led_off() for argument descriptions.
96  */
97 typedef int (*led_api_off)(const struct device *dev, uint32_t led);
98 
99 /**
100  * @typedef led_api_write_channels()
101  * @brief Callback API for writing a strip of LED channels
102  *
103  * @see led_api_write_channels() for arguments descriptions.
104  */
105 typedef int (*led_api_write_channels)(const struct device *dev,
106 				      uint32_t start_channel,
107 				      uint32_t num_channels,
108 				      const uint8_t *buf);
109 
110 /**
111  * @brief LED driver API
112  */
113 __subsystem struct led_driver_api {
114 	/* Mandatory callbacks. */
115 	led_api_on on;
116 	led_api_off off;
117 	/* Optional callbacks. */
118 	led_api_blink blink;
119 	led_api_get_info get_info;
120 	led_api_set_brightness set_brightness;
121 	led_api_set_color set_color;
122 	led_api_write_channels write_channels;
123 };
124 
125 /**
126  * @brief Blink an LED
127  *
128  * This optional routine starts blinking a LED forever with the given time
129  * period.
130  *
131  * @param dev LED device
132  * @param led LED number
133  * @param delay_on Time period (in milliseconds) an LED should be ON
134  * @param delay_off Time period (in milliseconds) an LED should be OFF
135  * @return 0 on success, negative on error
136  */
137 __syscall int led_blink(const struct device *dev, uint32_t led,
138 			    uint32_t delay_on, uint32_t delay_off);
139 
z_impl_led_blink(const struct device * dev,uint32_t led,uint32_t delay_on,uint32_t delay_off)140 static inline int z_impl_led_blink(const struct device *dev, uint32_t led,
141 				   uint32_t delay_on, uint32_t delay_off)
142 {
143 	const struct led_driver_api *api =
144 		(const struct led_driver_api *)dev->api;
145 
146 	if (api->blink == NULL) {
147 		return -ENOSYS;
148 	}
149 	return api->blink(dev, led, delay_on, delay_off);
150 }
151 
152 /**
153  * @brief Get LED information
154  *
155  * This optional routine provides information about a LED.
156  *
157  * @param dev LED device
158  * @param led LED number
159  * @param info Pointer to a pointer filled with LED information
160  * @return 0 on success, negative on error
161  */
162 __syscall int led_get_info(const struct device *dev, uint32_t led,
163 			   const struct led_info **info);
164 
z_impl_led_get_info(const struct device * dev,uint32_t led,const struct led_info ** info)165 static inline int z_impl_led_get_info(const struct device *dev, uint32_t led,
166 				      const struct led_info **info)
167 {
168 	const struct led_driver_api *api =
169 		(const struct led_driver_api *)dev->api;
170 
171 	if (api->get_info == NULL) {
172 		*info = NULL;
173 		return -ENOSYS;
174 	}
175 	return api->get_info(dev, led, info);
176 }
177 
178 /**
179  * @brief Set LED brightness
180  *
181  * This optional routine sets the brightness of a LED to the given value.
182  * Calling this function after led_blink() won't affect blinking.
183  *
184  * LEDs which can only be turned on or off may provide this function.
185  * These should simply turn the LED on if @p value is nonzero, and off
186  * if @p value is zero.
187  *
188  * @param dev LED device
189  * @param led LED number
190  * @param value Brightness value to set in percent
191  * @return 0 on success, negative on error
192  */
193 __syscall int led_set_brightness(const struct device *dev, uint32_t led,
194 				     uint8_t value);
195 
z_impl_led_set_brightness(const struct device * dev,uint32_t led,uint8_t value)196 static inline int z_impl_led_set_brightness(const struct device *dev,
197 					    uint32_t led,
198 					    uint8_t value)
199 {
200 	const struct led_driver_api *api =
201 		(const struct led_driver_api *)dev->api;
202 
203 	if (api->set_brightness == NULL) {
204 		return -ENOSYS;
205 	}
206 	return api->set_brightness(dev, led, value);
207 }
208 
209 /**
210  * @brief Write/update a strip of LED channels
211  *
212  * This optional routine writes a strip of LED channels to the given array of
213  * levels. Therefore it can be used to configure several LEDs at the same time.
214  *
215  * Calling this function after led_blink() won't affect blinking.
216  *
217  * @param dev LED device
218  * @param start_channel Absolute number (i.e. not relative to a LED) of the
219  *        first channel to update.
220  * @param num_channels The number of channels to write/update.
221  * @param buf array of values to configure the channels with. num_channels
222  *        entries must be provided.
223  * @return 0 on success, negative on error
224  */
225 __syscall int led_write_channels(const struct device *dev,
226 				 uint32_t start_channel,
227 				 uint32_t num_channels, const uint8_t *buf);
228 
229 static inline int
z_impl_led_write_channels(const struct device * dev,uint32_t start_channel,uint32_t num_channels,const uint8_t * buf)230 z_impl_led_write_channels(const struct device *dev, uint32_t start_channel,
231 			  uint32_t num_channels, const uint8_t *buf)
232 {
233 	const struct led_driver_api *api =
234 		(const struct led_driver_api *)dev->api;
235 
236 	if (api->write_channels == NULL) {
237 		return -ENOSYS;
238 	}
239 	return api->write_channels(dev, start_channel, num_channels, buf);
240 }
241 
242 /**
243  * @brief Set a single LED channel
244  *
245  * This optional routine sets a single LED channel to the given value.
246  *
247  * Calling this function after led_blink() won't affect blinking.
248  *
249  * @param dev LED device
250  * @param channel Absolute channel number (i.e. not relative to a LED)
251  * @param value Value to configure the channel with
252  * @return 0 on success, negative on error
253  */
254 __syscall int led_set_channel(const struct device *dev,
255 			      uint32_t channel, uint8_t value);
256 
z_impl_led_set_channel(const struct device * dev,uint32_t channel,uint8_t value)257 static inline int z_impl_led_set_channel(const struct device *dev,
258 					 uint32_t channel, uint8_t value)
259 {
260 	return z_impl_led_write_channels(dev, channel, 1, &value);
261 }
262 
263 /**
264  * @brief Set LED color
265  *
266  * This routine configures all the color channels of a LED with the given
267  * color array.
268  *
269  * Calling this function after led_blink() won't affect blinking.
270  *
271  * @param dev LED device
272  * @param led LED number
273  * @param num_colors Number of colors in the array.
274  * @param color Array of colors. It must be ordered following the color
275  *        mapping of the LED controller. See the the color_mapping member
276  *        in struct led_info.
277  * @return 0 on success, negative on error
278  */
279 __syscall int led_set_color(const struct device *dev, uint32_t led,
280 			    uint8_t num_colors, const uint8_t *color);
281 
z_impl_led_set_color(const struct device * dev,uint32_t led,uint8_t num_colors,const uint8_t * color)282 static inline int z_impl_led_set_color(const struct device *dev, uint32_t led,
283 				       uint8_t num_colors, const uint8_t *color)
284 {
285 	const struct led_driver_api *api =
286 		(const struct led_driver_api *)dev->api;
287 
288 	if (api->set_color == NULL) {
289 		return -ENOSYS;
290 	}
291 	return api->set_color(dev, led, num_colors, color);
292 }
293 
294 /**
295  * @brief Turn on an LED
296  *
297  * This routine turns on an LED
298  *
299  * @param dev LED device
300  * @param led LED number
301  * @return 0 on success, negative on error
302  */
303 __syscall int led_on(const struct device *dev, uint32_t led);
304 
z_impl_led_on(const struct device * dev,uint32_t led)305 static inline int z_impl_led_on(const struct device *dev, uint32_t led)
306 {
307 	const struct led_driver_api *api =
308 		(const struct led_driver_api *)dev->api;
309 
310 	return api->on(dev, led);
311 }
312 
313 /**
314  * @brief Turn off an LED
315  *
316  * This routine turns off an LED
317  *
318  * @param dev LED device
319  * @param led LED number
320  * @return 0 on success, negative on error
321  */
322 __syscall int led_off(const struct device *dev, uint32_t led);
323 
z_impl_led_off(const struct device * dev,uint32_t led)324 static inline int z_impl_led_off(const struct device *dev, uint32_t led)
325 {
326 	const struct led_driver_api *api =
327 		(const struct led_driver_api *)dev->api;
328 
329 	return api->off(dev, led);
330 }
331 
332 /**
333  * @}
334  */
335 
336 #ifdef __cplusplus
337 }
338 #endif
339 
340 #include <syscalls/led.h>
341 
342 #endif	/* ZEPHYR_INCLUDE_DRIVERS_LED_H_ */
343