1 /*
2 * Copyright (c) 2017 Linaro Limited
3 * Copyright (c) 2024 Jamie McCrae
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /**
9 * @file
10 * @brief Public API for controlling linear strips of LEDs.
11 *
12 * This library abstracts the chipset drivers for individually
13 * addressable strips of LEDs.
14 */
15
16 #ifndef ZEPHYR_INCLUDE_DRIVERS_LED_STRIP_H_
17 #define ZEPHYR_INCLUDE_DRIVERS_LED_STRIP_H_
18
19 /**
20 * @brief LED Strip Interface
21 * @defgroup led_strip_interface LED Strip Interface
22 * @ingroup io_interfaces
23 * @{
24 */
25
26 #include <errno.h>
27 #include <zephyr/types.h>
28 #include <zephyr/device.h>
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 /**
35 * @brief Color value for a single RGB LED.
36 *
37 * Individual strip drivers may ignore lower-order bits if their
38 * resolution in any channel is less than a full byte.
39 */
40 struct led_rgb {
41 #ifdef CONFIG_LED_STRIP_RGB_SCRATCH
42 /*
43 * Pad/scratch space needed by some drivers. Users should
44 * ignore.
45 */
46 uint8_t scratch;
47 #endif
48 /** Red channel */
49 uint8_t r;
50 /** Green channel */
51 uint8_t g;
52 /** Blue channel */
53 uint8_t b;
54 };
55
56 /**
57 * @typedef led_api_update_rgb
58 * @brief Callback API for updating an RGB LED strip
59 *
60 * @see led_strip_update_rgb() for argument descriptions.
61 */
62 typedef int (*led_api_update_rgb)(const struct device *dev,
63 struct led_rgb *pixels,
64 size_t num_pixels);
65
66 /**
67 * @typedef led_api_update_channels
68 * @brief Callback API for updating channels without an RGB interpretation.
69 *
70 * @see led_strip_update_channels() for argument descriptions.
71 */
72 typedef int (*led_api_update_channels)(const struct device *dev,
73 uint8_t *channels,
74 size_t num_channels);
75
76 /**
77 * @typedef led_api_length
78 * @brief Callback API for getting length of an LED strip.
79 *
80 * @see led_strip_length() for argument descriptions.
81 */
82 typedef size_t (*led_api_length)(const struct device *dev);
83
84 /**
85 * @brief LED strip driver API
86 *
87 * This is the mandatory API any LED strip driver needs to expose.
88 */
89 __subsystem struct led_strip_driver_api {
90 led_api_update_rgb update_rgb;
91 led_api_update_channels update_channels;
92 led_api_length length;
93 };
94
95 /**
96 * @brief Mandatory function to update an LED strip with the given RGB array.
97 *
98 * @param dev LED strip device.
99 * @param pixels Array of pixel data.
100 * @param num_pixels Length of pixels array.
101 *
102 * @retval 0 on success.
103 * @retval -errno negative errno code on failure.
104 *
105 * @warning This routine may overwrite @a pixels.
106 */
led_strip_update_rgb(const struct device * dev,struct led_rgb * pixels,size_t num_pixels)107 static inline int led_strip_update_rgb(const struct device *dev,
108 struct led_rgb *pixels,
109 size_t num_pixels)
110 {
111 const struct led_strip_driver_api *api =
112 (const struct led_strip_driver_api *)dev->api;
113
114 /* Allow for out-of-tree drivers that do not have this function for 2 Zephyr releases
115 * until making it mandatory, function added after Zephyr 3.6
116 */
117 if (api->length != NULL) {
118 /* Ensure supplied pixel size is valid for this device */
119 if (api->length(dev) < num_pixels) {
120 return -ERANGE;
121 }
122 }
123
124 return api->update_rgb(dev, pixels, num_pixels);
125 }
126
127 /**
128 * @brief Optional function to update an LED strip with the given channel array
129 * (each channel byte corresponding to an individually addressable color
130 * channel or LED. Channels are updated linearly in strip order.
131 *
132 * @param dev LED strip device.
133 * @param channels Array of per-channel data.
134 * @param num_channels Length of channels array.
135 *
136 * @retval 0 on success.
137 * @retval -ENOSYS if not implemented.
138 * @retval -errno negative errno code on other failure.
139 *
140 * @warning This routine may overwrite @a channels.
141 */
led_strip_update_channels(const struct device * dev,uint8_t * channels,size_t num_channels)142 static inline int led_strip_update_channels(const struct device *dev,
143 uint8_t *channels,
144 size_t num_channels)
145 {
146 const struct led_strip_driver_api *api =
147 (const struct led_strip_driver_api *)dev->api;
148
149 if (api->update_channels == NULL) {
150 return -ENOSYS;
151 }
152
153 return api->update_channels(dev, channels, num_channels);
154 }
155
156 /**
157 * @brief Mandatory function to get chain length (in pixels) of an LED strip device.
158 *
159 * @param dev LED strip device.
160 *
161 * @retval Length of LED strip device.
162 */
led_strip_length(const struct device * dev)163 static inline size_t led_strip_length(const struct device *dev)
164 {
165 const struct led_strip_driver_api *api =
166 (const struct led_strip_driver_api *)dev->api;
167
168 return api->length(dev);
169 }
170
171 #ifdef __cplusplus
172 }
173 #endif
174
175 /**
176 * @}
177 */
178
179 #endif /* ZEPHYR_INCLUDE_DRIVERS_LED_STRIP_H_ */
180