blob: 1985a17c95787aad2511c16ffa138fd6aaf02ccf [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 Hendersone687f3f2017-01-24 12:13:39 +00005 * Copyright (c) 2012-2017 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 */
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010024#include <stdio.h>
25#include <stdlib.h>
26#include <stdint.h>
Gordon Hendersonda384432013-05-13 19:43:26 +010027#include <ctype.h>
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010028#include <string.h>
29#include <unistd.h>
30#include <errno.h>
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010031#include <fcntl.h>
Gordon Hendersonda384432013-05-13 19:43:26 +010032#include <sys/types.h>
33#include <sys/stat.h>
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010034
Gordon Henderson99095e32012-08-27 20:56:14 +010035#include <wiringPi.h>
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +000036#include <wpiExtensions.h>
Gordon Hendersonda384432013-05-13 19:43:26 +010037
Gordon Henderson99095e32012-08-27 20:56:14 +010038#include <gertboard.h>
Gordon Hendersonda384432013-05-13 19:43:26 +010039#include <piFace.h>
40
Gordon Hendersone687f3f2017-01-24 12:13:39 +000041#include "../version.h"
Gordon Henderson99095e32012-08-27 20:56:14 +010042
Gordon Henderson13bbba72013-01-14 11:31:56 +000043extern int wiringPiDebug ;
44
Gordon Henderson05e2f672014-05-20 11:43:07 +010045// External functions I can't be bothered creating a separate .h file for:
46
Gordon Henderson27698762013-06-27 21:51:55 +010047extern void doReadall (void) ;
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000048extern void doAllReadall (void) ;
Gordon Henderson05e2f672014-05-20 11:43:07 +010049extern void doPins (void) ;
joshua-yang4b08e7f2019-02-21 12:05:24 +090050extern void doUnexport (int argc, char *agrv []);
Gordon Henderson05e2f672014-05-20 11:43:07 +010051
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010052#ifndef TRUE
53# define TRUE (1==1)
54# define FALSE (1==2)
55#endif
56
Gordon Hendersondf453882014-07-17 22:23:57 +010057#define PI_USB_POWER_CONTROL 38
joshua-yang4b08e7f2019-02-21 12:05:24 +090058#define I2CDETECT "i2cdetect"
59#define MODPROBE "modprobe"
60#define RMMOD "rmmod"
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010061
Gordon Henderson27698762013-06-27 21:51:55 +010062int wpMode ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010063
64char *usage = "Usage: gpio -v\n"
joshua-yang4b08e7f2019-02-21 12:05:24 +090065 " gpio -h\n"
66 " gpio [-g|-1] ...\n"
67 " gpio [-d] ...\n"
68 " [-x extension:params] [[ -x ...]] ...\n"
69 " gpio [-p] <read/write/wb> ...\n"
70 " gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n"
71 " gpio <toggle/blink> <pin>\n"
72 " gpio readall/reset\n"
73 " gpio unexportall/exports\n"
74 " gpio export/edge/unexport ...\n"
75 " gpio wfi <pin> <mode>\n"
76 " gpio drive <pin> <value>\n"
77 " gpio pwm-bal/pwm-ms \n"
78 " gpio pwmr <range> \n"
79 " gpio pwmc <divider> \n"
80 " gpio load spi/i2c\n"
81 " gpio unload spi/i2c\n"
82 " gpio i2cd/i2cdetect\n"
83 " gpio rbx/rbd\n"
84 " gpio wb <value>\n"
85 " gpio usbp high/low\n"
86 " gpio gbr <channel>\n"
87 " gpio gbw <channel> <value>" ; // No trailing newline needed here.
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010088
89
Gordon Henderson6fba4032014-06-24 19:23:31 +010090#ifdef NOT_FOR_NOW
Gordon Hendersonbf0ad862012-08-16 15:04:43 +010091/*
Gordon Hendersonf18c8f72013-08-03 23:53:35 +010092 * decodePin:
93 * Decode a pin "number" which can actually be a pin name to represent
94 * one of the Pi's on-board pins.
95 *********************************************************************************
96 */
Gordon Hendersonf18c8f72013-08-03 23:53:35 +010097static int decodePin (const char *str)
98{
joshua-yang4b08e7f2019-02-21 12:05:24 +090099 // The first case - see if it's a number:
100 if (isdigit (str [0]))
101 return atoi (str) ;
Gordon Hendersonf18c8f72013-08-03 23:53:35 +0100102
joshua-yang4b08e7f2019-02-21 12:05:24 +0900103 return 0 ;
Gordon Hendersonf18c8f72013-08-03 23:53:35 +0100104}
Gordon Henderson6fba4032014-06-24 19:23:31 +0100105#endif
Gordon Hendersonf18c8f72013-08-03 23:53:35 +0100106
107
108/*
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000109 * findExecutable:
110 * Code to locate the path to the given executable. We have a fixed list
111 * of locations to try which completely overrides any $PATH environment.
112 * This may be detrimental, however it avoids the reliance on $PATH
113 * which may be a security issue when this program is run a set-uid-root.
114 *********************************************************************************
115 */
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000116static const char *searchPath [] =
117{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900118 "/sbin",
119 "/usr/sbin",
120 "/bin",
121 "/usr/bin",
122 NULL,
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000123} ;
124
125static char *findExecutable (const char *progName)
126{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900127 static char *path = NULL ;
128 int len = strlen (progName) ;
129 int i = 0 ;
130 struct stat statBuf ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000131
joshua-yang4b08e7f2019-02-21 12:05:24 +0900132 for (i = 0 ; searchPath [i] != NULL ; ++i) {
133 path = malloc (strlen (searchPath [i]) + len + 2) ;
134 sprintf (path, "%s/%s", searchPath [i], progName) ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000135
joshua-yang4b08e7f2019-02-21 12:05:24 +0900136 if (stat (path, &statBuf) == 0)
137 return path ;
138 free (path) ;
139 }
140 return NULL ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000141}
142
143
144/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100145 * changeOwner:
146 * Change the ownership of the file to the real userId of the calling
147 * program so we can access it.
148 *********************************************************************************
149 */
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100150static void changeOwner (char *cmd, char *file)
151{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900152 uid_t uid = getuid () ;
153 uid_t gid = getgid () ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100154
joshua-yang4b08e7f2019-02-21 12:05:24 +0900155 if (chown (file, uid, gid) != 0) {
156 // Removed (ignoring) the check for not existing as I'm fed-up with morons telling me that
157 // the warning message is an error.
158 if (errno != ENOENT)
159 fprintf (stderr, "%s: Unable to change ownership of %s: %s\n",
160 cmd, file, strerror (errno)) ;
161 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100162}
163
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100164/*
165 * doLoad:
166 * Load either the spi or i2c modules and change device ownerships, etc.
167 *********************************************************************************
168 */
Gordon Hendersonf6c40cb2015-09-24 22:35:31 +0100169static void checkDevTree (char *argv [])
170{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900171 struct stat statBuf ;
Gordon Hendersonf6c40cb2015-09-24 22:35:31 +0100172
joshua-yang4b08e7f2019-02-21 12:05:24 +0900173 // We're on a devtree system ...
174 if (stat ("/proc/device-tree", &statBuf) == 0) {
175 fprintf (stderr,
176 "%s: Unable to load/unload modules as this kernel has the device tree enabled.\n"
177 " You need to edit /etc/modprobe.d/blacklist-odroid.conf or update /media/models.dts file.\n"
178 " If you want to use SPI, you should find out spidev module line at the blacklist-odroid.conf\n"
179 " and uncomment that. Then reboot to enable the module.\n\n"
180 " Please refer to our wiki page:\n"
181 " https://wiki.odroid.com/start\n", argv [0]) ;
182 exit (1) ;
183 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100184}
185
Luke Go2ee8a0d2019-07-08 15:37:07 +0900186static void doLoad (int UNU argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100187{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900188 checkDevTree (argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100189}
190
191
Gordon Henderson183c5a62012-10-21 15:25:16 +0100192/*
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000193 * doUnLoad:
194 * Un-Load either the spi or i2c modules and change device ownerships, etc.
195 *********************************************************************************
196 */
Luke Go2ee8a0d2019-07-08 15:37:07 +0900197static void doUnLoad (int UNU argc, char *argv [])
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000198{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900199 checkDevTree (argv) ;
Gordon Hendersoneb1fc2c2015-01-30 18:14:49 +0000200}
201
202
203/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100204 * doI2Cdetect:
205 * Run the i2cdetect command with the right runes for this Pi revision
206 *********************************************************************************
207 */
Gordon Hendersone687f3f2017-01-24 12:13:39 +0000208static void doI2Cdetect (UNU int argc, char *argv [])
Gordon Hendersonda384432013-05-13 19:43:26 +0100209{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900210 int model, rev, mem, maker, overVolted, port;
joshua-yang4b08e7f2019-02-21 12:05:24 +0900211 char *c, *command ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100212
joshua-yang4b08e7f2019-02-21 12:05:24 +0900213 piBoardId(&model, &rev, &mem, &maker, &overVolted);
Gordon Hendersonda384432013-05-13 19:43:26 +0100214
joshua-yang4b08e7f2019-02-21 12:05:24 +0900215 switch (model) {
216 case MODEL_ODROID_C1: case MODEL_ODROID_C2:
217 case MODEL_ODROID_XU3:
joshua-yang4b08e7f2019-02-21 12:05:24 +0900218 port = 1;
219 break;
220 case MODEL_ODROID_N1:
joshua-yang4b08e7f2019-02-21 12:05:24 +0900221 port = 4;
222 break;
223 case MODEL_ODROID_N2:
joshua-yang4b08e7f2019-02-21 12:05:24 +0900224 port = 3;
Joshua Yang964b4222019-07-09 16:00:28 +0900225 break;
joshua-yang4b08e7f2019-02-21 12:05:24 +0900226 default:
227 break;
228 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100229
joshua-yang4b08e7f2019-02-21 12:05:24 +0900230 if ((c = findExecutable (I2CDETECT)) == NULL) {
231 fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ;
232 return ;
233 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100234
Joshua Yang964b4222019-07-09 16:00:28 +0900235 switch (model) {
236 case MODEL_ODROID_C1:
237 case MODEL_ODROID_C2:
joshua-yang4b08e7f2019-02-21 12:05:24 +0900238 if (!moduleLoaded (AML_MODULE_I2C)) {
239 fprintf (stderr, "%s: The I2C kernel module(s) are not loaded.\n", argv [0]) ;
joshua-yang4b08e7f2019-02-21 12:05:24 +0900240 }
Joshua Yang964b4222019-07-09 16:00:28 +0900241 break;
joshua-yang4b08e7f2019-02-21 12:05:24 +0900242 default:
243 break;
244 }
245
246 command = malloc (strlen (c) + 16) ;
247 sprintf (command, "%s -y %d", c, port) ;
248 if (system (command) < 0)
249 fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100250}
251
252
253/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100254 * doExports:
255 * List all GPIO exports
256 *********************************************************************************
257 */
Gordon Hendersone687f3f2017-01-24 12:13:39 +0000258static void doExports (UNU int argc, UNU char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100259{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900260 int fd ;
261 int i, l, first ;
262 char fName [128] ;
263 char buf [16] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100264
joshua-yang4b08e7f2019-02-21 12:05:24 +0900265 // Crude, but effective
266 for (first = 0, i = 0 ; i < 256 ; ++i) {
267 // Try to read the direction
268 sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ;
269 if ((fd = open (fName, O_RDONLY)) == -1)
270 continue ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100271
joshua-yang4b08e7f2019-02-21 12:05:24 +0900272 if (first == 0) {
273 ++first ;
274 printf ("GPIO Pins exported:\n") ;
275 }
276 printf ("%4d: ", i) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100277
joshua-yang4b08e7f2019-02-21 12:05:24 +0900278 if ((l = read (fd, buf, 16)) == 0)
279 sprintf (buf, "%s", "?") ;
Joshua Yang6e7a6e62019-07-09 15:57:26 +0900280
joshua-yang4b08e7f2019-02-21 12:05:24 +0900281 buf [l] = 0 ;
282 if ((buf [strlen (buf) - 1]) == '\n')
283 buf [strlen (buf) - 1] = 0 ;
284 printf ("%-3s", buf) ;
285 close (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100286
joshua-yang4b08e7f2019-02-21 12:05:24 +0900287 // Try to Read the value
288 sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ;
289 if ((fd = open (fName, O_RDONLY)) == -1) {
290 printf ("No Value file (huh?)\n") ;
291 continue ;
292 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100293
joshua-yang4b08e7f2019-02-21 12:05:24 +0900294 if ((l = read (fd, buf, 16)) == 0)
295 sprintf (buf, "%s", "?") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100296
joshua-yang4b08e7f2019-02-21 12:05:24 +0900297 buf [l] = 0 ;
298 if ((buf [strlen (buf) - 1]) == '\n')
299 buf [strlen (buf) - 1] = 0 ;
300 printf (" %s", buf) ;
301 close (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100302
joshua-yang4b08e7f2019-02-21 12:05:24 +0900303 // Read any edge trigger file
304 sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ;
305 if ((fd = open (fName, O_RDONLY)) == -1) {
306 printf ("\n") ;
307 continue ;
308 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100309
joshua-yang4b08e7f2019-02-21 12:05:24 +0900310 if ((l = read (fd, buf, 16)) == 0)
311 sprintf (buf, "%s", "?") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100312
joshua-yang4b08e7f2019-02-21 12:05:24 +0900313 buf [l] = 0 ;
314 if ((buf [strlen (buf) - 1]) == '\n')
315 buf [strlen (buf) - 1] = 0 ;
316 printf (" %-8s\n", buf) ;
317 close (fd) ;
318 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100319}
320
321
322/*
323 * doExport:
324 * gpio export pin mode
325 * This uses the /sys/class/gpio device interface.
326 *********************************************************************************
327 */
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100328void doExport (int argc, char *argv [])
329{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900330 FILE *fd ;
331 int pin ;
332 char *mode ;
333 char fName [128] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100334
joshua-yang4b08e7f2019-02-21 12:05:24 +0900335 if (argc != 4) {
336 fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ;
337 exit (1) ;
338 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100339
joshua-yang4b08e7f2019-02-21 12:05:24 +0900340 pin = atoi (argv [2]) ;
341 mode = argv [3] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100342
joshua-yang4b08e7f2019-02-21 12:05:24 +0900343 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) {
344 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
345 exit (1) ;
346 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100347
joshua-yang4b08e7f2019-02-21 12:05:24 +0900348 fprintf (fd, "%d\n", pin) ;
349 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100350
joshua-yang4b08e7f2019-02-21 12:05:24 +0900351 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
352 if ((fd = fopen (fName, "w")) == NULL) {
353 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
354 exit (1) ;
355 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100356
joshua-yang4b08e7f2019-02-21 12:05:24 +0900357 if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0))
358 fprintf (fd, "in\n") ;
359 else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0))
360 fprintf (fd, "out\n") ;
361 else if ((strcasecmp (mode, "high") == 0) || (strcasecmp (mode, "up") == 0))
362 fprintf (fd, "high\n") ;
363 else if ((strcasecmp (mode, "low") == 0) || (strcasecmp (mode, "down") == 0))
364 fprintf (fd, "low\n") ;
365 else {
366 fprintf (stderr, "%s: Invalid mode: %s. Should be in, out, high or low\n", argv [1], mode) ;
367 exit (1) ;
368 }
369 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100370
joshua-yang4b08e7f2019-02-21 12:05:24 +0900371 // Change ownership so the current user can actually use it
372 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
373 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100374
joshua-yang4b08e7f2019-02-21 12:05:24 +0900375 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
376 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100377}
378
379
380/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100381 * doWfi:
382 * gpio wfi pin mode
383 * Wait for Interrupt on a given pin.
384 * Slight cheat here - it's easier to actually use ISR now (which calls
385 * gpio to set the pin modes!) then we simply sleep, and expect the thread
386 * to exit the program. Crude but effective.
387 *********************************************************************************
388 */
joshua-yang4b08e7f2019-02-21 12:05:24 +0900389static void wfi (void) { exit (0) ; }
Gordon Hendersonda384432013-05-13 19:43:26 +0100390
391void doWfi (int argc, char *argv [])
392{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900393 int pin, mode ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100394
joshua-yang4b08e7f2019-02-21 12:05:24 +0900395 if (argc != 4) {
396 fprintf (stderr, "Usage: %s wfi pin mode\n", argv [0]) ;
397 exit (1) ;
398 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100399
joshua-yang4b08e7f2019-02-21 12:05:24 +0900400 pin = atoi (argv [2]) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100401
joshua-yang4b08e7f2019-02-21 12:05:24 +0900402 if (strcasecmp (argv [3], "rising") == 0) mode = INT_EDGE_RISING ;
403 else if (strcasecmp (argv [3], "falling") == 0) mode = INT_EDGE_FALLING ;
404 else if (strcasecmp (argv [3], "both") == 0) mode = INT_EDGE_BOTH ;
405 else {
406 fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv [1], argv [3]) ;
407 exit (1) ;
408 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100409
joshua-yang4b08e7f2019-02-21 12:05:24 +0900410 if (wiringPiISR (pin, mode, &wfi) < 0) {
411 fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ;
412 exit (1) ;
413 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100414
joshua-yang4b08e7f2019-02-21 12:05:24 +0900415 for (;;)
416 delay (9999) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100417}
418
419
Gordon Hendersonda384432013-05-13 19:43:26 +0100420/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100421 * doEdge:
422 * gpio edge pin mode
423 * Easy access to changing the edge trigger on a GPIO pin
424 * This uses the /sys/class/gpio device interface.
425 *********************************************************************************
426 */
427
428void doEdge (int argc, char *argv [])
429{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900430 FILE *fd ;
431 int pin ;
432 char *mode ;
433 char fName [128] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100434
joshua-yang4b08e7f2019-02-21 12:05:24 +0900435 // Reset gpio sysfs
436 doUnexport(3, argv);
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100437
joshua-yang4b08e7f2019-02-21 12:05:24 +0900438 if (argc != 4) {
439 fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ;
440 exit (1) ;
441 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100442
joshua-yang4b08e7f2019-02-21 12:05:24 +0900443 pin = atoi (argv [2]) ;
444 mode = argv [3] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100445
joshua-yang4b08e7f2019-02-21 12:05:24 +0900446 // Export the pin and set direction to input
447 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) {
448 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
449 exit (1) ;
450 }
451 fprintf (fd, "%d\n", pin) ;
452 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100453
joshua-yang4b08e7f2019-02-21 12:05:24 +0900454 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
455 if ((fd = fopen (fName, "w")) == NULL) {
456 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
457 exit (1) ;
458 }
459 fprintf (fd, "in\n") ;
460 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100461
joshua-yang4b08e7f2019-02-21 12:05:24 +0900462 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
463 if ((fd = fopen (fName, "w")) == NULL) {
464 fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
465 exit (1) ;
466 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100467
joshua-yang4b08e7f2019-02-21 12:05:24 +0900468 if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ;
469 else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ;
470 else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
471 else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ;
472 else {
473 fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
474 exit (1) ;
475 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100476
joshua-yang4b08e7f2019-02-21 12:05:24 +0900477 // Change ownership of the value and edge files, so the current user can actually use it!
478 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
479 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100480
joshua-yang4b08e7f2019-02-21 12:05:24 +0900481 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
482 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100483
joshua-yang4b08e7f2019-02-21 12:05:24 +0900484 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100485}
486
487
488/*
489 * doUnexport:
490 * gpio unexport pin
491 * This uses the /sys/class/gpio device interface.
492 *********************************************************************************
493 */
494
495void doUnexport (int argc, char *argv [])
496{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900497 FILE *fd ;
498 int pin ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100499
joshua-yang4b08e7f2019-02-21 12:05:24 +0900500 if (argc != 3) {
501 fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ;
502 exit (1) ;
503 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100504
joshua-yang4b08e7f2019-02-21 12:05:24 +0900505 pin = atoi (argv [2]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100506
joshua-yang4b08e7f2019-02-21 12:05:24 +0900507 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) {
508 fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
509 exit (1) ;
510 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100511
joshua-yang4b08e7f2019-02-21 12:05:24 +0900512 fprintf (fd, "%d\n", pin) ;
513 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100514}
515
516
517/*
518 * doUnexportAll:
519 * gpio unexportall
520 * Un-Export all the GPIO pins.
521 * This uses the /sys/class/gpio device interface.
522 *********************************************************************************
523 */
524
Gordon Hendersonda384432013-05-13 19:43:26 +0100525void doUnexportall (char *progName)
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100526{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900527 FILE *fd ;
528 int pin ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100529
joshua-yang4b08e7f2019-02-21 12:05:24 +0900530 for (pin = 0 ; pin < 256 ; ++pin) {
531 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) {
532 fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ;
533 exit (1) ;
534 }
535 fprintf (fd, "%d\n", pin) ;
536 fclose (fd) ;
537 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100538}
539
540
541/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100542 * doReset:
543 * Reset the GPIO pins - as much as we can do
544 *********************************************************************************
545 */
546
Gordon Hendersone687f3f2017-01-24 12:13:39 +0000547static void doReset (UNU char *progName)
Gordon Hendersonda384432013-05-13 19:43:26 +0100548{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900549 printf ("GPIO Reset is dangerous and has been removed from the gpio command.\n") ;
550 printf (" - Please write a shell-script to reset the GPIO pins into the state\n") ;
551 printf (" that you need them in for your applications.\n") ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100552}
553
554
555/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100556 * doMode:
557 * gpio mode pin mode ...
558 *********************************************************************************
559 */
560
561void doMode (int argc, char *argv [])
562{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900563 int pin ;
564 char *mode ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100565
joshua-yang4b08e7f2019-02-21 12:05:24 +0900566 if (argc != 4) {
567 fprintf (stderr, "Usage: %s mode pin mode\n", argv [0]) ;
568 exit (1) ;
569 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100570
joshua-yang4b08e7f2019-02-21 12:05:24 +0900571 pin = atoi (argv [2]) ;
572 mode = argv [3] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100573
joshua-yang4b08e7f2019-02-21 12:05:24 +0900574 if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
575 else if (strcasecmp (mode, "input") == 0) pinMode (pin, INPUT) ;
576 else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
577 else if (strcasecmp (mode, "output") == 0) pinMode (pin, OUTPUT) ;
578 else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
579 else if (strcasecmp (mode, "pwmTone") == 0) pinMode (pin, PWM_TONE_OUTPUT) ;
580 else if (strcasecmp (mode, "clock") == 0) pinMode (pin, GPIO_CLOCK) ;
581 else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
582 else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
583 else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
584 else if (strcasecmp (mode, "off") == 0) pullUpDnControl (pin, PUD_OFF) ;
585 else if (strcasecmp (mode, "alt0") == 0) pinModeAlt (pin, 0b100) ;
586 else if (strcasecmp (mode, "alt1") == 0) pinModeAlt (pin, 0b101) ;
587 else if (strcasecmp (mode, "alt2") == 0) pinModeAlt (pin, 0b110) ;
588 else if (strcasecmp (mode, "alt3") == 0) pinModeAlt (pin, 0b111) ;
589 else if (strcasecmp (mode, "alt4") == 0) pinModeAlt (pin, 0b011) ;
590 else if (strcasecmp (mode, "alt5") == 0) pinModeAlt (pin, 0b010) ;
591 else {
592 fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/clock/up/down/tri\n", argv [1], mode) ;
593 exit (1) ;
594 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100595}
596
597
598/*
599 * doPadDrive:
joshua-yang4b08e7f2019-02-21 12:05:24 +0900600 * gpio drive pin value for ODROIDs since it depends on the SoC
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100601 *********************************************************************************
602 */
603
Gordon Henderson1bb49892012-08-19 15:33:26 +0100604static void doPadDrive (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100605{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900606 int pin, val;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100607
joshua-yang4b08e7f2019-02-21 12:05:24 +0900608 if (argc != 4) {
609 fprintf (stderr, "Usage: %s drive pin value\n", argv [0]) ;
610 exit (1) ;
611 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100612
joshua-yang4b08e7f2019-02-21 12:05:24 +0900613 pin = atoi (argv [2]) ;
614 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100615
joshua-yang4b08e7f2019-02-21 12:05:24 +0900616 setPadDrive (pin, val) ;
Gordon Hendersondf453882014-07-17 22:23:57 +0100617}
618
619
620/*
Gordon Henderson99095e32012-08-27 20:56:14 +0100621 * doGbw:
622 * gpio gbw channel value
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000623 * Gertboard Write - To the Analog output
Gordon Henderson99095e32012-08-27 20:56:14 +0100624 *********************************************************************************
625 */
626
627static void doGbw (int argc, char *argv [])
628{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900629 int channel, value ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100630
joshua-yang4b08e7f2019-02-21 12:05:24 +0900631 if (argc != 4) {
632 fprintf (stderr, "Usage: %s gbw <channel> <value>\n", argv [0]) ;
633 exit (1) ;
634 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100635
joshua-yang4b08e7f2019-02-21 12:05:24 +0900636 channel = atoi (argv [2]) ;
637 value = atoi (argv [3]) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100638
joshua-yang4b08e7f2019-02-21 12:05:24 +0900639 if ((channel < 0) || (channel > 1)) {
640 fprintf (stderr, "%s: gbw: Channel number must be 0 or 1\n", argv [0]) ;
641 exit (1) ;
642 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100643
joshua-yang4b08e7f2019-02-21 12:05:24 +0900644 if ((value < 0) || (value > 255)) {
645 fprintf (stderr, "%s: gbw: Value must be from 0 to 255\n", argv [0]) ;
646 exit (1) ;
647 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100648
joshua-yang4b08e7f2019-02-21 12:05:24 +0900649 if (gertboardAnalogSetup (64) < 0) {
650 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
651 exit (1) ;
652 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100653
joshua-yang4b08e7f2019-02-21 12:05:24 +0900654 analogWrite (64 + channel, value) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100655}
656
657
658/*
659 * doGbr:
660 * gpio gbr channel
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000661 * From the analog input
Gordon Henderson99095e32012-08-27 20:56:14 +0100662 *********************************************************************************
663 */
Gordon Henderson99095e32012-08-27 20:56:14 +0100664static void doGbr (int argc, char *argv [])
665{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900666 int channel ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100667
joshua-yang4b08e7f2019-02-21 12:05:24 +0900668 if (argc != 3) {
669 fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ;
670 exit (1) ;
671 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100672
joshua-yang4b08e7f2019-02-21 12:05:24 +0900673 channel = atoi (argv [2]) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100674
joshua-yang4b08e7f2019-02-21 12:05:24 +0900675 if ((channel < 0) || (channel > 1)) {
676 fprintf (stderr, "%s: gbr: Channel number must be 0 or 1\n", argv [0]) ;
677 exit (1) ;
678 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100679
joshua-yang4b08e7f2019-02-21 12:05:24 +0900680 if (gertboardAnalogSetup (64) < 0) {
681 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
682 exit (1) ;
683 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100684
joshua-yang4b08e7f2019-02-21 12:05:24 +0900685 printf ("%d\n", analogRead (64 + channel)) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100686}
687
688
Gordon Henderson99095e32012-08-27 20:56:14 +0100689/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100690 * doWrite:
691 * gpio write pin value
692 *********************************************************************************
693 */
694
Gordon Henderson1bb49892012-08-19 15:33:26 +0100695static void doWrite (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100696{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900697 int pin, val ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100698
joshua-yang4b08e7f2019-02-21 12:05:24 +0900699 if (argc != 4) {
700 fprintf (stderr, "Usage: %s write pin value\n", argv [0]) ;
701 exit (1) ;
702 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100703
joshua-yang4b08e7f2019-02-21 12:05:24 +0900704 pin = atoi (argv [2]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100705
joshua-yang4b08e7f2019-02-21 12:05:24 +0900706 if ((strcasecmp (argv [3], "up") == 0) || (strcasecmp (argv [3], "on") == 0))
707 val = 1 ;
708 else if ((strcasecmp (argv [3], "down") == 0) || (strcasecmp (argv [3], "off") == 0))
709 val = 0 ;
710 else
711 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100712
joshua-yang4b08e7f2019-02-21 12:05:24 +0900713 if (val == 0)
714 digitalWrite (pin, LOW) ;
715 else
716 digitalWrite (pin, HIGH) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100717}
718
Gordon Hendersonda384432013-05-13 19:43:26 +0100719
720/*
721 * doAwriterite:
722 * gpio awrite pin value
723 *********************************************************************************
724 */
725
Luke Go2ee8a0d2019-07-08 15:37:07 +0900726static void UNU doAwrite (int argc, char *argv [])
Gordon Hendersonda384432013-05-13 19:43:26 +0100727{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900728 int pin, val ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100729
joshua-yang4b08e7f2019-02-21 12:05:24 +0900730 if (argc != 4) {
731 fprintf (stderr, "Usage: %s awrite pin value\n", argv [0]) ;
732 exit (1) ;
733 }
734 pin = atoi (argv [2]) ;
735 val = atoi (argv [3]) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100736
joshua-yang4b08e7f2019-02-21 12:05:24 +0900737 analogWrite (pin, val) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100738}
739
740
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000741/*
742 * doWriteByte:
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000743 * gpio wb value
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000744 *********************************************************************************
745 */
746
747static void doWriteByte (int argc, char *argv [])
748{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900749 int val ;
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000750
joshua-yang4b08e7f2019-02-21 12:05:24 +0900751 if (argc != 3) {
752 fprintf (stderr, "Usage: %s wb value\n", argv [0]) ;
753 exit (1) ;
754 }
755 val = (int)strtol (argv [2], NULL, 0) ;
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000756
joshua-yang4b08e7f2019-02-21 12:05:24 +0900757 digitalWriteByte (val) ;
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000758}
759
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100760
761/*
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000762 * doReadByte:
763 * gpio rbx|rbd value
764 *********************************************************************************
765 */
766
767static void doReadByte (int argc, char *argv [], int printHex)
768{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900769 int val ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000770
joshua-yang4b08e7f2019-02-21 12:05:24 +0900771 if (argc != 2) {
772 fprintf (stderr, "Usage: %s rbx|rbd\n", argv [0]) ;
773 exit (1) ;
774 }
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000775
joshua-yang4b08e7f2019-02-21 12:05:24 +0900776 val = digitalReadByte () ;
777 if (printHex)
778 printf ("%02X\n", val) ;
779 else
780 printf ("%d\n", val) ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000781}
782
783
784/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100785 * doRead:
786 * Read a pin and return the value
787 *********************************************************************************
788 */
789
Joshua Yang6e7a6e62019-07-09 15:57:26 +0900790void doRead (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100791{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900792 int pin, val ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100793
joshua-yang4b08e7f2019-02-21 12:05:24 +0900794 if (argc != 3) {
795 fprintf (stderr, "Usage: %s read pin\n", argv [0]) ;
796 exit (1) ;
797 }
798 pin = atoi (argv [2]) ;
799 val = digitalRead (pin) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100800
joshua-yang4b08e7f2019-02-21 12:05:24 +0900801 printf ("%s\n", val == 0 ? "0" : "1") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100802}
803
804
805/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100806 * doAread:
807 * Read an analog pin and return the value
808 *********************************************************************************
809 */
810
Joshua Yang6e7a6e62019-07-09 15:57:26 +0900811void doAread (int argc, char *argv [])
Gordon Hendersonda384432013-05-13 19:43:26 +0100812{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900813 if (argc != 3) {
814 fprintf (stderr, "Usage: %s aread pin\n", argv [0]) ;
815 exit (1) ;
816 }
817 printf ("%d\n", analogRead (atoi (argv [2]))) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100818}
819
820
821/*
822 * doToggle:
823 * Toggle an IO pin
824 *********************************************************************************
825 */
826
827void doToggle (int argc, char *argv [])
828{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900829 int pin ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100830
joshua-yang4b08e7f2019-02-21 12:05:24 +0900831 if (argc != 3) {
832 fprintf (stderr, "Usage: %s toggle pin\n", argv [0]) ;
833 exit (1) ;
834 }
835 pin = atoi (argv [2]) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100836
joshua-yang4b08e7f2019-02-21 12:05:24 +0900837 digitalWrite (pin, !digitalRead (pin)) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100838}
839
Gordon Hendersondca8a192014-07-14 08:39:38 +0100840
841/*
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000842 * doBlink:
843 * Blink an IO pin
844 *********************************************************************************
845 */
846
847void doBlink (int argc, char *argv [])
848{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900849 int pin ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000850
joshua-yang4b08e7f2019-02-21 12:05:24 +0900851 if (argc != 3) {
852 fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ;
853 exit (1) ;
854 }
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000855
joshua-yang4b08e7f2019-02-21 12:05:24 +0900856 pin = atoi (argv [2]) ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000857
joshua-yang4b08e7f2019-02-21 12:05:24 +0900858 pinMode (pin, OUTPUT) ;
859 for (;;) {
860 digitalWrite (pin, !digitalRead (pin)) ;
861 delay (500) ;
862 }
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000863}
864
865
866/*
Gordon Hendersondca8a192014-07-14 08:39:38 +0100867 * doPwmTone:
868 * Output a tone in a PWM pin
869 *********************************************************************************
870 */
871
872void doPwmTone (int argc, char *argv [])
873{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900874 int pin, freq ;
Gordon Hendersondca8a192014-07-14 08:39:38 +0100875
joshua-yang4b08e7f2019-02-21 12:05:24 +0900876 if (argc != 4) {
877 fprintf (stderr, "Usage: %s pwmTone <pin> <freq>\n", argv [0]) ;
878 exit (1) ;
879 }
Gordon Hendersondca8a192014-07-14 08:39:38 +0100880
joshua-yang4b08e7f2019-02-21 12:05:24 +0900881 pin = atoi (argv [2]) ;
882 freq = atoi (argv [3]) ;
Gordon Hendersondca8a192014-07-14 08:39:38 +0100883
joshua-yang4b08e7f2019-02-21 12:05:24 +0900884 pwmToneWrite (pin, freq) ;
Gordon Hendersondca8a192014-07-14 08:39:38 +0100885}
886
887
Gordon Hendersonda384432013-05-13 19:43:26 +0100888/*
Gordon Henderson56c77b52013-02-01 20:19:22 +0000889 * doClock:
890 * Output a clock on a pin
891 *********************************************************************************
892 */
893
894void doClock (int argc, char *argv [])
895{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900896 int pin, freq ;
Gordon Henderson56c77b52013-02-01 20:19:22 +0000897
joshua-yang4b08e7f2019-02-21 12:05:24 +0900898 if (argc != 4) {
899 fprintf (stderr, "Usage: %s clock <pin> <freq>\n", argv [0]) ;
900 exit (1) ;
901 }
Gordon Henderson56c77b52013-02-01 20:19:22 +0000902
joshua-yang4b08e7f2019-02-21 12:05:24 +0900903 pin = atoi (argv [2]) ;
Gordon Henderson56c77b52013-02-01 20:19:22 +0000904
joshua-yang4b08e7f2019-02-21 12:05:24 +0900905 freq = atoi (argv [3]) ;
Gordon Henderson56c77b52013-02-01 20:19:22 +0000906
joshua-yang4b08e7f2019-02-21 12:05:24 +0900907 gpioClockSet (pin, freq) ;
Gordon Henderson56c77b52013-02-01 20:19:22 +0000908}
909
910
911/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100912 * doPwm:
913 * Output a PWM value on a pin
914 *********************************************************************************
915 */
916
917void doPwm (int argc, char *argv [])
918{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900919 int pin, val ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100920
joshua-yang4b08e7f2019-02-21 12:05:24 +0900921 if (argc != 4) {
922 fprintf (stderr, "Usage: %s pwm <pin> <value>\n", argv [0]) ;
923 exit (1) ;
924 }
925 pin = atoi (argv [2]) ;
926 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100927
joshua-yang4b08e7f2019-02-21 12:05:24 +0900928 pwmWrite (pin, val) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100929}
930
931
932/*
Gordon Henderson8cb49392012-09-16 10:15:32 +0100933 * doPwmMode: doPwmRange: doPwmClock:
934 * Change the PWM mode, range and clock divider values
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100935 *********************************************************************************
936 */
937
Luke Go2ee8a0d2019-07-08 15:37:07 +0900938static void UNU doPwmMode (int mode)
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100939{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900940 pwmSetMode (mode) ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100941}
942
Luke Go2ee8a0d2019-07-08 15:37:07 +0900943static void UNU doPwmRange (int argc, char *argv [])
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100944{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900945 unsigned int range ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100946
joshua-yang4b08e7f2019-02-21 12:05:24 +0900947 if (argc != 3) {
948 fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
949 exit (1) ;
950 }
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100951
joshua-yang4b08e7f2019-02-21 12:05:24 +0900952 range = (unsigned int)strtoul (argv [2], NULL, 10) ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100953
joshua-yang4b08e7f2019-02-21 12:05:24 +0900954 if (range == 0) {
955 fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
956 exit (1) ;
957 }
958 pwmSetRange (range) ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100959}
960
Luke Go2ee8a0d2019-07-08 15:37:07 +0900961static void UNU doPwmClock (int argc, char *argv [])
Gordon Henderson8cb49392012-09-16 10:15:32 +0100962{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900963 unsigned int clock ;
Gordon Henderson8cb49392012-09-16 10:15:32 +0100964
joshua-yang4b08e7f2019-02-21 12:05:24 +0900965 if (argc != 3) {
966 fprintf (stderr, "Usage: %s pwmc <clock>\n", argv [0]) ;
967 exit (1) ;
968 }
Gordon Henderson8cb49392012-09-16 10:15:32 +0100969
joshua-yang4b08e7f2019-02-21 12:05:24 +0900970 clock = (unsigned int)strtoul (argv [2], NULL, 10) ;
Gordon Henderson8cb49392012-09-16 10:15:32 +0100971
joshua-yang4b08e7f2019-02-21 12:05:24 +0900972 if ((clock < 1) || (clock > 4095)) {
973 fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ;
974 exit (1) ;
975 }
976 pwmSetClock (clock) ;
Gordon Henderson8cb49392012-09-16 10:15:32 +0100977}
978
joshua-yang4b08e7f2019-02-21 12:05:24 +0900979/*
980 * doNothing:
981 * function is not support by ODROID Board.
982 *********************************************************************************
983 */
Luke Go2ee8a0d2019-07-08 15:37:07 +0900984static void doNothing (int UNU argc, char *argv [])
joshua-yang4b08e7f2019-02-21 12:05:24 +0900985{
986 fprintf(stderr, "warn : (%s) : This function is not supported by ODROID Board.\n",
987 argv[1]);
988}
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100989
990/*
Gordon Hendersonbb6f0842015-11-29 21:08:04 +0000991 * doVersion:
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000992 * Handle the ever more complicated version command and print out
993 * some usefull information.
Gordon Hendersonbb6f0842015-11-29 21:08:04 +0000994 *********************************************************************************
995 */
Gordon Hendersonbb6f0842015-11-29 21:08:04 +0000996static void doVersion (char *argv [])
997{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900998 int model, rev, mem, maker, warranty ;
999 struct stat statBuf ;
1000 char name [80] ;
1001 FILE *fd ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001002
Joshua Yang41a423e2019-07-16 18:08:16 +09001003 int vMaj;
1004 char *vMin[32];
Gordon Hendersone687f3f2017-01-24 12:13:39 +00001005
Joshua Yang41a423e2019-07-16 18:08:16 +09001006 wiringPiVersion (&vMaj, vMin) ;
1007 printf ("gpio version: %d.%s\n", vMaj, *vMin) ;
joshua-yang4b08e7f2019-02-21 12:05:24 +09001008 printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
1009 printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
1010 printf ("For details type: %s -warranty\n", argv [0]) ;
1011 printf ("\n") ;
1012 piBoardId (&model, &rev, &mem, &maker, &warranty) ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001013
joshua-yang4b08e7f2019-02-21 12:05:24 +09001014 printf ("ODROID Board Details:\n") ;
1015 printf (" Type: %s, Revision: %s, Memory: %dMB\n" \
Joshua Yang6e7a6e62019-07-09 15:57:26 +09001016 " Maker: %s, Chip-Vendor: %s\n",
joshua-yang4b08e7f2019-02-21 12:05:24 +09001017 piModelNames [model],
1018 piRevisionNames [rev],
1019 piMemorySize [mem],
1020 "Hardkernel",
1021 piMakerNames [maker]);
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001022
joshua-yang4b08e7f2019-02-21 12:05:24 +09001023 // Check for device tree
1024 if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ...
1025 printf (" * Device tree is enabled.\n") ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001026
joshua-yang4b08e7f2019-02-21 12:05:24 +09001027 // Output Kernel idea of board type
1028 if (stat ("/proc/device-tree/model", &statBuf) == 0) {
1029 if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL) {
Joshua Yang6e7a6e62019-07-09 15:57:26 +09001030 if (fgets (name, 80, fd) == NULL)
1031 fprintf(stderr, "Unable to read from the file descriptor: %s \n", strerror(errno));
joshua-yang4b08e7f2019-02-21 12:05:24 +09001032 fclose (fd) ;
1033 printf (" *--> %s\n", name) ;
1034 }
1035 }
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001036
joshua-yang4b08e7f2019-02-21 12:05:24 +09001037 // User level GPIO is GO
1038 if (stat ("/dev/gpiomem", &statBuf) == 0)
1039 printf (" * Supports user-level GPIO access.\n") ;
1040 else
1041 printf (" * Root or sudo required for GPIO access.\n") ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001042}
1043
1044
1045/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001046 * main:
1047 * Start here
1048 *********************************************************************************
1049 */
1050
1051int main (int argc, char *argv [])
1052{
joshua-yang4b08e7f2019-02-21 12:05:24 +09001053 int i ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001054
joshua-yang4b08e7f2019-02-21 12:05:24 +09001055 if (getenv ("WIRINGPI_DEBUG") != NULL) {
1056 printf ("gpio: wiringPi debug mode enabled\n") ;
1057 wiringPiDebug = TRUE ;
1058 }
Gordon Henderson13bbba72013-01-14 11:31:56 +00001059
joshua-yang4b08e7f2019-02-21 12:05:24 +09001060 if (argc == 1) {
1061 fprintf (stderr, "%s\n", usage) ;
1062 return 1 ;
1063 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001064
joshua-yang4b08e7f2019-02-21 12:05:24 +09001065 // Help
1066 if (strcasecmp (argv [1], "-h") == 0) {
1067 printf ("%s: %s\n", argv [0], usage) ;
1068 return 0 ;
1069 }
Gordon Hendersonda384432013-05-13 19:43:26 +01001070
joshua-yang4b08e7f2019-02-21 12:05:24 +09001071 // Version & Warranty
1072 // Wish I could remember why I have both -R and -V ...
1073 if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0)) {
1074 printf ("%d\n", piGpioLayout ()) ;
1075 return 0 ;
1076 }
Gordon Henderson178ea082012-08-19 15:17:03 +01001077
joshua-yang4b08e7f2019-02-21 12:05:24 +09001078 // Version and information
1079 if (strcmp (argv [1], "-v") == 0) {
1080 doVersion (argv) ;
1081 return 0 ;
1082 }
Gordon Hendersonda384432013-05-13 19:43:26 +01001083
joshua-yang4b08e7f2019-02-21 12:05:24 +09001084 if (strcasecmp (argv [1], "-warranty") == 0) {
1085 printf ("gpio version: %s\n", VERSION) ;
1086 printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
1087 printf ("\n") ;
1088 printf (" This program is free software; you can redistribute it and/or modify\n") ;
1089 printf (" it under the terms of the GNU Leser General Public License as published\n") ;
1090 printf (" by the Free Software Foundation, either version 3 of the License, or\n") ;
1091 printf (" (at your option) any later version.\n") ;
1092 printf ("\n") ;
1093 printf (" This program is distributed in the hope that it will be useful,\n") ;
1094 printf (" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
1095 printf (" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") ;
1096 printf (" GNU Lesser General Public License for more details.\n") ;
1097 printf ("\n") ;
1098 printf (" You should have received a copy of the GNU Lesser General Public License\n") ;
1099 printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
1100 printf ("\n") ;
1101 return 0 ;
1102 }
Gordon Hendersonda384432013-05-13 19:43:26 +01001103
joshua-yang4b08e7f2019-02-21 12:05:24 +09001104 if (geteuid () != 0) {
1105 fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
1106 return 1 ;
1107 }
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001108
joshua-yang4b08e7f2019-02-21 12:05:24 +09001109 // Initial test for /sys/class/gpio operations:
1110 if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; }
1111 else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; }
1112 else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; }
1113 else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }
1114 else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argv [0]) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001115
joshua-yang4b08e7f2019-02-21 12:05:24 +09001116 // Check for load command:
1117 if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; }
1118 if (strcasecmp (argv [1], "unload" ) == 0) { doUnLoad (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001119
joshua-yang4b08e7f2019-02-21 12:05:24 +09001120 // Check for usb power command
1121 if (strcasecmp (argv [1], "usbp" ) == 0) { doNothing(argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001122
joshua-yang4b08e7f2019-02-21 12:05:24 +09001123 // Gertboard commands
1124 if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; }
1125 if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001126
joshua-yang4b08e7f2019-02-21 12:05:24 +09001127 // Check for allreadall command, force Gpio mode
1128 if (strcasecmp (argv [1], "allreadall") == 0) {
1129 wiringPiSetupGpio () ;
1130 doAllReadall () ;
1131 return 0 ;
1132 }
Gordon Henderson178ea082012-08-19 15:17:03 +01001133
joshua-yang4b08e7f2019-02-21 12:05:24 +09001134 if (strcasecmp (argv [1], "-g") == 0) { // Check for -g argument
1135 wiringPiSetupGpio () ;
Gordon Henderson178ea082012-08-19 15:17:03 +01001136
joshua-yang4b08e7f2019-02-21 12:05:24 +09001137 for (i = 2 ; i < argc ; ++i)
1138 argv [i - 1] = argv [i] ;
1139 --argc ;
1140 wpMode = MODE_GPIO ;
1141 } else if (strcasecmp (argv [1], "-1") == 0) { // Check for -1 argument
1142 wiringPiSetupPhys () ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001143
joshua-yang4b08e7f2019-02-21 12:05:24 +09001144 for (i = 2 ; i < argc ; ++i)
1145 argv [i - 1] = argv [i] ;
1146 --argc ;
1147 wpMode = MODE_PHYS ;
1148 } else if (strcasecmp (argv [1], "-p") == 0) { // Check for -p argument for PiFace
1149 piFaceSetup (200) ;
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001150
joshua-yang4b08e7f2019-02-21 12:05:24 +09001151 for (i = 2 ; i < argc ; ++i)
1152 argv [i - 1] = argv [i] ;
1153 --argc ;
1154 wpMode = MODE_PIFACE ;
1155 } else if (strcasecmp (argv [1], "-z") == 0) { // Check for -z argument so we don't actually initialise wiringPi
1156 for (i = 2 ; i < argc ; ++i)
1157 argv [i - 1] = argv [i] ;
1158 --argc ;
1159 wpMode = MODE_UNINITIALISED ;
1160 } else { // Default to wiringPi mode
1161 wiringPiSetup () ;
1162 wpMode = MODE_PINS ;
1163 }
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001164
joshua-yang4b08e7f2019-02-21 12:05:24 +09001165 // Check for -x argument to load in a new extension
1166 // -x extension:base:args
1167 // Can load many modules, but unless daemon mode we can only send one
1168 // command at a time.
1169 while (strcasecmp (argv [1], "-x") == 0) {
1170 if (argc < 3) {
1171 fprintf (stderr, "%s: -x missing extension command.\n", argv [0]) ;
1172 exit (EXIT_FAILURE) ;
1173 }
Gordon Henderson99095e32012-08-27 20:56:14 +01001174
joshua-yang4b08e7f2019-02-21 12:05:24 +09001175 if (!loadWPiExtension (argv [0], argv [2], TRUE)) {
1176 fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ;
1177 exit (EXIT_FAILURE) ;
1178 }
Gordon Henderson99095e32012-08-27 20:56:14 +01001179
joshua-yang4b08e7f2019-02-21 12:05:24 +09001180 // Shift args down by 2
1181 for (i = 3 ; i < argc ; ++i)
1182 argv [i - 2] = argv [i] ;
1183 argc -= 2 ;
1184 }
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001185
joshua-yang4b08e7f2019-02-21 12:05:24 +09001186 if (argc <= 1) {
1187 fprintf (stderr, "%s: no command given\n", argv [0]) ;
1188 exit (EXIT_FAILURE) ;
1189 }
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001190
joshua-yang4b08e7f2019-02-21 12:05:24 +09001191 // Core wiringPi functions
1192 /**/ if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ;
1193 else if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ;
1194 else if (strcasecmp (argv [1], "write" ) == 0) doWrite (argc, argv) ;
1195 else if (strcasecmp (argv [1], "pwm" ) == 0) doNothing (argc, argv) ;
1196 else if (strcasecmp (argv [1], "awrite" ) == 0) doNothing (argc, argv) ;
1197 else if (strcasecmp (argv [1], "aread" ) == 0) doAread (argc, argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001198
joshua-yang4b08e7f2019-02-21 12:05:24 +09001199 // GPIO Nicies
1200 else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ;
1201 else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001202
joshua-yang4b08e7f2019-02-21 12:05:24 +09001203 // Pi Specifics
1204 else if (strcasecmp (argv [1], "pwm-bal" ) == 0) doNothing (argc, argv) ;
1205 else if (strcasecmp (argv [1], "pwm-ms" ) == 0) doNothing (argc, argv) ;
1206 else if (strcasecmp (argv [1], "pwmr" ) == 0) doNothing (argc, argv) ;
1207 else if (strcasecmp (argv [1], "pwmc" ) == 0) doNothing (argc, argv) ;
1208 else if (strcasecmp (argv [1], "pwmTone" ) == 0) doNothing (argc, argv) ;
1209 else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ;
1210 else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ;
1211 else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ;
1212 else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ;
1213 else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect (argc, argv) ;
1214 else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ;
1215 else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ;
1216 else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ;
1217 else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ;
1218 else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ;
1219 else if (strcasecmp (argv [1], "clock" ) == 0) doNothing (argc, argv) ;
1220 else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ;
1221 else {
1222 fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
1223 exit (EXIT_FAILURE) ;
1224 }
1225 return 0 ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001226}