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 === |
| 713 | The 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 | |
| 724 | int 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 |