rpi_gpio 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/Gemfile +3 -0
 - data/Gemfile.lock +12 -0
 - data/LICENSE +23 -0
 - data/README.md +122 -0
 - data/Rakefile +3 -0
 - data/ext/rpi_gpio/c_gpio.c +233 -0
 - data/ext/rpi_gpio/c_gpio.h +50 -0
 - data/ext/rpi_gpio/common.c +100 -0
 - data/ext/rpi_gpio/common.h +46 -0
 - data/ext/rpi_gpio/constants.c +61 -0
 - data/ext/rpi_gpio/constants.h +40 -0
 - data/ext/rpi_gpio/cpuinfo.c +88 -0
 - data/ext/rpi_gpio/cpuinfo.h +27 -0
 - data/ext/rpi_gpio/event_gpio.c +556 -0
 - data/ext/rpi_gpio/event_gpio.h +40 -0
 - data/ext/rpi_gpio/extconf.rb +5 -0
 - data/ext/rpi_gpio/rb_gpio.c +405 -0
 - data/ext/rpi_gpio/rb_gpio.h +44 -0
 - data/ext/rpi_gpio/rb_pwm.c +131 -0
 - data/ext/rpi_gpio/rb_pwm.h +40 -0
 - data/ext/rpi_gpio/rpi_gpio.c +45 -0
 - data/ext/rpi_gpio/rpi_gpio.h +28 -0
 - data/ext/rpi_gpio/soft_pwm.c +218 -0
 - data/ext/rpi_gpio/soft_pwm.h +32 -0
 - data/lib/rpi_gpio.so +0 -0
 - metadata +69 -0
 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*
         
     | 
| 
      
 2 
     | 
    
         
            +
            Original code by Ben Croston modified for Ruby by Nick Lowery
         
     | 
| 
      
 3 
     | 
    
         
            +
            (github.com/clockvapor)
         
     | 
| 
      
 4 
     | 
    
         
            +
            Copyright (c) 2014-2015 Nick Lowery
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Copyright (c) 2013-2014 Ben Croston
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy of
         
     | 
| 
      
 9 
     | 
    
         
            +
            this software and associated documentation files (the "Software"), to deal in
         
     | 
| 
      
 10 
     | 
    
         
            +
            the Software without restriction, including without limitation the rights to
         
     | 
| 
      
 11 
     | 
    
         
            +
            use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
         
     | 
| 
      
 12 
     | 
    
         
            +
            of the Software, and to permit persons to whom the Software is furnished to do
         
     | 
| 
      
 13 
     | 
    
         
            +
            so, subject to the following conditions:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 16 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 19 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 20 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 22 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 23 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 24 
     | 
    
         
            +
            SOFTWARE.
         
     | 
| 
      
 25 
     | 
    
         
            +
            */
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            #define PY_PUD_CONST_OFFSET 20
         
     | 
| 
      
 28 
     | 
    
         
            +
            #define PY_EVENT_CONST_OFFSET 30
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            VALUE pwm;
         
     | 
| 
      
 31 
     | 
    
         
            +
            VALUE serial;
         
     | 
| 
      
 32 
     | 
    
         
            +
            VALUE i2c;
         
     | 
| 
      
 33 
     | 
    
         
            +
            VALUE spi;
         
     | 
| 
      
 34 
     | 
    
         
            +
            VALUE unknown;
         
     | 
| 
      
 35 
     | 
    
         
            +
            VALUE rising_edge;
         
     | 
| 
      
 36 
     | 
    
         
            +
            VALUE falling_edge;
         
     | 
| 
      
 37 
     | 
    
         
            +
            VALUE both_edge;
         
     | 
| 
      
 38 
     | 
    
         
            +
            VALUE version;
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            void define_constants(VALUE module);
         
     | 
| 
         @@ -0,0 +1,88 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*
         
     | 
| 
      
 2 
     | 
    
         
            +
            Original code by Ben Croston modified for Ruby by Nick Lowery
         
     | 
| 
      
 3 
     | 
    
         
            +
            (github.com/clockvapor)
         
     | 
| 
      
 4 
     | 
    
         
            +
            Copyright (c) 2014-2015 Nick Lowery
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Copyright (c) 2013-2014 Ben Croston
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy of
         
     | 
| 
      
 9 
     | 
    
         
            +
            this software and associated documentation files (the "Software"), to deal in
         
     | 
| 
      
 10 
     | 
    
         
            +
            the Software without restriction, including without limitation the rights to
         
     | 
| 
      
 11 
     | 
    
         
            +
            use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
         
     | 
| 
      
 12 
     | 
    
         
            +
            of the Software, and to permit persons to whom the Software is furnished to do
         
     | 
| 
      
 13 
     | 
    
         
            +
            so, subject to the following conditions:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 16 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 19 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 20 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 22 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 23 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 24 
     | 
    
         
            +
            SOFTWARE.
         
     | 
| 
      
 25 
     | 
    
         
            +
            */
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            #include <stdio.h>
         
     | 
| 
      
 28 
     | 
    
         
            +
            #include <string.h>
         
     | 
| 
      
 29 
     | 
    
         
            +
            #include "cpuinfo.h"
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            char *get_cpuinfo_revision(char *revision)
         
     | 
| 
      
 32 
     | 
    
         
            +
            {
         
     | 
| 
      
 33 
     | 
    
         
            +
               FILE *fp;
         
     | 
| 
      
 34 
     | 
    
         
            +
               char buffer[1024];
         
     | 
| 
      
 35 
     | 
    
         
            +
               char hardware[1024];
         
     | 
| 
      
 36 
     | 
    
         
            +
               int  rpi_found = 0;
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
               if ((fp = fopen("/proc/cpuinfo", "r")) == NULL)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  return 0;
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
               while(!feof(fp)) {
         
     | 
| 
      
 42 
     | 
    
         
            +
                  fgets(buffer, sizeof(buffer) , fp);
         
     | 
| 
      
 43 
     | 
    
         
            +
                  sscanf(buffer, "Hardware	: %s", hardware);
         
     | 
| 
      
 44 
     | 
    
         
            +
                  if (strcmp(hardware, "BCM2708") == 0)
         
     | 
| 
      
 45 
     | 
    
         
            +
                     rpi_found = 1;
         
     | 
| 
      
 46 
     | 
    
         
            +
                  sscanf(buffer, "Revision	: %s", revision);
         
     | 
| 
      
 47 
     | 
    
         
            +
               }
         
     | 
| 
      
 48 
     | 
    
         
            +
               fclose(fp);
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
               if (!rpi_found)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  revision = NULL;
         
     | 
| 
      
 52 
     | 
    
         
            +
               return revision;
         
     | 
| 
      
 53 
     | 
    
         
            +
            }
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            int get_rpi_revision(void)
         
     | 
| 
      
 56 
     | 
    
         
            +
            {
         
     | 
| 
      
 57 
     | 
    
         
            +
               char raw_revision[1024] = {'\0'};
         
     | 
| 
      
 58 
     | 
    
         
            +
               int len;
         
     | 
| 
      
 59 
     | 
    
         
            +
               char *revision;
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
               if (get_cpuinfo_revision(raw_revision) == NULL)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  return -1;
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
               // get last four characters (ignore preceeding 1000 for overvolt)
         
     | 
| 
      
 65 
     | 
    
         
            +
               len = strlen(raw_revision);
         
     | 
| 
      
 66 
     | 
    
         
            +
               if (len > 4)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  revision = (char *)&raw_revision+len-4;
         
     | 
| 
      
 68 
     | 
    
         
            +
               else
         
     | 
| 
      
 69 
     | 
    
         
            +
                  revision = raw_revision;
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
               if ((strcmp(revision, "0002") == 0) ||
         
     | 
| 
      
 72 
     | 
    
         
            +
                   (strcmp(revision, "0003") == 0))
         
     | 
| 
      
 73 
     | 
    
         
            +
                  return 1;
         
     | 
| 
      
 74 
     | 
    
         
            +
               else if ((strcmp(revision, "0004") == 0) ||
         
     | 
| 
      
 75 
     | 
    
         
            +
                        (strcmp(revision, "0005") == 0) ||
         
     | 
| 
      
 76 
     | 
    
         
            +
                        (strcmp(revision, "0006") == 0) ||
         
     | 
| 
      
 77 
     | 
    
         
            +
                        (strcmp(revision, "0007") == 0) ||
         
     | 
| 
      
 78 
     | 
    
         
            +
                        (strcmp(revision, "0008") == 0) ||
         
     | 
| 
      
 79 
     | 
    
         
            +
                        (strcmp(revision, "0009") == 0) ||
         
     | 
| 
      
 80 
     | 
    
         
            +
                        (strcmp(revision, "000d") == 0) ||
         
     | 
| 
      
 81 
     | 
    
         
            +
                        (strcmp(revision, "000e") == 0) ||
         
     | 
| 
      
 82 
     | 
    
         
            +
                        (strcmp(revision, "000f") == 0))
         
     | 
| 
      
 83 
     | 
    
         
            +
                  return 2;  // revision 2
         
     | 
| 
      
 84 
     | 
    
         
            +
               else if (strcmp(revision, "0011") == 0)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  return 0;  // compute module
         
     | 
| 
      
 86 
     | 
    
         
            +
               else   // assume B+ (0010) or A+ (0012)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  return 3;
         
     | 
| 
      
 88 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*
         
     | 
| 
      
 2 
     | 
    
         
            +
            Original code by Ben Croston modified for Ruby by Nick Lowery
         
     | 
| 
      
 3 
     | 
    
         
            +
            (github.com/clockvapor)
         
     | 
| 
      
 4 
     | 
    
         
            +
            Copyright (c) 2014-2015 Nick Lowery
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Copyright (c) 2013-2014 Ben Croston
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy of
         
     | 
| 
      
 9 
     | 
    
         
            +
            this software and associated documentation files (the "Software"), to deal in
         
     | 
| 
      
 10 
     | 
    
         
            +
            the Software without restriction, including without limitation the rights to
         
     | 
| 
      
 11 
     | 
    
         
            +
            use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
         
     | 
| 
      
 12 
     | 
    
         
            +
            of the Software, and to permit persons to whom the Software is furnished to do
         
     | 
| 
      
 13 
     | 
    
         
            +
            so, subject to the following conditions:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 16 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 19 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 20 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 22 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 23 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 24 
     | 
    
         
            +
            SOFTWARE.
         
     | 
| 
      
 25 
     | 
    
         
            +
            */
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            int get_rpi_revision(void);
         
     | 
| 
         @@ -0,0 +1,556 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*
         
     | 
| 
      
 2 
     | 
    
         
            +
            Original code by Ben Croston modified for Ruby by Nick Lowery
         
     | 
| 
      
 3 
     | 
    
         
            +
            (github.com/clockvapor)
         
     | 
| 
      
 4 
     | 
    
         
            +
            Copyright (c) 2014-2015 Nick Lowery
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Copyright (c) 2013-2014 Ben Croston
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy of
         
     | 
| 
      
 9 
     | 
    
         
            +
            this software and associated documentation files (the "Software"), to deal in
         
     | 
| 
      
 10 
     | 
    
         
            +
            the Software without restriction, including without limitation the rights to
         
     | 
| 
      
 11 
     | 
    
         
            +
            use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
         
     | 
| 
      
 12 
     | 
    
         
            +
            of the Software, and to permit persons to whom the Software is furnished to do
         
     | 
| 
      
 13 
     | 
    
         
            +
            so, subject to the following conditions:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 16 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 19 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 20 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 22 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 23 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 24 
     | 
    
         
            +
            SOFTWARE.
         
     | 
| 
      
 25 
     | 
    
         
            +
            */
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            #include <pthread.h>
         
     | 
| 
      
 28 
     | 
    
         
            +
            #include <sys/epoll.h>
         
     | 
| 
      
 29 
     | 
    
         
            +
            #include <stdio.h>
         
     | 
| 
      
 30 
     | 
    
         
            +
            #include <stdlib.h>
         
     | 
| 
      
 31 
     | 
    
         
            +
            #include <fcntl.h>
         
     | 
| 
      
 32 
     | 
    
         
            +
            #include <unistd.h>
         
     | 
| 
      
 33 
     | 
    
         
            +
            #include <string.h>
         
     | 
| 
      
 34 
     | 
    
         
            +
            #include <sys/time.h>
         
     | 
| 
      
 35 
     | 
    
         
            +
            #include "event_gpio.h"
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            const char *stredge[4] = {"none", "rising", "falling", "both"};
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            struct gpios
         
     | 
| 
      
 40 
     | 
    
         
            +
            {
         
     | 
| 
      
 41 
     | 
    
         
            +
                unsigned int gpio;
         
     | 
| 
      
 42 
     | 
    
         
            +
                int value_fd;
         
     | 
| 
      
 43 
     | 
    
         
            +
                int exported;
         
     | 
| 
      
 44 
     | 
    
         
            +
                int edge;
         
     | 
| 
      
 45 
     | 
    
         
            +
                int initial_thread;
         
     | 
| 
      
 46 
     | 
    
         
            +
                int initial_wait;
         
     | 
| 
      
 47 
     | 
    
         
            +
                int thread_added;
         
     | 
| 
      
 48 
     | 
    
         
            +
                int bouncetime;
         
     | 
| 
      
 49 
     | 
    
         
            +
                unsigned long long lastcall;
         
     | 
| 
      
 50 
     | 
    
         
            +
                struct gpios *next;
         
     | 
| 
      
 51 
     | 
    
         
            +
            };
         
     | 
| 
      
 52 
     | 
    
         
            +
            struct gpios *gpio_list = NULL;
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            // event callbacks
         
     | 
| 
      
 55 
     | 
    
         
            +
            struct callback
         
     | 
| 
      
 56 
     | 
    
         
            +
            {
         
     | 
| 
      
 57 
     | 
    
         
            +
                unsigned int gpio;
         
     | 
| 
      
 58 
     | 
    
         
            +
                void (*func)(unsigned int gpio);
         
     | 
| 
      
 59 
     | 
    
         
            +
                struct callback *next;
         
     | 
| 
      
 60 
     | 
    
         
            +
            };
         
     | 
| 
      
 61 
     | 
    
         
            +
            struct callback *callbacks = NULL;
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            pthread_t threads;
         
     | 
| 
      
 64 
     | 
    
         
            +
            int event_occurred[54] = { 0 };
         
     | 
| 
      
 65 
     | 
    
         
            +
            int thread_running = 0;
         
     | 
| 
      
 66 
     | 
    
         
            +
            int epfd_thread = -1;
         
     | 
| 
      
 67 
     | 
    
         
            +
            int epfd_blocking = -1;
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            /************* /sys/class/gpio functions ************/
         
     | 
| 
      
 70 
     | 
    
         
            +
            int gpio_export(unsigned int gpio)
         
     | 
| 
      
 71 
     | 
    
         
            +
            {
         
     | 
| 
      
 72 
     | 
    
         
            +
                int fd, len;
         
     | 
| 
      
 73 
     | 
    
         
            +
                char str_gpio[3];
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                if ((fd = open("/sys/class/gpio/export", O_WRONLY)) < 0)
         
     | 
| 
      
 76 
     | 
    
         
            +
                   return -1;
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio);
         
     | 
| 
      
 79 
     | 
    
         
            +
                write(fd, str_gpio, len);
         
     | 
| 
      
 80 
     | 
    
         
            +
                close(fd);
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 83 
     | 
    
         
            +
            }
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            int gpio_unexport(unsigned int gpio)
         
     | 
| 
      
 86 
     | 
    
         
            +
            {
         
     | 
| 
      
 87 
     | 
    
         
            +
                int fd, len;
         
     | 
| 
      
 88 
     | 
    
         
            +
                char str_gpio[3];
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                if ((fd = open("/sys/class/gpio/unexport", O_WRONLY)) < 0)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    return -1;
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio);
         
     | 
| 
      
 94 
     | 
    
         
            +
                write(fd, str_gpio, len);
         
     | 
| 
      
 95 
     | 
    
         
            +
                close(fd);
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 98 
     | 
    
         
            +
            }
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
            int gpio_set_direction(unsigned int gpio, unsigned int in_flag)
         
     | 
| 
      
 101 
     | 
    
         
            +
            {
         
     | 
| 
      
 102 
     | 
    
         
            +
                int fd;
         
     | 
| 
      
 103 
     | 
    
         
            +
                char filename[33];
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/direction", gpio);
         
     | 
| 
      
 106 
     | 
    
         
            +
                if ((fd = open(filename, O_WRONLY)) < 0)
         
     | 
| 
      
 107 
     | 
    
         
            +
                    return -1;
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                if (in_flag)
         
     | 
| 
      
 110 
     | 
    
         
            +
                    write(fd, "in", 3);
         
     | 
| 
      
 111 
     | 
    
         
            +
                else
         
     | 
| 
      
 112 
     | 
    
         
            +
                    write(fd, "out", 4);
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                close(fd);
         
     | 
| 
      
 115 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 116 
     | 
    
         
            +
            }
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            int gpio_set_edge(unsigned int gpio, unsigned int edge)
         
     | 
| 
      
 119 
     | 
    
         
            +
            {
         
     | 
| 
      
 120 
     | 
    
         
            +
                int fd;
         
     | 
| 
      
 121 
     | 
    
         
            +
                char filename[28];
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio);
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                if ((fd = open(filename, O_WRONLY)) < 0)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    return -1;
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                write(fd, stredge[edge], strlen(stredge[edge]) + 1);
         
     | 
| 
      
 129 
     | 
    
         
            +
                close(fd);
         
     | 
| 
      
 130 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 131 
     | 
    
         
            +
            }
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
            int open_value_file(unsigned int gpio)
         
     | 
| 
      
 134 
     | 
    
         
            +
            {
         
     | 
| 
      
 135 
     | 
    
         
            +
                int fd;
         
     | 
| 
      
 136 
     | 
    
         
            +
                char filename[29];
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                // create file descriptor of value file
         
     | 
| 
      
 139 
     | 
    
         
            +
                snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", gpio);
         
     | 
| 
      
 140 
     | 
    
         
            +
                if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0)
         
     | 
| 
      
 141 
     | 
    
         
            +
                    return -1;
         
     | 
| 
      
 142 
     | 
    
         
            +
                return fd;
         
     | 
| 
      
 143 
     | 
    
         
            +
            }
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
            /********* gpio list functions **********/
         
     | 
| 
      
 146 
     | 
    
         
            +
            struct gpios *get_gpio(unsigned int gpio)
         
     | 
| 
      
 147 
     | 
    
         
            +
            {
         
     | 
| 
      
 148 
     | 
    
         
            +
                struct gpios *g = gpio_list;
         
     | 
| 
      
 149 
     | 
    
         
            +
                while (g != NULL) {
         
     | 
| 
      
 150 
     | 
    
         
            +
                    if (g->gpio == gpio)
         
     | 
| 
      
 151 
     | 
    
         
            +
                        return g;
         
     | 
| 
      
 152 
     | 
    
         
            +
                    g = g->next;
         
     | 
| 
      
 153 
     | 
    
         
            +
                }
         
     | 
| 
      
 154 
     | 
    
         
            +
                return NULL;
         
     | 
| 
      
 155 
     | 
    
         
            +
            }
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
            struct gpios *get_gpio_from_value_fd(int fd)
         
     | 
