blob: 7b84abddf31ef284c4bf279147d24e3158219cbf [file] [log] [blame]
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001/*
2 * gpio.c:
Gordon Henderson99095e32012-08-27 20:56:14 +01003 * Swiss-Army-Knife, Set-UID command-line interface to the Raspberry
4 * Pi's GPIO.
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01005 * Copyright (c) 2012 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
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010025
26#include <stdio.h>
27#include <stdlib.h>
28#include <stdint.h>
29#include <string.h>
30#include <unistd.h>
31#include <errno.h>
32#include <sys/types.h>
33#include <fcntl.h>
34
Gordon Henderson99095e32012-08-27 20:56:14 +010035#include <wiringPi.h>
36#include <gertboard.h>
37
Gordon Henderson13bbba72013-01-14 11:31:56 +000038extern int wiringPiDebug ;
39
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010040#ifndef TRUE
41# define TRUE (1==1)
42# define FALSE (1==2)
43#endif
44
Gordon Henderson13bbba72013-01-14 11:31:56 +000045#define VERSION "1.6"
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010046
47static int wpMode ;
48
49char *usage = "Usage: gpio -v\n"
Gordon Henderson178ea082012-08-19 15:17:03 +010050 " gpio -h\n"
Gordon Henderson25e4ec52012-12-06 21:49:41 +000051 " gpio [-g] <read/write/wb/pwm/mode> ...\n"
52 " gpio [-p] <read/write/wb> ...\n"
Gordon Henderson183c5a62012-10-21 15:25:16 +010053 " gpio readall\n"
54 " gpio unexportall/exports ...\n"
55 " gpio export/edge/unexport ...\n"
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010056 " gpio drive <group> <value>\n"
Gordon Hendersonf99ffed2012-08-19 15:12:45 +010057 " gpio pwm-bal/pwm-ms \n"
58 " gpio pwmr <range> \n"
Gordon Henderson8cb49392012-09-16 10:15:32 +010059 " gpio pwmc <divider> \n"
Gordon Henderson99095e32012-08-27 20:56:14 +010060 " gpio load spi/i2c\n"
61 " gpio gbr <channel>\n"
Gordon Henderson8cb49392012-09-16 10:15:32 +010062 " gpio gbw <channel> <value>" ; // No trailing newline needed here.
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010063
64
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010065/*
66 * changeOwner:
67 * Change the ownership of the file to the real userId of the calling
68 * program so we can access it.
69 *********************************************************************************
70 */
71
72static void changeOwner (char *cmd, char *file)
73{
74 uid_t uid = getuid () ;
75 uid_t gid = getgid () ;
76
77 if (chown (file, uid, gid) != 0)
78 {
79 if (errno == ENOENT) // Warn that it's not there
80 fprintf (stderr, "%s: Warning: File not present: %s\n", cmd, file) ;
81 else
82 {
83 fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ;
84 exit (1) ;
85 }
86 }
87}
88
89
90/*
91 * moduleLoaded:
92 * Return true/false if the supplied module is loaded
93 *********************************************************************************
94 */
95
96static int moduleLoaded (char *modName)
97{
98 int len = strlen (modName) ;
99 int found = FALSE ;
100 FILE *fd = fopen ("/proc/modules", "r") ;
101 char line [80] ;
102
103 if (fd == NULL)
104 {
105 fprintf (stderr, "gpio: Unable to check modules: %s\n", strerror (errno)) ;
106 exit (1) ;
107 }
108
109 while (fgets (line, 80, fd) != NULL)
110 {
111 if (strncmp (line, modName, len) != 0)
112 continue ;
113
114 found = TRUE ;
115 break ;
116 }
117
118 fclose (fd) ;
119
120 return found ;
121}
122
123
124/*
125 * doLoad:
126 * Load either the spi or i2c modules and change device ownerships, etc.
127 *********************************************************************************
128 */
129
130static void _doLoadUsage (char *argv [])
131{
Gordon Henderson13bbba72013-01-14 11:31:56 +0000132 fprintf (stderr, "Usage: %s load <spi/i2c> [bufferSize in KB for spi]\n", argv [0]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100133 exit (1) ;
134}
135
136static void doLoad (int argc, char *argv [])
137{
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000138 char *module1, *module2 ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100139 char cmd [80] ;
140 char *file1, *file2 ;
Gordon Henderson13bbba72013-01-14 11:31:56 +0000141 char spiBuf [32] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100142
Gordon Henderson13bbba72013-01-14 11:31:56 +0000143 if (argc < 3)
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100144 _doLoadUsage (argv) ;
145
Gordon Henderson13bbba72013-01-14 11:31:56 +0000146 spiBuf [0] = 0 ;
147
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100148 /**/ if (strcasecmp (argv [2], "spi") == 0)
149 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000150 module1 = "spidev" ;
151 module2 = "spi_bcm2708" ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100152 file1 = "/dev/spidev0.0" ;
153 file2 = "/dev/spidev0.1" ;
Gordon Henderson13bbba72013-01-14 11:31:56 +0000154 if (argc == 4)
155 sprintf (spiBuf, " bufsize=%d", atoi (argv [3]) * 1024) ;
156 else if (argc > 4)
157 _doLoadUsage (argv) ;
158
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100159 }
160 else if (strcasecmp (argv [2], "i2c") == 0)
161 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000162 module1 = "i2c_dev" ;
163 module2 = "i2c_bcm2708" ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100164 file1 = "/dev/i2c-0" ;
165 file2 = "/dev/i2c-1" ;
166 }
167 else
168 _doLoadUsage (argv) ;
169
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000170 if (!moduleLoaded (module1))
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100171 {
Gordon Henderson13bbba72013-01-14 11:31:56 +0000172 sprintf (cmd, "modprobe %s%s", module1, spiBuf) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100173 system (cmd) ;
174 }
175
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000176 if (!moduleLoaded (module2))
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100177 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000178 sprintf (cmd, "modprobe %s", module2) ;
179 system (cmd) ;
180 }
181
182 if (!moduleLoaded (module2))
183 {
184 fprintf (stderr, "%s: Unable to load %s\n", argv [0], module2) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100185 exit (1) ;
186 }
187
188 sleep (1) ; // To let things get settled
189
190 changeOwner (argv [0], file1) ;
191 changeOwner (argv [0], file2) ;
192}
193
194
Gordon Henderson183c5a62012-10-21 15:25:16 +0100195/*
196 * doReadall:
197 * Read all the GPIO pins
198 *********************************************************************************
199 */
200
201static char *pinNames [] =
202{
203 "GPIO 0",
204 "GPIO 1",
205 "GPIO 2",
206 "GPIO 3",
207 "GPIO 4",
208 "GPIO 5",
209 "GPIO 6",
210 "GPIO 7",
211 "SDA ",
212 "SCL ",
213 "CE0 ",
214 "CE1 ",
215 "MOSI ",
216 "MISO ",
217 "SCLK ",
218 "TxD ",
219 "RxD ",
220 "GPIO 8",
221 "GPIO 9",
222 "GPIO10",
223 "GPIO11",
224} ;
225
226static void doReadall (void)
227{
228 int pin ;
229
230 printf ("+----------+------+--------+-------+\n") ;
231 printf ("| wiringPi | GPIO | Name | Value |\n") ;
232 printf ("+----------+------+--------+-------+\n") ;
233
234 for (pin = 0 ; pin < NUM_PINS ; ++pin)
235 printf ("| %6d | %3d | %s | %s |\n",
236 pin, wpiPinToGpio (pin),
237 pinNames [pin],
238 digitalRead (pin) == HIGH ? "High" : "Low ") ;
239
240 printf ("+----------+------+--------+-------+\n") ;
241
242 if (piBoardRev () == 1)
243 return ;
244
245 for (pin = 17 ; pin <= 20 ; ++pin)
246 printf ("| %6d | %3d | %s | %s |\n",
247 pin, wpiPinToGpio (pin),
248 pinNames [pin],
249 digitalRead (pin) == HIGH ? "High" : "Low ") ;
250
251 printf ("+----------+------+--------+-------+\n") ;
252}
253
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100254
255/*
256 * doExports:
257 * List all GPIO exports
258 *********************************************************************************
259 */
260
Gordon Henderson178ea082012-08-19 15:17:03 +0100261static void doExports (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100262{
263 int fd ;
264 int i, l, first ;
265 char fName [128] ;
266 char buf [16] ;
267
268// Rather crude, but who knows what others are up to...
269
270 for (first = 0, i = 0 ; i < 64 ; ++i)
271 {
272
273// Try to read the direction
274
275 sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ;
276 if ((fd = open (fName, O_RDONLY)) == -1)
277 continue ;
278
279 if (first == 0)
280 {
281 ++first ;
282 printf ("GPIO Pins exported:\n") ;
283 }
284
285 printf ("%4d: ", i) ;
286
287 if ((l = read (fd, buf, 16)) == 0)
288 sprintf (buf, "%s", "?") ;
289
290 buf [l] = 0 ;
291 if ((buf [strlen (buf) - 1]) == '\n')
292 buf [strlen (buf) - 1] = 0 ;
293
294 printf ("%-3s", buf) ;
295
296 close (fd) ;
297
298// Try to Read the value
299
300 sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ;
301 if ((fd = open (fName, O_RDONLY)) == -1)
302 {
303 printf ("No Value file (huh?)\n") ;
304 continue ;
305 }
306
307 if ((l = read (fd, buf, 16)) == 0)
308 sprintf (buf, "%s", "?") ;
309
310 buf [l] = 0 ;
311 if ((buf [strlen (buf) - 1]) == '\n')
312 buf [strlen (buf) - 1] = 0 ;
313
314 printf (" %s", buf) ;
315
316// Read any edge trigger file
317
318 sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ;
319 if ((fd = open (fName, O_RDONLY)) == -1)
320 {
321 printf ("\n") ;
322 continue ;
323 }
324
325 if ((l = read (fd, buf, 16)) == 0)
326 sprintf (buf, "%s", "?") ;
327
328 buf [l] = 0 ;
329 if ((buf [strlen (buf) - 1]) == '\n')
330 buf [strlen (buf) - 1] = 0 ;
331
332 printf (" %-8s\n", buf) ;
333
334 close (fd) ;
335 }
336}
337
338
339/*
340 * doExport:
341 * gpio export pin mode
342 * This uses the /sys/class/gpio device interface.
343 *********************************************************************************
344 */
345
346void doExport (int argc, char *argv [])
347{
348 FILE *fd ;
349 int pin ;
350 char *mode ;
351 char fName [128] ;
352
353 if (argc != 4)
354 {
355 fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ;
356 exit (1) ;
357 }
358
359 pin = atoi (argv [2]) ;
360
361 mode = argv [3] ;
362
363 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
364 {
365 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
366 exit (1) ;
367 }
368
369 fprintf (fd, "%d\n", pin) ;
370 fclose (fd) ;
371
372 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
373 if ((fd = fopen (fName, "w")) == NULL)
374 {
375 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
376 exit (1) ;
377 }
378
379 /**/ if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0))
380 fprintf (fd, "in\n") ;
381 else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0))
382 fprintf (fd, "out\n") ;
383 else
384 {
385 fprintf (stderr, "%s: Invalid mode: %s. Should be in or out\n", argv [1], mode) ;
386 exit (1) ;
387 }
388
389 fclose (fd) ;
390
391// Change ownership so the current user can actually use it!
392
393 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
394 changeOwner (argv [0], fName) ;
395
396 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
397 changeOwner (argv [0], fName) ;
398
399}
400
401
402/*
403 * doEdge:
404 * gpio edge pin mode
405 * Easy access to changing the edge trigger on a GPIO pin
406 * This uses the /sys/class/gpio device interface.
407 *********************************************************************************
408 */
409
410void doEdge (int argc, char *argv [])
411{
412 FILE *fd ;
413 int pin ;
414 char *mode ;
415 char fName [128] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100416
417 if (argc != 4)
418 {
419 fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ;
420 exit (1) ;
421 }
422
Gordon Henderson178ea082012-08-19 15:17:03 +0100423 pin = atoi (argv [2]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100424 mode = argv [3] ;
425
426// Export the pin and set direction to input
427
428 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
429 {
430 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
431 exit (1) ;
432 }
433
434 fprintf (fd, "%d\n", pin) ;
435 fclose (fd) ;
436
437 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
438 if ((fd = fopen (fName, "w")) == NULL)
439 {
440 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
441 exit (1) ;
442 }
443
444 fprintf (fd, "in\n") ;
445 fclose (fd) ;
446
447 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
448 if ((fd = fopen (fName, "w")) == NULL)
449 {
450 fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
451 exit (1) ;
452 }
453
Gordon Henderson178ea082012-08-19 15:17:03 +0100454 /**/ if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ;
455 else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ;
456 else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
457 else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100458 else
459 {
460 fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
461 exit (1) ;
462 }
463
Gordon Henderson178ea082012-08-19 15:17:03 +0100464// Change ownership of the value and edge files, so the current user can actually use it!
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100465
466 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
Gordon Henderson178ea082012-08-19 15:17:03 +0100467 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100468
469 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
Gordon Henderson178ea082012-08-19 15:17:03 +0100470 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100471
472 fclose (fd) ;
473}
474
475
476/*
477 * doUnexport:
478 * gpio unexport pin
479 * This uses the /sys/class/gpio device interface.
480 *********************************************************************************
481 */
482
483void doUnexport (int argc, char *argv [])
484{
485 FILE *fd ;
486 int pin ;
487
488 if (argc != 3)
489 {
490 fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ;
491 exit (1) ;
492 }
493
494 pin = atoi (argv [2]) ;
495
496 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
497 {
498 fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
499 exit (1) ;
500 }
501
502 fprintf (fd, "%d\n", pin) ;
503 fclose (fd) ;
504}
505
506
507/*
508 * doUnexportAll:
509 * gpio unexportall
510 * Un-Export all the GPIO pins.
511 * This uses the /sys/class/gpio device interface.
512 *********************************************************************************
513 */
514
515void doUnexportall (int argc, char *argv [])
516{
517 FILE *fd ;
518 int pin ;
519
520 for (pin = 0 ; pin < 63 ; ++pin)
521 {
522 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
523 {
524 fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
525 exit (1) ;
526 }
527 fprintf (fd, "%d\n", pin) ;
528 fclose (fd) ;
529 }
530}
531
532
533/*
534 * doMode:
535 * gpio mode pin mode ...
536 *********************************************************************************
537 */
538
539void doMode (int argc, char *argv [])
540{
541 int pin ;
542 char *mode ;
543
544 if (argc != 4)
545 {
546 fprintf (stderr, "Usage: %s mode pin mode\n", argv [0]) ;
547 exit (1) ;
548 }
549
550 pin = atoi (argv [2]) ;
551
552 if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
553 return ;
554
555 mode = argv [3] ;
556
Gordon Henderson178ea082012-08-19 15:17:03 +0100557 /**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
558 else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
559 else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
560 else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
561 else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
562 else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100563 else
564 {
565 fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/up/down/tri\n", argv [1], mode) ;
566 exit (1) ;
567 }
568}
569
570
571/*
572 * doPadDrive:
573 * gpio drive group value
574 *********************************************************************************
575 */
576
Gordon Henderson1bb49892012-08-19 15:33:26 +0100577static void doPadDrive (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100578{
579 int group, val ;
580
581 if (argc != 4)
582 {
583 fprintf (stderr, "Usage: %s drive group value\n", argv [0]) ;
584 exit (1) ;
585 }
586
587 group = atoi (argv [2]) ;
588 val = atoi (argv [3]) ;
589
590 if ((group < 0) || (group > 2))
591 {
592 fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ;
593 exit (1) ;
594 }
595
596 if ((val < 0) || (val > 7))
597 {
598 fprintf (stderr, "%s: drive value not 0-7: %d\n", argv [0], val) ;
599 exit (1) ;
600 }
601
602 setPadDrive (group, val) ;
603}
604
605
606/*
Gordon Henderson99095e32012-08-27 20:56:14 +0100607 * doGbw:
608 * gpio gbw channel value
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000609 * Gertboard Write - To the Analog output
Gordon Henderson99095e32012-08-27 20:56:14 +0100610 *********************************************************************************
611 */
612
613static void doGbw (int argc, char *argv [])
614{
615 int channel, value ;
616
617 if (argc != 4)
618 {
619 fprintf (stderr, "Usage: %s gbr <channel> <value>\n", argv [0]) ;
620 exit (1) ;
621 }
622
623 channel = atoi (argv [2]) ;
624 value = atoi (argv [3]) ;
625
626 if ((channel < 0) || (channel > 1))
627 {
628 fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ;
629 exit (1) ;
630 }
631
632 if ((value < 0) || (value > 1023))
633 {
634 fprintf (stderr, "%s: value must be from 0 to 255\n", argv [0]) ;
635 exit (1) ;
636 }
637
638 if (gertboardSPISetup () == -1)
639 {
640 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
641 exit (1) ;
642 }
643
644 gertboardAnalogWrite (channel, value) ;
645}
646
647
648/*
649 * doGbr:
650 * gpio gbr channel
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000651 * From the analog input
Gordon Henderson99095e32012-08-27 20:56:14 +0100652 *********************************************************************************
653 */
654
655static void doGbr (int argc, char *argv [])
656{
657 int channel ;
658
659 if (argc != 3)
660 {
661 fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ;
662 exit (1) ;
663 }
664
665 channel = atoi (argv [2]) ;
666
667 if ((channel < 0) || (channel > 1))
668 {
669 fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ;
670 exit (1) ;
671 }
672
673 if (gertboardSPISetup () == -1)
674 {
675 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
676 exit (1) ;
677 }
678
679 printf ("%d\n",gertboardAnalogRead (channel)) ;
680}
681
682
683
684/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100685 * doWrite:
686 * gpio write pin value
687 *********************************************************************************
688 */
689
Gordon Henderson1bb49892012-08-19 15:33:26 +0100690static void doWrite (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100691{
692 int pin, val ;
693
694 if (argc != 4)
695 {
696 fprintf (stderr, "Usage: %s write pin value\n", argv [0]) ;
697 exit (1) ;
698 }
699
700 pin = atoi (argv [2]) ;
701
702 if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
703 return ;
704
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000705 /**/ if ((strcasecmp (argv [3], "up") == 0) || (strcasecmp (argv [3], "on") == 0))
706 val = 1 ;
707 else if ((strcasecmp (argv [3], "down") == 0) || (strcasecmp (argv [3], "off") == 0))
708 val = 0 ;
709 else
710 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100711
712 /**/ if (val == 0)
713 digitalWrite (pin, LOW) ;
714 else
715 digitalWrite (pin, HIGH) ;
716}
717
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000718/*
719 * doWriteByte:
720 * gpio write value
721 *********************************************************************************
722 */
723
724static void doWriteByte (int argc, char *argv [])
725{
726 int val ;
727
728 if (argc != 3)
729 {
730 fprintf (stderr, "Usage: %s wb value\n", argv [0]) ;
731 exit (1) ;
732 }
733
734 val = (int)strtol (argv [2], NULL, 0) ;
735
736 digitalWriteByte (val) ;
737}
738
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100739
740/*
741 * doRead:
742 * Read a pin and return the value
743 *********************************************************************************
744 */
745
746void doRead (int argc, char *argv [])
747{
748 int pin, val ;
749
750 if (argc != 3)
751 {
752 fprintf (stderr, "Usage: %s read pin\n", argv [0]) ;
753 exit (1) ;
754 }
755
756 pin = atoi (argv [2]) ;
757
758 if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
759 {
760 printf ("0\n") ;
761 return ;
762 }
763
764 val = digitalRead (pin) ;
765
766 printf ("%s\n", val == 0 ? "0" : "1") ;
767}
768
769
770/*
771 * doPwm:
772 * Output a PWM value on a pin
773 *********************************************************************************
774 */
775
776void doPwm (int argc, char *argv [])
777{
778 int pin, val ;
779
780 if (argc != 4)
781 {
782 fprintf (stderr, "Usage: %s pwm <pin> <value>\n", argv [0]) ;
783 exit (1) ;
784 }
785
786 pin = atoi (argv [2]) ;
787
788 if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
789 return ;
790
791 val = atoi (argv [3]) ;
792
793 pwmWrite (pin, val) ;
794}
795
796
797/*
Gordon Henderson8cb49392012-09-16 10:15:32 +0100798 * doPwmMode: doPwmRange: doPwmClock:
799 * Change the PWM mode, range and clock divider values
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100800 *********************************************************************************
801 */
802
803static void doPwmMode (int mode)
804{
805 pwmSetMode (mode) ;
806}
807
808static void doPwmRange (int argc, char *argv [])
809{
810 unsigned int range ;
811
812 if (argc != 3)
813 {
814 fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
815 exit (1) ;
816 }
817
818 range = (unsigned int)strtoul (argv [2], NULL, 10) ;
819
820 if (range == 0)
821 {
822 fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
823 exit (1) ;
824 }
825
826 pwmSetRange (range) ;
827}
828
Gordon Henderson8cb49392012-09-16 10:15:32 +0100829static void doPwmClock (int argc, char *argv [])
830{
831 unsigned int clock ;
832
833 if (argc != 3)
834 {
835 fprintf (stderr, "Usage: %s pwmc <clock>\n", argv [0]) ;
836 exit (1) ;
837 }
838
839 clock = (unsigned int)strtoul (argv [2], NULL, 10) ;
840
841 if ((clock < 1) || (clock > 4095))
842 {
843 fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ;
844 exit (1) ;
845 }
846
847 pwmSetClock (clock) ;
848}
849
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100850
851/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100852 * main:
853 * Start here
854 *********************************************************************************
855 */
856
857int main (int argc, char *argv [])
858{
859 int i ;
860
Gordon Henderson13bbba72013-01-14 11:31:56 +0000861 if (getenv ("WIRINGPI_DEBUG") != NULL)
862 {
863 printf ("gpio: wiringPi debug mode enabled\n") ;
864 wiringPiDebug = TRUE ;
865 }
866
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100867 if (argc == 1)
868 {
Gordon Henderson86a5c682012-10-02 14:32:12 +0100869 fprintf (stderr, "%s\n", usage) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100870 return 1 ;
871 }
872
Gordon Henderson178ea082012-08-19 15:17:03 +0100873 if (strcasecmp (argv [1], "-h") == 0)
874 {
875 printf ("%s: %s\n", argv [0], usage) ;
876 return 0 ;
877 }
878
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100879 if (strcasecmp (argv [1], "-v") == 0)
880 {
881 printf ("gpio version: %s\n", VERSION) ;
882 printf ("Copyright (c) 2012 Gordon Henderson\n") ;
883 printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
884 printf ("For details type: %s -warranty\n", argv [0]) ;
Gordon Henderson86a5c682012-10-02 14:32:12 +0100885 printf ("\n") ;
886 printf ("This Raspberry Pi is a revision %d board.\n", piBoardRev ()) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100887 return 0 ;
888 }
889
890 if (strcasecmp (argv [1], "-warranty") == 0)
891 {
892 printf ("gpio version: %s\n", VERSION) ;
893 printf ("Copyright (c) 2012 Gordon Henderson\n") ;
894 printf ("\n") ;
895 printf (" This program is free software; you can redistribute it and/or modify\n") ;
896 printf (" it under the terms of the GNU Leser General Public License as published\n") ;
897 printf (" by the Free Software Foundation, either version 3 of the License, or\n") ;
898 printf (" (at your option) any later version.\n") ;
899 printf ("\n") ;
900 printf (" This program is distributed in the hope that it will be useful,\n") ;
901 printf (" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
902 printf (" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") ;
903 printf (" GNU Lesser General Public License for more details.\n") ;
904 printf ("\n") ;
905 printf (" You should have received a copy of the GNU Lesser General Public License\n") ;
906 printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
907 printf ("\n") ;
908 return 0 ;
909 }
910
911 if (geteuid () != 0)
912 {
913 fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
914 return 1 ;
915 }
916
917// Initial test for /sys/class/gpio operations:
918
Gordon Henderson178ea082012-08-19 15:17:03 +0100919 /**/ if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; }
920 else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; }
921 else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100922 else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argc, argv) ; return 0 ; }
Gordon Henderson178ea082012-08-19 15:17:03 +0100923 else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }
924
Gordon Henderson86a5c682012-10-02 14:32:12 +0100925// Check for load command:
Gordon Henderson178ea082012-08-19 15:17:03 +0100926
Gordon Henderson178ea082012-08-19 15:17:03 +0100927 if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100928
Gordon Henderson99095e32012-08-27 20:56:14 +0100929// Gertboard commands
930
931 if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; }
932 if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; }
933
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100934// Check for -g argument
935
936 if (strcasecmp (argv [1], "-g") == 0)
937 {
938 if (wiringPiSetupGpio () == -1)
939 {
Gordon Henderson178ea082012-08-19 15:17:03 +0100940 fprintf (stderr, "%s: Unable to initialise GPIO mode.\n", argv [0]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100941 exit (1) ;
942 }
943
944 for (i = 2 ; i < argc ; ++i)
945 argv [i - 1] = argv [i] ;
946 --argc ;
947 wpMode = WPI_MODE_GPIO ;
948 }
949
950// Check for -p argument for PiFace
951
952 else if (strcasecmp (argv [1], "-p") == 0)
953 {
954 if (wiringPiSetupPiFaceForGpioProg () == -1)
955 {
956 fprintf (stderr, "%s: Unable to initialise PiFace.\n", argv [0]) ;
957 exit (1) ;
958 }
959
960 for (i = 2 ; i < argc ; ++i)
961 argv [i - 1] = argv [i] ;
962 --argc ;
963 wpMode = WPI_MODE_PIFACE ;
964 }
965
966// Default to wiringPi mode
967
968 else
969 {
970 if (wiringPiSetup () == -1)
971 {
Gordon Henderson178ea082012-08-19 15:17:03 +0100972 fprintf (stderr, "%s: Unable to initialise wiringPi mode\n", argv [0]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100973 exit (1) ;
974 }
975 wpMode = WPI_MODE_PINS ;
976 }
977
Gordon Henderson86a5c682012-10-02 14:32:12 +0100978// Check for PWM or Pad Drive operations
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100979
980 if (wpMode != WPI_MODE_PIFACE)
981 {
Gordon Henderson86a5c682012-10-02 14:32:12 +0100982 if (strcasecmp (argv [1], "pwm-bal") == 0) { doPwmMode (PWM_MODE_BAL) ; return 0 ; }
983 if (strcasecmp (argv [1], "pwm-ms") == 0) { doPwmMode (PWM_MODE_MS) ; return 0 ; }
984 if (strcasecmp (argv [1], "pwmr") == 0) { doPwmRange (argc, argv) ; return 0 ; }
985 if (strcasecmp (argv [1], "pwmc") == 0) { doPwmClock (argc, argv) ; return 0 ; }
986 if (strcasecmp (argv [1], "drive") == 0) { doPadDrive (argc, argv) ; return 0 ; }
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100987 }
988
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100989// Check for wiring commands
990
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000991 /**/ if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ;
992 else if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ;
993 else if (strcasecmp (argv [1], "write") == 0) doWrite (argc, argv) ;
994 else if (strcasecmp (argv [1], "wb") == 0) doWriteByte (argc, argv) ;
995 else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ;
996 else if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100997 else
998 {
Gordon Henderson178ea082012-08-19 15:17:03 +0100999 fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001000 exit (1) ;
1001 }
1002 return 0 ;
1003}