]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - cmd/led.c
dm: led: Add a new 'led' command
[people/ms/u-boot.git] / cmd / led.c
diff --git a/cmd/led.c b/cmd/led.c
new file mode 100644 (file)
index 0000000..84173f8
--- /dev/null
+++ b/cmd/led.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <led.h>
+#include <dm/uclass-internal.h>
+
+#define LED_TOGGLE LEDST_COUNT
+
+static const char *const state_label[] = {
+       [LEDST_OFF]     = "off",
+       [LEDST_ON]      = "on",
+       [LEDST_TOGGLE]  = "toggle",
+#ifdef CONFIG_LED_BLINK
+       [LEDST_BLINK]   = "blink",
+#endif
+};
+
+enum led_state_t get_led_cmd(char *var)
+{
+       int i;
+
+       for (i = 0; i < LEDST_COUNT; i++) {
+               if (!strncmp(var, state_label[i], strlen(var)))
+                       return i;
+       }
+
+       return -1;
+}
+
+static int show_led_state(struct udevice *dev)
+{
+       int ret;
+
+       ret = led_get_state(dev);
+       if (ret >= LEDST_COUNT)
+               ret = -EINVAL;
+       if (ret >= 0)
+               printf("%s\n", state_label[ret]);
+
+       return ret;
+}
+
+static int list_leds(void)
+{
+       struct udevice *dev;
+       int ret;
+
+       for (uclass_find_first_device(UCLASS_LED, &dev);
+            dev;
+            uclass_find_next_device(&dev)) {
+               struct led_uc_plat *plat = dev_get_uclass_platdata(dev);
+
+               if (!plat->label)
+                       continue;
+               printf("%-15s ", plat->label);
+               if (device_active(dev)) {
+                       ret = show_led_state(dev);
+                       if (ret < 0)
+                               printf("Error %d\n", ret);
+               } else {
+                       printf("<inactive>\n");
+               }
+       }
+
+       return 0;
+}
+
+int do_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       enum led_state_t cmd;
+       const char *led_label;
+       struct udevice *dev;
+#ifdef CONFIG_LED_BLINK
+       int freq_ms = 0;
+#endif
+       int ret;
+
+       /* Validate arguments */
+       if (argc < 2)
+               return CMD_RET_USAGE;
+       led_label = argv[1];
+       if (*led_label == 'l')
+               return list_leds();
+
+       cmd = argc > 2 ? get_led_cmd(argv[2]) : LEDST_COUNT;
+       if (cmd < 0)
+               return CMD_RET_USAGE;
+#ifdef CONFIG_LED_BLINK
+       if (cmd == LEDST_BLINK) {
+               if (argc < 4)
+                       return CMD_RET_USAGE;
+               freq_ms = simple_strtoul(argv[3], NULL, 10);
+       }
+#endif
+       ret = led_get_by_label(led_label, &dev);
+       if (ret) {
+               printf("LED '%s' not found (err=%d)\n", led_label, ret);
+               return CMD_RET_FAILURE;
+       }
+       switch (cmd) {
+       case LEDST_OFF:
+       case LEDST_ON:
+       case LEDST_TOGGLE:
+               ret = led_set_state(dev, cmd);
+               break;
+#ifdef CONFIG_LED_BLINK
+       case LEDST_BLINK:
+               ret = led_set_period(dev, freq_ms);
+               if (!ret)
+                       ret = led_set_state(dev, LEDST_BLINK);
+               break;
+#endif
+       case LEDST_COUNT:
+               printf("LED '%s': ", led_label);
+               ret = show_led_state(dev);
+               break;
+       }
+       if (ret < 0) {
+               printf("LED '%s' operation failed (err=%d)\n", led_label, ret);
+               return CMD_RET_FAILURE;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_LED_BLINK
+#define BLINK "|blink [blink-freq in ms]"
+#else
+#define BLINK ""
+#endif
+
+U_BOOT_CMD(
+       led, 4, 1, do_led,
+       "manage LEDs",
+       "<led_label> on|off|toggle" BLINK "\tChange LED state\n"
+       "led [<led_label>\tGet LED state\n"
+       "led list\t\tshow a list of LEDs"
+);