summaryrefslogtreecommitdiffstats
path: root/drivers/led/led-triggers.c
blob: cba94d54617d31583dbb84c75e93fef64e49e0dd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * LED trigger support for barebox
 *
 * (C) Copyright 2010 Sascha Hauer, Pengutronix
 */

#include <common.h>
#include <poller.h>
#include <errno.h>
#include <clock.h>
#include <led.h>
#include <init.h>

/**
 * @file
 * @brief LED trigger framework
 *
 * This file contains triggers which can be associated to LEDs.
 *
 * With this framework LEDs can be associated to different events.
 * An event can be a heartbeat, network activity or panic.
 * led_trigger() is the central function which is called in the
 * different barebox frameworks to trigger an event.
 *
 * currently there are the following triggers are defined:
 *
 * led_trigger_panic:		triggered in panic()
 * led_trigger_heartbeat:	shows the heartbeat of barebox. Blinks as long
 *				barebox is up and running.
 * led_trigger_net_rx:		Triggered during network packet reception
 * led_trigger_net_tx:		Triggered during network packet transmission
 * led_trigger_net_txrx:	combination of the two above
 */

struct led_trigger_struct {
	struct led *led;
	struct list_head list;
	enum led_trigger trigger;
};

static LIST_HEAD(led_triggers);

/**
 * led_trigger - triggers a trigger
 * @param trigger	The trigger to enable/disable
 * @param enable	true if enable
 *
 * Enable/disable a LED for a given trigger.
 */
void led_trigger(enum led_trigger trigger, enum trigger_type type)
{
	struct led_trigger_struct *led_trigger;

	if (trigger >= LED_TRIGGER_MAX)
		return;

	list_for_each_entry(led_trigger, &led_triggers, list) {
		if (led_trigger->trigger != trigger)
			continue;

		switch (type) {
		case TRIGGER_FLASH:
			led_flash(led_trigger->led, 200);
			break;
		case TRIGGER_ENABLE:
			led_set(led_trigger->led, led_trigger->led->max_value);
			break;
		case TRIGGER_DISABLE:
			led_set(led_trigger->led, 0);
			break;
		}
	}
}

static struct led_trigger_struct *led_find_trigger(struct led *led)
{
	struct led_trigger_struct *led_trigger;

	list_for_each_entry(led_trigger, &led_triggers, list)
		if (led_trigger->led == led)
			return led_trigger;

	return NULL;
}

void led_trigger_disable(struct led *led)
{
	struct led_trigger_struct *led_trigger;

	led_trigger = led_find_trigger(led);
	if (!led_trigger)
		return;

	list_del(&led_trigger->list);

	led_set(led, 0);

	free(led_trigger);
}

/**
 * led_set_trigger - set the LED for a trigger
 * @param trigger	The trigger to set a LED for
 * @param led		The LED
 *
 * This function associates a trigger with a LED. Pass led = NULL
 * to disable a trigger
 */
int led_set_trigger(enum led_trigger trigger, struct led *led)
{
	struct led_trigger_struct *led_trigger;

	if (trigger >= LED_TRIGGER_MAX)
		return -EINVAL;

	led_trigger_disable(led);

	led_trigger = xzalloc(sizeof(*led_trigger));

	led_trigger->led = led;
	led_trigger->trigger = trigger;
	list_add_tail(&led_trigger->list, &led_triggers);

	if (trigger == LED_TRIGGER_DEFAULT_ON)
		led_set(led, led->max_value);
	if (trigger == LED_TRIGGER_HEARTBEAT)
		led_blink(led, 200, 1000);

	return 0;
}

/**
 * led_triggers_show_info - Show information about all registered
 * triggers
 */
void led_triggers_show_info(void)
{
	struct led_trigger_struct *led_trigger;
	int i;

	for (i = 0; i < LED_TRIGGER_MAX; i++) {
		printf("%s", trigger_name(i));

		list_for_each_entry(led_trigger, &led_triggers, list) {
			struct led *led = led_trigger->led;

			if (led_trigger->trigger != i)
				continue;

			printf("\n  LED %d (%s)", led->num, led->name);
		}

		printf("\n");
	}
}