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