Changes between Version 99 and Version 100 of gsc


Ignore:
Timestamp:
04/12/2022 09:13:18 PM (4 months ago)
Author:
Tim Harvey
Comment:

updated code example for a Linux Input Event

Legend:

Unmodified
Added
Removed
Modified
  • gsc

    v99 v100  
    671671  * please see [#IRQ_GPIO_CHANGE here] regarding un-terminated inputs causing spurious GPIO_CHANGE events
    672672
    673 The gpio-keys kernel driver will produce Linux Input events for the above interrupts.
     673The gpio-keys kernel driver will produce Linux Input events for the above interrupts. This is configured in the board device-tree and maps the pushbutton GPIO to a BTN_0 event such that when the button is down the value will be 1 and up will be 0.
     674
    674675
    675676In addition, the user pushbutton state is available on a GPIO in case you need to do anything more flexible than the above built-in interrupt functionality:
     
    709710
    710711
    711 === Code Examples for software user pushbutton detection ===
    712 The following example will configure the GSC for SW pushbutton interrupt and read the PB state by polling the GPIO (see above):
    713 {{{
    714 #!bash
    715 # clear R0.1 bit to disable pushbutton hard reset - taking care to not disturb other bits
    716 R0=$(i2cget -f -y 0 0x20 0) && \
    717   R0=$((R0 & ~0x01)) && \
    718   i2cset -f -y 0 0x20 0 $R0 || echo i2c error
    719 # export gpio240 to userspace (Note this value is board specific - see above table)
    720 # If using mainline BSP with different GPIO ranges "cat /sys/kernel/gpio" look for pca9555 emulated over i2c, if Ventana use lowest number in range, if Newport use lowest number in range + 2
    721 echo 240 > /sys/class/gpio/export
    722 while [ 1 ]; do
    723   cat /sys/class/gpio/gpio240/value ;# PB state 0 or 1
    724 done
    725 }}}
    726 
    727 A more appropriate method of detection may be to use the fact that the GSC has interrupt support and use the libc {{{poll(2)}}} function to block on the GPIO until it changes state. See [wiki:gpio#catchingagpiochangefromuserspacewithoutpolling Catching a GPIO from Userspace w/o polling] for an example of how to do that.
     712=== Code Example for software user pushbutton detection ===
     713The following code example shows how to watch for a Linux Input event of BTN_0 for the gpio-keys driver:
     714{{{
     715#include <fcntl.h>
     716#include <poll.h>
     717#include <stdio.h>
     718#include <stdlib.h>
     719#include <string.h>
     720#include <time.h>
     721#include <unistd.h>
     722#include <linux/input.h>
     723
     724int main(int argc, char *argv[])
     725{
     726        const char *dev = "/dev/input/by-path/platform-gpio-keys-event";
     727        int report_sec = 5; /* seconds between report held activity */
     728        struct input_event ie, last_ie; /* input event tracking */
     729        int timeout_sec = 1; /* poll period */
     730        int report = 0; /* last report time */
     731        int count = 0; /* successive click counter */
     732        struct pollfd fdset;
     733        int fd;
     734
     735        /* open input device for gpio-keys */
     736        if ((fd = open(dev, O_RDONLY)) == -1) {
     737                perror("opening device");
     738                exit(EXIT_FAILURE);
     739        }
     740
     741        last_ie.time.tv_sec = time(NULL);
     742        report = time(NULL);
     743        while (1) {
     744                /* use poll to block for timeout_sec seconds */
     745                fdset.fd = fd;
     746                fdset.events = POLLIN;
     747                fdset.revents = 0;
     748                if (poll(&fdset, 1, timeout_sec * 1000) == -1) {
     749                        perror("poll");
     750                        exit(EXIT_FAILURE);
     751                }
     752
     753                /* if we have a button event - capture it */
     754                if (fdset.revents == POLLIN) {
     755                        read(fd, &ie, sizeof(struct input_event));
     756                        if (ie.type == EV_KEY && ie.code == BTN_0) {
     757                                memcpy(&last_ie, &ie, sizeof(ie));
     758                                report = 0;
     759                                /* increment click count on up */
     760                                if (!ie.value)
     761                                        count++;
     762                        }
     763                }
     764
     765                /* if no state change in more than 1s reset click count */
     766                if ((time(NULL) - last_ie.time.tv_sec) > 1) {
     767                        count = 0;
     768                        report = 0;
     769                }
     770
     771                /* if time to report */
     772                if ((time(NULL) - report) >= report_sec) {
     773                        fprintf(stderr,
     774                                "%d: %s for %d secs\n", count,
     775                                last_ie.value ? "down" : "up",
     776                                (int) (time(NULL) - last_ie.time.tv_sec));
     777                        report = time(NULL);
     778                }
     779        }
     780
     781        close(fd);
     782
     783        return EXIT_SUCCESS;
     784}
     785
     786}}}
     787 * poll() is used with a timeout of 1s to simplify the tracking of time
     788 * we are only interested above in BTN_0 events from {{{/dev/input/by-path/platform-gpio-keys-event}}} which coorespond to a change in user pushbutton
     789 * you most likely want to clear R0.1 to disable hard reset on a 1x quick-press-and-release if using the above
     790 * we increment a click counter if the button state change occured within 1 second of the last
     791 * each time a button up/down event occurs the current click count and state will be displayed
     792 * when button state has not changed in 5 seconds (report_sec) the a message will show the current button state and seconds it has been in that state; this could be used to mean 'held (up or down) for <report_sec>' time if you want to catch a hold event
    728793
    729794See also: