Skip to content
Snippets Groups Projects
led.c 2.64 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * 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;
    #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"
    );