blob: bdfb16c0e098820f9f1c0a0cbe9853d5fafa782c [file] [log] [blame]
Simon Glassfc8a5292017-04-10 11:34:59 -06001/*
2 * Copyright (c) 2017 Google, Inc
3 * Written by Simon Glass <sjg@chromium.org>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <command.h>
10#include <dm.h>
11#include <led.h>
12#include <dm/uclass-internal.h>
13
14#define LED_TOGGLE LEDST_COUNT
15
16static const char *const state_label[] = {
17 [LEDST_OFF] = "off",
18 [LEDST_ON] = "on",
19 [LEDST_TOGGLE] = "toggle",
20#ifdef CONFIG_LED_BLINK
21 [LEDST_BLINK] = "blink",
22#endif
23};
24
25enum led_state_t get_led_cmd(char *var)
26{
27 int i;
28
29 for (i = 0; i < LEDST_COUNT; i++) {
30 if (!strncmp(var, state_label[i], strlen(var)))
31 return i;
32 }
33
34 return -1;
35}
36
37static int show_led_state(struct udevice *dev)
38{
39 int ret;
40
41 ret = led_get_state(dev);
42 if (ret >= LEDST_COUNT)
43 ret = -EINVAL;
44 if (ret >= 0)
45 printf("%s\n", state_label[ret]);
46
47 return ret;
48}
49
50static int list_leds(void)
51{
52 struct udevice *dev;
53 int ret;
54
55 for (uclass_find_first_device(UCLASS_LED, &dev);
56 dev;
57 uclass_find_next_device(&dev)) {
58 struct led_uc_plat *plat = dev_get_uclass_platdata(dev);
59
60 if (!plat->label)
61 continue;
62 printf("%-15s ", plat->label);
63 if (device_active(dev)) {
64 ret = show_led_state(dev);
65 if (ret < 0)
66 printf("Error %d\n", ret);
67 } else {
68 printf("<inactive>\n");
69 }
70 }
71
72 return 0;
73}
74
75int do_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
76{
77 enum led_state_t cmd;
78 const char *led_label;
79 struct udevice *dev;
80#ifdef CONFIG_LED_BLINK
81 int freq_ms = 0;
82#endif
83 int ret;
84
85 /* Validate arguments */
86 if (argc < 2)
87 return CMD_RET_USAGE;
88 led_label = argv[1];
89 if (*led_label == 'l')
90 return list_leds();
91
92 cmd = argc > 2 ? get_led_cmd(argv[2]) : LEDST_COUNT;
Simon Glassfc8a5292017-04-10 11:34:59 -060093#ifdef CONFIG_LED_BLINK
94 if (cmd == LEDST_BLINK) {
95 if (argc < 4)
96 return CMD_RET_USAGE;
97 freq_ms = simple_strtoul(argv[3], NULL, 10);
98 }
99#endif
100 ret = led_get_by_label(led_label, &dev);
101 if (ret) {
102 printf("LED '%s' not found (err=%d)\n", led_label, ret);
103 return CMD_RET_FAILURE;
104 }
105 switch (cmd) {
106 case LEDST_OFF:
107 case LEDST_ON:
108 case LEDST_TOGGLE:
109 ret = led_set_state(dev, cmd);
110 break;
111#ifdef CONFIG_LED_BLINK
112 case LEDST_BLINK:
113 ret = led_set_period(dev, freq_ms);
114 if (!ret)
115 ret = led_set_state(dev, LEDST_BLINK);
116 break;
117#endif
118 case LEDST_COUNT:
119 printf("LED '%s': ", led_label);
120 ret = show_led_state(dev);
121 break;
122 }
123 if (ret < 0) {
124 printf("LED '%s' operation failed (err=%d)\n", led_label, ret);
125 return CMD_RET_FAILURE;
126 }
127
128 return 0;
129}
130
131#ifdef CONFIG_LED_BLINK
132#define BLINK "|blink [blink-freq in ms]"
133#else
134#define BLINK ""
135#endif
136
137U_BOOT_CMD(
138 led, 4, 1, do_led,
139 "manage LEDs",
140 "<led_label> on|off|toggle" BLINK "\tChange LED state\n"
141 "led [<led_label>\tGet LED state\n"
142 "led list\t\tshow a list of LEDs"
143);