| 
      
 158 
     | 
    
         
            +
            {
         
     | 
| 
      
 159 
     | 
    
         
            +
                struct gpios *g = gpio_list;
         
     | 
| 
      
 160 
     | 
    
         
            +
                while (g != NULL) {
         
     | 
| 
      
 161 
     | 
    
         
            +
                    if (g->value_fd == fd)
         
     | 
| 
      
 162 
     | 
    
         
            +
                       return g;
         
     | 
| 
      
 163 
     | 
    
         
            +
                    g = g->next;
         
     | 
| 
      
 164 
     | 
    
         
            +
                }
         
     | 
| 
      
 165 
     | 
    
         
            +
                return NULL;
         
     | 
| 
      
 166 
     | 
    
         
            +
            }
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
            struct gpios *new_gpio(unsigned int gpio)
         
     | 
| 
      
 169 
     | 
    
         
            +
            {
         
     | 
| 
      
 170 
     | 
    
         
            +
                struct gpios *new_gpio;
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                new_gpio = malloc(sizeof(struct gpios));
         
     | 
| 
      
 173 
     | 
    
         
            +
                if (new_gpio == 0)
         
     | 
| 
      
 174 
     | 
    
         
            +
                    return NULL;  // out of memory
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                new_gpio->gpio = gpio;
         
     | 
| 
      
 177 
     | 
    
         
            +
                if (gpio_export(gpio) != 0) {
         
     | 
| 
      
 178 
     | 
    
         
            +
                    free(new_gpio);
         
     | 
| 
      
 179 
     | 
    
         
            +
                    return NULL;
         
     | 
| 
      
 180 
     | 
    
         
            +
                }
         
     | 
| 
      
 181 
     | 
    
         
            +
                new_gpio->exported = 1;
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                if (gpio_set_direction(gpio,1) != 0) { // 1==input
         
     | 
| 
      
 184 
     | 
    
         
            +
                    free(new_gpio);
         
     | 
| 
      
 185 
     | 
    
         
            +
                    return NULL;
         
     | 
| 
      
 186 
     | 
    
         
            +
                }
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                if ((new_gpio->value_fd = open_value_file(gpio)) == -1) {
         
     | 
| 
      
 189 
     | 
    
         
            +
                    gpio_unexport(gpio);
         
     | 
| 
      
 190 
     | 
    
         
            +
                    free(new_gpio);
         
     | 
| 
      
 191 
     | 
    
         
            +
                    return NULL;
         
     | 
| 
      
 192 
     | 
    
         
            +
                }
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                new_gpio->initial_thread = 1;
         
     | 
| 
      
 195 
     | 
    
         
            +
                new_gpio->initial_wait = 1;
         
     | 
| 
      
 196 
     | 
    
         
            +
                new_gpio->bouncetime = -666;
         
     | 
| 
      
 197 
     | 
    
         
            +
                new_gpio->lastcall = 0;
         
     | 
| 
      
 198 
     | 
    
         
            +
                new_gpio->thread_added = 0;
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                if (gpio_list == NULL) {
         
     | 
| 
      
 201 
     | 
    
         
            +
                    new_gpio->next = NULL;
         
     | 
| 
      
 202 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 203 
     | 
    
         
            +
                    new_gpio->next = gpio_list;
         
     | 
| 
      
 204 
     | 
    
         
            +
                }
         
     | 
| 
      
 205 
     | 
    
         
            +
                gpio_list = new_gpio;
         
     | 
| 
      
 206 
     | 
    
         
            +
                return new_gpio;
         
     | 
| 
      
 207 
     | 
    
         
            +
            }
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
            void delete_gpio(unsigned int gpio)
         
     | 
| 
      
 210 
     | 
    
         
            +
            {
         
     | 
| 
      
 211 
     | 
    
         
            +
                struct gpios *g = gpio_list;
         
     | 
| 
      
 212 
     | 
    
         
            +
                struct gpios *temp;
         
     | 
| 
      
 213 
     | 
    
         
            +
                struct gpios *prev = NULL;
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                while (g != NULL) {
         
     | 
| 
      
 216 
     | 
    
         
            +
                    if (g->gpio == gpio) {
         
     | 
| 
      
 217 
     | 
    
         
            +
                        if (prev == NULL)
         
     | 
| 
      
 218 
     | 
    
         
            +
                            gpio_list = g->next;
         
     | 
| 
      
 219 
     | 
    
         
            +
                        else
         
     | 
| 
      
 220 
     | 
    
         
            +
                            prev->next = g->next;
         
     | 
| 
      
 221 
     | 
    
         
            +
                        temp = g;
         
     | 
| 
      
 222 
     | 
    
         
            +
                        g = g->next;
         
     | 
| 
      
 223 
     | 
    
         
            +
                        free(temp);
         
     | 
| 
      
 224 
     | 
    
         
            +
                        return;
         
     | 
| 
      
 225 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 226 
     | 
    
         
            +
                        prev = g;
         
     | 
| 
      
 227 
     | 
    
         
            +
                        g = g->next;
         
     | 
| 
      
 228 
     | 
    
         
            +
                    }
         
     | 
| 
      
 229 
     | 
    
         
            +
                }
         
     | 
| 
      
 230 
     | 
    
         
            +
            }
         
     | 
| 
      
 231 
     | 
    
         
            +
             
     | 
| 
      
 232 
     | 
    
         
            +
            int gpio_event_added(unsigned int gpio)
         
     | 
| 
      
 233 
     | 
    
         
            +
            {
         
     | 
| 
      
 234 
     | 
    
         
            +
                struct gpios *g = gpio_list;
         
     | 
| 
      
 235 
     | 
    
         
            +
                while (g != NULL) {
         
     | 
| 
      
 236 
     | 
    
         
            +
                    if (g->gpio == gpio)
         
     | 
| 
      
 237 
     | 
    
         
            +
                        return g->edge;
         
     | 
| 
      
 238 
     | 
    
         
            +
                    g = g->next;
         
     | 
| 
      
 239 
     | 
    
         
            +
                }
         
     | 
| 
      
 240 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 241 
     | 
    
         
            +
            }
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
            /******* callback list functions ********/
         
     | 
| 
      
 244 
     | 
    
         
            +
            int add_edge_callback(unsigned int gpio, void (*func)(unsigned int gpio))
         
     | 
