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 } 85