blob: 385fe831ecb43e40da109d06238a1976d41586e5 [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;
225 default:
226 break;
227 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100228
joshua-yang4b08e7f2019-02-21 12:05:24 +0900229 if ((c = findExecutable (I2CDETECT)) == NULL) {
230 fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ;
231 return ;
232 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100233
joshua-yang4b08e7f2019-02-21 12:05:24 +0900234 switch (maker) {
235 case MAKER_AMLOGIC:
236 if (!moduleLoaded (AML_MODULE_I2C)) {
237 fprintf (stderr, "%s: The I2C kernel module(s) are not loaded.\n", argv [0]) ;
joshua-yang4b08e7f2019-02-21 12:05:24 +0900238 }
239 default:
240 break;
241 }
242
243 command = malloc (strlen (c) + 16) ;
244 sprintf (command, "%s -y %d", c, port) ;
245 if (system (command) < 0)
246 fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100247}
248
249
250/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100251 * doExports:
252 * List all GPIO exports
253 *********************************************************************************
254 */
Gordon Hendersone687f3f2017-01-24 12:13:39 +0000255static void doExports (UNU int argc, UNU char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100256{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900257 int fd ;
258 int i, l, first ;
259 char fName [128] ;
260 char buf [16] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100261
joshua-yang4b08e7f2019-02-21 12:05:24 +0900262 // Crude, but effective
263 for (first = 0, i = 0 ; i < 256 ; ++i) {
264 // Try to read the direction
265 sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ;
266 if ((fd = open (fName, O_RDONLY)) == -1)
267 continue ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100268
joshua-yang4b08e7f2019-02-21 12:05:24 +0900269 if (first == 0) {
270 ++first ;
271 printf ("GPIO Pins exported:\n") ;
272 }
273 printf ("%4d: ", i) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100274
joshua-yang4b08e7f2019-02-21 12:05:24 +0900275 if ((l = read (fd, buf, 16)) == 0)
276 sprintf (buf, "%s", "?") ;
Joshua Yang6e7a6e62019-07-09 15:57:26 +0900277
joshua-yang4b08e7f2019-02-21 12:05:24 +0900278 buf [l] = 0 ;
279 if ((buf [strlen (buf) - 1]) == '\n')
280 buf [strlen (buf) - 1] = 0 ;
281 printf ("%-3s", buf) ;
282 close (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100283
joshua-yang4b08e7f2019-02-21 12:05:24 +0900284 // Try to Read the value
285 sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ;
286 if ((fd = open (fName, O_RDONLY)) == -1) {
287 printf ("No Value file (huh?)\n") ;
288 continue ;
289 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100290
joshua-yang4b08e7f2019-02-21 12:05:24 +0900291 if ((l = read (fd, buf, 16)) == 0)
292 sprintf (buf, "%s", "?") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100293
joshua-yang4b08e7f2019-02-21 12:05:24 +0900294 buf [l] = 0 ;
295 if ((buf [strlen (buf) - 1]) == '\n')
296 buf [strlen (buf) - 1] = 0 ;
297 printf (" %s", buf) ;
298 close (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100299
joshua-yang4b08e7f2019-02-21 12:05:24 +0900300 // Read any edge trigger file
301 sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ;
302 if ((fd = open (fName, O_RDONLY)) == -1) {
303 printf ("\n") ;
304 continue ;
305 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100306
joshua-yang4b08e7f2019-02-21 12:05:24 +0900307 if ((l = read (fd, buf, 16)) == 0)
308 sprintf (buf, "%s", "?") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100309
joshua-yang4b08e7f2019-02-21 12:05:24 +0900310 buf [l] = 0 ;
311 if ((buf [strlen (buf) - 1]) == '\n')
312 buf [strlen (buf) - 1] = 0 ;
313 printf (" %-8s\n", buf) ;
314 close (fd) ;
315 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100316}
317
318
319/*
320 * doExport:
321 * gpio export pin mode
322 * This uses the /sys/class/gpio device interface.
323 *********************************************************************************
324 */
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100325void doExport (int argc, char *argv [])
326{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900327 FILE *fd ;
328 int pin ;
329 char *mode ;
330 char fName [128] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100331
joshua-yang4b08e7f2019-02-21 12:05:24 +0900332 if (argc != 4) {
333 fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ;
334 exit (1) ;
335 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100336
joshua-yang4b08e7f2019-02-21 12:05:24 +0900337 pin = atoi (argv [2]) ;
338 mode = argv [3] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100339
joshua-yang4b08e7f2019-02-21 12:05:24 +0900340 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) {
341 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
342 exit (1) ;
343 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100344
joshua-yang4b08e7f2019-02-21 12:05:24 +0900345 fprintf (fd, "%d\n", pin) ;
346 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100347
joshua-yang4b08e7f2019-02-21 12:05:24 +0900348 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
349 if ((fd = fopen (fName, "w")) == NULL) {
350 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
351 exit (1) ;
352 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100353
joshua-yang4b08e7f2019-02-21 12:05:24 +0900354 if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0))
355 fprintf (fd, "in\n") ;
356 else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0))
357 fprintf (fd, "out\n") ;
358 else if ((strcasecmp (mode, "high") == 0) || (strcasecmp (mode, "up") == 0))
359 fprintf (fd, "high\n") ;
360 else if ((strcasecmp (mode, "low") == 0) || (strcasecmp (mode, "down") == 0))
361 fprintf (fd, "low\n") ;
362 else {
363 fprintf (stderr, "%s: Invalid mode: %s. Should be in, out, high or low\n", argv [1], mode) ;
364 exit (1) ;
365 }
366 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100367
joshua-yang4b08e7f2019-02-21 12:05:24 +0900368 // Change ownership so the current user can actually use it
369 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
370 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100371
joshua-yang4b08e7f2019-02-21 12:05:24 +0900372 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
373 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100374}
375
376
377/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100378 * doWfi:
379 * gpio wfi pin mode
380 * Wait for Interrupt on a given pin.
381 * Slight cheat here - it's easier to actually use ISR now (which calls
382 * gpio to set the pin modes!) then we simply sleep, and expect the thread
383 * to exit the program. Crude but effective.
384 *********************************************************************************
385 */
joshua-yang4b08e7f2019-02-21 12:05:24 +0900386static void wfi (void) { exit (0) ; }
Gordon Hendersonda384432013-05-13 19:43:26 +0100387
388void doWfi (int argc, char *argv [])
389{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900390 int pin, mode ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100391
joshua-yang4b08e7f2019-02-21 12:05:24 +0900392 if (argc != 4) {
393 fprintf (stderr, "Usage: %s wfi pin mode\n", argv [0]) ;
394 exit (1) ;
395 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100396
joshua-yang4b08e7f2019-02-21 12:05:24 +0900397 pin = atoi (argv [2]) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100398
joshua-yang4b08e7f2019-02-21 12:05:24 +0900399 if (strcasecmp (argv [3], "rising") == 0) mode = INT_EDGE_RISING ;
400 else if (strcasecmp (argv [3], "falling") == 0) mode = INT_EDGE_FALLING ;
401 else if (strcasecmp (argv [3], "both") == 0) mode = INT_EDGE_BOTH ;
402 else {
403 fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv [1], argv [3]) ;
404 exit (1) ;
405 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100406
joshua-yang4b08e7f2019-02-21 12:05:24 +0900407 if (wiringPiISR (pin, mode, &wfi) < 0) {
408 fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ;
409 exit (1) ;
410 }
Gordon Hendersonda384432013-05-13 19:43:26 +0100411
joshua-yang4b08e7f2019-02-21 12:05:24 +0900412 for (;;)
413 delay (9999) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100414}
415
416
Gordon Hendersonda384432013-05-13 19:43:26 +0100417/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100418 * doEdge:
419 * gpio edge pin mode
420 * Easy access to changing the edge trigger on a GPIO pin
421 * This uses the /sys/class/gpio device interface.
422 *********************************************************************************
423 */
424
425void doEdge (int argc, char *argv [])
426{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900427 FILE *fd ;
428 int pin ;
429 char *mode ;
430 char fName [128] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100431
joshua-yang4b08e7f2019-02-21 12:05:24 +0900432 // Reset gpio sysfs
433 doUnexport(3, argv);
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100434
joshua-yang4b08e7f2019-02-21 12:05:24 +0900435 if (argc != 4) {
436 fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ;
437 exit (1) ;
438 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100439
joshua-yang4b08e7f2019-02-21 12:05:24 +0900440 pin = atoi (argv [2]) ;
441 mode = argv [3] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100442
joshua-yang4b08e7f2019-02-21 12:05:24 +0900443 // Export the pin and set direction to input
444 if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) {
445 fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
446 exit (1) ;
447 }
448 fprintf (fd, "%d\n", pin) ;
449 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100450
joshua-yang4b08e7f2019-02-21 12:05:24 +0900451 sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
452 if ((fd = fopen (fName, "w")) == NULL) {
453 fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
454 exit (1) ;
455 }
456 fprintf (fd, "in\n") ;
457 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100458
joshua-yang4b08e7f2019-02-21 12:05:24 +0900459 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
460 if ((fd = fopen (fName, "w")) == NULL) {
461 fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
462 exit (1) ;
463 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100464
joshua-yang4b08e7f2019-02-21 12:05:24 +0900465 if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ;
466 else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ;
467 else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
468 else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ;
469 else {
470 fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
471 exit (1) ;
472 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100473
joshua-yang4b08e7f2019-02-21 12:05:24 +0900474 // Change ownership of the value and edge files, so the current user can actually use it!
475 sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
476 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100477
joshua-yang4b08e7f2019-02-21 12:05:24 +0900478 sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
479 changeOwner (argv [0], fName) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100480
joshua-yang4b08e7f2019-02-21 12:05:24 +0900481 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100482}
483
484
485/*
486 * doUnexport:
487 * gpio unexport pin
488 * This uses the /sys/class/gpio device interface.
489 *********************************************************************************
490 */
491
492void doUnexport (int argc, char *argv [])
493{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900494 FILE *fd ;
495 int pin ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100496
joshua-yang4b08e7f2019-02-21 12:05:24 +0900497 if (argc != 3) {
498 fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ;
499 exit (1) ;
500 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100501
joshua-yang4b08e7f2019-02-21 12:05:24 +0900502 pin = atoi (argv [2]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100503
joshua-yang4b08e7f2019-02-21 12:05:24 +0900504 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) {
505 fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
506 exit (1) ;
507 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100508
joshua-yang4b08e7f2019-02-21 12:05:24 +0900509 fprintf (fd, "%d\n", pin) ;
510 fclose (fd) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100511}
512
513
514/*
515 * doUnexportAll:
516 * gpio unexportall
517 * Un-Export all the GPIO pins.
518 * This uses the /sys/class/gpio device interface.
519 *********************************************************************************
520 */
521
Gordon Hendersonda384432013-05-13 19:43:26 +0100522void doUnexportall (char *progName)
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100523{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900524 FILE *fd ;
525 int pin ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100526
joshua-yang4b08e7f2019-02-21 12:05:24 +0900527 for (pin = 0 ; pin < 256 ; ++pin) {
528 if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) {
529 fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ;
530 exit (1) ;
531 }
532 fprintf (fd, "%d\n", pin) ;
533 fclose (fd) ;
534 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100535}
536
537
538/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100539 * doReset:
540 * Reset the GPIO pins - as much as we can do
541 *********************************************************************************
542 */
543
Gordon Hendersone687f3f2017-01-24 12:13:39 +0000544static void doReset (UNU char *progName)
Gordon Hendersonda384432013-05-13 19:43:26 +0100545{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900546 printf ("GPIO Reset is dangerous and has been removed from the gpio command.\n") ;
547 printf (" - Please write a shell-script to reset the GPIO pins into the state\n") ;
548 printf (" that you need them in for your applications.\n") ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100549}
550
551
552/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100553 * doMode:
554 * gpio mode pin mode ...
555 *********************************************************************************
556 */
557
558void doMode (int argc, char *argv [])
559{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900560 int pin ;
561 char *mode ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100562
joshua-yang4b08e7f2019-02-21 12:05:24 +0900563 if (argc != 4) {
564 fprintf (stderr, "Usage: %s mode pin mode\n", argv [0]) ;
565 exit (1) ;
566 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100567
joshua-yang4b08e7f2019-02-21 12:05:24 +0900568 pin = atoi (argv [2]) ;
569 mode = argv [3] ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100570
joshua-yang4b08e7f2019-02-21 12:05:24 +0900571 if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
572 else if (strcasecmp (mode, "input") == 0) pinMode (pin, INPUT) ;
573 else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
574 else if (strcasecmp (mode, "output") == 0) pinMode (pin, OUTPUT) ;
575 else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
576 else if (strcasecmp (mode, "pwmTone") == 0) pinMode (pin, PWM_TONE_OUTPUT) ;
577 else if (strcasecmp (mode, "clock") == 0) pinMode (pin, GPIO_CLOCK) ;
578 else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
579 else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
580 else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
581 else if (strcasecmp (mode, "off") == 0) pullUpDnControl (pin, PUD_OFF) ;
582 else if (strcasecmp (mode, "alt0") == 0) pinModeAlt (pin, 0b100) ;
583 else if (strcasecmp (mode, "alt1") == 0) pinModeAlt (pin, 0b101) ;
584 else if (strcasecmp (mode, "alt2") == 0) pinModeAlt (pin, 0b110) ;
585 else if (strcasecmp (mode, "alt3") == 0) pinModeAlt (pin, 0b111) ;
586 else if (strcasecmp (mode, "alt4") == 0) pinModeAlt (pin, 0b011) ;
587 else if (strcasecmp (mode, "alt5") == 0) pinModeAlt (pin, 0b010) ;
588 else {
589 fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/clock/up/down/tri\n", argv [1], mode) ;
590 exit (1) ;
591 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100592}
593
594
595/*
596 * doPadDrive:
joshua-yang4b08e7f2019-02-21 12:05:24 +0900597 * gpio drive pin value for ODROIDs since it depends on the SoC
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100598 *********************************************************************************
599 */
600
Gordon Henderson1bb49892012-08-19 15:33:26 +0100601static void doPadDrive (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100602{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900603 int pin, val;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100604
joshua-yang4b08e7f2019-02-21 12:05:24 +0900605 if (argc != 4) {
606 fprintf (stderr, "Usage: %s drive pin value\n", argv [0]) ;
607 exit (1) ;
608 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100609
joshua-yang4b08e7f2019-02-21 12:05:24 +0900610 pin = atoi (argv [2]) ;
611 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100612
joshua-yang4b08e7f2019-02-21 12:05:24 +0900613 setPadDrive (pin, val) ;
Gordon Hendersondf453882014-07-17 22:23:57 +0100614}
615
616
617/*
Gordon Henderson99095e32012-08-27 20:56:14 +0100618 * doGbw:
619 * gpio gbw channel value
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000620 * Gertboard Write - To the Analog output
Gordon Henderson99095e32012-08-27 20:56:14 +0100621 *********************************************************************************
622 */
623
624static void doGbw (int argc, char *argv [])
625{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900626 int channel, value ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100627
joshua-yang4b08e7f2019-02-21 12:05:24 +0900628 if (argc != 4) {
629 fprintf (stderr, "Usage: %s gbw <channel> <value>\n", argv [0]) ;
630 exit (1) ;
631 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100632
joshua-yang4b08e7f2019-02-21 12:05:24 +0900633 channel = atoi (argv [2]) ;
634 value = atoi (argv [3]) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100635
joshua-yang4b08e7f2019-02-21 12:05:24 +0900636 if ((channel < 0) || (channel > 1)) {
637 fprintf (stderr, "%s: gbw: Channel number must be 0 or 1\n", argv [0]) ;
638 exit (1) ;
639 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100640
joshua-yang4b08e7f2019-02-21 12:05:24 +0900641 if ((value < 0) || (value > 255)) {
642 fprintf (stderr, "%s: gbw: Value must be from 0 to 255\n", argv [0]) ;
643 exit (1) ;
644 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100645
joshua-yang4b08e7f2019-02-21 12:05:24 +0900646 if (gertboardAnalogSetup (64) < 0) {
647 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
648 exit (1) ;
649 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100650
joshua-yang4b08e7f2019-02-21 12:05:24 +0900651 analogWrite (64 + channel, value) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100652}
653
654
655/*
656 * doGbr:
657 * gpio gbr channel
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000658 * From the analog input
Gordon Henderson99095e32012-08-27 20:56:14 +0100659 *********************************************************************************
660 */
Gordon Henderson99095e32012-08-27 20:56:14 +0100661static void doGbr (int argc, char *argv [])
662{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900663 int channel ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100664
joshua-yang4b08e7f2019-02-21 12:05:24 +0900665 if (argc != 3) {
666 fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ;
667 exit (1) ;
668 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100669
joshua-yang4b08e7f2019-02-21 12:05:24 +0900670 channel = atoi (argv [2]) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100671
joshua-yang4b08e7f2019-02-21 12:05:24 +0900672 if ((channel < 0) || (channel > 1)) {
673 fprintf (stderr, "%s: gbr: Channel number must be 0 or 1\n", argv [0]) ;
674 exit (1) ;
675 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100676
joshua-yang4b08e7f2019-02-21 12:05:24 +0900677 if (gertboardAnalogSetup (64) < 0) {
678 fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
679 exit (1) ;
680 }
Gordon Henderson99095e32012-08-27 20:56:14 +0100681
joshua-yang4b08e7f2019-02-21 12:05:24 +0900682 printf ("%d\n", analogRead (64 + channel)) ;
Gordon Henderson99095e32012-08-27 20:56:14 +0100683}
684
685
Gordon Henderson99095e32012-08-27 20:56:14 +0100686/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100687 * doWrite:
688 * gpio write pin value
689 *********************************************************************************
690 */
691
Gordon Henderson1bb49892012-08-19 15:33:26 +0100692static void doWrite (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100693{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900694 int pin, val ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100695
joshua-yang4b08e7f2019-02-21 12:05:24 +0900696 if (argc != 4) {
697 fprintf (stderr, "Usage: %s write pin value\n", argv [0]) ;
698 exit (1) ;
699 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100700
joshua-yang4b08e7f2019-02-21 12:05:24 +0900701 pin = atoi (argv [2]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100702
joshua-yang4b08e7f2019-02-21 12:05:24 +0900703 if ((strcasecmp (argv [3], "up") == 0) || (strcasecmp (argv [3], "on") == 0))
704 val = 1 ;
705 else if ((strcasecmp (argv [3], "down") == 0) || (strcasecmp (argv [3], "off") == 0))
706 val = 0 ;
707 else
708 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100709
joshua-yang4b08e7f2019-02-21 12:05:24 +0900710 if (val == 0)
711 digitalWrite (pin, LOW) ;
712 else
713 digitalWrite (pin, HIGH) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100714}
715
Gordon Hendersonda384432013-05-13 19:43:26 +0100716
717/*
718 * doAwriterite:
719 * gpio awrite pin value
720 *********************************************************************************
721 */
722
Luke Go2ee8a0d2019-07-08 15:37:07 +0900723static void UNU doAwrite (int argc, char *argv [])
Gordon Hendersonda384432013-05-13 19:43:26 +0100724{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900725 int pin, val ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100726
joshua-yang4b08e7f2019-02-21 12:05:24 +0900727 if (argc != 4) {
728 fprintf (stderr, "Usage: %s awrite pin value\n", argv [0]) ;
729 exit (1) ;
730 }
731 pin = atoi (argv [2]) ;
732 val = atoi (argv [3]) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100733
joshua-yang4b08e7f2019-02-21 12:05:24 +0900734 analogWrite (pin, val) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100735}
736
737
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000738/*
739 * doWriteByte:
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000740 * gpio wb value
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000741 *********************************************************************************
742 */
743
744static void doWriteByte (int argc, char *argv [])
745{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900746 int val ;
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000747
joshua-yang4b08e7f2019-02-21 12:05:24 +0900748 if (argc != 3) {
749 fprintf (stderr, "Usage: %s wb value\n", argv [0]) ;
750 exit (1) ;
751 }
752 val = (int)strtol (argv [2], NULL, 0) ;
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000753
joshua-yang4b08e7f2019-02-21 12:05:24 +0900754 digitalWriteByte (val) ;
Gordon Henderson25e4ec52012-12-06 21:49:41 +0000755}
756
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100757
758/*
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000759 * doReadByte:
760 * gpio rbx|rbd value
761 *********************************************************************************
762 */
763
764static void doReadByte (int argc, char *argv [], int printHex)
765{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900766 int val ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000767
joshua-yang4b08e7f2019-02-21 12:05:24 +0900768 if (argc != 2) {
769 fprintf (stderr, "Usage: %s rbx|rbd\n", argv [0]) ;
770 exit (1) ;
771 }
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000772
joshua-yang4b08e7f2019-02-21 12:05:24 +0900773 val = digitalReadByte () ;
774 if (printHex)
775 printf ("%02X\n", val) ;
776 else
777 printf ("%d\n", val) ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000778}
779
780
781/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100782 * doRead:
783 * Read a pin and return the value
784 *********************************************************************************
785 */
786
Joshua Yang6e7a6e62019-07-09 15:57:26 +0900787void doRead (int argc, char *argv [])
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100788{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900789 int pin, val ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100790
joshua-yang4b08e7f2019-02-21 12:05:24 +0900791 if (argc != 3) {
792 fprintf (stderr, "Usage: %s read pin\n", argv [0]) ;
793 exit (1) ;
794 }
795 pin = atoi (argv [2]) ;
796 val = digitalRead (pin) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100797
joshua-yang4b08e7f2019-02-21 12:05:24 +0900798 printf ("%s\n", val == 0 ? "0" : "1") ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100799}
800
801
802/*
Gordon Hendersonda384432013-05-13 19:43:26 +0100803 * doAread:
804 * Read an analog pin and return the value
805 *********************************************************************************
806 */
807
Joshua Yang6e7a6e62019-07-09 15:57:26 +0900808void doAread (int argc, char *argv [])
Gordon Hendersonda384432013-05-13 19:43:26 +0100809{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900810 if (argc != 3) {
811 fprintf (stderr, "Usage: %s aread pin\n", argv [0]) ;
812 exit (1) ;
813 }
814 printf ("%d\n", analogRead (atoi (argv [2]))) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100815}
816
817
818/*
819 * doToggle:
820 * Toggle an IO pin
821 *********************************************************************************
822 */
823
824void doToggle (int argc, char *argv [])
825{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900826 int pin ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100827
joshua-yang4b08e7f2019-02-21 12:05:24 +0900828 if (argc != 3) {
829 fprintf (stderr, "Usage: %s toggle pin\n", argv [0]) ;
830 exit (1) ;
831 }
832 pin = atoi (argv [2]) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100833
joshua-yang4b08e7f2019-02-21 12:05:24 +0900834 digitalWrite (pin, !digitalRead (pin)) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100835}
836
Gordon Hendersondca8a192014-07-14 08:39:38 +0100837
838/*
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000839 * doBlink:
840 * Blink an IO pin
841 *********************************************************************************
842 */
843
844void doBlink (int argc, char *argv [])
845{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900846 int pin ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000847
joshua-yang4b08e7f2019-02-21 12:05:24 +0900848 if (argc != 3) {
849 fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ;
850 exit (1) ;
851 }
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000852
joshua-yang4b08e7f2019-02-21 12:05:24 +0900853 pin = atoi (argv [2]) ;
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000854
joshua-yang4b08e7f2019-02-21 12:05:24 +0900855 pinMode (pin, OUTPUT) ;
856 for (;;) {
857 digitalWrite (pin, !digitalRead (pin)) ;
858 delay (500) ;
859 }
Gordon Hendersonb1dfc182016-12-12 14:19:55 +0000860}
861
862
863/*
Gordon Hendersondca8a192014-07-14 08:39:38 +0100864 * doPwmTone:
865 * Output a tone in a PWM pin
866 *********************************************************************************
867 */
868
869void doPwmTone (int argc, char *argv [])
870{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900871 int pin, freq ;
Gordon Hendersondca8a192014-07-14 08:39:38 +0100872
joshua-yang4b08e7f2019-02-21 12:05:24 +0900873 if (argc != 4) {
874 fprintf (stderr, "Usage: %s pwmTone <pin> <freq>\n", argv [0]) ;
875 exit (1) ;
876 }
Gordon Hendersondca8a192014-07-14 08:39:38 +0100877
joshua-yang4b08e7f2019-02-21 12:05:24 +0900878 pin = atoi (argv [2]) ;
879 freq = atoi (argv [3]) ;
Gordon Hendersondca8a192014-07-14 08:39:38 +0100880
joshua-yang4b08e7f2019-02-21 12:05:24 +0900881 pwmToneWrite (pin, freq) ;
Gordon Hendersondca8a192014-07-14 08:39:38 +0100882}
883
884
Gordon Hendersonda384432013-05-13 19:43:26 +0100885/*
Gordon Henderson56c77b52013-02-01 20:19:22 +0000886 * doClock:
887 * Output a clock on a pin
888 *********************************************************************************
889 */
890
891void doClock (int argc, char *argv [])
892{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900893 int pin, freq ;
Gordon Henderson56c77b52013-02-01 20:19:22 +0000894
joshua-yang4b08e7f2019-02-21 12:05:24 +0900895 if (argc != 4) {
896 fprintf (stderr, "Usage: %s clock <pin> <freq>\n", argv [0]) ;
897 exit (1) ;
898 }
Gordon Henderson56c77b52013-02-01 20:19:22 +0000899
joshua-yang4b08e7f2019-02-21 12:05:24 +0900900 pin = atoi (argv [2]) ;
Gordon Henderson56c77b52013-02-01 20:19:22 +0000901
joshua-yang4b08e7f2019-02-21 12:05:24 +0900902 freq = atoi (argv [3]) ;
Gordon Henderson56c77b52013-02-01 20:19:22 +0000903
joshua-yang4b08e7f2019-02-21 12:05:24 +0900904 gpioClockSet (pin, freq) ;
Gordon Henderson56c77b52013-02-01 20:19:22 +0000905}
906
907
908/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100909 * doPwm:
910 * Output a PWM value on a pin
911 *********************************************************************************
912 */
913
914void doPwm (int argc, char *argv [])
915{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900916 int pin, val ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100917
joshua-yang4b08e7f2019-02-21 12:05:24 +0900918 if (argc != 4) {
919 fprintf (stderr, "Usage: %s pwm <pin> <value>\n", argv [0]) ;
920 exit (1) ;
921 }
922 pin = atoi (argv [2]) ;
923 val = atoi (argv [3]) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100924
joshua-yang4b08e7f2019-02-21 12:05:24 +0900925 pwmWrite (pin, val) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +0100926}
927
928
929/*
Gordon Henderson8cb49392012-09-16 10:15:32 +0100930 * doPwmMode: doPwmRange: doPwmClock:
931 * Change the PWM mode, range and clock divider values
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100932 *********************************************************************************
933 */
934
Luke Go2ee8a0d2019-07-08 15:37:07 +0900935static void UNU doPwmMode (int mode)
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100936{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900937 pwmSetMode (mode) ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100938}
939
Luke Go2ee8a0d2019-07-08 15:37:07 +0900940static void UNU doPwmRange (int argc, char *argv [])
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100941{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900942 unsigned int range ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100943
joshua-yang4b08e7f2019-02-21 12:05:24 +0900944 if (argc != 3) {
945 fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
946 exit (1) ;
947 }
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100948
joshua-yang4b08e7f2019-02-21 12:05:24 +0900949 range = (unsigned int)strtoul (argv [2], NULL, 10) ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100950
joshua-yang4b08e7f2019-02-21 12:05:24 +0900951 if (range == 0) {
952 fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
953 exit (1) ;
954 }
955 pwmSetRange (range) ;
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100956}
957
Luke Go2ee8a0d2019-07-08 15:37:07 +0900958static void UNU doPwmClock (int argc, char *argv [])
Gordon Henderson8cb49392012-09-16 10:15:32 +0100959{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900960 unsigned int clock ;
Gordon Henderson8cb49392012-09-16 10:15:32 +0100961
joshua-yang4b08e7f2019-02-21 12:05:24 +0900962 if (argc != 3) {
963 fprintf (stderr, "Usage: %s pwmc <clock>\n", argv [0]) ;
964 exit (1) ;
965 }
Gordon Henderson8cb49392012-09-16 10:15:32 +0100966
joshua-yang4b08e7f2019-02-21 12:05:24 +0900967 clock = (unsigned int)strtoul (argv [2], NULL, 10) ;
Gordon Henderson8cb49392012-09-16 10:15:32 +0100968
joshua-yang4b08e7f2019-02-21 12:05:24 +0900969 if ((clock < 1) || (clock > 4095)) {
970 fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ;
971 exit (1) ;
972 }
973 pwmSetClock (clock) ;
Gordon Henderson8cb49392012-09-16 10:15:32 +0100974}
975
joshua-yang4b08e7f2019-02-21 12:05:24 +0900976/*
977 * doNothing:
978 * function is not support by ODROID Board.
979 *********************************************************************************
980 */
Luke Go2ee8a0d2019-07-08 15:37:07 +0900981static void doNothing (int UNU argc, char *argv [])
joshua-yang4b08e7f2019-02-21 12:05:24 +0900982{
983 fprintf(stderr, "warn : (%s) : This function is not supported by ODROID Board.\n",
984 argv[1]);
985}
Gordon Hendersonf99ffed2012-08-19 15:12:45 +0100986
987/*
Gordon Hendersonbb6f0842015-11-29 21:08:04 +0000988 * doVersion:
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000989 * Handle the ever more complicated version command and print out
990 * some usefull information.
Gordon Hendersonbb6f0842015-11-29 21:08:04 +0000991 *********************************************************************************
992 */
Gordon Hendersonbb6f0842015-11-29 21:08:04 +0000993static void doVersion (char *argv [])
994{
joshua-yang4b08e7f2019-02-21 12:05:24 +0900995 int model, rev, mem, maker, warranty ;
996 struct stat statBuf ;
997 char name [80] ;
998 FILE *fd ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +0000999
joshua-yang4b08e7f2019-02-21 12:05:24 +09001000 int vMaj, vMin ;
Gordon Hendersone687f3f2017-01-24 12:13:39 +00001001
joshua-yang4b08e7f2019-02-21 12:05:24 +09001002 wiringPiVersion (&vMaj, &vMin) ;
1003 printf ("gpio version: %d.%d\n", vMaj, vMin) ;
1004 printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
1005 printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
1006 printf ("For details type: %s -warranty\n", argv [0]) ;
1007 printf ("\n") ;
1008 piBoardId (&model, &rev, &mem, &maker, &warranty) ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001009
joshua-yang4b08e7f2019-02-21 12:05:24 +09001010 printf ("ODROID Board Details:\n") ;
1011 printf (" Type: %s, Revision: %s, Memory: %dMB\n" \
Joshua Yang6e7a6e62019-07-09 15:57:26 +09001012 " Maker: %s, Chip-Vendor: %s\n",
joshua-yang4b08e7f2019-02-21 12:05:24 +09001013 piModelNames [model],
1014 piRevisionNames [rev],
1015 piMemorySize [mem],
1016 "Hardkernel",
1017 piMakerNames [maker]);
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001018
joshua-yang4b08e7f2019-02-21 12:05:24 +09001019 // Check for device tree
1020 if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ...
1021 printf (" * Device tree is enabled.\n") ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001022
joshua-yang4b08e7f2019-02-21 12:05:24 +09001023 // Output Kernel idea of board type
1024 if (stat ("/proc/device-tree/model", &statBuf) == 0) {
1025 if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL) {
Joshua Yang6e7a6e62019-07-09 15:57:26 +09001026 if (fgets (name, 80, fd) == NULL)
1027 fprintf(stderr, "Unable to read from the file descriptor: %s \n", strerror(errno));
joshua-yang4b08e7f2019-02-21 12:05:24 +09001028 fclose (fd) ;
1029 printf (" *--> %s\n", name) ;
1030 }
1031 }
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001032
joshua-yang4b08e7f2019-02-21 12:05:24 +09001033 // User level GPIO is GO
1034 if (stat ("/dev/gpiomem", &statBuf) == 0)
1035 printf (" * Supports user-level GPIO access.\n") ;
1036 else
1037 printf (" * Root or sudo required for GPIO access.\n") ;
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001038}
1039
1040
1041/*
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001042 * main:
1043 * Start here
1044 *********************************************************************************
1045 */
1046
1047int main (int argc, char *argv [])
1048{
joshua-yang4b08e7f2019-02-21 12:05:24 +09001049 int i ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001050
joshua-yang4b08e7f2019-02-21 12:05:24 +09001051 if (getenv ("WIRINGPI_DEBUG") != NULL) {
1052 printf ("gpio: wiringPi debug mode enabled\n") ;
1053 wiringPiDebug = TRUE ;
1054 }
Gordon Henderson13bbba72013-01-14 11:31:56 +00001055
joshua-yang4b08e7f2019-02-21 12:05:24 +09001056 if (argc == 1) {
1057 fprintf (stderr, "%s\n", usage) ;
1058 return 1 ;
1059 }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001060
joshua-yang4b08e7f2019-02-21 12:05:24 +09001061 // Help
1062 if (strcasecmp (argv [1], "-h") == 0) {
1063 printf ("%s: %s\n", argv [0], usage) ;
1064 return 0 ;
1065 }
Gordon Hendersonda384432013-05-13 19:43:26 +01001066
joshua-yang4b08e7f2019-02-21 12:05:24 +09001067 // Version & Warranty
1068 // Wish I could remember why I have both -R and -V ...
1069 if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0)) {
1070 printf ("%d\n", piGpioLayout ()) ;
1071 return 0 ;
1072 }
Gordon Henderson178ea082012-08-19 15:17:03 +01001073
joshua-yang4b08e7f2019-02-21 12:05:24 +09001074 // Version and information
1075 if (strcmp (argv [1], "-v") == 0) {
1076 doVersion (argv) ;
1077 return 0 ;
1078 }
Gordon Hendersonda384432013-05-13 19:43:26 +01001079
joshua-yang4b08e7f2019-02-21 12:05:24 +09001080 if (strcasecmp (argv [1], "-warranty") == 0) {
1081 printf ("gpio version: %s\n", VERSION) ;
1082 printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
1083 printf ("\n") ;
1084 printf (" This program is free software; you can redistribute it and/or modify\n") ;
1085 printf (" it under the terms of the GNU Leser General Public License as published\n") ;
1086 printf (" by the Free Software Foundation, either version 3 of the License, or\n") ;
1087 printf (" (at your option) any later version.\n") ;
1088 printf ("\n") ;
1089 printf (" This program is distributed in the hope that it will be useful,\n") ;
1090 printf (" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
1091 printf (" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") ;
1092 printf (" GNU Lesser General Public License for more details.\n") ;
1093 printf ("\n") ;
1094 printf (" You should have received a copy of the GNU Lesser General Public License\n") ;
1095 printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
1096 printf ("\n") ;
1097 return 0 ;
1098 }
Gordon Hendersonda384432013-05-13 19:43:26 +01001099
joshua-yang4b08e7f2019-02-21 12:05:24 +09001100 if (geteuid () != 0) {
1101 fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
1102 return 1 ;
1103 }
Gordon Hendersonbb6f0842015-11-29 21:08:04 +00001104
joshua-yang4b08e7f2019-02-21 12:05:24 +09001105 // Initial test for /sys/class/gpio operations:
1106 if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; }
1107 else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; }
1108 else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; }
1109 else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }
1110 else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argv [0]) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001111
joshua-yang4b08e7f2019-02-21 12:05:24 +09001112 // Check for load command:
1113 if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; }
1114 if (strcasecmp (argv [1], "unload" ) == 0) { doUnLoad (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001115
joshua-yang4b08e7f2019-02-21 12:05:24 +09001116 // Check for usb power command
1117 if (strcasecmp (argv [1], "usbp" ) == 0) { doNothing(argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001118
joshua-yang4b08e7f2019-02-21 12:05:24 +09001119 // Gertboard commands
1120 if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; }
1121 if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; }
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001122
joshua-yang4b08e7f2019-02-21 12:05:24 +09001123 // Check for allreadall command, force Gpio mode
1124 if (strcasecmp (argv [1], "allreadall") == 0) {
1125 wiringPiSetupGpio () ;
1126 doAllReadall () ;
1127 return 0 ;
1128 }
Gordon Henderson178ea082012-08-19 15:17:03 +01001129
joshua-yang4b08e7f2019-02-21 12:05:24 +09001130 if (strcasecmp (argv [1], "-g") == 0) { // Check for -g argument
1131 wiringPiSetupGpio () ;
Gordon Henderson178ea082012-08-19 15:17:03 +01001132
joshua-yang4b08e7f2019-02-21 12:05:24 +09001133 for (i = 2 ; i < argc ; ++i)
1134 argv [i - 1] = argv [i] ;
1135 --argc ;
1136 wpMode = MODE_GPIO ;
1137 } else if (strcasecmp (argv [1], "-1") == 0) { // Check for -1 argument
1138 wiringPiSetupPhys () ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001139
joshua-yang4b08e7f2019-02-21 12:05:24 +09001140 for (i = 2 ; i < argc ; ++i)
1141 argv [i - 1] = argv [i] ;
1142 --argc ;
1143 wpMode = MODE_PHYS ;
1144 } else if (strcasecmp (argv [1], "-p") == 0) { // Check for -p argument for PiFace
1145 piFaceSetup (200) ;
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001146
joshua-yang4b08e7f2019-02-21 12:05:24 +09001147 for (i = 2 ; i < argc ; ++i)
1148 argv [i - 1] = argv [i] ;
1149 --argc ;
1150 wpMode = MODE_PIFACE ;
1151 } else if (strcasecmp (argv [1], "-z") == 0) { // Check for -z argument so we don't actually initialise wiringPi
1152 for (i = 2 ; i < argc ; ++i)
1153 argv [i - 1] = argv [i] ;
1154 --argc ;
1155 wpMode = MODE_UNINITIALISED ;
1156 } else { // Default to wiringPi mode
1157 wiringPiSetup () ;
1158 wpMode = MODE_PINS ;
1159 }
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001160
joshua-yang4b08e7f2019-02-21 12:05:24 +09001161 // Check for -x argument to load in a new extension
1162 // -x extension:base:args
1163 // Can load many modules, but unless daemon mode we can only send one
1164 // command at a time.
1165 while (strcasecmp (argv [1], "-x") == 0) {
1166 if (argc < 3) {
1167 fprintf (stderr, "%s: -x missing extension command.\n", argv [0]) ;
1168 exit (EXIT_FAILURE) ;
1169 }
Gordon Henderson99095e32012-08-27 20:56:14 +01001170
joshua-yang4b08e7f2019-02-21 12:05:24 +09001171 if (!loadWPiExtension (argv [0], argv [2], TRUE)) {
1172 fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ;
1173 exit (EXIT_FAILURE) ;
1174 }
Gordon Henderson99095e32012-08-27 20:56:14 +01001175
joshua-yang4b08e7f2019-02-21 12:05:24 +09001176 // Shift args down by 2
1177 for (i = 3 ; i < argc ; ++i)
1178 argv [i - 2] = argv [i] ;
1179 argc -= 2 ;
1180 }
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001181
joshua-yang4b08e7f2019-02-21 12:05:24 +09001182 if (argc <= 1) {
1183 fprintf (stderr, "%s: no command given\n", argv [0]) ;
1184 exit (EXIT_FAILURE) ;
1185 }
Gordon Hendersonb0a60c32016-02-29 06:57:38 +00001186
joshua-yang4b08e7f2019-02-21 12:05:24 +09001187 // Core wiringPi functions
1188 /**/ if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ;
1189 else if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ;
1190 else if (strcasecmp (argv [1], "write" ) == 0) doWrite (argc, argv) ;
1191 else if (strcasecmp (argv [1], "pwm" ) == 0) doNothing (argc, argv) ;
1192 else if (strcasecmp (argv [1], "awrite" ) == 0) doNothing (argc, argv) ;
1193 else if (strcasecmp (argv [1], "aread" ) == 0) doAread (argc, argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001194
joshua-yang4b08e7f2019-02-21 12:05:24 +09001195 // GPIO Nicies
1196 else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ;
1197 else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001198
joshua-yang4b08e7f2019-02-21 12:05:24 +09001199 // Pi Specifics
1200 else if (strcasecmp (argv [1], "pwm-bal" ) == 0) doNothing (argc, argv) ;
1201 else if (strcasecmp (argv [1], "pwm-ms" ) == 0) doNothing (argc, argv) ;
1202 else if (strcasecmp (argv [1], "pwmr" ) == 0) doNothing (argc, argv) ;
1203 else if (strcasecmp (argv [1], "pwmc" ) == 0) doNothing (argc, argv) ;
1204 else if (strcasecmp (argv [1], "pwmTone" ) == 0) doNothing (argc, argv) ;
1205 else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ;
1206 else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ;
1207 else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ;
1208 else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ;
1209 else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect (argc, argv) ;
1210 else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ;
1211 else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ;
1212 else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ;
1213 else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ;
1214 else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ;
1215 else if (strcasecmp (argv [1], "clock" ) == 0) doNothing (argc, argv) ;
1216 else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ;
1217 else {
1218 fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
1219 exit (EXIT_FAILURE) ;
1220 }
1221 return 0 ;
Gordon Hendersonbf0ad862012-08-16 15:04:43 +01001222}