| 
      
 245 
     | 
    
         
            +
            {
         
     | 
| 
      
 246 
     | 
    
         
            +
                struct callback *cb = callbacks;
         
     | 
| 
      
 247 
     | 
    
         
            +
                struct callback *new_cb;
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                new_cb = malloc(sizeof(struct callback));
         
     | 
| 
      
 250 
     | 
    
         
            +
                if (new_cb == 0)
         
     | 
| 
      
 251 
     | 
    
         
            +
                    return -1;  // out of memory
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                new_cb->gpio = gpio;
         
     | 
| 
      
 254 
     | 
    
         
            +
                new_cb->func = func;
         
     | 
| 
      
 255 
     | 
    
         
            +
                new_cb->next = NULL;
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
                if (callbacks == NULL) {
         
     | 
| 
      
 258 
     | 
    
         
            +
                    // start new list
         
     | 
| 
      
 259 
     | 
    
         
            +
                    callbacks = new_cb;
         
     | 
| 
      
 260 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 261 
     | 
    
         
            +
                    // add to end of list
         
     | 
| 
      
 262 
     | 
    
         
            +
                    while (cb->next != NULL)
         
     | 
| 
      
 263 
     | 
    
         
            +
                        cb = cb->next;
         
     | 
| 
      
 264 
     | 
    
         
            +
                    cb->next = new_cb;
         
     | 
| 
      
 265 
     | 
    
         
            +
                }
         
     | 
| 
      
 266 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 267 
     | 
    
         
            +
            }
         
     | 
| 
      
 268 
     | 
    
         
            +
             
     | 
| 
      
 269 
     | 
    
         
            +
            int callback_exists(unsigned int gpio)
         
     | 
| 
      
 270 
     | 
    
         
            +
            {
         
     | 
| 
      
 271 
     | 
    
         
            +
                struct callback *cb = callbacks;
         
     | 
| 
      
 272 
     | 
    
         
            +
                while (cb != NULL) {
         
     | 
| 
      
 273 
     | 
    
         
            +
                    if (cb->gpio == gpio)
         
     | 
| 
      
 274 
     | 
    
         
            +
                        return 1;
         
     | 
| 
      
 275 
     | 
    
         
            +
                    cb = cb->next;
         
     | 
| 
      
 276 
     | 
    
         
            +
                }
         
     | 
| 
      
 277 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 278 
     | 
    
         
            +
            }
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
            void run_callbacks(unsigned int gpio)
         
     | 
| 
      
 281 
     | 
    
         
            +
            {
         
     | 
| 
      
 282 
     | 
    
         
            +
                struct callback *cb = callbacks;
         
     | 
| 
      
 283 
     | 
    
         
            +
                while (cb != NULL)
         
     | 
| 
      
 284 
     | 
    
         
            +
                {
         
     | 
| 
      
 285 
     | 
    
         
            +
                    if (cb->gpio == gpio)
         
     | 
| 
      
 286 
     | 
    
         
            +
                        cb->func(cb->gpio);
         
     | 
| 
      
 287 
     | 
    
         
            +
                    cb = cb->next;
         
     | 
| 
      
 288 
     | 
    
         
            +
                }
         
     | 
| 
      
 289 
     | 
    
         
            +
            }
         
     | 
| 
      
 290 
     | 
    
         
            +
             
     | 
| 
      
 291 
     | 
    
         
            +
            void remove_callbacks(unsigned int gpio)
         
     | 
| 
      
 292 
     | 
    
         
            +
            {
         
     | 
| 
      
 293 
     | 
    
         
            +
                struct callback *cb = callbacks;
         
     | 
| 
      
 294 
     | 
    
         
            +
                struct callback *temp;
         
     | 
| 
      
 295 
     | 
    
         
            +
                struct callback *prev = NULL;
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
                while (cb != NULL)
         
     | 
| 
      
 298 
     | 
    
         
            +
                {
         
     | 
| 
      
 299 
     | 
    
         
            +
                    if (cb->gpio == gpio)
         
     | 
| 
      
 300 
     | 
    
         
            +
                    {
         
     | 
| 
      
 301 
     | 
    
         
            +
                        if (prev == NULL)
         
     | 
| 
      
 302 
     | 
    
         
            +
                            callbacks = cb->next;
         
     | 
| 
      
 303 
     | 
    
         
            +
                        else
         
     | 
| 
      
 304 
     | 
    
         
            +
                            prev->next = cb->next;
         
     | 
| 
      
 305 
     | 
    
         
            +
                        temp = cb;
         
     | 
| 
      
 306 
     | 
    
         
            +
                        cb = cb->next;
         
     | 
| 
      
 307 
     | 
    
         
            +
                        free(temp);
         
     | 
| 
      
 308 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 309 
     | 
    
         
            +
                        prev = cb;
         
     | 
| 
      
 310 
     | 
    
         
            +
                        cb = cb->next;
         
     | 
| 
      
 311 
     | 
    
         
            +
                    }
         
     | 
| 
      
 312 
     | 
    
         
            +
                }
         
     | 
| 
      
 313 
     | 
    
         
            +
            }
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
            void *poll_thread(void *threadarg)
         
     | 
| 
      
 316 
     | 
    
         
            +
            {
         
     | 
| 
      
 317 
     | 
    
         
            +
                struct epoll_event events;
         
     | 
| 
      
 318 
     | 
    
         
            +
                char buf;
         
     | 
| 
      
 319 
     | 
    
         
            +
                struct timeval tv_timenow;
         
     | 
| 
      
 320 
     | 
    
         
            +
                unsigned long long timenow;
         
     | 
| 
      
 321 
     | 
    
         
            +
                struct gpios *g;
         
     | 
| 
      
 322 
     | 
    
         
            +
                int n;
         
     | 
| 
      
 323 
     | 
    
         
            +
             
     | 
| 
      
 324 
     | 
    
         
            +
                thread_running = 1;
         
     | 
| 
      
 325 
     | 
    
         
            +
                while (thread_running) {
         
     | 
| 
      
 326 
     | 
    
         
            +
                    if ((n = epoll_wait(epfd_thread, &events, 1, -1)) == -1) {
         
     | 
| 
      
 327 
     | 
    
         
            +
                        thread_running = 0;
         
     | 
| 
      
 328 
     | 
    
         
            +
                        pthread_exit(NULL);
         
     | 
| 
      
 329 
     | 
    
         
            +
                    }
         
     | 
| 
      
 330 
     | 
    
         
            +
                    if (n > 0) {
         
     | 
| 
      
 331 
     | 
    
         
            +
                        lseek(events.data.fd, 0, SEEK_SET);
         
     | 
| 
      
 332 
     | 
    
         
            +
                        if (read(events.data.fd, &buf, 1) != 1) {
         
     | 
| 
      
 333 
     | 
    
         
            +
                            thread_running = 0;
         
     | 
| 
      
 334 
     | 
    
         
            +
                            pthread_exit(NULL);
         
     | 
| 
      
 335 
     | 
    
         
            +
                        }
         
     | 
| 
      
 336 
     | 
    
         
            +
                        g = get_gpio_from_value_fd(events.data.fd);
         
     | 
| 
      
 337 
     | 
    
         
            +
                        if (g->initial_thread) {     // ignore first epoll trigger
         
     | 
| 
      
 338 
     | 
    
         
            +
                            g->initial_thread = 0;
         
     | 
| 
      
 339 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 340 
     | 
    
         
            +
                            gettimeofday(&tv_timenow, NULL);
         
     | 
| 
      
 341 
     | 
    
         
            +
                            timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec;
         
     | 
| 
      
 342 
     | 
    
         
            +
                            if (g->bouncetime == -666 || timenow - g->lastcall > g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) {
         
     | 
| 
      
 343 
     | 
    
         
            +
                                g->lastcall = timenow;
         
     | 
| 
      
 344 
     | 
    
         
            +
                                event_occurred[g->gpio] = 1;
         
     | 
| 
      
 345 
     | 
    
         
            +
                                run_callbacks(g->gpio);
         
     | 
| 
      
 346 
     | 
    
         
            +
                            }
         
     | 
| 
      
 347 
     | 
    
         
            +
                        }
         
     | 
| 
      
 348 
     | 
    
         
            +
                    }
         
     | 
| 
      
 349 
     | 
    
         
            +
                }
         
     | 
| 
      
 350 
     | 
    
         
            +
                thread_running = 0;
         
     | 
| 
      
 351 
     | 
    
         
            +
                pthread_exit(NULL);
         
     | 
| 
      
 352 
     | 
    
         
            +
            }
         
     | 
| 
      
 353 
     | 
    
         
            +
             
     | 
| 
      
 354 
     | 
    
         
            +
            void remove_edge_detect(unsigned int gpio)
         
     | 
| 
      
 355 
     | 
    
         
            +
            {
         
     | 
| 
      
 356 
     | 
    
         
            +
                struct epoll_event ev;
         
     | 
| 
      
 357 
     | 
    
         
            +
                struct gpios *g = get_gpio(gpio);
         
     | 
| 
      
 358 
     | 
    
         
            +
             
     | 
| 
      
 359 
     | 
    
         
            +
                if (g == NULL)
         
     | 
| 
      
 360 
     | 
    
         
            +
                    return;
         
     | 
| 
      
 361 
     | 
    
         
            +
             
     | 
| 
      
 362 
     | 
    
         
            +
                // delete epoll of fd
         
     | 
| 
      
 363 
     | 
    
         
            +
             
     | 
| 
      
 364 
     | 
    
         
            +
                ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
         
     | 
| 
      
 365 
     | 
    
         
            +
                ev.data.fd = g->value_fd;
         
     | 
| 
      
 366 
     | 
    
         
            +
                epoll_ctl(epfd_thread, EPOLL_CTL_DEL, g->value_fd, &ev);
         
     | 
| 
      
 367 
     | 
    
         
            +
             
     | 
| 
      
 368 
     | 
    
         
            +
                // delete callbacks for gpio
         
     | 
| 
      
 369 
     | 
    
         
            +
                remove_callbacks(gpio);
         
     | 
| 
      
 370 
     | 
    
         
            +
             
     | 
| 
      
 371 
     | 
    
         
            +
                // btc fixme - check return result??
         
     | 
| 
      
 372 
     | 
    
         
            +
                gpio_set_edge(gpio, NO_EDGE);
         
     | 
| 
      
 373 
     | 
    
         
            +
                g->edge = NO_EDGE;
         
     | 
| 
      
 374 
     | 
    
         
            +
             
     | 
| 
      
 375 
     | 
    
         
            +
                if (g->value_fd != -1)
         
     | 
| 
      
 376 
     | 
    
         
            +
                    close(g->value_fd);
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
                // btc fixme - check return result??
         
     | 
| 
      
 379 
     | 
    
         
            +
                gpio_unexport(gpio);
         
     | 
| 
      
 380 
     | 
    
         
            +
                event_occurred[gpio] = 0;
         
     | 
| 
      
 381 
     | 
    
         
            +
             
     | 
| 
      
 382 
     | 
    
         
            +
                delete_gpio(gpio);
         
     | 
| 
      
 383 
     | 
    
         
            +
            }
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
            int event_detected(unsigned int gpio)
         
     | 
| 
      
 386 
     | 
    
         
            +
            {
         
     | 
| 
      
 387 
     | 
    
         
            +
                if (event_occurred[gpio]) {
         
     | 
| 
      
 388 
     | 
    
         
            +
                    event_occurred[gpio] = 0;
         
     | 
| 
      
 389 
     | 
    
         
            +
                    return 1;
         
     | 
| 
      
 390 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 391 
     | 
    
         
            +
                    return 0;
         
     | 
| 
      
 392 
     | 
    
         
            +
                }
         
     | 
| 
      
 393 
     | 
    
         
            +
            }
         
     | 
| 
      
 394 
     | 
    
         
            +
             
     | 
| 
      
 395 
     | 
    
         
            +
            void event_cleanup(unsigned int gpio)
         
     | 
| 
      
 396 
     | 
    
         
            +
            // gpio of -666 means clean every channel used
         
     | 
| 
      
 397 
     | 
    
         
            +
            {
         
     | 
| 
      
 398 
     | 
    
         
            +
                struct gpios *g = gpio_list;
         
     | 
| 
      
 399 
     | 
    
         
            +
                struct gpios *temp = NULL;
         
     | 
| 
      
 400 
     | 
    
         
            +
             
     | 
| 
      
 401 
     | 
    
         
            +
                while (g != NULL) {
         
     | 
| 
      
 402 
     | 
    
         
            +
                    if ((gpio == -666) || (g->gpio == gpio))
         
     | 
| 
      
 403 
     | 
    
         
            +
                        temp = g->next;
         
     | 
| 
      
 404 
     | 
    
         
            +
                        remove_edge_detect(g->gpio);
         
     | 
| 
      
 405 
     | 
    
         
            +
                        g = temp;
         
     | 
| 
      
 406 
     | 
    
         
            +
                }
         
     | 
| 
      
 407 
     | 
    
         
            +
                if (gpio_list == NULL)
         
     | 
| 
      
 408 
     | 
    
         
            +
                    if (epfd_blocking != -1)
         
     | 
| 
      
 409 
     | 
    
         
            +
                        close(epfd_blocking);
         
     | 
| 
      
 410 
     | 
    
         
            +
                        epfd_blocking = -1;
         
     | 
| 
      
 411 
     | 
    
         
            +
                    if (epfd_thread != -1)
         
     | 
| 
      
 412 
     | 
    
         
            +
                        close(epfd_thread);
         
     | 
| 
      
 413 
     | 
    
         
            +
                        epfd_thread = -1;
         
     | 
| 
      
 414 
     | 
    
         
            +
                    thread_running = 0;
         
     | 
| 
      
 415 
     | 
    
         
            +
            }
         
     | 
| 
      
 416 
     | 
    
         
            +
             
     | 
| 
      
 417 
     | 
    
         
            +
            void event_cleanup_all(void)
         
     | 
| 
      
 418 
     | 
    
         
            +
            {
         
     | 
| 
      
 419 
     | 
    
         
            +
               event_cleanup(-666);
         
     | 
| 
      
 420 
     | 
    
         
            +
            }
         
     | 
| 
      
 421 
     | 
    
         
            +
             
     | 
| 
      
 422 
     | 
    
         
            +
            int add_edge_detect(unsigned int gpio, unsigned int edge, int bouncetime)
         
     | 
| 
      
 423 
     | 
    
         
            +
            // return values:
         
     | 
| 
      
 424 
     | 
    
         
            +
            // 0 - Success
         
     | 
| 
      
 425 
     | 
    
         
            +
            // 1 - Edge detection already added
         
     | 
| 
      
 426 
     | 
    
         
            +
            // 2 - Other error
         
     | 
| 
      
 427 
     | 
    
         
            +
            {
         
     | 
| 
      
 428 
     | 
    
         
            +
                pthread_t threads;
         
     | 
| 
      
 429 
     | 
    
         
            +
                struct epoll_event ev;
         
     | 
| 
      
 430 
     | 
    
         
            +
                long t = 0;
         
     | 
| 
      
 431 
     | 
    
         
            +
                struct gpios *g;
         
     | 
| 
      
 432 
     | 
    
         
            +
                int i = -1;
         
     | 
| 
      
 433 
     | 
    
         
            +
             
     | 
| 
      
 434 
     | 
    
         
            +
                i = gpio_event_added(gpio);
         
     | 
| 
      
 435 
     | 
    
         
            +
                if (i == 0) {    // event not already added
         
     | 
| 
      
 436 
     | 
    
         
            +
                    if ((g = new_gpio(gpio)) == NULL)
         
     | 
| 
      
 437 
     | 
    
         
            +
                        return 2;
         
     | 
| 
      
 438 
     | 
    
         
            +
             
     | 
| 
      
 439 
     | 
    
         
            +
                    gpio_set_edge(gpio, edge);
         
     | 
| 
      
 440 
     | 
    
         
            +
                    g->edge = edge;
         
     | 
| 
      
 441 
     | 
    
         
            +
                    g->bouncetime = bouncetime;
         
     | 
| 
      
 442 
     | 
    
         
            +
                } else if (i == edge) {  // get existing event
         
     | 
| 
      
 443 
     | 
    
         
            +
                    g = get_gpio(gpio);
         
     | 
| 
      
 444 
     | 
    
         
            +
                    if ((bouncetime != -666 && g->bouncetime != bouncetime) ||  // different event bouncetime used
         
     | 
| 
      
 445 
     | 
    
         
            +
                        (g->thread_added))                // event already added
         
     | 
| 
      
 446 
     | 
    
         
            +
                        return 1;
         
     | 
| 
      
 447 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 448 
     | 
    
         
            +
                    return 1;
         
     | 
| 
      
 449 
     | 
    
         
            +
                }
         
     | 
| 
      
 450 
     | 
    
         
            +
             
     | 
| 
      
 451 
     | 
    
         
            +
                // create epfd_thread if not already open
         
     | 
| 
      
 452 
     | 
    
         
            +
                if ((epfd_thread == -1) && ((epfd_thread = epoll_create(1)) == -1))
         
     | 
| 
      
 453 
     | 
    
         
            +
                    return 2;
         
     | 
| 
      
 454 
     | 
    
         
            +
             
     | 
| 
      
 455 
     | 
    
         
            +
                // add to epoll fd
         
     | 
| 
      
 456 
     | 
    
         
            +
                ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
         
     | 
| 
      
 457 
     | 
    
         
            +
                ev.data.fd = g->value_fd;
         
     | 
| 
      
 458 
     | 
    
         
            +
                if (epoll_ctl(epfd_thread, EPOLL_CTL_ADD, g->value_fd, &ev) == -1) {
         
     | 
| 
      
 459 
     | 
    
         
            +
                    remove_edge_detect(gpio);
         
     | 
| 
      
 460 
     | 
    
         
            +
                    return 2;
         
     | 
| 
      
 461 
     | 
    
         
            +
                }
         
     | 
| 
      
 462 
     | 
    
         
            +
                g->thread_added = 1;
         
     | 
| 
      
 463 
     | 
    
         
            +
             
     | 
| 
      
 464 
     | 
    
         
            +
                // start poll thread if it is not already running
         
     | 
| 
      
 465 
     | 
    
         
            +
                if (!thread_running) {
         
     | 
| 
      
 466 
     | 
    
         
            +
                    if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0) {
         
     | 
| 
      
 467 
     | 
    
         
            +
                       remove_edge_detect(gpio);
         
     | 
| 
      
 468 
     | 
    
         
            +
                       return 2;
         
     | 
| 
      
 469 
     | 
    
         
            +
                    }
         
     | 
| 
      
 470 
     | 
    
         
            +
                }
         
     | 
| 
      
 471 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 472 
     | 
    
         
            +
            }
         
     | 
| 
      
 473 
     | 
    
         
            +
             
     | 
| 
      
 474 
     | 
    
         
            +
            int blocking_wait_for_edge(unsigned int gpio, unsigned int edge, int bouncetime)
         
     | 
| 
      
 475 
     | 
    
         
            +
            // return values:
         
     | 
| 
      
 476 
     | 
    
         
            +
            //    0 - Success
         
     | 
| 
      
 477 
     | 
    
         
            +
            //    1 - Edge detection already added
         
     | 
| 
      
 478 
     | 
    
         
            +
            //    2 - Other error
         
     | 
| 
      
 479 
     | 
    
         
            +
            {
         
     | 
| 
      
 480 
     | 
    
         
            +
                int n, ed;
         
     | 
| 
      
 481 
     | 
    
         
            +
                struct epoll_event events, ev;
         
     | 
| 
      
 482 
     | 
    
         
            +
                char buf;
         
     | 
| 
      
 483 
     | 
    
         
            +
                struct gpios *g = NULL;
         
     | 
| 
      
 484 
     | 
    
         
            +
                struct timeval tv_timenow;
         
     | 
| 
      
 485 
     | 
    
         
            +
                unsigned long long timenow;
         
     | 
| 
      
 486 
     | 
    
         
            +
                int finished = 0;
         
     | 
| 
      
 487 
     | 
    
         
            +
             
     | 
| 
      
 488 
     | 
    
         
            +
                if (callback_exists(gpio))
         
     | 
| 
      
 489 
     | 
    
         
            +
                    return 1;
         
     | 
| 
      
 490 
     | 
    
         
            +
             
     | 
| 
      
 491 
     | 
    
         
            +
                // add gpio if it has not been added already
         
     | 
| 
      
 492 
     | 
    
         
            +
                ed = gpio_event_added(gpio);
         
     | 
| 
      
 493 
     | 
    
         
            +
                if (ed == edge) {   // get existing record
         
     | 
| 
      
 494 
     | 
    
         
            +
                    g = get_gpio(gpio);
         
     | 
| 
      
 495 
     | 
    
         
            +
                    if (g->bouncetime != -666 && g->bouncetime != bouncetime) {
         
     | 
| 
      
 496 
     | 
    
         
            +
                        return 1;
         
     | 
| 
      
 497 
     | 
    
         
            +
                    }
         
     | 
| 
      
 498 
     | 
    
         
            +
                } else if (ed == NO_EDGE) {   // not found so add event
         
     | 
| 
      
 499 
     | 
    
         
            +
                    if ((g = new_gpio(gpio)) == NULL)
         
     | 
| 
      
 500 
     | 
    
         
            +
                        return 2;
         
     | 
| 
      
 501 
     | 
    
         
            +
                    gpio_set_edge(gpio, edge);
         
     | 
| 
      
 502 
     | 
    
         
            +
                    g->edge = edge;
         
     | 
| 
      
 503 
     | 
    
         
            +
                    g->bouncetime = bouncetime;
         
     | 
| 
      
 504 
     | 
    
         
            +
                } else {    // ed != edge - event for a different edge
         
     | 
| 
      
 505 
     | 
    
         
            +
                    g = get_gpio(gpio);
         
     | 
| 
      
 506 
     | 
    
         
            +
                    gpio_set_edge(gpio, edge);
         
     | 
| 
      
 507 
     | 
    
         
            +
                    g->edge = edge;
         
     | 
| 
      
 508 
     | 
    
         
            +
                    g->bouncetime = bouncetime;
         
     | 
| 
      
 509 
     | 
    
         
            +
                    g->initial_wait = 1;
         
     | 
| 
      
 510 
     | 
    
         
            +
                }
         
     | 
| 
      
 511 
     | 
    
         
            +
             
     | 
| 
      
 512 
     | 
    
         
            +
                // create epfd_blocking if not already open
         
     | 
| 
      
 513 
     | 
    
         
            +
                if ((epfd_blocking == -1) && ((epfd_blocking = epoll_create(1)) == -1)) {
         
     | 
| 
      
 514 
     | 
    
         
            +
                    return 2;
         
     | 
| 
      
 515 
     | 
    
         
            +
                }
         
     | 
| 
      
 516 
     | 
    
         
            +
             
     | 
| 
      
 517 
     | 
    
         
            +
                // add to epoll fd
         
     | 
| 
      
 518 
     | 
    
         
            +
                ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
         
     | 
| 
      
 519 
     | 
    
         
            +
                ev.data.fd = g->value_fd;
         
     | 
| 
      
 520 
     | 
    
         
            +
                if (epoll_ctl(epfd_blocking, EPOLL_CTL_ADD, g->value_fd, &ev) == -1) {
         
     | 
| 
      
 521 
     | 
    
         
            +
                    return 2;
         
     | 
| 
      
 522 
     | 
    
         
            +
                }
         
     | 
| 
      
 523 
     | 
    
         
            +
             
     | 
| 
      
 524 
     | 
    
         
            +
                // wait for edge
         
     | 
| 
      
 525 
     | 
    
         
            +
                while (!finished) {
         
     | 
| 
      
 526 
     | 
    
         
            +
                    if ((n = epoll_wait(epfd_blocking, &events, 1, -1)) == -1) {
         
     | 
| 
      
 527 
     | 
    
         
            +
                        epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
         
     | 
| 
      
 528 
     | 
    
         
            +
                        return 2;
         
     | 
| 
      
 529 
     | 
    
         
            +
                    }
         
     | 
| 
      
 530 
     | 
    
         
            +
                    if (g->initial_wait) {    // first time triggers with current state, so ignore
         
     | 
| 
      
 531 
     | 
    
         
            +
                        g->initial_wait = 0;
         
     | 
| 
      
 532 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 533 
     | 
    
         
            +
                        gettimeofday(&tv_timenow, NULL);
         
     | 
| 
      
 534 
     | 
    
         
            +
                        timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec;
         
     | 
| 
      
 535 
     | 
    
         
            +
                        if (g->bouncetime == -666 || timenow - g->lastcall > g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) {
         
     | 
| 
      
 536 
     | 
    
         
            +
                            g->lastcall = timenow;
         
     | 
| 
      
 537 
     | 
    
         
            +
                            finished = 1;
         
     | 
| 
      
 538 
     | 
    
         
            +
                        }
         
     | 
| 
      
 539 
     | 
    
         
            +
                    }
         
     | 
| 
      
 540 
     | 
    
         
            +
                }
         
     | 
| 
      
 541 
     | 
    
         
            +
             
     | 
| 
      
 542 
     | 
    
         
            +
                if (n > 0) {
         
     | 
| 
      
 543 
     | 
    
         
            +
                    lseek(events.data.fd, 0, SEEK_SET);
         
     | 
| 
      
 544 
     | 
    
         
            +
                    if (read(events.data.fd, &buf, 1) != 1) {
         
     | 
| 
      
 545 
     | 
    
         
            +
                        epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
         
     | 
| 
      
 546 
     | 
    
         
            +
                        return 2;
         
     | 
| 
      
 547 
     | 
    
         
            +
                    }
         
     | 
| 
      
 548 
     | 
    
         
            +
                    if (events.data.fd != g->value_fd) {
         
     | 
| 
      
 549 
     | 
    
         
            +
                        epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
         
     | 
| 
      
 550 
     | 
    
         
            +
                        return 2;
         
     | 
| 
      
 551 
     | 
    
         
            +
                    }
         
     | 
| 
      
 552 
     | 
    
         
            +
                }
         
     | 
| 
      
 553 
     | 
    
         
            +
             
     | 
| 
      
 554 
     | 
    
         
            +
                epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
         
     | 
| 
      
 555 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 556 
     | 
    
         
            +
            }
         
     |