diff options
author | Jacek Anaszewski <jacek.anaszewski@gmail.com> | 2017-01-29 06:52:31 -0500 |
---|---|---|
committer | Jacek Anaszewski <jacek.anaszewski@gmail.com> | 2017-02-14 16:20:23 -0500 |
commit | ae3473231e77a3f1909d48cd144cebe5e1d049b3 (patch) | |
tree | 8541d32cc0a4e7b426bb1b962de504fd1f0e02fc | |
parent | 0cb8eb30d425d2d2ae28ab630596c44a158784c4 (diff) |
tools/leds: Add led_hw_brightness_mon program
LED subsystem supports POLLPRI on "brightness_hw_changed" sysfs file
of LED class devices. This tool demonstrates how to use the feature.
Signed-off-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
-rw-r--r-- | tools/leds/Makefile | 4 | ||||
-rw-r--r-- | tools/leds/led_hw_brightness_mon.c | 84 |
2 files changed, 86 insertions, 2 deletions
diff --git a/tools/leds/Makefile b/tools/leds/Makefile index c03a79ebf9c8..078b666fd78b 100644 --- a/tools/leds/Makefile +++ b/tools/leds/Makefile | |||
@@ -3,11 +3,11 @@ | |||
3 | CC = $(CROSS_COMPILE)gcc | 3 | CC = $(CROSS_COMPILE)gcc |
4 | CFLAGS = -Wall -Wextra -g -I../../include/uapi | 4 | CFLAGS = -Wall -Wextra -g -I../../include/uapi |
5 | 5 | ||
6 | all: uledmon | 6 | all: uledmon led_hw_brightness_mon |
7 | %: %.c | 7 | %: %.c |
8 | $(CC) $(CFLAGS) -o $@ $^ | 8 | $(CC) $(CFLAGS) -o $@ $^ |
9 | 9 | ||
10 | clean: | 10 | clean: |
11 | $(RM) uledmon | 11 | $(RM) uledmon led_hw_brightness_mon |
12 | 12 | ||
13 | .PHONY: all clean | 13 | .PHONY: all clean |
diff --git a/tools/leds/led_hw_brightness_mon.c b/tools/leds/led_hw_brightness_mon.c new file mode 100644 index 000000000000..64642ccfe442 --- /dev/null +++ b/tools/leds/led_hw_brightness_mon.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * led_hw_brightness_mon.c | ||
3 | * | ||
4 | * This program monitors LED brightness level changes having its origin | ||
5 | * in hardware/firmware, i.e. outside of kernel control. | ||
6 | * A timestamp and brightness value is printed each time the brightness changes. | ||
7 | * | ||
8 | * Usage: led_hw_brightness_mon <device-name> | ||
9 | * | ||
10 | * <device-name> is the name of the LED class device to be monitored. Pressing | ||
11 | * CTRL+C will exit. | ||
12 | */ | ||
13 | |||
14 | #include <errno.h> | ||
15 | #include <fcntl.h> | ||
16 | #include <poll.h> | ||
17 | #include <stdio.h> | ||
18 | #include <stdlib.h> | ||
19 | #include <string.h> | ||
20 | #include <time.h> | ||
21 | #include <unistd.h> | ||
22 | |||
23 | #include <linux/uleds.h> | ||
24 | |||
25 | int main(int argc, char const *argv[]) | ||
26 | { | ||
27 | int fd, ret; | ||
28 | char brightness_file_path[LED_MAX_NAME_SIZE + 11]; | ||
29 | struct pollfd pollfd; | ||
30 | struct timespec ts; | ||
31 | char buf[11]; | ||
32 | |||
33 | if (argc != 2) { | ||
34 | fprintf(stderr, "Requires <device-name> argument\n"); | ||
35 | return 1; | ||
36 | } | ||
37 | |||
38 | snprintf(brightness_file_path, LED_MAX_NAME_SIZE, | ||
39 | "/sys/class/leds/%s/brightness_hw_changed", argv[1]); | ||
40 | |||
41 | fd = open(brightness_file_path, O_RDONLY); | ||
42 | if (fd == -1) { | ||
43 | printf("Failed to open %s file\n", brightness_file_path); | ||
44 | return 1; | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * read may fail if no hw brightness change has occurred so far, | ||
49 | * but it is required to avoid spurious poll notifications in | ||
50 | * the opposite case. | ||
51 | */ | ||
52 | read(fd, buf, sizeof(buf)); | ||
53 | |||
54 | pollfd.fd = fd; | ||
55 | pollfd.events = POLLPRI; | ||
56 | |||
57 | while (1) { | ||
58 | ret = poll(&pollfd, 1, -1); | ||
59 | if (ret == -1) { | ||
60 | printf("Failed to poll %s file (%d)\n", | ||
61 | brightness_file_path, ret); | ||
62 | ret = 1; | ||
63 | break; | ||
64 | } | ||
65 | |||
66 | clock_gettime(CLOCK_MONOTONIC, &ts); | ||
67 | |||
68 | ret = read(fd, buf, sizeof(buf)); | ||
69 | if (ret < 0) | ||
70 | break; | ||
71 | |||
72 | ret = lseek(pollfd.fd, 0, SEEK_SET); | ||
73 | if (ret < 0) { | ||
74 | printf("lseek failed (%d)\n", ret); | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | printf("[%ld.%09ld] %d\n", ts.tv_sec, ts.tv_nsec, atoi(buf)); | ||
79 | } | ||
80 | |||
81 | close(fd); | ||
82 | |||
83 | return ret; | ||
84 | } | ||