diff --git a/examples/speed.c b/examples/speed.c index 2cd2fe1..19b2b06 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -84,12 +84,19 @@ int main (void) pinMode (11, OUTPUT) ; speedTest (11, FAST_COUNT) ; -// Switch to SYS mode: +// Switch to SYS mode: -> character device ABI - system ("/usr/local/bin/gpio export 17 out") ; printf ("\n/sys/class/gpio method: (%8d iterations)\n", SLOW_COUNT) ; wiringPiSetupSys () ; speedTest (17, SLOW_COUNT) ; +// character device ABI + + printf ("\ncharacter device ABI method: (%8d iterations)\n", SLOW_COUNT) ; + wiringPiSetupGpioDevice () ; + pinMode (17, OUTPUT) ; + speedTest (17, SLOW_COUNT) ; + + return 0 ; } diff --git a/gpio/gpio.1 b/gpio/gpio.1 index b1be603..84bbbde 100644 --- a/gpio/gpio.1 +++ b/gpio/gpio.1 @@ -29,13 +29,6 @@ gpio \- Command-line access to Raspberry Pi's GPIO .B readall .PP .B gpio -.B unexportall/exports -.PP -.B gpio -.B export/edge/unexport -.B ... -.PP -.B gpio .B wfi .B ... .PP @@ -77,10 +70,6 @@ somewhat slow control of the GPIO pins. It can also control the IO's on the PiFace IO board and load the SPI and I2C kernel modules if required. -Additionally, it can be used to set the exports in the \fI/sys/class/gpio\fR -system directory to allow subsequent programs to use the \fR/sys/class/gpio\fR -interface without needing to be run as root. - .SH OPTIONS .TP @@ -90,15 +79,14 @@ Output the current version including the board revision of the Raspberry Pi. .TP .B \-g Use the BCM_GPIO pins numbers rather than wiringPi pin numbers. -\fINote:\fR The BCM_GPIO pin numbers are always used with the -export and edge commands. +.\" \fINote:\fR The BCM_GPIO pin numbers are always used with character device ABI. .TP .B \-1 Use the physical pin numbers rather than wiringPi pin numbers. \fINote:\fR that this applies to the P1 connector only. It is not possible to use pins on the Revision 2 P5 connector this way, and as with \-g the -BCM_GPIO pin numbers are always used with the export and edge commands. +.\" BCM_GPIO pin numbers are always used with character device ABI. .TP .B \-x extension @@ -190,47 +178,6 @@ pull-up, pull-down or tristate (off) controls. The ALT modes can also be set using \fIalt0\fR, \fIalt1\fR, ... \fIalt5\fR. -.TP -.B unexportall -Un-Export all the GPIO pins in the /sys/class/gpio directory. - -.TP -.B exports -Print a list (if any) of all the exported GPIO pins and their current values. - -.TP -.B export -Export a GPIO pin in the \fI/sys/class/gpio\fR directory. Use like the -mode command above however only \fIin\fR, \fIout\fR, \fIhigh\fR and -\fRlow\fR are supported at this time. Note that the pin number is the -\fBBCM_GPIO\fR number and not the wiringPi number. The \fIhigh\fR and -\fIlow\fR commands pre-set the output value at the same time as the -export to output mode. - -Once a GPIO pin has been exported, the \fBgpio\fR program changes the -ownership of the \fI/sys/class/gpio/gpioX/value\fR and if present in -later kernels, the \fI/sys/class/gpio/gpioX/edge\fR pseudo files to -that of the user running the \fBgpio\fR program. This means that you -can have a small script of gpio exports to setup the gpio pins as your -program requires without the need to run anything as root, or with the -sudo command. - -.TP -.B edge -This exports a GPIO pin in the \fI/sys/class/gpio\fR directory, set -the direction to input and set the edge interrupt method to \fInone\fR, -\fIrising\fR, \fIfalling\fR or \fIboth\fR. Use like the export command -above and note that \fBBCM_GPIO\fR pin number is used not not wiringPi pin -numbering. - -Like the export commands above, ownership is set to that of the -calling user, allowing subsequent access from user programs without -requiring root/sudo. - -.TP -.B unexport -Un-Export a GPIO pin in the /sys/class/gpio directory. - .TP .B wfi This set the given pin to the supplied interrupt mode: rising, falling @@ -299,18 +246,10 @@ gpio mode 1 pwm # Set pin 1 to PWM mode .PP gpio pwm 1 512 # Set pin 1 to PWM value 512 - half brightness .PP -gpio export 17 out # Set GPIO Pin 17 to output -.PP -gpio export 0 in # Set GPIO Pin 0 (SDA0) to input. -.PP gpio -g read 0 # Read GPIO Pin 0 (SDA0) .SH "NOTES" -When using the \fIexport\fR, \fIedge\fR or \fIunexport\fR commands, the -pin numbers are \fBalways\fR native BCM_GPIO numbers and never wiringPi -pin numbers. - As of kernels 4.1.7, a user-level GPIO access mechanism is available, however wiringPi will not use this by default - because at this time there appears to be issues when trying to program the PWM or clock output @@ -326,13 +265,13 @@ in future releases once the /dev/gpiomem interface is fully operational. .SH "SEE ALSO" .LP -WiringPi's home page +WiringPi's development .IP https://github.com/WiringPi/WiringPi/ .SH AUTHOR -Gordon Henderson +Gordon Henderson and contributors .SH "REPORTING BUGS" @@ -340,7 +279,8 @@ Please report bugs to https://github.com/WiringPi/WiringPi/issues .SH COPYRIGHT -Copyright (c) 2012-2018 Gordon Henderson +Copyright (c) 2012-2024 Gordon Henderson and contributors +.brq This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/gpio/gpio.c b/gpio/gpio.c index fb2da2f..0e49560 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -72,8 +72,8 @@ char *usage = "Usage: gpio -v\n" " gpio ...\n" " gpio \n" " gpio readall\n" - " gpio unexportall/exports\n" - " gpio export/edge/unexport ...\n" +// " gpio unexportall/exports\n" +// " gpio export/edge/unexport ...\n" " gpio wfi \n" " gpio drive \n" " gpio pwm-bal/pwm-ms \n" @@ -89,15 +89,6 @@ char *usage = "Usage: gpio -v\n" " gpio gbw " ; // No trailing newline needed here. -int GPIOToSysFS_ExitonFail (const int pin, const char* name) { - int pinFS = GPIOToSysFS(pin); - if (pinFS<0) { - fprintf (stderr, "%s: invalid sysfs pin of bcm pin %d\n", name, pin) ; - exit (1) ; - } - return pinFS; -} - #ifdef NOT_FOR_NOW /* * decodePin: @@ -392,160 +383,23 @@ static void doI2Cdetect (UNU int argc, char *argv []) } +void SYSFS_DEPRECATED(const char *progName) { + fprintf(stderr, "%s: GPIO Sysfs Interface for Userspace is deprecated (https://www.kernel.org/doc/Documentation/gpio/sysfs.txt).\n Function is now useless and empty.\n\n", progName); +} + /* - * doExports: + * doExports: -> deprecated, removed * List all GPIO exports ********************************************************************************* */ -static void doExports (UNU int argc, UNU char *argv []) -{ - int fd ; - int pin, l, first ; - char fName [128] ; - char buf [16] ; - - for (first = 0, pin = 0 ; pin < 64 ; ++pin) // Crude, but effective - { - -// Try to read the direction - int pinFS = GPIOToSysFS(pin); - if (pinFS<0) { - continue; - } - sprintf (fName, "/sys/class/gpio/gpio%d/direction", pinFS) ; - if ((fd = open (fName, O_RDONLY)) == -1) - continue ; - - if (first == 0) - { - ++first ; - printf ("GPIO Pins exported:\n") ; - } - - if(pinFS==pin) { - printf ("%4d: ", pin) ; - } else { - printf ("%4d (%4d): ", pin, pinFS) ; - } - - if ((l = read (fd, buf, 16)) == 0) - sprintf (buf, "%s", "?") ; - - buf [l] = 0 ; - if ((buf [strlen (buf) - 1]) == '\n') - buf [strlen (buf) - 1] = 0 ; - - printf ("%-3s", buf) ; - - close (fd) ; - -// Try to Read the value - - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - if ((fd = open (fName, O_RDONLY)) == -1) - { - printf ("No Value file (huh?)\n") ; - continue ; - } - - if ((l = read (fd, buf, 16)) == 0) - sprintf (buf, "%s", "?") ; - - buf [l] = 0 ; - if ((buf [strlen (buf) - 1]) == '\n') - buf [strlen (buf) - 1] = 0 ; - - printf (" %s", buf) ; - -// Read any edge trigger file - - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; - if ((fd = open (fName, O_RDONLY)) == -1) - { - printf ("\n") ; - continue ; - } - - if ((l = read (fd, buf, 16)) == 0) - sprintf (buf, "%s", "?") ; - - buf [l] = 0 ; - if ((buf [strlen (buf) - 1]) == '\n') - buf [strlen (buf) - 1] = 0 ; - - printf (" %-8s\n", buf) ; - - close (fd) ; - } -} - - /* - * doExport: + * doExport: -> deprecated, removed * gpio export pin mode * This uses the /sys/class/gpio device interface. ********************************************************************************* */ -void doExport (int argc, char *argv []) -{ - FILE *fd ; - int pin ; - char *mode ; - char fName [128] ; - - if (argc != 4) - { - fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ; - exit (1) ; - } - - pin = atoi (argv [2]) ; - int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); - mode = argv [3] ; - - if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ; - exit (1) ; - } - - fprintf (fd, "%d\n", pinFS) ; - fclose (fd) ; - sprintf (fName, "/sys/class/gpio/gpio%d/direction", pinFS) ; - if ((fd = fopen (fName, "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ; - exit (1) ; - } - - /**/ if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0)) - fprintf (fd, "in\n") ; - else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0)) - fprintf (fd, "out\n") ; - else if ((strcasecmp (mode, "high") == 0) || (strcasecmp (mode, "up") == 0)) - fprintf (fd, "high\n") ; - else if ((strcasecmp (mode, "low") == 0) || (strcasecmp (mode, "down") == 0)) - fprintf (fd, "low\n") ; - else - { - fprintf (stderr, "%s: Invalid mode: %s. Should be in, out, high or low\n", argv [1], mode) ; - exit (1) ; - } - - fclose (fd) ; - -// Change ownership so the current user can actually use it - - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - changeOwner (argv [0], fName) ; - - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; - changeOwner (argv [0], fName) ; - -} - /* * doWfi: @@ -630,142 +484,29 @@ void doWfi (int argc, char *argv []) } - /* - * doEdge: + * doEdge: -> deprecated, removed * gpio edge pin mode * Easy access to changing the edge trigger on a GPIO pin * This uses the /sys/class/gpio device interface. ********************************************************************************* */ -void doEdge (int argc, char *argv []) -{ - FILE *fd ; - int pin ; - char *mode ; - char fName [128] ; - - if (argc != 4) - { - fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ; - exit (1) ; - } - - pin = atoi (argv [2]) ; - int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); - mode = argv [3] ; - -// Export the pin and set direction to input - - if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ; - exit (1) ; - } - - fprintf (fd, "%d\n", pinFS) ; - fclose (fd) ; - - sprintf (fName, "/sys/class/gpio/gpio%d/direction", pinFS) ; - if ((fd = fopen (fName, "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ; - exit (1) ; - } - - fprintf (fd, "in\n") ; - fclose (fd) ; - - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; - if ((fd = fopen (fName, "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ; - exit (1) ; - } - - /**/ if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ; - else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ; - else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ; - else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ; - else - { - fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ; - exit (1) ; - } - -// Change ownership of the value and edge files, so the current user can actually use it! - - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - changeOwner (argv [0], fName) ; - - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; - changeOwner (argv [0], fName) ; - - fclose (fd) ; -} - - /* - * doUnexport: + * doUnexport: -> deprecated, removed * gpio unexport pin * This uses the /sys/class/gpio device interface. ********************************************************************************* */ -void doUnexport (int argc, char *argv []) -{ - FILE *fd ; - int pin ; - - if (argc != 3) - { - fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ; - exit (1) ; - } - - pin = atoi (argv [2]) ; - int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); - - if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ; - exit (1) ; - } - - fprintf (fd, "%d\n", pinFS) ; - fclose (fd) ; -} - - /* - * doUnexportAll: + * doUnexportAll: -> deprecated, removed * gpio unexportall * Un-Export all the GPIO pins. * This uses the /sys/class/gpio device interface. ********************************************************************************* */ -void doUnexportall (char *progName) -{ - FILE *fd ; - int pin ; - - for (pin = 0 ; pin < 63 ; ++pin) - { - int pinFS = GPIOToSysFS(pin); - if (pinFS>=0) { - if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ; - exit (1) ; - } - fprintf (fd, "%d\n", pinFS) ; - fclose (fd) ; - } - } -} - /* * doReset: @@ -1486,13 +1227,13 @@ int main (int argc, char *argv []) exit (EXIT_FAILURE) ; } -// Initial test for /sys/class/gpio operations: +// Initial test for /sys/class/gpio operations: - -> deprecated, empty but still there - /**/ if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; } - else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; } - else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; } - else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; } - else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argv [0]) ; return 0 ; } + /**/ if (strcasecmp (argv [1], "exports" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } + else if (strcasecmp (argv [1], "export" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } + else if (strcasecmp (argv [1], "edge" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } + else if (strcasecmp (argv [1], "unexport" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } + else if (strcasecmp (argv [1], "unexportall") == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } // Check for load command: diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 2a05ce4..c083e80 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -395,9 +395,6 @@ int wiringPiReturnCodes = FALSE ; int wiringPiTryGpioMem = FALSE ; -// sysFds: -// Map a file descriptor from the /sys/class/gpio/gpioX/value - static unsigned int lineFlags [64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -414,7 +411,7 @@ static int lineFds [64] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } ; -static int sysFds [64] = +static int isrFds [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, @@ -2323,7 +2320,7 @@ int waitForInterrupt (int pin, int mS) else if (wiringPiMode == WPI_MODE_PHYS) pin = physToGpio [pin] ; - if ((fd = sysFds [pin]) == -1) + if ((fd = isrFds [pin]) == -1) return -2 ; // Setup poll structure @@ -2338,10 +2335,10 @@ int waitForInterrupt (int pin, int mS) } else { //if (polls.revents & POLLIN) if (wiringPiDebug) { - printf ("wiringPi: IRQ line %d received %d, fd=%d\n", pin, ret, sysFds [pin]) ; + printf ("wiringPi: IRQ line %d received %d, fd=%d\n", pin, ret, isrFds[pin]) ; } /* read event data */ - int readret = read(sysFds [pin], &evdata, sizeof(evdata)); + int readret = read(isrFds [pin], &evdata, sizeof(evdata)); if (readret == sizeof(evdata)) { if (wiringPiDebug) { printf ("wiringPi: IRQ data id: %d, timestamp: %lld\n", evdata.id, evdata.timestamp) ; @@ -2407,7 +2404,7 @@ int waitForInterruptInit (int pin, int mode) /* set event fd nonbloack read */ int fd_line = req.fd; - sysFds [pin] = fd_line; + isrFds [pin] = fd_line; int flags = fcntl(fd_line, F_GETFL); flags |= O_NONBLOCK; ret = fcntl(fd_line, F_SETFL, flags); @@ -2421,7 +2418,7 @@ int waitForInterruptInit (int pin, int mode) int waitForInterruptClose (int pin) { - if (sysFds[pin]>0) { + if (isrFds[pin]>0) { if (wiringPiDebug) { printf ("wiringPi: waitForInterruptClose close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ; } @@ -2434,9 +2431,9 @@ int waitForInterruptClose (int pin) { fprintf (stderr, "wiringPi: waitForInterruptClose could not cancel thread\n"); } } - close(sysFds [pin]); + close(isrFds [pin]); } - sysFds [pin] = -1; + isrFds [pin] = -1; isrFunctions [pin] = NULL; /* -not closing so far - other isr may be using it - only close if no other is using - will code later diff --git a/wiringPi/wiringPiLegacy.c b/wiringPi/wiringPiLegacy.c index e14b45a..0ec4f8c 100644 --- a/wiringPi/wiringPiLegacy.c +++ b/wiringPi/wiringPiLegacy.c @@ -186,66 +186,3 @@ int piGpioLayoutLegacy (void) return gpioLayout ; } - - -/* - * wiringPiSetupSys: - * Must be called once at the start of your program execution. - * - * Initialisation (again), however this time we are using the /sys/class/gpio - * interface to the GPIO systems - slightly slower, but always usable as - * a non-root user, assuming the devices are already exported and setup correctly. - */ - -/* -int wiringPiSetupSys (void) -{ - char fName [128] ; - - if (wiringPiSetuped) - return 0 ; - - wiringPiSetuped = TRUE ; - - if (getenv (ENV_DEBUG) != NULL) - wiringPiDebug = TRUE ; - - if (getenv (ENV_CODES) != NULL) - wiringPiReturnCodes = TRUE ; - - if (wiringPiDebug) - printf ("wiringPi: wiringPiSetupSys called\n") ; - - int model, rev, mem, maker, overVolted ; - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - - if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1) - { - pinToGpio = pinToGpioR1 ; - physToGpio = physToGpioR1 ; - } - else - { - pinToGpio = pinToGpioR2 ; - physToGpio = physToGpioR2 ; - } - -// Open and scan the directory, looking for exported GPIOs, and pre-open -// the 'value' interface to speed things up for later - - for (int pin = 0, maxpin=GetMaxPin() ; pin <= maxpin ; ++pin) - { - int pinFS = GPIOToSysFS(pin); - if (pinFS>=0) { - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - sysFds [pin] = open (fName, O_RDWR) ; - } - } - - initialiseEpoch () ; - - wiringPiMode = WPI_MODE_GPIO_SYS ; - - return 0 ; -} -*/