blob: 52fcb6fc554470032f6e21782098c15e792ef5c3 [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 Hendersonbf0ad862012-08-16 15:04:43 +010038#ifndef TRUE
39# define TRUE (1==1)
40# define FALSE (1==2)
41#endif
42
Gordon Henderson25e4ec52012-12-06 21:49:41 +000043#define VERSION "1.5"
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010044
45static int wpMode ;
46
47char *usage = "Usage: gpio -v\n"
Gordon Henderson178ea082012-08-19 15:17:03 +010048 " gpio -h\n"
Gordon Henderson25e4ec52012-12-06 21:49:41 +000049 " gpio [-g] <read/write/wb/pwm/mode> ...\n"
50 " gpio [-p] <read/write/wb> ...\n"
Gordon Henderson183c5a62012-10-21 15:25:16 +010051 " gpio readall\n"
52 " gpio unexportall/exports ...\n"
53 " gpio export/edge/unexport ...\n"
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010054 " gpio drive <group> <value>\n"
Gordon Hendersonf99ffed2012-08-19 15:12:45 +010055 " gpio pwm-bal/pwm-ms \n"
56 " gpio pwmr <range> \n"
Gordon Henderson8cb49392012-09-16 10:15:32 +010057 " gpio pwmc <divider> \n"
Gordon Henderson99095e32012-08-27 20:56:14 +010058 " gpio load spi/i2c\n"
59 " gpio gbr <channel>\n"
Gordon Henderson8cb49392012-09-16 10:15:32 +010060 " gpio gbw <channel> <value>" ; // No trailing newline needed here.
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010061
62
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010063/*
64 * changeOwner:
65 * Change the ownership of the file to the real userId of the calling
66 * program so we can access it.
67 *********************************************************************************
68 */
69
70static void changeOwner (char *cmd, char *file)
71{
72 uid_t uid = getuid () ;
73 uid_t gid = getgid () ;
74
75 if (chown (file, uid, gid) != 0)
76 {
77 if (errno == ENOENT) // Warn that it's not there
78 fprintf (stderr, "%s: Warning: File not present: %s\n", cmd, file) ;
79 else
80 {
81 fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ;
82 exit (1) ;
83 }
84 }
85}
86
87
88/*
89 * moduleLoaded:
90 * Return true/false if the supplied module is loaded
91 *********************************************************************************
92 */
93
94static int moduleLoaded (char *modName)
95{
96 int len = strlen (modName) ;
97 int found = FALSE ;
98 FILE *fd = fopen ("/proc/modules", "r") ;
99 char line [80] ;
100
101 if (fd == NULL)
102 {
103 fprintf (stderr, "gpio: Unable to check modules: %s\n", strerror (errno)) ;
104 exit (1) ;
105 }
106
107 while (fgets (line, 80, fd) != NULL)
108 {
109 if (strncmp (line, modName, len) != 0)
110 continue ;
111
112 found = TRUE ;
113 break ;
114 }
115
116 fclose (fd) ;
117
118 return found ;
119}
120
121
122/*
123 * doLoad:
124 * Load either the spi or i2c modules and change device ownerships, etc.
125 *********************************************************************************
126 */
127
128static void _doLoadUsage (char *argv [])
129{
130 fprintf (stderr, "Usage: %s load <spi/i2c>\n", argv [0]) ;
131 exit (1) ;
132}
133
134static void doLoad (int argc, char *argv [])
135{
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000136 char *module1, *module2 ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100137 char cmd [80] ;
138 char *file1, *file2 ;
139
140 if (argc != 3)
141 _doLoadUsage (argv) ;
142
143 /**/ if (strcasecmp (argv [2], "spi") == 0)
144 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000145 module1 = "spidev" ;
146 module2 = "spi_bcm2708" ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100147 file1 = "/dev/spidev0.0" ;
148 file2 = "/dev/spidev0.1" ;
149 }
150 else if (strcasecmp (argv [2], "i2c") == 0)
151 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000152 module1 = "i2c_dev" ;
153 module2 = "i2c_bcm2708" ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100154 file1 = "/dev/i2c-0" ;
155 file2 = "/dev/i2c-1" ;
156 }
157 else
158 _doLoadUsage (argv) ;
159
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000160 if (!moduleLoaded (module1))
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100161 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000162 sprintf (cmd, "modprobe %s", module1) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100163 system (cmd) ;
164 }
165
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000166 if (!moduleLoaded (module2))
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100167 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000168 sprintf (cmd, "modprobe %s", module2) ;
169 system (cmd) ;
170 }
171
172 if (!moduleLoaded (module2))
173 {
174 fprintf (stderr, "%s: Unable to load %s\n", argv [0], module2) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100175 exit (1) ;
176 }
177
178 sleep (1) ; // To let things get settled
179
180 changeOwner (argv [0], file1) ;
181 changeOwner (argv [0], file2) ;
182}
183
184
Gordon Henderson183c5a62012-10-21 15:25:16 +0100185/*
186 * doReadall:
187 * Read all the GPIO pins
188 *********************************************************************************
189 */
190
191static char *pinNames [] =
192{
193 "GPIO 0",
194 "GPIO 1",
195 "GPIO 2",
196 "GPIO 3",
197 "GPIO 4",
198 "GPIO 5",
199 "GPIO 6",
200 "GPIO 7",
201 "SDA ",
202 "SCL ",
203 "CE0 ",
204 "CE1 ",
205 "MOSI ",
206 "MISO ",
207 "SCLK ",
208 "TxD ",
209 "RxD ",
210 "GPIO 8",
211 "GPIO 9",
212 "GPIO10",
213 "GPIO11",
214} ;
215
216static void doReadall (void)
217{
218 int pin ;
219
220 printf ("+----------+------+--------+-------+\n") ;
221 printf ("| wiringPi | GPIO | Name | Value |\n") ;
222 printf ("+----------+------+--------+-------+\n") ;
223
224 for (pin = 0 ; pin < NUM_PINS ; ++pin)
225 printf ("| %6d | %3d | %s | %s |\n",
226 pin, wpiPinToGpio (pin),
227 pinNames [pin],
228 digitalRead (pin) == HIGH ? "High" : "Low ") ;
229
230 printf ("+----------+------+--------+-------+\n") ;
231
232 if (piBoardRev () == 1)
233 return ;
234
235 for (pin = 17 ; pin <= 20 ; ++pin)
236 printf ("| %6d | %3d | %s | %s |\n",
237 pin, wpiPinToGpio (pin),
238 pinNames [pin],
239 digitalRead (pin) == HIGH ? "High" : "Low ") ;
240
241 printf ("+----------+------+--------+-------+\n") ;
242}
243
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100244
245/*
246 * doExports:
247 * List all GPIO exports
248 *********************************************************************************
249 */
250
Gordon Henderson178ea082012-08-19 15:17:03 +0100251static void doExports (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100252{
253 int fd ;
254 int i, l, first ;
255 char fName [128] ;
256 char buf [16] ;
257
258// Rather crude, but who knows what others are up to...
259
260 for (first = 0, i = 0 ; i < 64 ; ++i)
261 {
262
263// Try to read the direction
264
265 sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ;
266 if ((fd = open (fName, O_RDONLY)) == -1)
267 continue ;
268
269 if (first == 0)
270 {
271 ++first ;
272 printf ("GPIO Pins exported:\n") ;
273 }
274
275 printf ("%4d: ", i) ;
276
277 if ((l = read (fd, buf, 16)) == 0)
278 sprintf (buf, "%s", "?") ;
279
280 buf [l] = 0 ;
281 if ((buf [strlen (buf) - 1]) == '\n')
282 buf [strlen (buf) - 1] = 0 ;
283
284 printf ("%-3s", buf) ;
285
286 close (fd) ;
287
288// Try to Read the value
289
290 sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ;
291 if ((fd = open (fName, O_RDONLY)) == -1)
292 {
293 printf ("No Value file (huh?)\n") ;
294 continue ;
295 }
296
297 if ((l = read (fd, buf, 16)) == 0)
298 sprintf (buf, "%s", "?") ;
299
300 buf [l] = 0 ;
301 if ((buf [strlen (buf) - 1]) == '\n')
302 buf [strlen (buf) - 1] = 0 ;
303
304 printf (" %s", buf) ;
305
306// Read any edge trigger file
307
308 sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ;
309 if ((fd = open (fName, O_RDONLY)) == -1)
310 {
311 printf ("\n") ;
312 continue ;
313 }
314
315 if ((l = read (fd, buf, 16)) == 0)
316 sprintf (buf, "%s", "?") ;
317
318 buf [l] = 0 ;
319 if ((buf [strlen (buf) - 1]) == '\n')
320 buf [strlen (buf) - 1] = 0 ;
321
322 printf (" %-8s\n", buf) ;
323
324 close (fd) ;
325 }
326}
327
328
329/*
330 * doExport:
331 * gpio export pin mode
332 * This uses the /sys/class/gpio device interface.
333 *********************************************************************************
334 */
335
336void doExport (int argc, char *argv [])
337{
338 FILE *fd ;
339 int pin ;
340 char *mode ;
341 char fName [128] ;
342
343 if (argc != 4)
344 {
345 fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ;
346 exit (1) ;
347 }
348
349 pin = atoi (argv [2]) ;
350
351 mode = argv [3] ;
352
353 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
354 {
355 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
356 exit (1) ;
357 }
358
359 fprintf (fd, "%d\n", pin) ;
360 fclose (fd) ;
361
362 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
363 if ((fd = fopen (fName, "w")) == NULL)
364 {
365 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
366 exit (1) ;
367 }
368
369 /**/ if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0))
370 fprintf (fd, "in\n") ;
371 else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0))
372 fprintf (fd, "out\n") ;
373 else
374 {
375 fprintf (stderr, "%s: Invalid mode: %s. Should be in or out\n", argv [1], mode) ;
376 exit (1) ;
377 }
378
379 fclose (fd) ;
380
381// Change ownership so the current user can actually use it!
382
383 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
384 changeOwner (argv [0], fName) ;
385
386 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
387 changeOwner (argv [0], fName) ;
388
389}
390
391
392/*
393 * doEdge:
394 * gpio edge pin mode
395 * Easy access to changing the edge trigger on a GPIO pin
396 * This uses the /sys/class/gpio device interface.
397 *********************************************************************************
398 */
399
400void doEdge (int argc, char *argv [])
401{
402 FILE *fd ;
403 int pin ;
404 char *mode ;
405 char fName [128] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100406
407 if (argc != 4)
408 {
409 fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ;
410 exit (1) ;
411 }
412
Gordon Henderson178ea082012-08-19 15:17:03 +0100413 pin = atoi (argv [2]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100414 mode = argv [3] ;
415
416// Export the pin and set direction to input
417
418 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
419 {
420 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
421 exit (1) ;
422 }
423
424 fprintf (fd, "%d\n", pin) ;
425 fclose (fd) ;
426
427 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
428 if ((fd = fopen (fName, "w")) == NULL)
429 {
430 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
431 exit (1) ;
432 }
433
434 fprintf (fd, "in\n") ;
435 fclose (fd) ;
436
437 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
438 if ((fd = fopen (fName, "w")) == NULL)
439 {
440 fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
441 exit (1) ;
442 }
443
Gordon Henderson178ea082012-08-19 15:17:03 +0100444 /**/ if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ;
445 else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ;
446 else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
447 else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100448 else
449 {
450 fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
451 exit (1) ;
452 }
453
Gordon Henderson178ea082012-08-19 15:17:03 +0100454// Change ownership of the value and edge files, so the current user can actually use it!
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100455
456 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
Gordon Henderson178ea082012-08-19 15:17:03 +0100457 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100458
459 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
Gordon Henderson178ea082012-08-19 15:17:03 +0100460 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100461
462 fclose (fd) ;
463}
464
465
466/*
467 * doUnexport:
468 * gpio unexport pin
469 * This uses the /sys/class/gpio device interface.
470 *********************************************************************************
471 */
472
473void doUnexport (int argc, char *argv [])
474{
475 FILE *fd ;
476 int pin ;
477
478 if (argc != 3)
479 {
480 fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ;
481 exit (1) ;
482 }
483
484 pin = atoi (argv [2]) ;
485
486 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
487 {
488 fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
489 exit (1) ;
490 }
491
492 fprintf (fd, "%d\n", pin) ;
493 fclose (fd) ;
494}
495
496
497/*
498 * doUnexportAll:
499 * gpio unexportall
500 * Un-Export all the GPIO pins.
501 * This uses the /sys/class/gpio device interface.
502 *********************************************************************************
503 */
504
505void doUnexportall (int argc, char *argv [])
506{
507 FILE *fd ;
508 int pin ;
509
510 for (pin = 0 ; pin < 63 ; ++pin)
511 {
512 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
513 {
514 fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
515 exit (1) ;
516 }
517 fprintf (fd, "%d\n", pin) ;
518 fclose (fd) ;
519 }
520}
521
522
523/*
524 * doMode:
525 * gpio mode pin mode ...
526 *********************************************************************************
527 */
528
529void doMode (int argc, char *argv [])
530{
531 int pin ;
532 char *mode ;
533
534 if (argc != 4)
535 {
536 fprintf (stderr, "Usage: %s mode pin mode\n", argv [0]) ;
537 exit (1) ;
538 }
539
540 pin = atoi (argv [2]) ;
541
542 if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
543 return ;
544
545 mode = argv [3] ;
546
Gordon Henderson178ea082012-08-19 15:17:03 +0100547 /**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
548 else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
549 else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
550 else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
551 else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
552 else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100553 else
554 {
555 fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/up/down/tri\n", argv [1], mode) ;
556 exit (1) ;
557 }
558}
559
560
561/*
562 * doPadDrive:
563 * gpio drive group value
564 *********************************************************************************
565 */
566
Gordon Henderson1bb49892012-08-19 15:33:26 +0100567static void doPadDrive (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100568{
569 int group, val ;
570
571 if (argc != 4)
572 {
573 fprintf (stderr, "Usage: %s drive group value\n", argv [0]) ;
574 exit (1) ;
575 }
576
577 group = atoi (argv [2]) ;
578 val = atoi (argv [3]) ;
579
580 if ((group < 0) || (group > 2))
581 {
582 fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ;
583 exit (1) ;
584 }
585
586 if ((val < 0) || (val > 7))
587 {
588 fprintf (stderr, "%s: drive value not 0-7: %d\n", argv [0], val) ;
589 exit (1) ;
590 }
591
592 setPadDrive (group, val) ;
593}
594
595
596/*
Gordon Henderson99095e32012-08-27 20:56:14 +0100597 * doGbw:
598 * gpio gbw channel value
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000599 * Gertboard Write - To the Analog output
Gordon Henderson99095e32012-08-27 20:56:14 +0100600 *********************************************************************************
601 */
602
603static void doGbw (int argc, char *argv [])
604{
605 int channel, value ;
606
607 if (argc != 4)
608 {
609 fprintf (stderr, "Usage: %s gbr <channel> <value>\n", argv [0]) ;
610 exit (1) ;
611 }
612
613 channel = atoi (argv [2]) ;
614 value = atoi (argv [3]) ;
615
616 if ((channel < 0) || (channel > 1))
617 {
618 fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ;
619 exit (1) ;
620 }
621
622 if ((value < 0) || (value > 1023))
623 {
624 fprintf (stderr, "%s: value must be from 0 to 255\n", argv [0]) ;
625 exit (1) ;
626 }
627
628 if (gertboardSPISetup () == -1)
629 {
630 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
631 exit (1) ;
632 }
633
634 gertboardAnalogWrite (channel, value) ;
635}
636
637
638/*
639 * doGbr:
640 * gpio gbr channel
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000641 * From the analog input
Gordon Henderson99095e32012-08-27 20:56:14 +0100642 *********************************************************************************
643 */
644
645static void doGbr (int argc, char *argv [])
646{
647 int channel ;
648
649 if (argc != 3)
650 {
651 fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ;
652 exit (1) ;
653 }
654
655 channel = atoi (argv [2]) ;
656
657 if ((channel < 0) || (channel > 1))
658 {
659 fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ;
660 exit (1) ;
661 }
662
663 if (gertboardSPISetup () == -1)
664 {
665 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
666 exit (1) ;
667 }
668
669 printf ("%d\n",gertboardAnalogRead (channel)) ;
670}
671
672
673
674/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100675 * doWrite:
676 * gpio write pin value
677 *********************************************************************************
678 */
679
Gordon Henderson1bb49892012-08-19 15:33:26 +0100680static void doWrite (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100681{
682 int pin, val ;
683
684 if (argc != 4)
685 {
686 fprintf (stderr, "Usage: %s write pin value\n", argv [0]) ;
687 exit (1) ;
688 }
689
690 pin = atoi (argv [2]) ;
691
692 if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
693 return ;
694
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000695 /**/ if ((strcasecmp (argv [3], "up") == 0) || (strcasecmp (argv [3], "on") == 0))
696 val = 1 ;
697 else if ((strcasecmp (argv [3], "down") == 0) || (strcasecmp (argv [3], "off") == 0))
698 val = 0 ;
699 else
700 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100701
702 /**/ if (val == 0)
703 digitalWrite (pin, LOW) ;
704 else
705 digitalWrite (pin, HIGH) ;
706}
707
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000708/*
709 * doWriteByte:
710 * gpio write value
711 *********************************************************************************
712 */
713
714static void doWriteByte (int argc, char *argv [])
715{
716 int val ;
717
718 if (argc != 3)
719 {
720 fprintf (stderr, "Usage: %s wb value\n", argv [0]) ;
721 exit (1) ;
722 }
723
724 val = (int)strtol (argv [2], NULL, 0) ;
725
726 digitalWriteByte (val) ;
727}
728
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100729
730/*
731 * doRead:
732 * Read a pin and return the value
733 *********************************************************************************
734 */
735
736void doRead (int argc, char *argv [])
737{
738 int pin, val ;
739
740 if (argc != 3)
741 {
742 fprintf (stderr, "Usage: %s read pin\n", argv [0]) ;
743 exit (1) ;
744 }
745
746 pin = atoi (argv [2]) ;
747
748 if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
749 {
750 printf ("0\n") ;
751 return ;
752 }
753
754 val = digitalRead (pin) ;
755
756 printf ("%s\n", val == 0 ? "0" : "1") ;
757}
758
759
760/*
761 * doPwm:
762 * Output a PWM value on a pin
763 *********************************************************************************
764 */
765
766void doPwm (int argc, char *argv [])
767{
768 int pin, val ;
769
770 if (argc != 4)
771 {
772 fprintf (stderr, "Usage: %s pwm <pin> <value>\n", argv [0]) ;
773 exit (1) ;
774 }
775
776 pin = atoi (argv [2]) ;
777
778 if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
779 return ;
780
781 val = atoi (argv [3]) ;
782
783 pwmWrite (pin, val) ;
784}
785
786
787/*
Gordon Henderson8cb49392012-09-16 10:15:32 +0100788 * doPwmMode: doPwmRange: doPwmClock:
789 * Change the PWM mode, range and clock divider values
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100790 *********************************************************************************
791 */
792
793static void doPwmMode (int mode)
794{
795 pwmSetMode (mode) ;
796}
797
798static void doPwmRange (int argc, char *argv [])
799{
800 unsigned int range ;
801
802 if (argc != 3)
803 {
804 fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
805 exit (1) ;
806 }
807
808 range = (unsigned int)strtoul (argv [2], NULL, 10) ;
809
810 if (range == 0)
811 {
812 fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
813 exit (1) ;
814 }
815
816 pwmSetRange (range) ;
817}
818
Gordon Henderson8cb49392012-09-16 10:15:32 +0100819static void doPwmClock (int argc, char *argv [])
820{
821 unsigned int clock ;
822
823 if (argc != 3)
824 {
825 fprintf (stderr, "Usage: %s pwmc <clock>\n", argv [0]) ;
826 exit (1) ;
827 }
828
829 clock = (unsigned int)strtoul (argv [2], NULL, 10) ;
830
831 if ((clock < 1) || (clock > 4095))
832 {
833 fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ;
834 exit (1) ;
835 }
836
837 pwmSetClock (clock) ;
838}
839
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100840
841/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100842 * main:
843 * Start here
844 *********************************************************************************
845 */
846
847int main (int argc, char *argv [])
848{
849 int i ;
850
851 if (argc == 1)
852 {
Gordon Henderson86a5c682012-10-02 14:32:12 +0100853 fprintf (stderr, "%s\n", usage) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100854 return 1 ;
855 }
856
Gordon Henderson178ea082012-08-19 15:17:03 +0100857 if (strcasecmp (argv [1], "-h") == 0)
858 {
859 printf ("%s: %s\n", argv [0], usage) ;
860 return 0 ;
861 }
862
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100863 if (strcasecmp (argv [1], "-v") == 0)
864 {
865 printf ("gpio version: %s\n", VERSION) ;
866 printf ("Copyright (c) 2012 Gordon Henderson\n") ;
867 printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
868 printf ("For details type: %s -warranty\n", argv [0]) ;
Gordon Henderson86a5c682012-10-02 14:32:12 +0100869 printf ("\n") ;
870 printf ("This Raspberry Pi is a revision %d board.\n", piBoardRev ()) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100871 return 0 ;
872 }
873
874 if (strcasecmp (argv [1], "-warranty") == 0)
875 {
876 printf ("gpio version: %s\n", VERSION) ;
877 printf ("Copyright (c) 2012 Gordon Henderson\n") ;
878 printf ("\n") ;
879 printf (" This program is free software; you can redistribute it and/or modify\n") ;
880 printf (" it under the terms of the GNU Leser General Public License as published\n") ;
881 printf (" by the Free Software Foundation, either version 3 of the License, or\n") ;
882 printf (" (at your option) any later version.\n") ;
883 printf ("\n") ;
884 printf (" This program is distributed in the hope that it will be useful,\n") ;
885 printf (" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
886 printf (" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") ;
887 printf (" GNU Lesser General Public License for more details.\n") ;
888 printf ("\n") ;
889 printf (" You should have received a copy of the GNU Lesser General Public License\n") ;
890 printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
891 printf ("\n") ;
892 return 0 ;
893 }
894
895 if (geteuid () != 0)
896 {
897 fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
898 return 1 ;
899 }
900
901// Initial test for /sys/class/gpio operations:
902
Gordon Henderson178ea082012-08-19 15:17:03 +0100903 /**/ if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; }
904 else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; }
905 else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100906 else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argc, argv) ; return 0 ; }
Gordon Henderson178ea082012-08-19 15:17:03 +0100907 else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }
908
Gordon Henderson86a5c682012-10-02 14:32:12 +0100909// Check for load command:
Gordon Henderson178ea082012-08-19 15:17:03 +0100910
Gordon Henderson178ea082012-08-19 15:17:03 +0100911 if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100912
Gordon Henderson99095e32012-08-27 20:56:14 +0100913// Gertboard commands
914
915 if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; }
916 if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; }
917
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100918// Check for -g argument
919
920 if (strcasecmp (argv [1], "-g") == 0)
921 {
922 if (wiringPiSetupGpio () == -1)
923 {
Gordon Henderson178ea082012-08-19 15:17:03 +0100924 fprintf (stderr, "%s: Unable to initialise GPIO mode.\n", argv [0]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100925 exit (1) ;
926 }
927
928 for (i = 2 ; i < argc ; ++i)
929 argv [i - 1] = argv [i] ;
930 --argc ;
931 wpMode = WPI_MODE_GPIO ;
932 }
933
934// Check for -p argument for PiFace
935
936 else if (strcasecmp (argv [1], "-p") == 0)
937 {
938 if (wiringPiSetupPiFaceForGpioProg () == -1)
939 {
940 fprintf (stderr, "%s: Unable to initialise PiFace.\n", argv [0]) ;
941 exit (1) ;
942 }
943
944 for (i = 2 ; i < argc ; ++i)
945 argv [i - 1] = argv [i] ;
946 --argc ;
947 wpMode = WPI_MODE_PIFACE ;
948 }
949
950// Default to wiringPi mode
951
952 else
953 {
954 if (wiringPiSetup () == -1)
955 {
Gordon Henderson178ea082012-08-19 15:17:03 +0100956 fprintf (stderr, "%s: Unable to initialise wiringPi mode\n", argv [0]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100957 exit (1) ;
958 }
959 wpMode = WPI_MODE_PINS ;
960 }
961
Gordon Henderson86a5c682012-10-02 14:32:12 +0100962// Check for PWM or Pad Drive operations
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100963
964 if (wpMode != WPI_MODE_PIFACE)
965 {
Gordon Henderson86a5c682012-10-02 14:32:12 +0100966 if (strcasecmp (argv [1], "pwm-bal") == 0) { doPwmMode (PWM_MODE_BAL) ; return 0 ; }
967 if (strcasecmp (argv [1], "pwm-ms") == 0) { doPwmMode (PWM_MODE_MS) ; return 0 ; }
968 if (strcasecmp (argv [1], "pwmr") == 0) { doPwmRange (argc, argv) ; return 0 ; }
969 if (strcasecmp (argv [1], "pwmc") == 0) { doPwmClock (argc, argv) ; return 0 ; }
970 if (strcasecmp (argv [1], "drive") == 0) { doPadDrive (argc, argv) ; return 0 ; }
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100971 }
972
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100973// Check for wiring commands
974
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000975 /**/ if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ;
976 else if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ;
977 else if (strcasecmp (argv [1], "write") == 0) doWrite (argc, argv) ;
978 else if (strcasecmp (argv [1], "wb") == 0) doWriteByte (argc, argv) ;
979 else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ;
980 else if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100981 else
982 {
Gordon Henderson178ea082012-08-19 15:17:03 +0100983 fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100984 exit (1) ;
985 }
986 return 0 ;
987}