blob: c954f3b9f09e4338d35285115c8eaa2859f547af [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 Hendersoneb1fc2c2015-01-30 18:14:49 +00005 * Copyright (c) 2012-2015 Gordon Henderson
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01006 ***********************************************************************
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>
Gordon Hendersonda384432013-05-13 19:43:26 +010029#include <ctype.h>
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010030#include <string.h>
31#include <unistd.h>
32#include <errno.h>
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010033#include <fcntl.h>
Gordon Hendersonda384432013-05-13 19:43:26 +010034#include <sys/types.h>
35#include <sys/stat.h>
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010036
Gordon Henderson99095e32012-08-27 20:56:14 +010037#include <wiringPi.h>
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +000038#include <wpiExtensions.h>
Gordon Hendersonda384432013-05-13 19:43:26 +010039
Gordon Henderson99095e32012-08-27 20:56:14 +010040#include <gertboard.h>
Gordon Hendersonda384432013-05-13 19:43:26 +010041#include <piFace.h>
42
Gordon Henderson7cb81742015-01-31 16:43:08 +000043#include "version.h"
Gordon Henderson99095e32012-08-27 20:56:14 +010044
Gordon Henderson13bbba72013-01-14 11:31:56 +000045extern int wiringPiDebug ;
46
Gordon Henderson05e2f672014-05-20 11:43:07 +010047// External functions I can't be bothered creating a separate .h file for:
48
Gordon Henderson27698762013-06-27 21:51:55 +010049extern void doReadall (void) ;
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000050extern void doAllReadall (void) ;
Gordon Henderson05e2f672014-05-20 11:43:07 +010051extern void doPins (void) ;
52
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010053#ifndef TRUE
54# define TRUE (1==1)
55# define FALSE (1==2)
56#endif
57
Gordon Hendersondf453882014-07-17 22:23:57 +010058#define PI_USB_POWER_CONTROL 38
59#define I2CDETECT "/usr/sbin/i2cdetect"
Gordon Hendersonb1dfc182016-12-12 14:19:55 +000060#define MODPROBE "/sbin/modprobe"
61#define RMMOD "/sbin/rmmod"
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010062
Gordon Henderson27698762013-06-27 21:51:55 +010063int wpMode ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010064
65char *usage = "Usage: gpio -v\n"
Gordon Henderson178ea082012-08-19 15:17:03 +010066 " gpio -h\n"
Gordon Hendersonda384432013-05-13 19:43:26 +010067 " gpio [-g|-1] [-x extension:params] ...\n"
Gordon Henderson25e4ec52012-12-06 21:49:41 +000068 " gpio [-p] <read/write/wb> ...\n"
Gordon Hendersonda384432013-05-13 19:43:26 +010069 " gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n"
Gordon Hendersonb1dfc182016-12-12 14:19:55 +000070 " gpio <toggle/blink> <pin>\n"
Gordon Hendersonda384432013-05-13 19:43:26 +010071 " gpio readall/reset\n"
72 " gpio unexportall/exports\n"
Gordon Henderson183c5a62012-10-21 15:25:16 +010073 " gpio export/edge/unexport ...\n"
Gordon Hendersonda384432013-05-13 19:43:26 +010074 " gpio wfi <pin> <mode>\n"
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010075 " gpio drive <group> <value>\n"
Gordon Hendersonf99ffed2012-08-19 15:12:45 +010076 " gpio pwm-bal/pwm-ms \n"
77 " gpio pwmr <range> \n"
Gordon Henderson8cb49392012-09-16 10:15:32 +010078 " gpio pwmc <divider> \n"
Gordon Henderson99095e32012-08-27 20:56:14 +010079 " gpio load spi/i2c\n"
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +000080 " gpio unload spi/i2c\n"
Gordon Hendersonda384432013-05-13 19:43:26 +010081 " gpio i2cd/i2cdetect\n"
Gordon Hendersonb1dfc182016-12-12 14:19:55 +000082 " gpio rbx/rbd\n"
83 " gpio wb <value>\n"
Gordon Hendersondf453882014-07-17 22:23:57 +010084 " gpio usbp high/low\n"
Gordon Henderson99095e32012-08-27 20:56:14 +010085 " gpio gbr <channel>\n"
Gordon Henderson8cb49392012-09-16 10:15:32 +010086 " gpio gbw <channel> <value>" ; // No trailing newline needed here.
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010087
88
Gordon Henderson6fba4032014-06-24 19:23:31 +010089#ifdef NOT_FOR_NOW
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010090/*
Gordon Hendersonf18c8f72013-08-03 23:53:35 +010091 * decodePin:
92 * Decode a pin "number" which can actually be a pin name to represent
93 * one of the Pi's on-board pins.
94 *********************************************************************************
95 */
96
97static int decodePin (const char *str)
98{
99
100// The first case - see if it's a number:
101
102 if (isdigit (str [0]))
103 return atoi (str) ;
104
105 return 0 ;
106}
Gordon Henderson6fba4032014-06-24 19:23:31 +0100107#endif
Gordon Hendersonf18c8f72013-08-03 23:53:35 +0100108
109
110/*
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000111 * findExecutable:
112 * Code to locate the path to the given executable. We have a fixed list
113 * of locations to try which completely overrides any $PATH environment.
114 * This may be detrimental, however it avoids the reliance on $PATH
115 * which may be a security issue when this program is run a set-uid-root.
116 *********************************************************************************
117 */
118
119static const char *searchPath [] =
120{
121 "/sbin",
122 "/usr/sbin",
123 "/bin",
124 "/usr/bin",
125 NULL,
126} ;
127
128static char *findExecutable (const char *progName)
129{
130 static char *path = NULL ;
131 int len = strlen (progName) ;
132 int i = 0 ;
133 struct stat statBuf ;
134
135 for (i = 0 ; searchPath [i] != NULL ; ++i)
136 {
137 path = malloc (strlen (searchPath [i]) + len + 2) ;
138 sprintf (path, "%s/%s", searchPath [i], progName) ;
139
140 if (stat (path, &statBuf) == 0)
141 return path ;
142 free (path) ;
143 }
144
145 return NULL ;
146}
147
148
149/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100150 * changeOwner:
151 * Change the ownership of the file to the real userId of the calling
152 * program so we can access it.
153 *********************************************************************************
154 */
155
156static void changeOwner (char *cmd, char *file)
157{
158 uid_t uid = getuid () ;
159 uid_t gid = getgid () ;
160
161 if (chown (file, uid, gid) != 0)
162 {
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000163
164// Removed (ignoring) the check for not existing as I'm fed-up with morons telling me that
165// the warning message is an error.
166
167 if (errno != ENOENT)
168 fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100169 }
170}
171
172
173/*
174 * moduleLoaded:
175 * Return true/false if the supplied module is loaded
176 *********************************************************************************
177 */
178
179static int moduleLoaded (char *modName)
180{
181 int len = strlen (modName) ;
182 int found = FALSE ;
183 FILE *fd = fopen ("/proc/modules", "r") ;
184 char line [80] ;
185
186 if (fd == NULL)
187 {
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000188 fprintf (stderr, "gpio: Unable to check /proc/modules: %s\n", strerror (errno)) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100189 exit (1) ;
190 }
191
192 while (fgets (line, 80, fd) != NULL)
193 {
194 if (strncmp (line, modName, len) != 0)
195 continue ;
196
197 found = TRUE ;
198 break ;
199 }
200
201 fclose (fd) ;
202
203 return found ;
204}
205
206
207/*
208 * doLoad:
209 * Load either the spi or i2c modules and change device ownerships, etc.
210 *********************************************************************************
211 */
212
Gordon Hendersonf6c40cb2015-09-24 22:35:31 +0100213static void checkDevTree (char *argv [])
214{
215 struct stat statBuf ;
216
217 if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ...
218 {
219 fprintf (stderr,
220"%s: Unable to load/unload modules as this Pi has the device tree enabled.\n"
221" You need to run the raspi-config program (as root) and select the\n"
222" modules (SPI or I2C) that you wish to load/unload there and reboot.\n"
223" There is more information here:\n"
224" https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=97314\n", argv [0]) ;
225 exit (1) ;
226 }
227}
228
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100229static void _doLoadUsage (char *argv [])
230{
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000231 fprintf (stderr, "Usage: %s load <spi/i2c> [I2C baudrate in Kb/sec]\n", argv [0]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100232 exit (1) ;
233}
234
235static void doLoad (int argc, char *argv [])
236{
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000237 char *module1, *module2 ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100238 char cmd [80] ;
239 char *file1, *file2 ;
Gordon Hendersone8f62582013-01-28 13:00:47 +0000240 char args1 [32], args2 [32] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100241
Gordon Hendersonf6c40cb2015-09-24 22:35:31 +0100242 checkDevTree (argv) ;
243
Gordon Henderson13bbba72013-01-14 11:31:56 +0000244 if (argc < 3)
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100245 _doLoadUsage (argv) ;
246
Gordon Hendersone8f62582013-01-28 13:00:47 +0000247 args1 [0] = args2 [0] = 0 ;
Gordon Henderson13bbba72013-01-14 11:31:56 +0000248
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100249 /**/ if (strcasecmp (argv [2], "spi") == 0)
250 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000251 module1 = "spidev" ;
252 module2 = "spi_bcm2708" ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100253 file1 = "/dev/spidev0.0" ;
254 file2 = "/dev/spidev0.1" ;
Gordon Henderson13bbba72013-01-14 11:31:56 +0000255 if (argc == 4)
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000256 {
257 fprintf (stderr, "%s: Unable to set the buffer size now. Load aborted. Please see the man page.\n", argv [0]) ;
258 exit (1) ;
259 }
Gordon Henderson13bbba72013-01-14 11:31:56 +0000260 else if (argc > 4)
261 _doLoadUsage (argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100262 }
263 else if (strcasecmp (argv [2], "i2c") == 0)
264 {
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000265 module1 = "i2c_dev" ;
266 module2 = "i2c_bcm2708" ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100267 file1 = "/dev/i2c-0" ;
268 file2 = "/dev/i2c-1" ;
Gordon Hendersone8f62582013-01-28 13:00:47 +0000269 if (argc == 4)
270 sprintf (args2, " baudrate=%d", atoi (argv [3]) * 1000) ;
271 else if (argc > 4)
272 _doLoadUsage (argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100273 }
274 else
275 _doLoadUsage (argv) ;
276
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000277 if (findExecutable ("modprobe") == NULL)
278 printf ("No found\n") ;
279
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000280 if (!moduleLoaded (module1))
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100281 {
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000282 sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100283 system (cmd) ;
284 }
285
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000286 if (!moduleLoaded (module2))
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100287 {
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000288 sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ;
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000289 system (cmd) ;
290 }
291
292 if (!moduleLoaded (module2))
293 {
294 fprintf (stderr, "%s: Unable to load %s\n", argv [0], module2) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100295 exit (1) ;
296 }
297
298 sleep (1) ; // To let things get settled
299
300 changeOwner (argv [0], file1) ;
301 changeOwner (argv [0], file2) ;
302}
303
304
Gordon Henderson183c5a62012-10-21 15:25:16 +0100305/*
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000306 * doUnLoad:
307 * Un-Load either the spi or i2c modules and change device ownerships, etc.
308 *********************************************************************************
309 */
310
311static void _doUnLoadUsage (char *argv [])
312{
313 fprintf (stderr, "Usage: %s unload <spi/i2c>\n", argv [0]) ;
314 exit (1) ;
315}
316
317static void doUnLoad (int argc, char *argv [])
318{
319 char *module1, *module2 ;
320 char cmd [80] ;
321
Gordon Hendersonf6c40cb2015-09-24 22:35:31 +0100322 checkDevTree (argv) ;
323
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000324 if (argc != 3)
325 _doUnLoadUsage (argv) ;
326
327 /**/ if (strcasecmp (argv [2], "spi") == 0)
328 {
329 module1 = "spidev" ;
330 module2 = "spi_bcm2708" ;
331 }
332 else if (strcasecmp (argv [2], "i2c") == 0)
333 {
334 module1 = "i2c_dev" ;
335 module2 = "i2c_bcm2708" ;
336 }
337 else
338 _doUnLoadUsage (argv) ;
339
340 if (moduleLoaded (module1))
341 {
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000342 sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ;
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000343 system (cmd) ;
344 }
345
346 if (moduleLoaded (module2))
347 {
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000348 sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ;
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000349 system (cmd) ;
350 }
351}
352
353
354/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100355 * doI2Cdetect:
356 * Run the i2cdetect command with the right runes for this Pi revision
357 *********************************************************************************
358 */
359
360static void doI2Cdetect (int argc, char *argv [])
361{
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000362 int port = piGpioLayout () == 1 ? 0 : 1 ;
363 char *c, *command ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100364
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000365 if ((c = findExecutable (I2CDETECT)) == NULL)
Gordon Hendersonda384432013-05-13 19:43:26 +0100366 {
367 fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ;
368 return ;
369 }
370
371 if (!moduleLoaded ("i2c_dev"))
372 {
373 fprintf (stderr, "%s: The I2C kernel module(s) are not loaded.\n", argv [0]) ;
374 return ;
375 }
376
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000377 command = malloc (strlen (c) + 16) ;
378 sprintf (command, "%s -y %d", c, port) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100379 if (system (command) < 0)
380 fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ;
381
382}
383
384
385/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100386 * doExports:
387 * List all GPIO exports
388 *********************************************************************************
389 */
390
Gordon Henderson178ea082012-08-19 15:17:03 +0100391static void doExports (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100392{
393 int fd ;
394 int i, l, first ;
395 char fName [128] ;
396 char buf [16] ;
397
Gordon Hendersonda384432013-05-13 19:43:26 +0100398 for (first = 0, i = 0 ; i < 64 ; ++i) // Crude, but effective
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100399 {
400
401// Try to read the direction
402
403 sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ;
404 if ((fd = open (fName, O_RDONLY)) == -1)
405 continue ;
406
407 if (first == 0)
408 {
409 ++first ;
410 printf ("GPIO Pins exported:\n") ;
411 }
412
413 printf ("%4d: ", i) ;
414
415 if ((l = read (fd, buf, 16)) == 0)
416 sprintf (buf, "%s", "?") ;
417
418 buf [l] = 0 ;
419 if ((buf [strlen (buf) - 1]) == '\n')
420 buf [strlen (buf) - 1] = 0 ;
421
422 printf ("%-3s", buf) ;
423
424 close (fd) ;
425
426// Try to Read the value
427
428 sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ;
429 if ((fd = open (fName, O_RDONLY)) == -1)
430 {
431 printf ("No Value file (huh?)\n") ;
432 continue ;
433 }
434
435 if ((l = read (fd, buf, 16)) == 0)
436 sprintf (buf, "%s", "?") ;
437
438 buf [l] = 0 ;
439 if ((buf [strlen (buf) - 1]) == '\n')
440 buf [strlen (buf) - 1] = 0 ;
441
442 printf (" %s", buf) ;
443
444// Read any edge trigger file
445
446 sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ;
447 if ((fd = open (fName, O_RDONLY)) == -1)
448 {
449 printf ("\n") ;
450 continue ;
451 }
452
453 if ((l = read (fd, buf, 16)) == 0)
454 sprintf (buf, "%s", "?") ;
455
456 buf [l] = 0 ;
457 if ((buf [strlen (buf) - 1]) == '\n')
458 buf [strlen (buf) - 1] = 0 ;
459
460 printf (" %-8s\n", buf) ;
461
462 close (fd) ;
463 }
464}
465
466
467/*
468 * doExport:
469 * gpio export pin mode
470 * This uses the /sys/class/gpio device interface.
471 *********************************************************************************
472 */
473
474void doExport (int argc, char *argv [])
475{
476 FILE *fd ;
477 int pin ;
478 char *mode ;
479 char fName [128] ;
480
481 if (argc != 4)
482 {
483 fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ;
484 exit (1) ;
485 }
486
487 pin = atoi (argv [2]) ;
488
489 mode = argv [3] ;
490
491 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
492 {
493 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
494 exit (1) ;
495 }
496
497 fprintf (fd, "%d\n", pin) ;
498 fclose (fd) ;
499
500 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
501 if ((fd = fopen (fName, "w")) == NULL)
502 {
503 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
504 exit (1) ;
505 }
506
Gordon Henderson72b2af22015-02-03 14:53:32 +0000507 /**/ if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0))
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100508 fprintf (fd, "in\n") ;
Gordon Henderson72b2af22015-02-03 14:53:32 +0000509 else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0))
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100510 fprintf (fd, "out\n") ;
Gordon Henderson72b2af22015-02-03 14:53:32 +0000511 else if ((strcasecmp (mode, "high") == 0) || (strcasecmp (mode, "up") == 0))
512 fprintf (fd, "high\n") ;
513 else if ((strcasecmp (mode, "low") == 0) || (strcasecmp (mode, "down") == 0))
514 fprintf (fd, "low\n") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100515 else
516 {
Gordon Henderson72b2af22015-02-03 14:53:32 +0000517 fprintf (stderr, "%s: Invalid mode: %s. Should be in, out, high or low\n", argv [1], mode) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100518 exit (1) ;
519 }
520
521 fclose (fd) ;
522
Gordon Henderson72b2af22015-02-03 14:53:32 +0000523// Change ownership so the current user can actually use it
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100524
525 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
526 changeOwner (argv [0], fName) ;
527
528 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
529 changeOwner (argv [0], fName) ;
530
531}
532
533
534/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100535 * doWfi:
536 * gpio wfi pin mode
537 * Wait for Interrupt on a given pin.
538 * Slight cheat here - it's easier to actually use ISR now (which calls
539 * gpio to set the pin modes!) then we simply sleep, and expect the thread
540 * to exit the program. Crude but effective.
541 *********************************************************************************
542 */
543
544static void wfi (void)
545 { exit (0) ; }
546
547void doWfi (int argc, char *argv [])
548{
549 int pin, mode ;
550
551 if (argc != 4)
552 {
553 fprintf (stderr, "Usage: %s wfi pin mode\n", argv [0]) ;
554 exit (1) ;
555 }
556
557 pin = atoi (argv [2]) ;
558
559 /**/ if (strcasecmp (argv [3], "rising") == 0) mode = INT_EDGE_RISING ;
560 else if (strcasecmp (argv [3], "falling") == 0) mode = INT_EDGE_FALLING ;
561 else if (strcasecmp (argv [3], "both") == 0) mode = INT_EDGE_BOTH ;
562 else
563 {
564 fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv [1], argv [3]) ;
565 exit (1) ;
566 }
567
568 if (wiringPiISR (pin, mode, &wfi) < 0)
569 {
570 fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ;
571 exit (1) ;
572 }
573
574 for (;;)
575 delay (9999) ;
576}
577
578
579
580/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100581 * doEdge:
582 * gpio edge pin mode
583 * Easy access to changing the edge trigger on a GPIO pin
584 * This uses the /sys/class/gpio device interface.
585 *********************************************************************************
586 */
587
588void doEdge (int argc, char *argv [])
589{
590 FILE *fd ;
591 int pin ;
592 char *mode ;
593 char fName [128] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100594
595 if (argc != 4)
596 {
597 fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ;
598 exit (1) ;
599 }
600
Gordon Henderson178ea082012-08-19 15:17:03 +0100601 pin = atoi (argv [2]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100602 mode = argv [3] ;
603
604// Export the pin and set direction to input
605
606 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
607 {
608 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
609 exit (1) ;
610 }
611
612 fprintf (fd, "%d\n", pin) ;
613 fclose (fd) ;
614
615 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
616 if ((fd = fopen (fName, "w")) == NULL)
617 {
618 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
619 exit (1) ;
620 }
621
622 fprintf (fd, "in\n") ;
623 fclose (fd) ;
624
625 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
626 if ((fd = fopen (fName, "w")) == NULL)
627 {
628 fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
629 exit (1) ;
630 }
631
Gordon Henderson178ea082012-08-19 15:17:03 +0100632 /**/ if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ;
633 else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ;
634 else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
635 else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100636 else
637 {
638 fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
639 exit (1) ;
640 }
641
Gordon Henderson178ea082012-08-19 15:17:03 +0100642// Change ownership of the value and edge files, so the current user can actually use it!
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100643
644 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
Gordon Henderson178ea082012-08-19 15:17:03 +0100645 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100646
647 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
Gordon Henderson178ea082012-08-19 15:17:03 +0100648 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100649
650 fclose (fd) ;
651}
652
653
654/*
655 * doUnexport:
656 * gpio unexport pin
657 * This uses the /sys/class/gpio device interface.
658 *********************************************************************************
659 */
660
661void doUnexport (int argc, char *argv [])
662{
663 FILE *fd ;
664 int pin ;
665
666 if (argc != 3)
667 {
668 fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ;
669 exit (1) ;
670 }
671
672 pin = atoi (argv [2]) ;
673
674 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
675 {
676 fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
677 exit (1) ;
678 }
679
680 fprintf (fd, "%d\n", pin) ;
681 fclose (fd) ;
682}
683
684
685/*
686 * doUnexportAll:
687 * gpio unexportall
688 * Un-Export all the GPIO pins.
689 * This uses the /sys/class/gpio device interface.
690 *********************************************************************************
691 */
692
Gordon Hendersonda384432013-05-13 19:43:26 +0100693void doUnexportall (char *progName)
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100694{
695 FILE *fd ;
696 int pin ;
697
698 for (pin = 0 ; pin < 63 ; ++pin)
699 {
700 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
701 {
Gordon Hendersonda384432013-05-13 19:43:26 +0100702 fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100703 exit (1) ;
704 }
705 fprintf (fd, "%d\n", pin) ;
706 fclose (fd) ;
707 }
708}
709
710
711/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100712 * doReset:
713 * Reset the GPIO pins - as much as we can do
714 *********************************************************************************
715 */
716
717static void doReset (char *progName)
718{
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000719 printf ("GPIO Reset is dangerous and has been removed from the gpio command.\n") ;
720 printf (" - Please write a shell-script to reset the GPIO pins into the state\n") ;
721 printf (" that you need them in for your applications.\n") ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100722}
723
724
725/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100726 * doMode:
727 * gpio mode pin mode ...
728 *********************************************************************************
729 */
730
731void doMode (int argc, char *argv [])
732{
733 int pin ;
734 char *mode ;
735
736 if (argc != 4)
737 {
738 fprintf (stderr, "Usage: %s mode pin mode\n", argv [0]) ;
739 exit (1) ;
740 }
741
742 pin = atoi (argv [2]) ;
743
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100744 mode = argv [3] ;
745
Gordon Hendersondca8a192014-07-14 08:39:38 +0100746 /**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
747 else if (strcasecmp (mode, "input") == 0) pinMode (pin, INPUT) ;
748 else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
749 else if (strcasecmp (mode, "output") == 0) pinMode (pin, OUTPUT) ;
750 else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
751 else if (strcasecmp (mode, "pwmTone") == 0) pinMode (pin, PWM_TONE_OUTPUT) ;
752 else if (strcasecmp (mode, "clock") == 0) pinMode (pin, GPIO_CLOCK) ;
753 else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
754 else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
755 else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
756 else if (strcasecmp (mode, "off") == 0) pullUpDnControl (pin, PUD_OFF) ;
Gordon Hendersonf18c8f72013-08-03 23:53:35 +0100757 else if (strcasecmp (mode, "alt0") == 0) pinModeAlt (pin, 0b100) ;
758 else if (strcasecmp (mode, "alt1") == 0) pinModeAlt (pin, 0b101) ;
759 else if (strcasecmp (mode, "alt2") == 0) pinModeAlt (pin, 0b110) ;
760 else if (strcasecmp (mode, "alt3") == 0) pinModeAlt (pin, 0b111) ;
761 else if (strcasecmp (mode, "alt4") == 0) pinModeAlt (pin, 0b011) ;
762 else if (strcasecmp (mode, "alt5") == 0) pinModeAlt (pin, 0b010) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100763 else
764 {
Gordon Henderson56c77b52013-02-01 20:19:22 +0000765 fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/clock/up/down/tri\n", argv [1], mode) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100766 exit (1) ;
767 }
768}
769
770
771/*
772 * doPadDrive:
773 * gpio drive group value
774 *********************************************************************************
775 */
776
Gordon Henderson1bb49892012-08-19 15:33:26 +0100777static void doPadDrive (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100778{
779 int group, val ;
780
781 if (argc != 4)
782 {
783 fprintf (stderr, "Usage: %s drive group value\n", argv [0]) ;
784 exit (1) ;
785 }
786
787 group = atoi (argv [2]) ;
788 val = atoi (argv [3]) ;
789
790 if ((group < 0) || (group > 2))
791 {
792 fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ;
793 exit (1) ;
794 }
795
796 if ((val < 0) || (val > 7))
797 {
798 fprintf (stderr, "%s: drive value not 0-7: %d\n", argv [0], val) ;
799 exit (1) ;
800 }
801
802 setPadDrive (group, val) ;
803}
804
805
806/*
Gordon Hendersondf453882014-07-17 22:23:57 +0100807 * doUsbP:
808 * Control USB Power - High (1.2A) or Low (600mA)
809 * gpio usbp high/low
810 *********************************************************************************
811 */
812
813static void doUsbP (int argc, char *argv [])
814{
815 int model, rev, mem, maker, overVolted ;
816
817 if (argc != 3)
818 {
819 fprintf (stderr, "Usage: %s usbp high|low\n", argv [0]) ;
820 exit (1) ;
821 }
822
823// Make sure we're on a B+
824
825 piBoardId (&model, &rev, &mem, &maker, &overVolted) ;
826
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000827 if (!((model == PI_MODEL_BP) || (model == PI_MODEL_2)))
Gordon Hendersondf453882014-07-17 22:23:57 +0100828 {
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000829 fprintf (stderr, "USB power contol is applicable to B+ and v2 boards only.\n") ;
Gordon Hendersondf453882014-07-17 22:23:57 +0100830 exit (1) ;
831 }
832
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000833// Make sure we start in BCM_GPIO mode
Gordon Hendersondf453882014-07-17 22:23:57 +0100834
835 wiringPiSetupGpio () ;
836
837 if ((strcasecmp (argv [2], "high") == 0) || (strcasecmp (argv [2], "hi") == 0))
838 {
839 digitalWrite (PI_USB_POWER_CONTROL, 1) ;
840 pinMode (PI_USB_POWER_CONTROL, OUTPUT) ;
841 printf ("Switched to HIGH current USB (1.2A)\n") ;
842 return ;
843 }
844
845 if ((strcasecmp (argv [2], "low") == 0) || (strcasecmp (argv [2], "lo") == 0))
846 {
847 digitalWrite (PI_USB_POWER_CONTROL, 0) ;
848 pinMode (PI_USB_POWER_CONTROL, OUTPUT) ;
849 printf ("Switched to LOW current USB (600mA)\n") ;
850 return ;
851 }
852
853 fprintf (stderr, "Usage: %s usbp high|low\n", argv [0]) ;
854 exit (1) ;
855}
856
857
858/*
Gordon Henderson99095e32012-08-27 20:56:14 +0100859 * doGbw:
860 * gpio gbw channel value
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000861 * Gertboard Write - To the Analog output
Gordon Henderson99095e32012-08-27 20:56:14 +0100862 *********************************************************************************
863 */
864
865static void doGbw (int argc, char *argv [])
866{
867 int channel, value ;
868
869 if (argc != 4)
870 {
Gordon Hendersonda384432013-05-13 19:43:26 +0100871 fprintf (stderr, "Usage: %s gbw <channel> <value>\n", argv [0]) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100872 exit (1) ;
873 }
874
875 channel = atoi (argv [2]) ;
876 value = atoi (argv [3]) ;
877
878 if ((channel < 0) || (channel > 1))
879 {
Gordon Hendersonda384432013-05-13 19:43:26 +0100880 fprintf (stderr, "%s: gbw: Channel number must be 0 or 1\n", argv [0]) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100881 exit (1) ;
882 }
883
Gordon Hendersondca8a192014-07-14 08:39:38 +0100884 if ((value < 0) || (value > 255))
Gordon Henderson99095e32012-08-27 20:56:14 +0100885 {
Gordon Hendersonda384432013-05-13 19:43:26 +0100886 fprintf (stderr, "%s: gbw: Value must be from 0 to 255\n", argv [0]) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100887 exit (1) ;
888 }
889
Gordon Hendersonda384432013-05-13 19:43:26 +0100890 if (gertboardAnalogSetup (64) < 0)
Gordon Henderson99095e32012-08-27 20:56:14 +0100891 {
892 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
893 exit (1) ;
894 }
895
Gordon Hendersonda384432013-05-13 19:43:26 +0100896 analogWrite (64 + channel, value) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100897}
898
899
900/*
901 * doGbr:
902 * gpio gbr channel
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000903 * From the analog input
Gordon Henderson99095e32012-08-27 20:56:14 +0100904 *********************************************************************************
905 */
906
907static void doGbr (int argc, char *argv [])
908{
909 int channel ;
910
911 if (argc != 3)
912 {
913 fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ;
914 exit (1) ;
915 }
916
917 channel = atoi (argv [2]) ;
918
919 if ((channel < 0) || (channel > 1))
920 {
Gordon Hendersonda384432013-05-13 19:43:26 +0100921 fprintf (stderr, "%s: gbr: Channel number must be 0 or 1\n", argv [0]) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100922 exit (1) ;
923 }
924
Gordon Hendersonda384432013-05-13 19:43:26 +0100925 if (gertboardAnalogSetup (64) < 0)
Gordon Henderson99095e32012-08-27 20:56:14 +0100926 {
927 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
928 exit (1) ;
929 }
930
Gordon Hendersonda384432013-05-13 19:43:26 +0100931 printf ("%d\n", analogRead (64 + channel)) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100932}
933
934
Gordon Henderson99095e32012-08-27 20:56:14 +0100935/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100936 * doWrite:
937 * gpio write pin value
938 *********************************************************************************
939 */
940
Gordon Henderson1bb49892012-08-19 15:33:26 +0100941static void doWrite (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100942{
943 int pin, val ;
944
945 if (argc != 4)
946 {
947 fprintf (stderr, "Usage: %s write pin value\n", argv [0]) ;
948 exit (1) ;
949 }
950
951 pin = atoi (argv [2]) ;
952
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000953 /**/ if ((strcasecmp (argv [3], "up") == 0) || (strcasecmp (argv [3], "on") == 0))
954 val = 1 ;
955 else if ((strcasecmp (argv [3], "down") == 0) || (strcasecmp (argv [3], "off") == 0))
956 val = 0 ;
957 else
958 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100959
960 /**/ if (val == 0)
961 digitalWrite (pin, LOW) ;
962 else
963 digitalWrite (pin, HIGH) ;
964}
965
Gordon Hendersonda384432013-05-13 19:43:26 +0100966
967/*
968 * doAwriterite:
969 * gpio awrite pin value
970 *********************************************************************************
971 */
972
973static void doAwrite (int argc, char *argv [])
974{
975 int pin, val ;
976
977 if (argc != 4)
978 {
979 fprintf (stderr, "Usage: %s awrite pin value\n", argv [0]) ;
980 exit (1) ;
981 }
982
983 pin = atoi (argv [2]) ;
984
985 val = atoi (argv [3]) ;
986
987 analogWrite (pin, val) ;
988}
989
990
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000991/*
992 * doWriteByte:
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000993 * gpio wb value
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000994 *********************************************************************************
995 */
996
997static void doWriteByte (int argc, char *argv [])
998{
999 int val ;
1000
1001 if (argc != 3)
1002 {
1003 fprintf (stderr, "Usage: %s wb value\n", argv [0]) ;
1004 exit (1) ;
1005 }
1006
1007 val = (int)strtol (argv [2], NULL, 0) ;
1008
1009 digitalWriteByte (val) ;
1010}
1011
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001012
1013/*
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001014 * doReadByte:
1015 * gpio rbx|rbd value
1016 *********************************************************************************
1017 */
1018
1019static void doReadByte (int argc, char *argv [], int printHex)
1020{
1021 int val ;
1022
1023 if (argc != 2)
1024 {
1025 fprintf (stderr, "Usage: %s rbx|rbd\n", argv [0]) ;
1026 exit (1) ;
1027 }
1028
1029 val = digitalReadByte () ;
1030 if (printHex)
1031 printf ("%02X\n", val) ;
1032 else
1033 printf ("%d\n", val) ;
1034}
1035
1036
1037/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001038 * doRead:
1039 * Read a pin and return the value
1040 *********************************************************************************
1041 */
1042
1043void doRead (int argc, char *argv [])
1044{
1045 int pin, val ;
1046
1047 if (argc != 3)
1048 {
1049 fprintf (stderr, "Usage: %s read pin\n", argv [0]) ;
1050 exit (1) ;
1051 }
1052
1053 pin = atoi (argv [2]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001054 val = digitalRead (pin) ;
1055
1056 printf ("%s\n", val == 0 ? "0" : "1") ;
1057}
1058
1059
1060/*
Gordon Hendersonda384432013-05-13 19:43:26 +01001061 * doAread:
1062 * Read an analog pin and return the value
1063 *********************************************************************************
1064 */
1065
1066void doAread (int argc, char *argv [])
1067{
Gordon Hendersonda384432013-05-13 19:43:26 +01001068 if (argc != 3)
1069 {
1070 fprintf (stderr, "Usage: %s aread pin\n", argv [0]) ;
1071 exit (1) ;
1072 }
1073
Gordon Hendersonbfaf2662013-05-20 21:13:44 +01001074 printf ("%d\n", analogRead (atoi (argv [2]))) ;
Gordon Hendersonda384432013-05-13 19:43:26 +01001075}
1076
1077
1078/*
1079 * doToggle:
1080 * Toggle an IO pin
1081 *********************************************************************************
1082 */
1083
1084void doToggle (int argc, char *argv [])
1085{
1086 int pin ;
1087
1088 if (argc != 3)
1089 {
1090 fprintf (stderr, "Usage: %s toggle pin\n", argv [0]) ;
1091 exit (1) ;
1092 }
1093
1094 pin = atoi (argv [2]) ;
1095
1096 digitalWrite (pin, !digitalRead (pin)) ;
1097}
1098
Gordon Hendersondca8a192014-07-14 08:39:38 +01001099
1100/*
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001101 * doBlink:
1102 * Blink an IO pin
1103 *********************************************************************************
1104 */
1105
1106void doBlink (int argc, char *argv [])
1107{
1108 int pin ;
1109
1110 if (argc != 3)
1111 {
1112 fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ;
1113 exit (1) ;
1114 }
1115
1116 pin = atoi (argv [2]) ;
1117
1118 pinMode (pin, OUTPUT) ;
1119 for (;;)
1120 {
1121 digitalWrite (pin, !digitalRead (pin)) ;
1122 delay (500) ;
1123 }
1124
1125}
1126
1127
1128/*
Gordon Hendersondca8a192014-07-14 08:39:38 +01001129 * doPwmTone:
1130 * Output a tone in a PWM pin
1131 *********************************************************************************
1132 */
1133
1134void doPwmTone (int argc, char *argv [])
1135{
1136 int pin, freq ;
1137
1138 if (argc != 4)
1139 {
1140 fprintf (stderr, "Usage: %s pwmTone <pin> <freq>\n", argv [0]) ;
1141 exit (1) ;
1142 }
1143
1144 pin = atoi (argv [2]) ;
1145 freq = atoi (argv [3]) ;
1146
1147 pwmToneWrite (pin, freq) ;
1148}
1149
1150
Gordon Hendersonda384432013-05-13 19:43:26 +01001151/*
Gordon Henderson56c77b52013-02-01 20:19:22 +00001152 * doClock:
1153 * Output a clock on a pin
1154 *********************************************************************************
1155 */
1156
1157void doClock (int argc, char *argv [])
1158{
1159 int pin, freq ;
1160
1161 if (argc != 4)
1162 {
1163 fprintf (stderr, "Usage: %s clock <pin> <freq>\n", argv [0]) ;
1164 exit (1) ;
1165 }
1166
1167 pin = atoi (argv [2]) ;
1168
Gordon Henderson56c77b52013-02-01 20:19:22 +00001169 freq = atoi (argv [3]) ;
1170
1171 gpioClockSet (pin, freq) ;
1172}
1173
1174
1175/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001176 * doPwm:
1177 * Output a PWM value on a pin
1178 *********************************************************************************
1179 */
1180
1181void doPwm (int argc, char *argv [])
1182{
1183 int pin, val ;
1184
1185 if (argc != 4)
1186 {
1187 fprintf (stderr, "Usage: %s pwm <pin> <value>\n", argv [0]) ;
1188 exit (1) ;
1189 }
1190
1191 pin = atoi (argv [2]) ;
1192
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001193 val = atoi (argv [3]) ;
1194
1195 pwmWrite (pin, val) ;
1196}
1197
1198
1199/*
Gordon Henderson8cb49392012-09-16 10:15:32 +01001200 * doPwmMode: doPwmRange: doPwmClock:
1201 * Change the PWM mode, range and clock divider values
Gordon Hendersonf99ffed2012-08-19 15:12:45 +01001202 *********************************************************************************
1203 */
1204
1205static void doPwmMode (int mode)
1206{
1207 pwmSetMode (mode) ;
1208}
1209
1210static void doPwmRange (int argc, char *argv [])
1211{
1212 unsigned int range ;
1213
1214 if (argc != 3)
1215 {
1216 fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
1217 exit (1) ;
1218 }
1219
1220 range = (unsigned int)strtoul (argv [2], NULL, 10) ;
1221
1222 if (range == 0)
1223 {
1224 fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
1225 exit (1) ;
1226 }
1227
1228 pwmSetRange (range) ;
1229}
1230
Gordon Henderson8cb49392012-09-16 10:15:32 +01001231static void doPwmClock (int argc, char *argv [])
1232{
1233 unsigned int clock ;
1234
1235 if (argc != 3)
1236 {
1237 fprintf (stderr, "Usage: %s pwmc <clock>\n", argv [0]) ;
1238 exit (1) ;
1239 }
1240
1241 clock = (unsigned int)strtoul (argv [2], NULL, 10) ;
1242
1243 if ((clock < 1) || (clock > 4095))
1244 {
1245 fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ;
1246 exit (1) ;
1247 }
1248
1249 pwmSetClock (clock) ;
1250}
1251
Gordon Hendersonf99ffed2012-08-19 15:12:45 +01001252
1253/*
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001254 * doVersion:
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001255 * Handle the ever more complicated version command and print out
1256 * some usefull information.
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001257 *********************************************************************************
1258 */
1259
1260static void doVersion (char *argv [])
1261{
1262 int model, rev, mem, maker, warranty ;
1263 struct stat statBuf ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001264 char name [80] ;
1265 FILE *fd ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001266
1267 printf ("gpio version: %s\n", VERSION) ;
1268 printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ;
1269 printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
1270 printf ("For details type: %s -warranty\n", argv [0]) ;
1271 printf ("\n") ;
1272 piBoardId (&model, &rev, &mem, &maker, &warranty) ;
1273
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001274 printf ("Raspberry Pi Details:\n") ;
1275 printf (" Type: %s, Revision: %s, Memory: %dMB, Maker: %s %s\n",
1276 piModelNames [model], piRevisionNames [rev], piMemorySize [mem], piMakerNames [maker], warranty ? "[Out of Warranty]" : "") ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001277
1278// Check for device tree
1279
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001280 if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ...
1281 printf (" * Device tree is enabled.\n") ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001282
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001283 if (stat ("/proc/device-tree/model", &statBuf) == 0) // Output Kernel idea of board type
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001284 {
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001285 if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL)
1286 {
1287 fgets (name, 80, fd) ;
1288 fclose (fd) ;
1289 printf (" *--> %s\n", name) ;
1290 }
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001291 }
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001292
1293 if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO
1294 printf (" * This Raspberry Pi supports user-level GPIO access.\n") ;
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001295 else
1296 printf (" * Root or sudo required for GPIO access.\n") ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001297}
1298
1299
1300/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001301 * main:
1302 * Start here
1303 *********************************************************************************
1304 */
1305
1306int main (int argc, char *argv [])
1307{
1308 int i ;
1309
Gordon Henderson13bbba72013-01-14 11:31:56 +00001310 if (getenv ("WIRINGPI_DEBUG") != NULL)
1311 {
1312 printf ("gpio: wiringPi debug mode enabled\n") ;
1313 wiringPiDebug = TRUE ;
1314 }
1315
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001316 if (argc == 1)
1317 {
Gordon Henderson86a5c682012-10-02 14:32:12 +01001318 fprintf (stderr, "%s\n", usage) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001319 return 1 ;
1320 }
1321
Gordon Hendersonda384432013-05-13 19:43:26 +01001322// Help
1323
Gordon Henderson178ea082012-08-19 15:17:03 +01001324 if (strcasecmp (argv [1], "-h") == 0)
1325 {
1326 printf ("%s: %s\n", argv [0], usage) ;
1327 return 0 ;
1328 }
1329
Gordon Hendersonda384432013-05-13 19:43:26 +01001330// Version & Warranty
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001331// Wish I could remember why I have both -R and -V ...
Gordon Hendersonda384432013-05-13 19:43:26 +01001332
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001333 if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0))
Gordon Hendersonda384432013-05-13 19:43:26 +01001334 {
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001335 printf ("%d\n", piGpioLayout ()) ;
Gordon Hendersonda384432013-05-13 19:43:26 +01001336 return 0 ;
1337 }
1338
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001339// Version and information
1340
Gordon Hendersonda384432013-05-13 19:43:26 +01001341 if (strcmp (argv [1], "-v") == 0)
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001342 {
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001343 doVersion (argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001344 return 0 ;
1345 }
1346
1347 if (strcasecmp (argv [1], "-warranty") == 0)
1348 {
1349 printf ("gpio version: %s\n", VERSION) ;
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +00001350 printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001351 printf ("\n") ;
1352 printf (" This program is free software; you can redistribute it and/or modify\n") ;
1353 printf (" it under the terms of the GNU Leser General Public License as published\n") ;
1354 printf (" by the Free Software Foundation, either version 3 of the License, or\n") ;
1355 printf (" (at your option) any later version.\n") ;
1356 printf ("\n") ;
1357 printf (" This program is distributed in the hope that it will be useful,\n") ;
1358 printf (" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
1359 printf (" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") ;
1360 printf (" GNU Lesser General Public License for more details.\n") ;
1361 printf ("\n") ;
1362 printf (" You should have received a copy of the GNU Lesser General Public License\n") ;
1363 printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
1364 printf ("\n") ;
1365 return 0 ;
1366 }
1367
1368 if (geteuid () != 0)
1369 {
1370 fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
1371 return 1 ;
1372 }
1373
1374// Initial test for /sys/class/gpio operations:
1375
Gordon Henderson178ea082012-08-19 15:17:03 +01001376 /**/ if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; }
1377 else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; }
1378 else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; }
Gordon Henderson178ea082012-08-19 15:17:03 +01001379 else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }
Gordon Hendersonda384432013-05-13 19:43:26 +01001380 else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argv [0]) ; return 0 ; }
Gordon Henderson178ea082012-08-19 15:17:03 +01001381
Gordon Henderson86a5c682012-10-02 14:32:12 +01001382// Check for load command:
Gordon Henderson178ea082012-08-19 15:17:03 +01001383
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +00001384 if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; }
1385 if (strcasecmp (argv [1], "unload" ) == 0) { doUnLoad (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001386
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001387// Check for usb power command
1388
1389 if (strcasecmp (argv [1], "usbp" ) == 0) { doUsbP (argc, argv) ; return 0 ; }
1390
Gordon Henderson99095e32012-08-27 20:56:14 +01001391// Gertboard commands
1392
1393 if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; }
1394 if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; }
1395
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001396// Check for allreadall command, force Gpio mode
1397
1398 if (strcasecmp (argv [1], "allreadall") == 0)
1399 {
1400 wiringPiSetupGpio () ;
1401 doAllReadall () ;
1402 return 0 ;
1403 }
1404
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001405// Check for -g argument
1406
Gordon Hendersonda384432013-05-13 19:43:26 +01001407 /**/ if (strcasecmp (argv [1], "-g") == 0)
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001408 {
Gordon Hendersonda384432013-05-13 19:43:26 +01001409 wiringPiSetupGpio () ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001410
1411 for (i = 2 ; i < argc ; ++i)
1412 argv [i - 1] = argv [i] ;
1413 --argc ;
1414 wpMode = WPI_MODE_GPIO ;
1415 }
1416
Gordon Hendersonda384432013-05-13 19:43:26 +01001417// Check for -1 argument
1418
1419 else if (strcasecmp (argv [1], "-1") == 0)
1420 {
1421 wiringPiSetupPhys () ;
1422
1423 for (i = 2 ; i < argc ; ++i)
1424 argv [i - 1] = argv [i] ;
1425 --argc ;
1426 wpMode = WPI_MODE_PHYS ;
1427 }
1428
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001429// Check for -p argument for PiFace
1430
1431 else if (strcasecmp (argv [1], "-p") == 0)
1432 {
Gordon Hendersonda384432013-05-13 19:43:26 +01001433 piFaceSetup (200) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001434
1435 for (i = 2 ; i < argc ; ++i)
1436 argv [i - 1] = argv [i] ;
1437 --argc ;
1438 wpMode = WPI_MODE_PIFACE ;
1439 }
1440
1441// Default to wiringPi mode
1442
1443 else
1444 {
Gordon Hendersonda384432013-05-13 19:43:26 +01001445 wiringPiSetup () ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001446 wpMode = WPI_MODE_PINS ;
1447 }
1448
Gordon Hendersonda384432013-05-13 19:43:26 +01001449// Check for -x argument to load in a new extension
Gordon Hendersonf99ffed2012-08-19 15:12:45 +01001450
Gordon Hendersonda384432013-05-13 19:43:26 +01001451 if (strcasecmp (argv [1], "-x") == 0)
Gordon Hendersonf99ffed2012-08-19 15:12:45 +01001452 {
Gordon Hendersonda384432013-05-13 19:43:26 +01001453 if (argc < 3)
1454 {
1455 fprintf (stderr, "%s: -x missing extension specification.\n", argv [0]) ;
1456 exit (EXIT_FAILURE) ;
1457 }
1458
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +00001459 if (!loadWPiExtension (argv [0], argv [2], TRUE)) // Prints its own error messages
Gordon Hendersonda384432013-05-13 19:43:26 +01001460 exit (EXIT_FAILURE) ;
1461
1462 for (i = 3 ; i < argc ; ++i)
1463 argv [i - 2] = argv [i] ;
1464 argc -= 2 ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +01001465 }
1466
Gordon Hendersonda384432013-05-13 19:43:26 +01001467 if (argc <= 1)
1468 {
1469 fprintf (stderr, "%s: no command given\n", argv [0]) ;
1470 exit (EXIT_FAILURE) ;
1471 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001472
Gordon Hendersonda384432013-05-13 19:43:26 +01001473// Core wiringPi functions
1474
1475 /**/ if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ;
1476 else if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ;
1477 else if (strcasecmp (argv [1], "write" ) == 0) doWrite (argc, argv) ;
1478 else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ;
1479 else if (strcasecmp (argv [1], "awrite" ) == 0) doAwrite (argc, argv) ;
1480 else if (strcasecmp (argv [1], "aread" ) == 0) doAread (argc, argv) ;
1481
1482// GPIO Nicies
1483
1484 else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001485 else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ;
Gordon Hendersonda384432013-05-13 19:43:26 +01001486
1487// Pi Specifics
1488
Gordon Henderson27698762013-06-27 21:51:55 +01001489 else if (strcasecmp (argv [1], "pwm-bal" ) == 0) doPwmMode (PWM_MODE_BAL) ;
1490 else if (strcasecmp (argv [1], "pwm-ms" ) == 0) doPwmMode (PWM_MODE_MS) ;
1491 else if (strcasecmp (argv [1], "pwmr" ) == 0) doPwmRange (argc, argv) ;
1492 else if (strcasecmp (argv [1], "pwmc" ) == 0) doPwmClock (argc, argv) ;
Gordon Hendersondca8a192014-07-14 08:39:38 +01001493 else if (strcasecmp (argv [1], "pwmTone" ) == 0) doPwmTone (argc, argv) ;
Gordon Henderson27698762013-06-27 21:51:55 +01001494 else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ;
Gordon Hendersondf453882014-07-17 22:23:57 +01001495 else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ;
Gordon Henderson8c8578a2013-07-23 09:19:34 +01001496 else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ;
Gordon Henderson05e2f672014-05-20 11:43:07 +01001497 else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ;
Gordon Henderson27698762013-06-27 21:51:55 +01001498 else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect (argc, argv) ;
1499 else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ;
1500 else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ;
1501 else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +00001502 else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ;
1503 else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ;
Gordon Henderson27698762013-06-27 21:51:55 +01001504 else if (strcasecmp (argv [1], "clock" ) == 0) doClock (argc, argv) ;
1505 else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001506 else
1507 {
Gordon Henderson178ea082012-08-19 15:17:03 +01001508 fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
Gordon Hendersonda384432013-05-13 19:43:26 +01001509 exit (EXIT_FAILURE) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001510 }
1511 return 0 ;
1512}