diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-20 17:31:23 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-20 17:31:23 -0800 |
commit | 7aa7d608112baf63a0b1278955f9619427373807 (patch) | |
tree | b6a7ed4233ddf3a6760bd72aed93d4b83b1f7c45 /tools | |
parent | 85adbcd54f0982040c8cc7a086f01554b8f64427 (diff) | |
parent | fb3d769173d26268d7bf068094a599bb28b2ac63 (diff) |
Merge tag 'leds_for_4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds
Pull LED updates from Jacek Anaszewski:
"New features and improvements:
- add new optional brightness_hw_changed attribute for the LEDs that
may have their brightness level changed autonomously (outside of
kernel control) by hardware / firmware. The attribute supports
userspace notifications through POLLPRI events
- add led_brightness_hw_mon tool that demonstrates how to use the
aforementioned feature
- add LED_ON enum for LEDs that can be only turned on/off, and don't
allow setting other brightness levels
- allow for adjusting heartbeat trigger blink brightness level
Fixes and cleanups:
- avoid harmless maybe-uninitialized warning in leds-ktd2692.c
- add context to the existing example entries in common LED bindings
to make the documentation more clear"
* tag 'leds_for_4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds:
leds: ledtrig-heartbeat: Make top brightness adjustable
tools/leds: Add led_hw_brightness_mon program
leds: class: Add new optional brightness_hw_changed attribute
leds: ktd2692: avoid harmless maybe-uninitialized warning
leds: add LED_ON brightness as boolean value
DT: leds: Improve examples by adding some context
Diffstat (limited to 'tools')
-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 @@ CC = $(CROSS_COMPILE)gcc CFLAGS = -Wall -Wextra -g -I../../include/uapi -all: uledmon +all: uledmon led_hw_brightness_mon %: %.c $(CC) $(CFLAGS) -o $@ $^ clean: - $(RM) uledmon + $(RM) uledmon led_hw_brightness_mon .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 @@ +/* + * led_hw_brightness_mon.c + * + * This program monitors LED brightness level changes having its origin + * in hardware/firmware, i.e. outside of kernel control. + * A timestamp and brightness value is printed each time the brightness changes. + * + * Usage: led_hw_brightness_mon <device-name> + * + * <device-name> is the name of the LED class device to be monitored. Pressing + * CTRL+C will exit. + */ + +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <linux/uleds.h> + +int main(int argc, char const *argv[]) +{ + int fd, ret; + char brightness_file_path[LED_MAX_NAME_SIZE + 11]; + struct pollfd pollfd; + struct timespec ts; + char buf[11]; + + if (argc != 2) { + fprintf(stderr, "Requires <device-name> argument\n"); + return 1; + } + + snprintf(brightness_file_path, LED_MAX_NAME_SIZE, + "/sys/class/leds/%s/brightness_hw_changed", argv[1]); + + fd = open(brightness_file_path, O_RDONLY); + if (fd == -1) { + printf("Failed to open %s file\n", brightness_file_path); + return 1; + } + + /* + * read may fail if no hw brightness change has occurred so far, + * but it is required to avoid spurious poll notifications in + * the opposite case. + */ + read(fd, buf, sizeof(buf)); + + pollfd.fd = fd; + pollfd.events = POLLPRI; + + while (1) { + ret = poll(&pollfd, 1, -1); + if (ret == -1) { + printf("Failed to poll %s file (%d)\n", + brightness_file_path, ret); + ret = 1; + break; + } + + clock_gettime(CLOCK_MONOTONIC, &ts); + + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) + break; + + ret = lseek(pollfd.fd, 0, SEEK_SET); + if (ret < 0) { + printf("lseek failed (%d)\n", ret); + break; + } + + printf("[%ld.%09ld] %d\n", ts.tv_sec, ts.tv_nsec, atoi(buf)); + } + + close(fd); + + return ret; +} |