1 /*
2 * Copyright (c) 2020 Seagate Technology LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <shell/shell.h>
8 #include <drivers/led.h>
9 #include <stdlib.h>
10
11 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
12 #include <logging/log.h>
13 LOG_MODULE_REGISTER(led_shell);
14
15 #define MAX_CHANNEL_ARGS 8
16
17 enum {
18 arg_idx_dev = 1,
19 arg_idx_led = 2,
20 arg_idx_value = 3,
21 };
22
parse_common_args(const struct shell * shell,char ** argv,const struct device ** dev,uint32_t * led)23 static int parse_common_args(const struct shell *shell, char **argv,
24 const struct device * *dev, uint32_t *led)
25 {
26 char *end_ptr;
27
28 *dev = device_get_binding(argv[arg_idx_dev]);
29 if (!*dev) {
30 shell_error(shell,
31 "LED device %s not found", argv[arg_idx_dev]);
32 return -ENODEV;
33 }
34
35 *led = strtoul(argv[arg_idx_led], &end_ptr, 0);
36 if (*end_ptr != '\0') {
37 shell_error(shell, "Invalid LED number parameter %s",
38 argv[arg_idx_led]);
39 return -EINVAL;
40 }
41
42 return 0;
43 }
44
cmd_off(const struct shell * shell,size_t argc,char ** argv)45 static int cmd_off(const struct shell *shell, size_t argc, char **argv)
46 {
47 const struct device *dev;
48 uint32_t led;
49 int err;
50
51 err = parse_common_args(shell, argv, &dev, &led);
52 if (err < 0) {
53 return err;
54 }
55
56 shell_print(shell, "%s: turning off LED %d", dev->name, led);
57
58 err = led_off(dev, led);
59 if (err) {
60 shell_error(shell, "Error: %d", err);
61 }
62
63 return err;
64 }
65
cmd_on(const struct shell * shell,size_t argc,char ** argv)66 static int cmd_on(const struct shell *shell, size_t argc, char **argv)
67 {
68 const struct device *dev;
69 uint32_t led;
70 int err;
71
72 err = parse_common_args(shell, argv, &dev, &led);
73 if (err < 0) {
74 return err;
75 }
76
77 shell_print(shell, "%s: turning on LED %d", dev->name, led);
78
79 err = led_on(dev, led);
80 if (err) {
81 shell_error(shell, "Error: %d", err);
82 }
83
84 return err;
85 }
86
cmd_get_info(const struct shell * shell,size_t argc,char ** argv)87 static int cmd_get_info(const struct shell *shell, size_t argc, char **argv)
88 {
89 const struct device *dev;
90 uint32_t led;
91 int err;
92 const struct led_info *info;
93 int i;
94
95 err = parse_common_args(shell, argv, &dev, &led);
96 if (err < 0) {
97 return err;
98 }
99
100 shell_print(shell, "%s: getting LED %d information", dev->name, led);
101
102 err = led_get_info(dev, led, &info);
103 if (err) {
104 shell_error(shell, "Error: %d", err);
105 return err;
106 }
107
108 shell_print(shell, "Label : %s", info->label ? : "<NULL>");
109 shell_print(shell, "Index : %d", info->index);
110 shell_print(shell, "Num colors : %d", info->num_colors);
111 if (info->color_mapping) {
112 shell_fprintf(shell, SHELL_NORMAL, "Colors : %d",
113 info->color_mapping[0]);
114 for (i = 1; i < info->num_colors; i++) {
115 shell_fprintf(shell, SHELL_NORMAL, ":%d",
116 info->color_mapping[i]);
117 }
118 shell_fprintf(shell, SHELL_NORMAL, "\n");
119 }
120
121 return 0;
122 }
123
cmd_set_brightness(const struct shell * shell,size_t argc,char ** argv)124 static int cmd_set_brightness(const struct shell *shell,
125 size_t argc, char **argv)
126 {
127 const struct device *dev;
128 uint32_t led;
129 int err;
130 char *end_ptr;
131 unsigned long value;
132
133 err = parse_common_args(shell, argv, &dev, &led);
134 if (err < 0) {
135 return err;
136 }
137
138 value = strtoul(argv[arg_idx_value], &end_ptr, 0);
139 if (*end_ptr != '\0') {
140 shell_error(shell, "Invalid LED brightness parameter %s",
141 argv[arg_idx_value]);
142 return -EINVAL;
143 }
144 if (value > 100) {
145 shell_error(shell, "Invalid LED brightness value %d (max 100)",
146 value);
147 return -EINVAL;
148 }
149
150 shell_print(shell, "%s: setting LED %d brightness to %d",
151 dev->name, led, value);
152
153 err = led_set_brightness(dev, led, (uint8_t) value);
154 if (err) {
155 shell_error(shell, "Error: %d", err);
156 }
157
158 return err;
159 }
160
cmd_set_color(const struct shell * shell,size_t argc,char ** argv)161 static int cmd_set_color(const struct shell *shell, size_t argc, char **argv)
162 {
163 const struct device *dev;
164 uint32_t led;
165 int err;
166 size_t num_colors;
167 uint8_t i;
168 uint8_t color[MAX_CHANNEL_ARGS];
169
170 err = parse_common_args(shell, argv, &dev, &led);
171 if (err < 0) {
172 return err;
173 }
174
175 num_colors = argc - arg_idx_value;
176 if (num_colors > MAX_CHANNEL_ARGS) {
177 shell_error(shell,
178 "Invalid number of colors %d (max %d)",
179 num_colors, MAX_CHANNEL_ARGS);
180 return -EINVAL;
181 }
182
183 for (i = 0; i < num_colors; i++) {
184 char *end_ptr;
185 unsigned long col;
186
187 col = strtoul(argv[arg_idx_value + i], &end_ptr, 0);
188 if (*end_ptr != '\0') {
189 shell_error(shell, "Invalid LED color parameter %s",
190 argv[arg_idx_value + i]);
191 return -EINVAL;
192 }
193 if (col > 255) {
194 shell_error(shell,
195 "Invalid LED color value %d (max 255)",
196 col);
197 return -EINVAL;
198 }
199 color[i] = col;
200 }
201
202 shell_fprintf(shell, SHELL_NORMAL, "%s: setting LED %d color to %d",
203 dev->name, led, color[0]);
204 for (i = 1; i < num_colors; i++) {
205 shell_fprintf(shell, SHELL_NORMAL, ":%d", color[i]);
206 }
207 shell_fprintf(shell, SHELL_NORMAL, "\n");
208
209 err = led_set_color(dev, led, num_colors, color);
210 if (err) {
211 shell_error(shell, "Error: %d", err);
212 }
213
214 return err;
215 }
216
cmd_set_channel(const struct shell * shell,size_t argc,char ** argv)217 static int cmd_set_channel(const struct shell *shell, size_t argc, char **argv)
218 {
219 const struct device *dev;
220 uint32_t channel;
221 int err;
222 char *end_ptr;
223 unsigned long value;
224
225 err = parse_common_args(shell, argv, &dev, &channel);
226 if (err < 0) {
227 return err;
228 }
229
230 value = strtoul(argv[arg_idx_value], &end_ptr, 0);
231 if (*end_ptr != '\0') {
232 shell_error(shell, "Invalid channel value parameter %s",
233 argv[arg_idx_value]);
234 return -EINVAL;
235 }
236 if (value > 255) {
237 shell_error(shell, "Invalid channel value %d (max 255)",
238 value);
239 return -EINVAL;
240 }
241
242 shell_print(shell, "%s: setting channel %d to %d",
243 dev->name, channel, value);
244
245 err = led_set_channel(dev, channel, (uint8_t) value);
246 if (err) {
247 shell_error(shell, "Error: %d", err);
248 }
249
250 return err;
251 }
252
253 static int
cmd_write_channels(const struct shell * shell,size_t argc,char ** argv)254 cmd_write_channels(const struct shell *shell, size_t argc, char **argv)
255 {
256 const struct device *dev;
257 uint32_t start_channel;
258 int err;
259 size_t num_channels;
260 uint8_t i;
261 uint8_t value[MAX_CHANNEL_ARGS];
262
263 err = parse_common_args(shell, argv, &dev, &start_channel);
264 if (err < 0) {
265 return err;
266 }
267
268 num_channels = argc - arg_idx_value;
269 if (num_channels > MAX_CHANNEL_ARGS) {
270 shell_error(shell,
271 "Can't write %d channels (max %d)",
272 num_channels, MAX_CHANNEL_ARGS);
273 return -EINVAL;
274 }
275
276 for (i = 0; i < num_channels; i++) {
277 char *end_ptr;
278 unsigned long val;
279
280 val = strtoul(argv[arg_idx_value + i], &end_ptr, 0);
281 if (*end_ptr != '\0') {
282 shell_error(shell,
283 "Invalid channel value parameter %s",
284 argv[arg_idx_value + i]);
285 return -EINVAL;
286 }
287 if (val > 255) {
288 shell_error(shell,
289 "Invalid channel value %d (max 255)", val);
290 return -EINVAL;
291 }
292 value[i] = val;
293 }
294
295 shell_fprintf(shell, SHELL_NORMAL, "%s: writing from channel %d: %d",
296 dev->name, start_channel, value[0]);
297 for (i = 1; i < num_channels; i++) {
298 shell_fprintf(shell, SHELL_NORMAL, " %d", value[i]);
299 }
300 shell_fprintf(shell, SHELL_NORMAL, "\n");
301
302 err = led_write_channels(dev, start_channel, num_channels, value);
303 if (err) {
304 shell_error(shell, "Error: %d", err);
305 }
306
307 return err;
308 }
309
310 SHELL_STATIC_SUBCMD_SET_CREATE(sub_led,
311 SHELL_CMD_ARG(off, NULL, "<device> <led>", cmd_off, 3, 0),
312 SHELL_CMD_ARG(on, NULL, "<device> <led>", cmd_on, 3, 0),
313 SHELL_CMD_ARG(get_info, NULL, "<device> <led>", cmd_get_info, 3, 0),
314 SHELL_CMD_ARG(set_brightness, NULL, "<device> <led> <value [0-255]>",
315 cmd_set_brightness, 4, 0),
316 SHELL_CMD_ARG(set_color, NULL,
317 "<device> <led> <color 0 [0-255]> ... <color N>",
318 cmd_set_color, 4, MAX_CHANNEL_ARGS - 1),
319 SHELL_CMD_ARG(set_channel, NULL, "<device> <channel> <value [0-255]>",
320 cmd_set_channel, 4, 0),
321 SHELL_CMD_ARG(write_channels, NULL,
322 "<device> <chan> <value 0 [0-255]> ... <value N>",
323 cmd_write_channels, 4, MAX_CHANNEL_ARGS - 1),
324 SHELL_SUBCMD_SET_END
325 );
326
327 SHELL_CMD_REGISTER(led, &sub_led, "LED commands", NULL);
328