0

I have developped a C program for my embedded Board. This program make the green LED lights on when I push and release the BUTTON.

The green LED is defined under "/sys/class/leds" and the BUTTON is under "/dev/input/event0".

This is the code :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>

#include <linux/input.h>

#define BTN_FILE_PATH "/dev/input/event0"
#define LED_PATH "/sys/class/leds"

#define green "green"

void change_led_state(char *led_path, int led_value)
{
    char    lpath[64];
    FILE    *led_fd;

    strncpy(lpath, led_path, sizeof(lpath) - 1);
    lpath[sizeof(lpath) - 1] = '\0';

    led_fd = fopen(lpath, "w");

    if (led_fd == NULL) {
        fprintf(stderr, "simplekey: unable to access led\n");
        return;
    }

    fprintf(led_fd, "%d\n", led_value);

    fclose(led_fd);
}

void reset_leds(void)
{

    change_led_state(LED_PATH "/" green "/brightness", 0);
}

int configure_leds(void)
{
    FILE    *l_fd;
    FILE    *r_fd;
    char    *none_str = "none";

    /* Configure leds for hand control */

    r_fd = fopen(LED_PATH "/" green "/trigger", "w");




    fprintf(r_fd, "%s\n", none_str);


    fclose(r_fd);


    /* Switch off leds */
    reset_leds();

    return 0;
}

void eval_keycode(int code)
{

    static int green_state = 0;

    switch (code) {
    case 260:
        printf("BTN pressed\n");

        /* figure out green state */

        green_state = green_state ? 0 : 1;

        change_led_state(LED_PATH "/" green "/brightness", green_state);
        break;
    }
}


int main(void)
{
    int file;
    /* how many bytes were read */
    size_t  rb;
    int ret;
    int yalv;
    /* the events (up to 64 at once) */
    struct input_event  ev[64];
    char    *str = BTN_FILE_PATH;

    printf("Starting simplekey app\n");

    ret = configure_leds();
    if (ret < 0)
        exit(1);

    printf("File Path: %s\n", str);

    if((file = open(str, O_RDONLY)) < 0) {
        perror("simplekey: File can not open");
        exit(1);
    }

    for (;;) {
        /* Blocking read */
        rb= read(file, &ev, sizeof(ev));


        for (yalv = 0;
            yalv < (int) (rb / sizeof(struct input_event));
            yalv++) {
            if (ev[yalv].type == EV_KEY) {

                /* Change state on button pressed */
                if (ev[yalv].value == 0)
                    eval_keycode(ev[yalv].code);
            }
        }
    }

    close(file);
    reset_leds();
    exit(0);
}

The compilation is going well.

When I execute the code it shows me this :

Starting simplekey app
File Path: /dev/input/event0

When I push the BUTTON nothing happens and when I release it the LED changes state and it shows me this in the terminal :

BTN pressed

The problem is that the code continue executing until I press CTRL+C to exit.

I just want it to wait until the event ( pressing BUTTON ) happens then change LED state and finally exit automatically.

My question is how to modify the program for this purpose ? I thought about using Threads and Signals but I don't have any idea about them. Thank you!

gaston
  • 405
  • 5
  • 22
  • add `break;` right before the closing brace ... `for (;;) { /* ... */ break; }` – pmg Oct 17 '19 at 09:32
  • I added break; before closing the for ( ; ; ) brace, but this does not work. When I push the BUTTON it exits from the loop without changing the LED state and without printing " BTN pressed " – gaston Oct 17 '19 at 09:42
  • 1
    Use a debugger to trace step-by-step to see where the program behavior deviates from your expectations. – Ruslan Oct 17 '19 at 09:43
  • What about adding `if (ev[yalv].code == 260) break;` inside the inner loop? – pmg Oct 17 '19 at 09:44
  • @pmg I added this line before closing the for ( ; ; ) brace but this works like my first code .. it changes LED state but exit until I press CTRL+C – gaston Oct 17 '19 at 09:54

1 Answers1

0

I presume you are running all this under a system complying either SVr4, or 4.3BSD ot POSIX.1-2001 (or later versions).

You are missing the the check on the read() return value, which is not size_t but rather ssize_t (that is it is signed).

Your code could then be changed like this:

/* ... */
    ssize_t  rb; /* !!! */
/* ... */
for (;;) {
        /* Blocking read */
        rb= read(file, &ev, sizeof(ev));
        if (rb <= 0) /* Check for the EOF */
          break;

        for (yalv = 0;
            yalv < (int) (rb / sizeof(struct input_event));
            yalv++) {
            if (ev[yalv].type == EV_KEY) {

                /* Change state on button pressed */
                if (ev[yalv].value == 0)
                    eval_keycode(ev[yalv].code);
            }
        }
    }

Please, refer to the friendly man pages.

EnzoR
  • 3,107
  • 2
  • 22
  • 25
  • This does not make my code exit when I press the button and the led changes state – gaston Oct 17 '19 at 10:04
  • Then you need to provide full details about the hosting machine, how the BUTTON is interfaced to the systems etc. – EnzoR Oct 31 '19 at 07:38