Skip to content

Instantly share code, notes, and snippets.

@m-kurbanov
Created October 26, 2022 12:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m-kurbanov/775408521c436a371c3640d49808d08d to your computer and use it in GitHub Desktop.
Save m-kurbanov/775408521c436a371c3640d49808d08d to your computer and use it in GitHub Desktop.
Example for led-trigger-pattern
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <limits.h>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
struct led_pattern {
const char *data;
const char *repeat;
};
static int open_led_attr(const char *led, const char *attr, int flags)
{
char name[PATH_MAX];
int fd;
snprintf(name, sizeof(name), "%s/%s", led, attr);
fd = open(name, flags);
if (fd < 0) {
fprintf(stderr, "Can't open file '%s'. Error %s\n",
name, strerror(errno));
return -1;
}
return fd;
}
static int write_led_attr(const char *led,
const char *attr,
const void *buf,
size_t size)
{
ssize_t n;
int fd;
fd = open_led_attr(led, attr, O_WRONLY);
if (fd < 0)
return fd;
n = write(fd, buf, size);
if (n != size) {
fprintf(stderr, "Can't write to file '%s/%s'. Error %s\n",
led, attr, strerror(errno));
return -EIO;
}
return 0;
}
static int enable_pattern_trigger(const char *led)
{
return write_led_attr(led, "trigger", "pattern", sizeof("pattern") - 1);
}
static bool pattern_ended(int fd)
{
char buf[12] = { 0 };
if (read(fd, buf, sizeof(buf) - 1) < 0) {
perror("read error");
return false;
}
return atoi(buf) == 0;
}
static int write_led_pattern(const char *led, const struct led_pattern *pattern)
{
// clear previous pattern
write_led_attr(led, "pattern", "\n", 1);
write_led_attr(led, "repeat", pattern->repeat, strlen(pattern->repeat));
write_led_attr(led, "pattern", pattern->data, strlen(pattern->data));
return 0;
}
static int write_all_led_pattern(const char *leds[],
size_t n,
const struct led_pattern *pattern)
{
size_t i;
for (i = 0; i < n; i++)
write_led_pattern(leds[i], pattern);
return 0;
}
static int wait_for_all_pattern(const int fds[], size_t n)
{
struct pollfd *pfd;
size_t i;
int ret = 0;
pfd = calloc(n, sizeof(struct pollfd));
if (!pfd)
return -ENOMEM;
while (true) {
size_t n_pfd = 0;
for (i = 0; i < n; i++) {
if (!pattern_ended(fds[i])) {
pfd[n_pfd].fd = fds[i];
pfd[n_pfd].events = POLLPRI;
pfd[n_pfd].revents = 0;
n_pfd++;
}
lseek(fds[i], 0, SEEK_SET);
}
if (!n_pfd)
goto exit1;
if (poll(pfd, n_pfd, -1) == -1) {
perror("Failed to poll\n");
ret = -EIO;
break;
}
}
exit1:
free(pfd);
return ret;
}
static const char *leds[] = {
"/sys/class/leds/red0",
"/sys/class/leds/red1",
"/sys/class/leds/red2",
"/sys/class/leds/red3",
"/sys/class/leds/red4",
};
static const struct led_pattern patterns[] = {
{
.data = "0 1000 255 2000",
.repeat = "1",
},
{
.data = "0 1000 0 0 255 2000 255 0",
.repeat = "1",
},
};
int main(int argc, char *argv[])
{
const size_t nleds = ARRAY_SIZE(leds);
const size_t npatterns = ARRAY_SIZE(patterns);
int fds[nleds];
int ret = 1;
size_t i;
for (i = 0; i < nleds; i++) {
if (enable_pattern_trigger(leds[i]))
return 1;
}
for (i = 0; i < nleds; i++) {
fds[i] = open_led_attr(leds[i], "is_running", O_RDONLY);
if (fds[i] < 0)
goto exit1;
}
for (i = 0; i < npatterns; i++) {
write_all_led_pattern(leds, nleds, &patterns[i]);
wait_for_all_pattern(fds, ARRAY_SIZE(fds));
}
ret = 0;
exit1:
for (i = 0; i < nleds && fds[i] >= 0; i++)
close(fds[i]);
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment