/* Interrupts functions extruded from wiringPi library by Oitzu. wiringPi Copyright (c) 2012 Gordon Henderson https://projects.drogon.net/raspberry-pi/wiringpi wiringPi is free software: GNU Lesser General Public License see */ #include #include #include #include #include #include #include #include #include #include #include #include "interrupt.h" #include #define delay(x) bcm2835_delay(x) static pthread_mutex_t pinMutex = PTHREAD_MUTEX_INITIALIZER; static volatile int pinPass = -1 ; pthread_t threadId [64]; // sysFds: // Map a file descriptor from the /sys/class/gpio/gpioX/value static int sysFds [64] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } ; // ISR Data static void (*isrFunctions [64])(void) ; int waitForInterrupt (int pin, int mS) { int fd, x ; uint8_t c ; struct pollfd polls ; if ((fd = sysFds [pin]) == -1) return -2 ; // Setup poll structure polls.fd = fd ; polls.events = POLLPRI ; // Urgent data! // Wait for it ... x = poll (&polls, 1, mS) ; // Do a dummy read to clear the interrupt // A one character read appars to be enough. // Followed by a seek to reset it. (void)read (fd, &c, 1) ; lseek (fd, 0, SEEK_SET) ; return x ; } int piHiPri (const int pri) { struct sched_param sched ; memset (&sched, 0, sizeof(sched)) ; if (pri > sched_get_priority_max (SCHED_RR)) sched.sched_priority = sched_get_priority_max (SCHED_RR) ; else sched.sched_priority = pri ; return sched_setscheduler (0, SCHED_RR, &sched) ; } void *interruptHandler (void *arg) { int myPin ; (void)piHiPri (55) ; // Only effective if we run as root myPin = pinPass ; pinPass = -1 ; for (;;) if (waitForInterrupt (myPin, -1) > 0){ pthread_mutex_lock (&pinMutex) ; isrFunctions [myPin] () ; pthread_mutex_unlock (&pinMutex) ; pthread_testcancel(); //Cancel at this point if we have an cancellation request. } return NULL ; } int attachInterrupt (int pin, int mode, void (*function)(void)) { const char *modeS ; char fName [64] ; char pinS [8] ; pid_t pid ; int count, i ; char c ; int bcmGpioPin ; bcmGpioPin = pin ; if (mode != INT_EDGE_SETUP) { /**/ if (mode == INT_EDGE_FALLING) modeS = "falling" ; else if (mode == INT_EDGE_RISING) modeS = "rising" ; else modeS = "both" ; sprintf (pinS, "%d", bcmGpioPin) ; if ((pid = fork ()) < 0) // Fail return printf("wiringPiISR: fork failed: %s\n", strerror (errno)) ; if (pid == 0) // Child, exec { /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) { execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; } else if (access ("/usr/bin/gpio", X_OK) == 0) { execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; } else return printf ("wiringPiISR: Can't find gpio program\n") ; } else // Parent, wait wait (NULL) ; } if (sysFds [bcmGpioPin] == -1) { sprintf (fName, "/sys/class/gpio/gpio%d/value",bcmGpioPin); if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0) return printf ("wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ; } ioctl (sysFds [bcmGpioPin], FIONREAD, &count) ; for (i = 0 ; i < count ; ++i) read (sysFds [bcmGpioPin], &c, 1) ; isrFunctions [pin] = function ; pthread_mutex_lock (&pinMutex) ; pinPass = pin ; pthread_create (&threadId[bcmGpioPin], NULL, interruptHandler, NULL) ; while (pinPass != -1) delay (1) ; pthread_mutex_unlock (&pinMutex) ; return 0 ; } int detachInterrupt (int pin) { char pinS [8]; const char *modeS = "none"; pid_t pid ; if (pthread_cancel(threadId[pin]) != 0) //Cancel the thread { return 0; } if (close(sysFds[pin]) != 0) //Close filehandle { return 0; } /* Set wiringPi to 'none' interrupt mode */ sprintf (pinS, "%d", pin) ; if ((pid = fork ()) < 0) // Fail return printf("wiringPiISR: fork failed: %s\n", strerror (errno)) ; if (pid == 0) // Child, exec { /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0) { execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; } else if (access ("/usr/bin/gpio", X_OK) == 0) { execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; return printf ("wiringPiISR: execl failed: %s\n", strerror (errno)) ; } else return printf ("wiringPiISR: Can't find gpio program\n") ; } else // Parent, wait wait (NULL) ; return 1; } void rfNoInterrupts(){ pthread_mutex_lock (&pinMutex) ; } void rfInterrupts(){ pthread_mutex_unlock (&pinMutex) ; }