Gordons Projects

--> Projects Top-Level GIT

6fd71f87ad537390aae67c1f1aa1ae09244e8f1e
[wiringPi] / gpio / gpio.c
1 /*
2  * gpio.c:
3  *      Swiss-Army-Knife, Set-UID command-line interface to the Raspberry
4  *      Pi's GPIO.
5  *      Copyright (c) 2012-2017 Gordon Henderson
6  ***********************************************************************
7  * This file is part of wiringPi:
8  *      https://projects.drogon.net/raspberry-pi/wiringpi/
9  *
10  *    wiringPi is free software: you can redistribute it and/or modify
11  *    it under the terms of the GNU Lesser General Public License as published by
12  *    the Free Software Foundation, either version 3 of the License, or
13  *    (at your option) any later version.
14  *
15  *    wiringPi is distributed in the hope that it will be useful,
16  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *    GNU Lesser General Public License for more details.
19  *
20  *    You should have received a copy of the GNU Lesser General Public License
21  *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
22  ***********************************************************************
23  */
24
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdint.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36
37 #include <wiringPi.h>
38 #include <wpiExtensions.h>
39
40 #include <gertboard.h>
41 #include <piFace.h>
42
43 #include "../version.h"
44
45 extern int wiringPiDebug ;
46
47 // External functions I can't be bothered creating a separate .h file for:
48
49 extern void doReadall    (void) ;
50 extern void doAllReadall (void) ;
51 extern void doPins       (void) ;
52
53 #ifndef TRUE
54 #  define       TRUE    (1==1)
55 #  define       FALSE   (1==2)
56 #endif
57
58 #define PI_USB_POWER_CONTROL    38
59 #define I2CDETECT               "/usr/sbin/i2cdetect"
60 #define MODPROBE                "/sbin/modprobe"
61 #define RMMOD                   "/sbin/rmmod"
62
63 int wpMode ;
64
65 char *usage = "Usage: gpio -v\n"
66               "       gpio -h\n"
67               "       gpio [-g|-1] ...\n"
68               "       gpio [-d] ...\n"
69               "       [-x extension:params] [[ -x ...]] ...\n"
70               "       gpio [-p] <read/write/wb> ...\n"
71               "       gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n"
72               "       gpio <toggle/blink> <pin>\n"
73               "       gpio readall/reset\n"
74               "       gpio unexportall/exports\n"
75               "       gpio export/edge/unexport ...\n"
76               "       gpio wfi <pin> <mode>\n"
77               "       gpio drive <group> <value>\n"
78               "       gpio pwm-bal/pwm-ms \n"
79               "       gpio pwmr <range> \n"
80               "       gpio pwmc <divider> \n"
81               "       gpio load spi/i2c\n"
82               "       gpio unload spi/i2c\n"
83               "       gpio i2cd/i2cdetect\n"
84               "       gpio rbx/rbd\n"
85               "       gpio wb <value>\n"
86               "       gpio usbp high/low\n"
87               "       gpio gbr <channel>\n"
88               "       gpio gbw <channel> <value>" ;     // No trailing newline needed here.
89
90
91 #ifdef  NOT_FOR_NOW
92 /*
93  * decodePin:
94  *      Decode a pin "number" which can actually be a pin name to represent
95  *      one of the Pi's on-board pins.
96  *********************************************************************************
97  */
98
99 static int decodePin (const char *str)
100 {
101
102 // The first case - see if it's a number:
103
104   if (isdigit (str [0]))
105     return atoi (str) ;
106
107   return 0 ;
108 }
109 #endif
110
111
112 /*
113  * findExecutable:
114  *      Code to locate the path to the given executable. We have a fixed list
115  *      of locations to try which completely overrides any $PATH environment.
116  *      This may be detrimental, however it avoids the reliance on $PATH
117  *      which may be a security issue when this program is run a set-uid-root.
118  *********************************************************************************
119  */
120
121 static const char *searchPath [] =
122 {
123   "/sbin",
124   "/usr/sbin",
125   "/bin",
126   "/usr/bin",
127   NULL,
128 } ;
129
130 static char *findExecutable (const char *progName)
131 {
132   static char *path = NULL ;
133   int len = strlen (progName) ;
134   int i = 0 ;
135   struct stat statBuf ;
136
137   for (i = 0 ; searchPath [i] != NULL ; ++i)
138   {
139     path = malloc (strlen (searchPath [i]) + len + 2) ;
140     sprintf (path, "%s/%s", searchPath [i], progName) ;
141
142     if (stat (path, &statBuf) == 0)
143       return path ;
144     free (path) ;
145   }
146
147   return NULL ;
148 }
149
150
151 /*
152  * changeOwner:
153  *      Change the ownership of the file to the real userId of the calling
154  *      program so we can access it.
155  *********************************************************************************
156  */
157
158 static void changeOwner (char *cmd, char *file)
159 {
160   uid_t uid = getuid () ;
161   uid_t gid = getgid () ;
162
163   if (chown (file, uid, gid) != 0)
164   {
165
166 // Removed (ignoring) the check for not existing as I'm fed-up with morons telling me that
167 //      the warning message is an error.
168
169     if (errno != ENOENT)
170       fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ;
171   }
172 }
173
174
175 /*
176  * moduleLoaded:
177  *      Return true/false if the supplied module is loaded
178  *********************************************************************************
179  */
180
181 static int moduleLoaded (char *modName)
182 {
183   int len   = strlen (modName) ;
184   int found = FALSE ;
185   FILE *fd = fopen ("/proc/modules", "r") ;
186   char line [80] ;
187
188   if (fd == NULL)
189   {
190     fprintf (stderr, "gpio: Unable to check /proc/modules: %s\n", strerror (errno)) ;
191     exit (1) ;
192   }
193
194   while (fgets (line, 80, fd) != NULL)
195   {
196     if (strncmp (line, modName, len) != 0)
197       continue ;
198
199     found = TRUE ;
200     break ;
201   }
202
203   fclose (fd) ;
204
205   return found ;
206 }
207
208
209 /*
210  * doLoad:
211  *      Load either the spi or i2c modules and change device ownerships, etc.
212  *********************************************************************************
213  */
214
215 static void checkDevTree (char *argv [])
216 {
217   struct stat statBuf ;
218
219   if (stat ("/proc/device-tree", &statBuf) == 0)        // We're on a devtree system ...
220   {
221     fprintf (stderr,
222 "%s: Unable to load/unload modules as this Pi has the device tree enabled.\n"
223 "  You need to run the raspi-config program (as root) and select the\n"
224 "  modules (SPI or I2C) that you wish to load/unload there and reboot.\n"
225 "  There is more information here:\n"
226 "      https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=97314\n", argv [0]) ;
227     exit (1) ;
228   }
229 }
230
231 static void _doLoadUsage (char *argv [])
232 {
233   fprintf (stderr, "Usage: %s load <spi/i2c> [I2C baudrate in Kb/sec]\n", argv [0]) ;
234   exit (1) ;
235 }
236
237 static void doLoad (int argc, char *argv [])
238 {
239   char *module1, *module2 ;
240   char cmd [80] ;
241   char *file1, *file2 ;
242   char args1 [32], args2 [32] ;
243
244   checkDevTree (argv) ;
245
246   if (argc < 3)
247     _doLoadUsage (argv) ;
248
249   args1 [0] = args2 [0] = 0 ;
250
251   /**/ if (strcasecmp (argv [2], "spi") == 0)
252   {
253     module1 = "spidev" ;
254     module2 = "spi_bcm2708" ;
255     file1  = "/dev/spidev0.0" ;
256     file2  = "/dev/spidev0.1" ;
257     if (argc == 4)
258     {
259       fprintf (stderr, "%s: Unable to set the buffer size now. Load aborted. Please see the man page.\n", argv [0]) ;
260       exit (1) ;
261     }
262     else if (argc > 4)
263       _doLoadUsage (argv) ;
264   }
265   else if (strcasecmp (argv [2], "i2c") == 0)
266   {
267     module1 = "i2c_dev" ;
268     module2 = "i2c_bcm2708" ;
269     file1  = "/dev/i2c-0" ;
270     file2  = "/dev/i2c-1" ;
271     if (argc == 4)
272       sprintf (args2, " baudrate=%d", atoi (argv [3]) * 1000) ;
273     else if (argc > 4)
274       _doLoadUsage (argv) ;
275   }
276   else
277     _doLoadUsage (argv) ;
278
279   if (findExecutable ("modprobe") == NULL)
280     printf ("No found\n") ;
281
282   if (!moduleLoaded (module1))
283   {
284     sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ;
285     system (cmd) ;
286   }
287
288   if (!moduleLoaded (module2))
289   {
290     sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ;
291     system (cmd) ;
292   }
293
294   if (!moduleLoaded (module2))
295   {
296     fprintf (stderr, "%s: Unable to load %s\n", argv [0], module2) ;
297     exit (1) ;
298   }
299
300   sleep (1) ;   // To let things get settled
301
302   changeOwner (argv [0], file1) ;
303   changeOwner (argv [0], file2) ;
304 }
305
306
307 /*
308  * doUnLoad:
309  *      Un-Load either the spi or i2c modules and change device ownerships, etc.
310  *********************************************************************************
311  */
312
313 static void _doUnLoadUsage (char *argv [])
314 {
315   fprintf (stderr, "Usage: %s unload <spi/i2c>\n", argv [0]) ;
316   exit (1) ;
317 }
318
319 static void doUnLoad (int argc, char *argv [])
320 {
321   char *module1, *module2 ;
322   char cmd [80] ;
323
324   checkDevTree (argv) ;
325
326   if (argc != 3)
327     _doUnLoadUsage (argv) ;
328
329   /**/ if (strcasecmp (argv [2], "spi") == 0)
330   {
331     module1 = "spidev" ;
332     module2 = "spi_bcm2708" ;
333   }
334   else if (strcasecmp (argv [2], "i2c") == 0)
335   {
336     module1 = "i2c_dev" ;
337     module2 = "i2c_bcm2708" ;
338   }
339   else
340     _doUnLoadUsage (argv) ;
341
342   if (moduleLoaded (module1))
343   {
344     sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ;
345     system (cmd) ;
346   }
347
348   if (moduleLoaded (module2))
349   {
350     sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ;
351     system (cmd) ;
352   }
353 }
354
355
356 /*
357  * doI2Cdetect:
358  *      Run the i2cdetect command with the right runes for this Pi revision
359  *********************************************************************************
360  */
361
362 static void doI2Cdetect (UNU int argc, char *argv [])
363 {
364   int port = piGpioLayout () == 1 ? 0 : 1 ;
365   char *c, *command ;
366
367   if ((c = findExecutable (I2CDETECT)) == NULL)
368   {
369     fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ;
370     return ;
371   }
372
373   if (!moduleLoaded ("i2c_dev"))
374   {
375     fprintf (stderr, "%s: The I2C kernel module(s) are not loaded.\n", argv [0]) ;
376     return ;
377   }
378
379   command = malloc (strlen (c) + 16) ;
380   sprintf (command, "%s -y %d", c, port) ;
381   if (system (command) < 0)
382     fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ;
383
384 }
385
386
387 /*
388  * doExports:
389  *      List all GPIO exports
390  *********************************************************************************
391  */
392
393 static void doExports (UNU int argc, UNU char *argv [])
394 {
395   int fd ;
396   int i, l, first ;
397   char fName [128] ;
398   char buf [16] ;
399
400   for (first = 0, i = 0 ; i < 64 ; ++i) // Crude, but effective
401   {
402
403 // Try to read the direction
404
405     sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ;
406     if ((fd = open (fName, O_RDONLY)) == -1)
407       continue ;
408
409     if (first == 0)
410     {
411       ++first ;
412       printf ("GPIO Pins exported:\n") ;
413     }
414
415     printf ("%4d: ", i) ;
416
417     if ((l = read (fd, buf, 16)) == 0)
418       sprintf (buf, "%s", "?") ;
419  
420     buf [l] = 0 ;
421     if ((buf [strlen (buf) - 1]) == '\n')
422       buf [strlen (buf) - 1] = 0 ;
423
424     printf ("%-3s", buf) ;
425
426     close (fd) ;
427
428 // Try to Read the value
429
430     sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ;
431     if ((fd = open (fName, O_RDONLY)) == -1)
432     {
433       printf ("No Value file (huh?)\n") ;
434       continue ;
435     }
436
437     if ((l = read (fd, buf, 16)) == 0)
438       sprintf (buf, "%s", "?") ;
439
440     buf [l] = 0 ;
441     if ((buf [strlen (buf) - 1]) == '\n')
442       buf [strlen (buf) - 1] = 0 ;
443
444     printf ("  %s", buf) ;
445
446 // Read any edge trigger file
447
448     sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ;
449     if ((fd = open (fName, O_RDONLY)) == -1)
450     {
451       printf ("\n") ;
452       continue ;
453     }
454
455     if ((l = read (fd, buf, 16)) == 0)
456       sprintf (buf, "%s", "?") ;
457
458     buf [l] = 0 ;
459     if ((buf [strlen (buf) - 1]) == '\n')
460       buf [strlen (buf) - 1] = 0 ;
461
462     printf ("  %-8s\n", buf) ;
463
464     close (fd) ;
465   }
466 }
467
468
469 /*
470  * doExport:
471  *      gpio export pin mode
472  *      This uses the /sys/class/gpio device interface.
473  *********************************************************************************
474  */
475
476 void doExport (int argc, char *argv [])
477 {
478   FILE *fd ;
479   int pin ;
480   char *mode ;
481   char fName [128] ;
482
483   if (argc != 4)
484   {
485     fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ;
486     exit (1) ;
487   }
488
489   pin = atoi (argv [2]) ;
490
491   mode = argv [3] ;
492
493   if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
494   {
495     fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
496     exit (1) ;
497   }
498
499   fprintf (fd, "%d\n", pin) ;
500   fclose (fd) ;
501
502   sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
503   if ((fd = fopen (fName, "w")) == NULL)
504   {
505     fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
506     exit (1) ;
507   }
508
509   /**/ if ((strcasecmp (mode, "in")   == 0) || (strcasecmp (mode, "input")  == 0))
510     fprintf (fd, "in\n") ;
511   else if ((strcasecmp (mode, "out")  == 0) || (strcasecmp (mode, "output") == 0))
512     fprintf (fd, "out\n") ;
513   else if ((strcasecmp (mode, "high") == 0) || (strcasecmp (mode, "up")     == 0))
514     fprintf (fd, "high\n") ;
515   else if ((strcasecmp (mode, "low")  == 0) || (strcasecmp (mode, "down")   == 0))
516     fprintf (fd, "low\n") ;
517   else
518   {
519     fprintf (stderr, "%s: Invalid mode: %s. Should be in, out, high or low\n", argv [1], mode) ;
520     exit (1) ;
521   }
522
523   fclose (fd) ;
524
525 // Change ownership so the current user can actually use it
526
527   sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
528   changeOwner (argv [0], fName) ;
529
530   sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
531   changeOwner (argv [0], fName) ;
532
533 }
534
535
536 /*
537  * doWfi:
538  *      gpio wfi pin mode
539  *      Wait for Interrupt on a given pin.
540  *      Slight cheat here - it's easier to actually use ISR now (which calls
541  *      gpio to set the pin modes!) then we simply sleep, and expect the thread
542  *      to exit the program. Crude but effective.
543  *********************************************************************************
544  */
545
546 static void wfi (void)
547   { exit (0) ; }
548
549 void doWfi (int argc, char *argv [])
550 {
551   int pin, mode ;
552
553   if (argc != 4)
554   {
555     fprintf (stderr, "Usage: %s wfi pin mode\n", argv [0]) ;
556     exit (1) ;
557   }
558
559   pin  = atoi (argv [2]) ;
560
561   /**/ if (strcasecmp (argv [3], "rising")  == 0) mode = INT_EDGE_RISING ;
562   else if (strcasecmp (argv [3], "falling") == 0) mode = INT_EDGE_FALLING ;
563   else if (strcasecmp (argv [3], "both")    == 0) mode = INT_EDGE_BOTH ;
564   else
565   {
566     fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv [1], argv [3]) ;
567     exit (1) ;
568   }
569
570   if (wiringPiISR (pin, mode, &wfi) < 0)
571   {
572     fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ;
573     exit (1) ;
574   }
575
576   for (;;)
577     delay (9999) ;
578 }
579
580
581
582 /*
583  * doEdge:
584  *      gpio edge pin mode
585  *      Easy access to changing the edge trigger on a GPIO pin
586  *      This uses the /sys/class/gpio device interface.
587  *********************************************************************************
588  */
589
590 void doEdge (int argc, char *argv [])
591 {
592   FILE *fd ;
593   int pin ;
594   char *mode ;
595   char fName [128] ;
596
597   if (argc != 4)
598   {
599     fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ;
600     exit (1) ;
601   }
602
603   pin  = atoi (argv [2]) ;
604   mode = argv [3] ;
605
606 // Export the pin and set direction to input
607
608   if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
609   {
610     fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
611     exit (1) ;
612   }
613
614   fprintf (fd, "%d\n", pin) ;
615   fclose (fd) ;
616
617   sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
618   if ((fd = fopen (fName, "w")) == NULL)
619   {
620     fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
621     exit (1) ;
622   }
623
624   fprintf (fd, "in\n") ;
625   fclose (fd) ;
626
627   sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
628   if ((fd = fopen (fName, "w")) == NULL)
629   {
630     fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
631     exit (1) ;
632   }
633
634   /**/ if (strcasecmp (mode, "none")    == 0) fprintf (fd, "none\n") ;
635   else if (strcasecmp (mode, "rising")  == 0) fprintf (fd, "rising\n") ;
636   else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
637   else if (strcasecmp (mode, "both")    == 0) fprintf (fd, "both\n") ;
638   else
639   {
640     fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
641     exit (1) ;
642   }
643
644 // Change ownership of the value and edge files, so the current user can actually use it!
645
646   sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
647   changeOwner (argv [0], fName) ;
648
649   sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
650   changeOwner (argv [0], fName) ;
651
652   fclose (fd) ;
653 }
654
655
656 /*
657  * doUnexport:
658  *      gpio unexport pin
659  *      This uses the /sys/class/gpio device interface.
660  *********************************************************************************
661  */
662
663 void doUnexport (int argc, char *argv [])
664 {
665   FILE *fd ;
666   int pin ;
667
668   if (argc != 3)
669   {
670     fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ;
671     exit (1) ;
672   }
673
674   pin = atoi (argv [2]) ;
675
676   if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
677   {
678     fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
679     exit (1) ;
680   }
681
682   fprintf (fd, "%d\n", pin) ;
683   fclose (fd) ;
684 }
685
686
687 /*
688  * doUnexportAll:
689  *      gpio unexportall
690  *      Un-Export all the GPIO pins.
691  *      This uses the /sys/class/gpio device interface.
692  *********************************************************************************
693  */
694
695 void doUnexportall (char *progName)
696 {
697   FILE *fd ;
698   int pin ;
699
700   for (pin = 0 ; pin < 63 ; ++pin)
701   {
702     if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
703     {
704       fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ;
705       exit (1) ;
706     }
707     fprintf (fd, "%d\n", pin) ;
708     fclose (fd) ;
709   }
710 }
711
712
713 /*
714  * doReset:
715  *      Reset the GPIO pins - as much as we can do
716  *********************************************************************************
717  */
718
719 static void doReset (UNU char *progName)
720 {
721   printf ("GPIO Reset is dangerous and has been removed from the gpio command.\n") ;
722   printf (" - Please write a shell-script to reset the GPIO pins into the state\n") ;
723   printf ("   that you need them in for your applications.\n") ;
724 }
725
726
727 /*
728  * doMode:
729  *      gpio mode pin mode ...
730  *********************************************************************************
731  */
732
733 void doMode (int argc, char *argv [])
734 {
735   int pin ;
736   char *mode ;
737
738   if (argc != 4)
739   {
740     fprintf (stderr, "Usage: %s mode pin mode\n", argv [0]) ;
741     exit (1) ;
742   }
743
744   pin = atoi (argv [2]) ;
745
746   mode = argv [3] ;
747
748   /**/ if (strcasecmp (mode, "in")      == 0) pinMode         (pin, INPUT) ;
749   else if (strcasecmp (mode, "input")   == 0) pinMode         (pin, INPUT) ;
750   else if (strcasecmp (mode, "out")     == 0) pinMode         (pin, OUTPUT) ;
751   else if (strcasecmp (mode, "output")  == 0) pinMode         (pin, OUTPUT) ;
752   else if (strcasecmp (mode, "pwm")     == 0) pinMode         (pin, PWM_OUTPUT) ;
753   else if (strcasecmp (mode, "pwmTone") == 0) pinMode         (pin, PWM_TONE_OUTPUT) ;
754   else if (strcasecmp (mode, "clock")   == 0) pinMode         (pin, GPIO_CLOCK) ;
755   else if (strcasecmp (mode, "up")      == 0) pullUpDnControl (pin, PUD_UP) ;
756   else if (strcasecmp (mode, "down")    == 0) pullUpDnControl (pin, PUD_DOWN) ;
757   else if (strcasecmp (mode, "tri")     == 0) pullUpDnControl (pin, PUD_OFF) ;
758   else if (strcasecmp (mode, "off")     == 0) pullUpDnControl (pin, PUD_OFF) ;
759   else if (strcasecmp (mode, "alt0")    == 0) pinModeAlt (pin, 0b100) ;
760   else if (strcasecmp (mode, "alt1")    == 0) pinModeAlt (pin, 0b101) ;
761   else if (strcasecmp (mode, "alt2")    == 0) pinModeAlt (pin, 0b110) ;
762   else if (strcasecmp (mode, "alt3")    == 0) pinModeAlt (pin, 0b111) ;
763   else if (strcasecmp (mode, "alt4")    == 0) pinModeAlt (pin, 0b011) ;
764   else if (strcasecmp (mode, "alt5")    == 0) pinModeAlt (pin, 0b010) ;
765   else
766   {
767     fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/clock/up/down/tri\n", argv [1], mode) ;
768     exit (1) ;
769   }
770 }
771
772
773 /*
774  * doPadDrive:
775  *      gpio drive group value
776  *********************************************************************************
777  */
778
779 static void doPadDrive (int argc, char *argv [])
780 {
781   int group, val ;
782
783   if (argc != 4)
784   {
785     fprintf (stderr, "Usage: %s drive group value\n", argv [0]) ;
786     exit (1) ;
787   }
788
789   group = atoi (argv [2]) ;
790   val   = atoi (argv [3]) ;
791
792   if ((group < 0) || (group > 2))
793   {
794     fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ;
795     exit (1) ;
796   }
797
798   if ((val < 0) || (val > 7))
799   {
800     fprintf (stderr, "%s: drive value not 0-7: %d\n", argv [0], val) ;
801     exit (1) ;
802   }
803
804   setPadDrive (group, val) ;
805 }
806
807
808 /*
809  * doUsbP:
810  *      Control USB Power - High (1.2A) or Low (600mA)
811  *      gpio usbp high/low
812  *********************************************************************************
813  */
814
815 static void doUsbP (int argc, char *argv [])
816 {
817   int model, rev, mem, maker, overVolted ;
818
819   if (argc != 3)
820   {
821     fprintf (stderr, "Usage: %s usbp high|low\n", argv [0]) ;
822     exit (1) ;
823   }
824
825 // Make sure we're on a B+
826
827   piBoardId (&model, &rev, &mem, &maker, &overVolted) ;
828
829   if (!((model == PI_MODEL_BP) || (model == PI_MODEL_2)))
830   {
831     fprintf (stderr, "USB power contol is applicable to B+ and v2 boards only.\n") ;
832     exit (1) ;
833   }
834     
835 // Make sure we start in BCM_GPIO mode
836
837   wiringPiSetupGpio () ;
838
839   if ((strcasecmp (argv [2], "high") == 0) || (strcasecmp (argv [2], "hi") == 0))
840   {
841     digitalWrite (PI_USB_POWER_CONTROL, 1) ;
842     pinMode (PI_USB_POWER_CONTROL, OUTPUT) ;
843     printf ("Switched to HIGH current USB (1.2A)\n") ;
844     return ;
845   }
846
847   if ((strcasecmp (argv [2], "low") == 0) || (strcasecmp (argv [2], "lo") == 0))
848   {
849     digitalWrite (PI_USB_POWER_CONTROL, 0) ;
850     pinMode (PI_USB_POWER_CONTROL, OUTPUT) ;
851     printf ("Switched to LOW current USB (600mA)\n") ;
852     return ;
853   }
854
855   fprintf (stderr, "Usage: %s usbp high|low\n", argv [0]) ;
856   exit (1) ;
857 }
858
859
860 /*
861  * doGbw:
862  *      gpio gbw channel value
863  *      Gertboard Write - To the Analog output
864  *********************************************************************************
865  */
866
867 static void doGbw (int argc, char *argv [])
868 {
869   int channel, value ;
870
871   if (argc != 4)
872   {
873     fprintf (stderr, "Usage: %s gbw <channel> <value>\n", argv [0]) ;
874     exit (1) ;
875   }
876
877   channel = atoi (argv [2]) ;
878   value   = atoi (argv [3]) ;
879
880   if ((channel < 0) || (channel > 1))
881   {
882     fprintf (stderr, "%s: gbw: Channel number must be 0 or 1\n", argv [0]) ;
883     exit (1) ;
884   }
885
886   if ((value < 0) || (value > 255))
887   {
888     fprintf (stderr, "%s: gbw: Value must be from 0 to 255\n", argv [0]) ;
889     exit (1) ;
890   }
891
892   if (gertboardAnalogSetup (64) < 0)
893   {
894     fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
895     exit (1) ;
896   }
897
898   analogWrite (64 + channel, value) ;
899 }
900
901
902 /*
903  * doGbr:
904  *      gpio gbr channel
905  *      From the analog input
906  *********************************************************************************
907  */
908
909 static void doGbr (int argc, char *argv [])
910 {
911   int channel ;
912
913   if (argc != 3)
914   {
915     fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ;
916     exit (1) ;
917   }
918
919   channel = atoi (argv [2]) ;
920
921   if ((channel < 0) || (channel > 1))
922   {
923     fprintf (stderr, "%s: gbr: Channel number must be 0 or 1\n", argv [0]) ;
924     exit (1) ;
925   }
926
927   if (gertboardAnalogSetup (64) < 0)
928   {
929     fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
930     exit (1) ;
931   }
932
933   printf ("%d\n", analogRead (64 + channel)) ;
934 }
935
936
937 /*
938  * doWrite:
939  *      gpio write pin value
940  *********************************************************************************
941  */
942
943 static void doWrite (int argc, char *argv [])
944 {
945   int pin, val ;
946
947   if (argc != 4)
948   {
949     fprintf (stderr, "Usage: %s write pin value\n", argv [0]) ;
950     exit (1) ;
951   }
952
953   pin = atoi (argv [2]) ;
954
955   /**/ if ((strcasecmp (argv [3], "up") == 0) || (strcasecmp (argv [3], "on") == 0))
956     val = 1 ;
957   else if ((strcasecmp (argv [3], "down") == 0) || (strcasecmp (argv [3], "off") == 0))
958     val = 0 ;
959   else
960     val = atoi (argv [3]) ;
961
962   /**/ if (val == 0)
963     digitalWrite (pin, LOW) ;
964   else
965     digitalWrite (pin, HIGH) ;
966 }
967
968
969 /*
970  * doAwriterite:
971  *      gpio awrite pin value
972  *********************************************************************************
973  */
974
975 static void doAwrite (int argc, char *argv [])
976 {
977   int pin, val ;
978
979   if (argc != 4)
980   {
981     fprintf (stderr, "Usage: %s awrite pin value\n", argv [0]) ;
982     exit (1) ;
983   }
984
985   pin = atoi (argv [2]) ;
986
987   val = atoi (argv [3]) ;
988
989   analogWrite (pin, val) ;
990 }
991
992
993 /*
994  * doWriteByte:
995  *      gpio wb value
996  *********************************************************************************
997  */
998
999 static void doWriteByte (int argc, char *argv [])
1000 {
1001   int val ;
1002
1003   if (argc != 3)
1004   {
1005     fprintf (stderr, "Usage: %s wb value\n", argv [0]) ;
1006     exit (1) ;
1007   }
1008
1009   val = (int)strtol (argv [2], NULL, 0) ;
1010
1011   digitalWriteByte (val) ;
1012 }
1013
1014
1015 /*
1016  * doReadByte:
1017  *      gpio rbx|rbd value
1018  *********************************************************************************
1019  */
1020
1021 static void doReadByte (int argc, char *argv [], int printHex)
1022 {
1023   int val ;
1024
1025   if (argc != 2)
1026   {
1027     fprintf (stderr, "Usage: %s rbx|rbd\n", argv [0]) ;
1028     exit (1) ;
1029   }
1030
1031   val = digitalReadByte () ;
1032   if (printHex)
1033     printf ("%02X\n", val) ;
1034   else
1035     printf ("%d\n", val) ;
1036 }
1037
1038
1039 /*
1040  * doRead:
1041  *      Read a pin and return the value
1042  *********************************************************************************
1043  */
1044
1045 void doRead (int argc, char *argv []) 
1046 {
1047   int pin, val ;
1048
1049   if (argc != 3)
1050   {
1051     fprintf (stderr, "Usage: %s read pin\n", argv [0]) ;
1052     exit (1) ;
1053   }
1054
1055   pin = atoi (argv [2]) ;
1056   val = digitalRead (pin) ;
1057
1058   printf ("%s\n", val == 0 ? "0" : "1") ;
1059 }
1060
1061
1062 /*
1063  * doAread:
1064  *      Read an analog pin and return the value
1065  *********************************************************************************
1066  */
1067
1068 void doAread (int argc, char *argv []) 
1069 {
1070   if (argc != 3)
1071   {
1072     fprintf (stderr, "Usage: %s aread pin\n", argv [0]) ;
1073     exit (1) ;
1074   }
1075
1076   printf ("%d\n", analogRead (atoi (argv [2]))) ;
1077 }
1078
1079
1080 /*
1081  * doToggle:
1082  *      Toggle an IO pin
1083  *********************************************************************************
1084  */
1085
1086 void doToggle (int argc, char *argv [])
1087 {
1088   int pin ;
1089
1090   if (argc != 3)
1091   {
1092     fprintf (stderr, "Usage: %s toggle pin\n", argv [0]) ;
1093     exit (1) ;
1094   }
1095
1096   pin = atoi (argv [2]) ;
1097
1098   digitalWrite (pin, !digitalRead (pin)) ;
1099 }
1100
1101
1102 /*
1103  * doBlink:
1104  *      Blink an IO pin
1105  *********************************************************************************
1106  */
1107
1108 void doBlink (int argc, char *argv [])
1109 {
1110   int pin ;
1111
1112   if (argc != 3)
1113   {
1114     fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ;
1115     exit (1) ;
1116   }
1117
1118   pin = atoi (argv [2]) ;
1119
1120   pinMode (pin, OUTPUT) ;
1121   for (;;)
1122   {
1123     digitalWrite (pin, !digitalRead (pin)) ;
1124     delay (500) ;
1125   }
1126
1127 }
1128
1129
1130 /*
1131  * doPwmTone:
1132  *      Output a tone in a PWM pin
1133  *********************************************************************************
1134  */
1135
1136 void doPwmTone (int argc, char *argv [])
1137 {
1138   int pin, freq ;
1139
1140   if (argc != 4)
1141   {
1142     fprintf (stderr, "Usage: %s pwmTone <pin> <freq>\n", argv [0]) ;
1143     exit (1) ;
1144   }
1145
1146   pin = atoi (argv [2]) ;
1147   freq = atoi (argv [3]) ;
1148
1149   pwmToneWrite (pin, freq) ;
1150 }
1151
1152
1153 /*
1154  * doClock:
1155  *      Output a clock on a pin
1156  *********************************************************************************
1157  */
1158
1159 void doClock (int argc, char *argv [])
1160 {
1161   int pin, freq ;
1162
1163   if (argc != 4)
1164   {
1165     fprintf (stderr, "Usage: %s clock <pin> <freq>\n", argv [0]) ;
1166     exit (1) ;
1167   }
1168
1169   pin = atoi (argv [2]) ;
1170
1171   freq = atoi (argv [3]) ;
1172
1173   gpioClockSet (pin, freq) ;
1174 }
1175
1176
1177 /*
1178  * doPwm:
1179  *      Output a PWM value on a pin
1180  *********************************************************************************
1181  */
1182
1183 void doPwm (int argc, char *argv [])
1184 {
1185   int pin, val ;
1186
1187   if (argc != 4)
1188   {
1189     fprintf (stderr, "Usage: %s pwm <pin> <value>\n", argv [0]) ;
1190     exit (1) ;
1191   }
1192
1193   pin = atoi (argv [2]) ;
1194
1195   val = atoi (argv [3]) ;
1196
1197   pwmWrite (pin, val) ;
1198 }
1199
1200
1201 /*
1202  * doPwmMode: doPwmRange: doPwmClock:
1203  *      Change the PWM mode, range and clock divider values
1204  *********************************************************************************
1205  */
1206
1207 static void doPwmMode (int mode)
1208 {
1209   pwmSetMode (mode) ;
1210 }
1211
1212 static void doPwmRange (int argc, char *argv [])
1213 {
1214   unsigned int range ;
1215
1216   if (argc != 3)
1217   {
1218     fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
1219     exit (1) ;
1220   }
1221
1222   range = (unsigned int)strtoul (argv [2], NULL, 10) ;
1223
1224   if (range == 0)
1225   {
1226     fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
1227     exit (1) ;
1228   }
1229
1230   pwmSetRange (range) ;
1231 }
1232
1233 static void doPwmClock (int argc, char *argv [])
1234 {
1235   unsigned int clock ;
1236
1237   if (argc != 3)
1238   {
1239     fprintf (stderr, "Usage: %s pwmc <clock>\n", argv [0]) ;
1240     exit (1) ;
1241   }
1242
1243   clock = (unsigned int)strtoul (argv [2], NULL, 10) ;
1244
1245   if ((clock < 1) || (clock > 4095))
1246   {
1247     fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ;
1248     exit (1) ;
1249   }
1250
1251   pwmSetClock (clock) ;
1252 }
1253
1254
1255 /*
1256  * doVersion:
1257  *      Handle the ever more complicated version command and print out
1258  *      some usefull information.
1259  *********************************************************************************
1260  */
1261
1262 static void doVersion (char *argv [])
1263 {
1264   int model, rev, mem, maker, warranty ;
1265   struct stat statBuf ;
1266   char name [80] ;
1267   FILE *fd ;
1268
1269   int vMaj, vMin ;
1270
1271   wiringPiVersion (&vMaj, &vMin) ;
1272   printf ("gpio version: %d.%d\n", vMaj, vMin) ;
1273   printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
1274   printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
1275   printf ("For details type: %s -warranty\n", argv [0]) ;
1276   printf ("\n") ;
1277   piBoardId (&model, &rev, &mem, &maker, &warranty) ;
1278
1279   printf ("Raspberry Pi Details:\n") ;
1280   printf ("  Type: %s, Revision: %s, Memory: %dMB, Maker: %s %s\n", 
1281       piModelNames [model], piRevisionNames [rev], piMemorySize [mem], piMakerNames [maker], warranty ? "[Out of Warranty]" : "") ;
1282
1283 // Check for device tree
1284
1285   if (stat ("/proc/device-tree", &statBuf) == 0)        // We're on a devtree system ...
1286     printf ("  * Device tree is enabled.\n") ;
1287
1288   if (stat ("/proc/device-tree/model", &statBuf) == 0)  // Output Kernel idea of board type
1289   {
1290     if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL)
1291     {
1292       fgets (name, 80, fd) ;
1293       fclose (fd) ;
1294       printf ("  *--> %s\n", name) ;
1295     }
1296   }
1297
1298   if (stat ("/dev/gpiomem", &statBuf) == 0)             // User level GPIO is GO
1299     printf ("  * This Raspberry Pi supports user-level GPIO access.\n") ;
1300   else
1301     printf ("  * Root or sudo required for GPIO access.\n") ;
1302 }
1303
1304
1305 /*
1306  * main:
1307  *      Start here
1308  *********************************************************************************
1309  */
1310
1311 int main (int argc, char *argv [])
1312 {
1313   int i ;
1314
1315   if (getenv ("WIRINGPI_DEBUG") != NULL)
1316   {
1317     printf ("gpio: wiringPi debug mode enabled\n") ;
1318     wiringPiDebug = TRUE ;
1319   }
1320
1321   if (argc == 1)
1322   {
1323     fprintf (stderr, "%s\n", usage) ;
1324     return 1 ;
1325   }
1326
1327 // Help
1328
1329   if (strcasecmp (argv [1], "-h") == 0)
1330   {
1331     printf ("%s: %s\n", argv [0], usage) ;
1332     return 0 ;
1333   }
1334
1335 // Version & Warranty
1336 //      Wish I could remember why I have both -R and -V ...
1337
1338   if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0))
1339   {
1340     printf ("%d\n", piGpioLayout ()) ;
1341     return 0 ;
1342   }
1343
1344 // Version and information
1345
1346   if (strcmp (argv [1], "-v") == 0)
1347   {
1348     doVersion (argv) ;
1349     return 0 ;
1350   }
1351
1352   if (strcasecmp (argv [1], "-warranty") == 0)
1353   {
1354     printf ("gpio version: %s\n", VERSION) ;
1355     printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
1356     printf ("\n") ;
1357     printf ("    This program is free software; you can redistribute it and/or modify\n") ;
1358     printf ("    it under the terms of the GNU Leser General Public License as published\n") ;
1359     printf ("    by the Free Software Foundation, either version 3 of the License, or\n") ;
1360     printf ("    (at your option) any later version.\n") ;
1361     printf ("\n") ;
1362     printf ("    This program is distributed in the hope that it will be useful,\n") ;
1363     printf ("    but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
1364     printf ("    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n") ;
1365     printf ("    GNU Lesser General Public License for more details.\n") ;
1366     printf ("\n") ;
1367     printf ("    You should have received a copy of the GNU Lesser General Public License\n") ;
1368     printf ("    along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
1369     printf ("\n") ;
1370     return 0 ;
1371   }
1372
1373   if (geteuid () != 0)
1374   {
1375     fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
1376     return 1 ;
1377   }
1378
1379 // Initial test for /sys/class/gpio operations:
1380
1381   /**/ if (strcasecmp (argv [1], "exports"    ) == 0)   { doExports     (argc, argv) ;  return 0 ; }
1382   else if (strcasecmp (argv [1], "export"     ) == 0)   { doExport      (argc, argv) ;  return 0 ; }
1383   else if (strcasecmp (argv [1], "edge"       ) == 0)   { doEdge        (argc, argv) ;  return 0 ; }
1384   else if (strcasecmp (argv [1], "unexport"   ) == 0)   { doUnexport    (argc, argv) ;  return 0 ; }
1385   else if (strcasecmp (argv [1], "unexportall") == 0)   { doUnexportall (argv [0]) ;    return 0 ; }
1386
1387 // Check for load command:
1388
1389   if (strcasecmp (argv [1], "load"   ) == 0)    { doLoad   (argc, argv) ; return 0 ; }
1390   if (strcasecmp (argv [1], "unload" ) == 0)    { doUnLoad (argc, argv) ; return 0 ; }
1391
1392 // Check for usb power command
1393
1394   if (strcasecmp (argv [1], "usbp"   ) == 0)    { doUsbP   (argc, argv) ; return 0 ; }
1395
1396 // Gertboard commands
1397
1398   if (strcasecmp (argv [1], "gbr" ) == 0)       { doGbr (argc, argv) ; return 0 ; }
1399   if (strcasecmp (argv [1], "gbw" ) == 0)       { doGbw (argc, argv) ; return 0 ; }
1400
1401 // Check for allreadall command, force Gpio mode
1402
1403   if (strcasecmp (argv [1], "allreadall") == 0)
1404   {
1405     wiringPiSetupGpio () ;
1406     doAllReadall      () ;
1407     return 0 ;
1408   }
1409
1410 // Check for -g argument
1411
1412   /**/ if (strcasecmp (argv [1], "-g") == 0)
1413   {
1414     wiringPiSetupGpio () ;
1415
1416     for (i = 2 ; i < argc ; ++i)
1417       argv [i - 1] = argv [i] ;
1418     --argc ;
1419     wpMode = WPI_MODE_GPIO ;
1420   }
1421
1422 // Check for -1 argument
1423
1424   else if (strcasecmp (argv [1], "-1") == 0)
1425   {
1426     wiringPiSetupPhys () ;
1427
1428     for (i = 2 ; i < argc ; ++i)
1429       argv [i - 1] = argv [i] ;
1430     --argc ;
1431     wpMode = WPI_MODE_PHYS ;
1432   }
1433
1434 // Check for -p argument for PiFace
1435
1436   else if (strcasecmp (argv [1], "-p") == 0)
1437   {
1438     piFaceSetup (200) ;
1439
1440     for (i = 2 ; i < argc ; ++i)
1441       argv [i - 1] = argv [i] ;
1442     --argc ;
1443     wpMode = WPI_MODE_PIFACE ;
1444   }
1445
1446 // Check for -z argument so we don't actually initialise wiringPi
1447
1448   else if (strcasecmp (argv [1], "-z") == 0)
1449   {
1450     for (i = 2 ; i < argc ; ++i)
1451       argv [i - 1] = argv [i] ;
1452     --argc ;
1453     wpMode = WPI_MODE_UNINITIALISED ;
1454   }
1455
1456 // Default to wiringPi mode
1457
1458   else
1459   {
1460     wiringPiSetup () ;
1461     wpMode = WPI_MODE_PINS ;
1462   }
1463
1464 // Check for -x argument to load in a new extension
1465 //      -x extension:base:args
1466 //      Can load many modules, but unless daemon mode we can only send one
1467 //      command at a time.
1468
1469   while (strcasecmp (argv [1], "-x") == 0)
1470   {
1471     if (argc < 3)
1472     {
1473       fprintf (stderr, "%s: -x missing extension command.\n", argv [0]) ;
1474       exit (EXIT_FAILURE) ;
1475     }
1476
1477     if (!loadWPiExtension (argv [0], argv [2], TRUE))
1478     {
1479       fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ;
1480       exit (EXIT_FAILURE) ;
1481     }
1482
1483 // Shift args down by 2
1484
1485     for (i = 3 ; i < argc ; ++i)
1486       argv [i - 2] = argv [i] ;
1487     argc -= 2 ;
1488   }
1489
1490   if (argc <= 1)
1491   {
1492     fprintf (stderr, "%s: no command given\n", argv [0]) ;
1493     exit (EXIT_FAILURE) ;
1494   }
1495
1496 // Core wiringPi functions
1497
1498   /**/ if (strcasecmp (argv [1], "mode"   ) == 0) doMode      (argc, argv) ;
1499   else if (strcasecmp (argv [1], "read"   ) == 0) doRead      (argc, argv) ;
1500   else if (strcasecmp (argv [1], "write"  ) == 0) doWrite     (argc, argv) ;
1501   else if (strcasecmp (argv [1], "pwm"    ) == 0) doPwm       (argc, argv) ;
1502   else if (strcasecmp (argv [1], "awrite" ) == 0) doAwrite    (argc, argv) ;
1503   else if (strcasecmp (argv [1], "aread"  ) == 0) doAread     (argc, argv) ;
1504
1505 // GPIO Nicies
1506
1507   else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle    (argc, argv) ;
1508   else if (strcasecmp (argv [1], "blink"  ) == 0) doBlink     (argc, argv) ;
1509
1510 // Pi Specifics
1511
1512   else if (strcasecmp (argv [1], "pwm-bal"  ) == 0) doPwmMode    (PWM_MODE_BAL) ;
1513   else if (strcasecmp (argv [1], "pwm-ms"   ) == 0) doPwmMode    (PWM_MODE_MS) ;
1514   else if (strcasecmp (argv [1], "pwmr"     ) == 0) doPwmRange   (argc, argv) ;
1515   else if (strcasecmp (argv [1], "pwmc"     ) == 0) doPwmClock   (argc, argv) ;
1516   else if (strcasecmp (argv [1], "pwmTone"  ) == 0) doPwmTone    (argc, argv) ;
1517   else if (strcasecmp (argv [1], "drive"    ) == 0) doPadDrive   (argc, argv) ;
1518   else if (strcasecmp (argv [1], "readall"  ) == 0) doReadall    () ;
1519   else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall    () ;
1520   else if (strcasecmp (argv [1], "pins"     ) == 0) doPins       () ;
1521   else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect  (argc, argv) ;
1522   else if (strcasecmp (argv [1], "i2cd"     ) == 0) doI2Cdetect  (argc, argv) ;
1523   else if (strcasecmp (argv [1], "reset"    ) == 0) doReset      (argv [0]) ;
1524   else if (strcasecmp (argv [1], "wb"       ) == 0) doWriteByte  (argc, argv) ;
1525   else if (strcasecmp (argv [1], "rbx"      ) == 0) doReadByte   (argc, argv, TRUE) ;
1526   else if (strcasecmp (argv [1], "rbd"      ) == 0) doReadByte   (argc, argv, FALSE) ;
1527   else if (strcasecmp (argv [1], "clock"    ) == 0) doClock      (argc, argv) ;
1528   else if (strcasecmp (argv [1], "wfi"      ) == 0) doWfi        (argc, argv) ;
1529   else
1530   {
1531     fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
1532     exit (EXIT_FAILURE) ;
1533   }
1534   return 0 ;
1535 }