summaryrefslogtreecommitdiff
path: root/io-module/mts_leds.c
blob: a5cfbbbaa413ccba3d58ca83ea0feb07503f155c (plain)
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
/*
 * Use the code below to control the brightness of the LEDs using
 * Linux LED framework instead of manipulating gpio pins or i2c registers
 * directly in the mts-io module.
 *
 * Usage:
 *
 * # associate a mts-io sysfs entry with the specific LEDs
 * echo led-sig1 > /sys/class/leds/pca955x:0/trigger
 * echo led-sig2 > /sys/class/leds/pca955x:1/trigger
 * echo led-sig3 > /sys/class/leds/pca955x:2/trigger
 *
 * # change the brightness
 * echo 1 > /sys/device/platform/mts-io/led-sig1
 * echo 1 > /sys/device/platform/mts-io/led-sig2
 *
 */

struct mts_led {
	const char label[32];          /* led name exposed by the mts-io kernel module */
	struct led_trigger *trigger;   /* linux led trigger */
};

static struct mts_led *mts_leds = NULL;

/*
 * Find a LED descriptor in mts_leds array by label name
 */
static
struct mts_led *mts_led_by_label(const char *label)
{
	struct mts_led *led = mts_leds;

	while (led && *led->label) {
		if (strcmp(led->label, label) == 0) {
			return led;
		}
		led++;
	}

	log_error("led with %s label is not found", label);

	return NULL;
}

/*
 * Change brightness for Linux LEDs devices
 */
static
void mts_led_set(const struct mts_led *led, int value)
{
	enum led_brightness brightness = LED_OFF;

	if (value != 0) brightness = LED_FULL;

	if (led->trigger) {
		led_trigger_event(led->trigger, brightness);
	}

	/*
	 * Note: there are also led_trigger_blink and led_trigger_blink_oneshot
	 *       functions which can potentially be used
	 */
}

/*
 * Blink one shot
 */
static
void mts_led_blink(const struct mts_led *led,
                   unsigned long *delay_on, unsigned long *delay_off,  int invert)
{
	if (led->trigger) {
		 led_trigger_blink_oneshot(led->trigger, delay_on, delay_off, invert);
	}
}


/*
 * Use the function to get current LED brightness for sysfs entry
 */
static
ssize_t mts_attr_show_led(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	return sprintf(buf, "%d\n", 0);
}

/*
 * Use the function to set LED brightness from sysfs entry
 */
static
ssize_t mts_attr_store_led(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	int value;

	const struct mts_led *led = mts_led_by_label(attr->attr.name);

	if (!led) {
		return -ENODEV;
	}

	if (sscanf(buf, "%i", &value) != 1) {
		return -EINVAL;
	}

	mts_led_set(led, value);

	return count;
}

/*
 * Register a LED trigger for each LED declared in the mts_leds array
 * Use in mts-io startup code.
 */
static
void mts_leds_register(void)
{
	struct mts_led *led = mts_leds;

	while (led && *led->label) {
		log_info("Registering %s led trigger", led->label);
		led_trigger_register_simple(led->label, &led->trigger);
		led++;
	}
}

/*
 * Unregister all registered LED triggers.
 * Use in mts-io cleanup code.
 */
static
void mts_leds_unregister(void)
{
	struct mts_led *led = mts_leds;

	while (led && *led->label) {
		log_info("Unregistering %s led trigger", led->label);
		if (led->trigger) {
			led_trigger_unregister_simple(led->trigger);
			led->trigger = NULL;
		}
		led++;
	}
}