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