You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1536 lines
36 KiB

  1. /*
  2. * gpio.c:
  3. * Swiss-Army-Knife, Set-UID command-line interface to the Raspberry
  4. * Pi's GPIO.
  5. * Copyright (c) 2012-2017 Gordon Henderson
  6. ***********************************************************************
  7. * This file is part of wiringPi:
  8. * https://projects.drogon.net/raspberry-pi/wiringpi/
  9. *
  10. * wiringPi is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Lesser General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * wiringPi is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public License
  21. * along with wiringPi. If not, see <http://www.gnu.org/licenses/>.
  22. ***********************************************************************
  23. */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <stdint.h>
  27. #include <ctype.h>
  28. #include <string.h>
  29. #include <unistd.h>
  30. #include <errno.h>
  31. #include <fcntl.h>
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <wiringPi.h>
  35. #include <wpiExtensions.h>
  36. #include <gertboard.h>
  37. #include <piFace.h>
  38. #include "../version.h"
  39. extern int wiringPiDebug ;
  40. // External functions I can't be bothered creating a separate .h file for:
  41. extern void doReadall (void) ;
  42. extern void doAllReadall (void) ;
  43. extern void doPins (void) ;
  44. #ifndef TRUE
  45. # define TRUE (1==1)
  46. # define FALSE (1==2)
  47. #endif
  48. #define PI_USB_POWER_CONTROL 38
  49. #define I2CDETECT "/usr/sbin/i2cdetect"
  50. #define MODPROBE "/sbin/modprobe"
  51. #define RMMOD "/sbin/rmmod"
  52. int wpMode ;
  53. char *usage = "Usage: gpio -v\n"
  54. " gpio -h\n"
  55. " gpio [-g|-1] ...\n"
  56. " gpio [-d] ...\n"
  57. " [-x extension:params] [[ -x ...]] ...\n"
  58. " gpio [-p] <read/write/wb> ...\n"
  59. " gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n"
  60. " gpio <toggle/blink> <pin>\n"
  61. " gpio readall/reset\n"
  62. " gpio unexportall/exports\n"
  63. " gpio export/edge/unexport ...\n"
  64. " gpio wfi <pin> <mode>\n"
  65. " gpio drive <group> <value>\n"
  66. " gpio pwm-bal/pwm-ms \n"
  67. " gpio pwmr <range> \n"
  68. " gpio pwmc <divider> \n"
  69. " gpio load spi/i2c\n"
  70. " gpio unload spi/i2c\n"
  71. " gpio i2cd/i2cdetect\n"
  72. " gpio rbx/rbd\n"
  73. " gpio wb <value>\n"
  74. " gpio usbp high/low\n"
  75. " gpio gbr <channel>\n"
  76. " gpio gbw <channel> <value>" ; // No trailing newline needed here.
  77. #ifdef NOT_FOR_NOW
  78. /*
  79. * decodePin:
  80. * Decode a pin "number" which can actually be a pin name to represent
  81. * one of the Pi's on-board pins.
  82. *********************************************************************************
  83. */
  84. static int decodePin (const char *str)
  85. {
  86. // The first case - see if it's a number:
  87. if (isdigit (str [0]))
  88. return atoi (str) ;
  89. return 0 ;
  90. }
  91. #endif
  92. /*
  93. * findExecutable:
  94. * Code to locate the path to the given executable. We have a fixed list
  95. * of locations to try which completely overrides any $PATH environment.
  96. * This may be detrimental, however it avoids the reliance on $PATH
  97. * which may be a security issue when this program is run a set-uid-root.
  98. *********************************************************************************
  99. */
  100. static const char *searchPath [] =
  101. {
  102. "/sbin",
  103. "/usr/sbin",
  104. "/bin",
  105. "/usr/bin",
  106. NULL,
  107. } ;
  108. static char *findExecutable (const char *progName)
  109. {
  110. static char *path = NULL ;
  111. int len = strlen (progName) ;
  112. int i = 0 ;
  113. struct stat statBuf ;
  114. for (i = 0 ; searchPath [i] != NULL ; ++i)
  115. {
  116. path = malloc (strlen (searchPath [i]) + len + 2) ;
  117. sprintf (path, "%s/%s", searchPath [i], progName) ;
  118. if (stat (path, &statBuf) == 0)
  119. return path ;
  120. free (path) ;
  121. }
  122. return NULL ;
  123. }
  124. /*
  125. * changeOwner:
  126. * Change the ownership of the file to the real userId of the calling
  127. * program so we can access it.
  128. *********************************************************************************
  129. */
  130. static void changeOwner (char *cmd, char *file)
  131. {
  132. uid_t uid = getuid () ;
  133. uid_t gid = getgid () ;
  134. if (chown (file, uid, gid) != 0)
  135. {
  136. // Removed (ignoring) the check for not existing as I'm fed-up with morons telling me that
  137. // the warning message is an error.
  138. if (errno != ENOENT)
  139. fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ;
  140. }
  141. }
  142. /*
  143. * moduleLoaded:
  144. * Return true/false if the supplied module is loaded
  145. *********************************************************************************
  146. */
  147. static int moduleLoaded (char *modName)
  148. {
  149. int len = strlen (modName) ;
  150. int found = FALSE ;
  151. FILE *fd = fopen ("/proc/modules", "r") ;
  152. char line [80] ;
  153. if (fd == NULL)
  154. {
  155. fprintf (stderr, "gpio: Unable to check /proc/modules: %s\n", strerror (errno)) ;
  156. exit (1) ;
  157. }
  158. while (fgets (line, 80, fd) != NULL)
  159. {
  160. if (strncmp (line, modName, len) != 0)
  161. continue ;
  162. found = TRUE ;
  163. break ;
  164. }
  165. fclose (fd) ;
  166. return found ;
  167. }
  168. /*
  169. * doLoad:
  170. * Load either the spi or i2c modules and change device ownerships, etc.
  171. *********************************************************************************
  172. */
  173. static void checkDevTree (char *argv [])
  174. {
  175. struct stat statBuf ;
  176. if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ...
  177. {
  178. fprintf (stderr,
  179. "%s: Unable to load/unload modules as this Pi has the device tree enabled.\n"
  180. " You need to run the raspi-config program (as root) and select the\n"
  181. " modules (SPI or I2C) that you wish to load/unload there and reboot.\n"
  182. " There is more information here:\n"
  183. " https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=97314\n", argv [0]) ;
  184. exit (1) ;
  185. }
  186. }
  187. static void _doLoadUsage (char *argv [])
  188. {
  189. fprintf (stderr, "Usage: %s load <spi/i2c> [I2C baudrate in Kb/sec]\n", argv [0]) ;
  190. exit (1) ;
  191. }
  192. static void doLoad (int argc, char *argv [])
  193. {
  194. char *module1, *module2 ;
  195. char cmd [80] ;
  196. char *file1, *file2 ;
  197. char args1 [32], args2 [32] ;
  198. checkDevTree (argv) ;
  199. if (argc < 3)
  200. _doLoadUsage (argv) ;
  201. args1 [0] = args2 [0] = 0 ;
  202. /**/ if (strcasecmp (argv [2], "spi") == 0)
  203. {
  204. module1 = "spidev" ;
  205. module2 = "spi_bcm2708" ;
  206. file1 = "/dev/spidev0.0" ;
  207. file2 = "/dev/spidev0.1" ;
  208. if (argc == 4)
  209. {
  210. fprintf (stderr, "%s: Unable to set the buffer size now. Load aborted. Please see the man page.\n", argv [0]) ;
  211. exit (1) ;
  212. }
  213. else if (argc > 4)
  214. _doLoadUsage (argv) ;
  215. }
  216. else if (strcasecmp (argv [2], "i2c") == 0)
  217. {
  218. module1 = "i2c_dev" ;
  219. module2 = "i2c_bcm2708" ;
  220. file1 = "/dev/i2c-0" ;
  221. file2 = "/dev/i2c-1" ;
  222. if (argc == 4)
  223. sprintf (args2, " baudrate=%d", atoi (argv [3]) * 1000) ;
  224. else if (argc > 4)
  225. _doLoadUsage (argv) ;
  226. }
  227. else
  228. _doLoadUsage (argv) ;
  229. if (findExecutable ("modprobe") == NULL)
  230. printf ("No found\n") ;
  231. if (!moduleLoaded (module1))
  232. {
  233. sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ;
  234. system (cmd) ;
  235. }
  236. if (!moduleLoaded (module2))
  237. {
  238. sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ;
  239. system (cmd) ;
  240. }
  241. if (!moduleLoaded (module2))
  242. {
  243. fprintf (stderr, "%s: Unable to load %s\n", argv [0], module2) ;
  244. exit (1) ;
  245. }
  246. sleep (1) ; // To let things get settled
  247. changeOwner (argv [0], file1) ;
  248. changeOwner (argv [0], file2) ;
  249. }
  250. /*
  251. * doUnLoad:
  252. * Un-Load either the spi or i2c modules and change device ownerships, etc.
  253. *********************************************************************************
  254. */
  255. static void _doUnLoadUsage (char *argv [])
  256. {
  257. fprintf (stderr, "Usage: %s unload <spi/i2c>\n", argv [0]) ;
  258. exit (1) ;
  259. }
  260. static void doUnLoad (int argc, char *argv [])
  261. {
  262. char *module1, *module2 ;
  263. char cmd [80] ;
  264. checkDevTree (argv) ;
  265. if (argc != 3)
  266. _doUnLoadUsage (argv) ;
  267. /**/ if (strcasecmp (argv [2], "spi") == 0)
  268. {
  269. module1 = "spidev" ;
  270. module2 = "spi_bcm2708" ;
  271. }
  272. else if (strcasecmp (argv [2], "i2c") == 0)
  273. {
  274. module1 = "i2c_dev" ;
  275. module2 = "i2c_bcm2708" ;
  276. }
  277. else
  278. _doUnLoadUsage (argv) ;
  279. if (moduleLoaded (module1))
  280. {
  281. sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ;
  282. system (cmd) ;
  283. }
  284. if (moduleLoaded (module2))
  285. {
  286. sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ;
  287. system (cmd) ;
  288. }
  289. }
  290. /*
  291. * doI2Cdetect:
  292. * Run the i2cdetect command with the right runes for this Pi revision
  293. *********************************************************************************
  294. */
  295. static void doI2Cdetect (UNU int argc, char *argv [])
  296. {
  297. int port = piGpioLayout () == 1 ? 0 : 1 ;
  298. char *c, *command ;
  299. if ((c = findExecutable (I2CDETECT)) == NULL)
  300. {
  301. fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ;
  302. return ;
  303. }
  304. if (!moduleLoaded ("i2c_dev"))
  305. {
  306. fprintf (stderr, "%s: The I2C kernel module(s) are not loaded.\n", argv [0]) ;
  307. return ;
  308. }
  309. command = malloc (strlen (c) + 16) ;
  310. sprintf (command, "%s -y %d", c, port) ;
  311. if (system (command) < 0)
  312. fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ;
  313. }
  314. /*
  315. * doExports:
  316. * List all GPIO exports
  317. *********************************************************************************
  318. */
  319. static void doExports (UNU int argc, UNU char *argv [])
  320. {
  321. int fd ;
  322. int i, l, first ;
  323. char fName [128] ;
  324. char buf [16] ;
  325. for (first = 0, i = 0 ; i < 64 ; ++i) // Crude, but effective
  326. {
  327. // Try to read the direction
  328. sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ;
  329. if ((fd = open (fName, O_RDONLY)) == -1)
  330. continue ;
  331. if (first == 0)
  332. {
  333. ++first ;
  334. printf ("GPIO Pins exported:\n") ;
  335. }
  336. printf ("%4d: ", i) ;
  337. if ((l = read (fd, buf, 16)) == 0)
  338. sprintf (buf, "%s", "?") ;
  339. buf [l] = 0 ;
  340. if ((buf [strlen (buf) - 1]) == '\n')
  341. buf [strlen (buf) - 1] = 0 ;
  342. printf ("%-3s", buf) ;
  343. close (fd) ;
  344. // Try to Read the value
  345. sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ;
  346. if ((fd = open (fName, O_RDONLY)) == -1)
  347. {
  348. printf ("No Value file (huh?)\n") ;
  349. continue ;
  350. }
  351. if ((l = read (fd, buf, 16)) == 0)
  352. sprintf (buf, "%s", "?") ;
  353. buf [l] = 0 ;
  354. if ((buf [strlen (buf) - 1]) == '\n')
  355. buf [strlen (buf) - 1] = 0 ;
  356. printf (" %s", buf) ;
  357. // Read any edge trigger file
  358. sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ;
  359. if ((fd = open (fName, O_RDONLY)) == -1)
  360. {
  361. printf ("\n") ;
  362. continue ;
  363. }
  364. if ((l = read (fd, buf, 16)) == 0)
  365. sprintf (buf, "%s", "?") ;
  366. buf [l] = 0 ;
  367. if ((buf [strlen (buf) - 1]) == '\n')
  368. buf [strlen (buf) - 1] = 0 ;
  369. printf (" %-8s\n", buf) ;
  370. close (fd) ;
  371. }
  372. }
  373. /*
  374. * doExport:
  375. * gpio export pin mode
  376. * This uses the /sys/class/gpio device interface.
  377. *********************************************************************************
  378. */
  379. void doExport (int argc, char *argv [])
  380. {
  381. FILE *fd ;
  382. int pin ;
  383. char *mode ;
  384. char fName [128] ;
  385. if (argc != 4)
  386. {
  387. fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ;
  388. exit (1) ;
  389. }
  390. pin = atoi (argv [2]) ;
  391. mode = argv [3] ;
  392. if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
  393. {
  394. fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
  395. exit (1) ;
  396. }
  397. fprintf (fd, "%d\n", pin) ;
  398. fclose (fd) ;
  399. sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
  400. if ((fd = fopen (fName, "w")) == NULL)
  401. {
  402. fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
  403. exit (1) ;
  404. }
  405. /**/ if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0))
  406. fprintf (fd, "in\n") ;
  407. else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0))
  408. fprintf (fd, "out\n") ;
  409. else if ((strcasecmp (mode, "high") == 0) || (strcasecmp (mode, "up") == 0))
  410. fprintf (fd, "high\n") ;
  411. else if ((strcasecmp (mode, "low") == 0) || (strcasecmp (mode, "down") == 0))
  412. fprintf (fd, "low\n") ;
  413. else
  414. {
  415. fprintf (stderr, "%s: Invalid mode: %s. Should be in, out, high or low\n", argv [1], mode) ;
  416. exit (1) ;
  417. }
  418. fclose (fd) ;
  419. // Change ownership so the current user can actually use it
  420. sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
  421. changeOwner (argv [0], fName) ;
  422. sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
  423. changeOwner (argv [0], fName) ;
  424. }
  425. /*
  426. * doWfi:
  427. * gpio wfi pin mode
  428. * Wait for Interrupt on a given pin.
  429. * Slight cheat here - it's easier to actually use ISR now (which calls
  430. * gpio to set the pin modes!) then we simply sleep, and expect the thread
  431. * to exit the program. Crude but effective.
  432. *********************************************************************************
  433. */
  434. static void wfi (void)
  435. { exit (0) ; }
  436. void doWfi (int argc, char *argv [])
  437. {
  438. int pin, mode ;
  439. if (argc != 4)
  440. {
  441. fprintf (stderr, "Usage: %s wfi pin mode\n", argv [0]) ;
  442. exit (1) ;
  443. }
  444. pin = atoi (argv [2]) ;
  445. /**/ if (strcasecmp (argv [3], "rising") == 0) mode = INT_EDGE_RISING ;
  446. else if (strcasecmp (argv [3], "falling") == 0) mode = INT_EDGE_FALLING ;
  447. else if (strcasecmp (argv [3], "both") == 0) mode = INT_EDGE_BOTH ;
  448. else
  449. {
  450. fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv [1], argv [3]) ;
  451. exit (1) ;
  452. }
  453. if (wiringPiISR (pin, mode, &wfi) < 0)
  454. {
  455. fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ;
  456. exit (1) ;
  457. }
  458. for (;;)
  459. delay (9999) ;
  460. }
  461. /*
  462. * doEdge:
  463. * gpio edge pin mode
  464. * Easy access to changing the edge trigger on a GPIO pin
  465. * This uses the /sys/class/gpio device interface.
  466. *********************************************************************************
  467. */
  468. void doEdge (int argc, char *argv [])
  469. {
  470. FILE *fd ;
  471. int pin ;
  472. char *mode ;
  473. char fName [128] ;
  474. if (argc != 4)
  475. {
  476. fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ;
  477. exit (1) ;
  478. }
  479. pin = atoi (argv [2]) ;
  480. mode = argv [3] ;
  481. // Export the pin and set direction to input
  482. if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
  483. {
  484. fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
  485. exit (1) ;
  486. }
  487. fprintf (fd, "%d\n", pin) ;
  488. fclose (fd) ;
  489. sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
  490. if ((fd = fopen (fName, "w")) == NULL)
  491. {
  492. fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
  493. exit (1) ;
  494. }
  495. fprintf (fd, "in\n") ;
  496. fclose (fd) ;
  497. sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
  498. if ((fd = fopen (fName, "w")) == NULL)
  499. {
  500. fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
  501. exit (1) ;
  502. }
  503. /**/ if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ;
  504. else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ;
  505. else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
  506. else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ;
  507. else
  508. {
  509. fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
  510. exit (1) ;
  511. }
  512. // Change ownership of the value and edge files, so the current user can actually use it!
  513. sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
  514. changeOwner (argv [0], fName) ;
  515. sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
  516. changeOwner (argv [0], fName) ;
  517. fclose (fd) ;
  518. }
  519. /*
  520. * doUnexport:
  521. * gpio unexport pin
  522. * This uses the /sys/class/gpio device interface.
  523. *********************************************************************************
  524. */
  525. void doUnexport (int argc, char *argv [])
  526. {
  527. FILE *fd ;
  528. int pin ;
  529. if (argc != 3)
  530. {
  531. fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ;
  532. exit (1) ;
  533. }
  534. pin = atoi (argv [2]) ;
  535. if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
  536. {
  537. fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
  538. exit (1) ;
  539. }
  540. fprintf (fd, "%d\n", pin) ;
  541. fclose (fd) ;
  542. }
  543. /*
  544. * doUnexportAll:
  545. * gpio unexportall
  546. * Un-Export all the GPIO pins.
  547. * This uses the /sys/class/gpio device interface.
  548. *********************************************************************************
  549. */
  550. void doUnexportall (char *progName)
  551. {
  552. FILE *fd ;
  553. int pin ;
  554. for (pin = 0 ; pin < 63 ; ++pin)
  555. {
  556. if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
  557. {
  558. fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ;
  559. exit (1) ;
  560. }
  561. fprintf (fd, "%d\n", pin) ;
  562. fclose (fd) ;
  563. }
  564. }
  565. /*
  566. * doReset:
  567. * Reset the GPIO pins - as much as we can do
  568. *********************************************************************************
  569. */
  570. static void doReset (UNU char *progName)
  571. {
  572. printf ("GPIO Reset is dangerous and has been removed from the gpio command.\n") ;
  573. printf (" - Please write a shell-script to reset the GPIO pins into the state\n") ;
  574. printf (" that you need them in for your applications.\n") ;
  575. }
  576. /*
  577. * doMode:
  578. * gpio mode pin mode ...
  579. *********************************************************************************
  580. */
  581. void doMode (int argc, char *argv [])
  582. {
  583. int pin ;
  584. char *mode ;
  585. if (argc != 4)
  586. {
  587. fprintf (stderr, "Usage: %s mode pin mode\n", argv [0]) ;
  588. exit (1) ;
  589. }
  590. pin = atoi (argv [2]) ;
  591. mode = argv [3] ;
  592. /**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
  593. else if (strcasecmp (mode, "input") == 0) pinMode (pin, INPUT) ;
  594. else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
  595. else if (strcasecmp (mode, "output") == 0) pinMode (pin, OUTPUT) ;
  596. else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
  597. else if (strcasecmp (mode, "pwmTone") == 0) pinMode (pin, PWM_TONE_OUTPUT) ;
  598. else if (strcasecmp (mode, "clock") == 0) pinMode (pin, GPIO_CLOCK) ;
  599. else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
  600. else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
  601. else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
  602. else if (strcasecmp (mode, "off") == 0) pullUpDnControl (pin, PUD_OFF) ;
  603. else if (strcasecmp (mode, "alt0") == 0) pinModeAlt (pin, 0b100) ;
  604. else if (strcasecmp (mode, "alt1") == 0) pinModeAlt (pin, 0b101) ;
  605. else if (strcasecmp (mode, "alt2") == 0) pinModeAlt (pin, 0b110) ;
  606. else if (strcasecmp (mode, "alt3") == 0) pinModeAlt (pin, 0b111) ;
  607. else if (strcasecmp (mode, "alt4") == 0) pinModeAlt (pin, 0b011) ;
  608. else if (strcasecmp (mode, "alt5") == 0) pinModeAlt (pin, 0b010) ;
  609. else
  610. {
  611. fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/clock/up/down/tri\n", argv [1], mode) ;
  612. exit (1) ;
  613. }
  614. }
  615. /*
  616. * doPadDrive:
  617. * gpio drive group value
  618. *********************************************************************************
  619. */
  620. static void doPadDrive (int argc, char *argv [])
  621. {
  622. int group, val ;
  623. if (argc != 4)
  624. {
  625. fprintf (stderr, "Usage: %s drive group value\n", argv [0]) ;
  626. exit (1) ;
  627. }
  628. group = atoi (argv [2]) ;
  629. val = atoi (argv [3]) ;
  630. if ((group < 0) || (group > 2))
  631. {
  632. fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ;
  633. exit (1) ;
  634. }
  635. if ((val < 0) || (val > 7))
  636. {
  637. fprintf (stderr, "%s: drive value not 0-7: %d\n", argv [0], val) ;
  638. exit (1) ;
  639. }
  640. setPadDrive (group, val) ;
  641. }
  642. /*
  643. * doUsbP:
  644. * Control USB Power - High (1.2A) or Low (600mA)
  645. * gpio usbp high/low
  646. *********************************************************************************
  647. */
  648. static void doUsbP (int argc, char *argv [])
  649. {
  650. int model, rev, mem, maker, overVolted ;
  651. if (argc != 3)
  652. {
  653. fprintf (stderr, "Usage: %s usbp high|low\n", argv [0]) ;
  654. exit (1) ;
  655. }
  656. // Make sure we're on a B+
  657. piBoardId (&model, &rev, &mem, &maker, &overVolted) ;
  658. if (!((model == PI_MODEL_BP) || (model == PI_MODEL_2)))
  659. {
  660. fprintf (stderr, "USB power contol is applicable to B+ and v2 boards only.\n") ;
  661. exit (1) ;
  662. }
  663. // Make sure we start in BCM_GPIO mode
  664. wiringPiSetupGpio () ;
  665. if ((strcasecmp (argv [2], "high") == 0) || (strcasecmp (argv [2], "hi") == 0))
  666. {
  667. digitalWrite (PI_USB_POWER_CONTROL, 1) ;
  668. pinMode (PI_USB_POWER_CONTROL, OUTPUT) ;
  669. printf ("Switched to HIGH current USB (1.2A)\n") ;
  670. return ;
  671. }
  672. if ((strcasecmp (argv [2], "low") == 0) || (strcasecmp (argv [2], "lo") == 0))
  673. {
  674. digitalWrite (PI_USB_POWER_CONTROL, 0) ;
  675. pinMode (PI_USB_POWER_CONTROL, OUTPUT) ;
  676. printf ("Switched to LOW current USB (600mA)\n") ;
  677. return ;
  678. }
  679. fprintf (stderr, "Usage: %s usbp high|low\n", argv [0]) ;
  680. exit (1) ;
  681. }
  682. /*
  683. * doGbw:
  684. * gpio gbw channel value
  685. * Gertboard Write - To the Analog output
  686. *********************************************************************************
  687. */
  688. static void doGbw (int argc, char *argv [])
  689. {
  690. int channel, value ;
  691. if (argc != 4)
  692. {
  693. fprintf (stderr, "Usage: %s gbw <channel> <value>\n", argv [0]) ;
  694. exit (1) ;
  695. }
  696. channel = atoi (argv [2]) ;
  697. value = atoi (argv [3]) ;
  698. if ((channel < 0) || (channel > 1))
  699. {
  700. fprintf (stderr, "%s: gbw: Channel number must be 0 or 1\n", argv [0]) ;
  701. exit (1) ;
  702. }
  703. if ((value < 0) || (value > 255))
  704. {
  705. fprintf (stderr, "%s: gbw: Value must be from 0 to 255\n", argv [0]) ;
  706. exit (1) ;
  707. }
  708. if (gertboardAnalogSetup (64) < 0)
  709. {
  710. fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
  711. exit (1) ;
  712. }
  713. analogWrite (64 + channel, value) ;
  714. }
  715. /*
  716. * doGbr:
  717. * gpio gbr channel
  718. * From the analog input
  719. *********************************************************************************
  720. */
  721. static void doGbr (int argc, char *argv [])
  722. {
  723. int channel ;
  724. if (argc != 3)
  725. {
  726. fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ;
  727. exit (1) ;
  728. }
  729. channel = atoi (argv [2]) ;
  730. if ((channel < 0) || (channel > 1))
  731. {
  732. fprintf (stderr, "%s: gbr: Channel number must be 0 or 1\n", argv [0]) ;
  733. exit (1) ;
  734. }
  735. if (gertboardAnalogSetup (64) < 0)
  736. {
  737. fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
  738. exit (1) ;
  739. }
  740. printf ("%d\n", analogRead (64 + channel)) ;
  741. }
  742. /*
  743. * doWrite:
  744. * gpio write pin value
  745. *********************************************************************************
  746. */
  747. static void doWrite (int argc, char *argv [])
  748. {
  749. int pin, val ;
  750. if (argc != 4)
  751. {
  752. fprintf (stderr, "Usage: %s write pin value\n", argv [0]) ;
  753. exit (1) ;
  754. }
  755. pin = atoi (argv [2]) ;
  756. /**/ if ((strcasecmp (argv [3], "up") == 0) || (strcasecmp (argv [3], "on") == 0))
  757. val = 1 ;
  758. else if ((strcasecmp (argv [3], "down") == 0) || (strcasecmp (argv [3], "off") == 0))
  759. val = 0 ;
  760. else
  761. val = atoi (argv [3]) ;
  762. /**/ if (val == 0)
  763. digitalWrite (pin, LOW) ;
  764. else
  765. digitalWrite (pin, HIGH) ;
  766. }
  767. /*
  768. * doAwriterite:
  769. * gpio awrite pin value
  770. *********************************************************************************
  771. */
  772. static void doAwrite (int argc, char *argv [])
  773. {
  774. int pin, val ;
  775. if (argc != 4)
  776. {
  777. fprintf (stderr, "Usage: %s awrite pin value\n", argv [0]) ;
  778. exit (1) ;
  779. }
  780. pin = atoi (argv [2]) ;
  781. val = atoi (argv [3]) ;
  782. analogWrite (pin, val) ;
  783. }
  784. /*
  785. * doWriteByte:
  786. * gpio wb value
  787. *********************************************************************************
  788. */
  789. static void doWriteByte (int argc, char *argv [])
  790. {
  791. int val ;
  792. if (argc != 3)
  793. {
  794. fprintf (stderr, "Usage: %s wb value\n", argv [0]) ;
  795. exit (1) ;
  796. }
  797. val = (int)strtol (argv [2], NULL, 0) ;
  798. digitalWriteByte (val) ;
  799. }
  800. /*
  801. * doReadByte:
  802. * gpio rbx|rbd value
  803. *********************************************************************************
  804. */
  805. static void doReadByte (int argc, char *argv [], int printHex)
  806. {
  807. int val ;
  808. if (argc != 2)
  809. {
  810. fprintf (stderr, "Usage: %s rbx|rbd\n", argv [0]) ;
  811. exit (1) ;
  812. }
  813. val = digitalReadByte () ;
  814. if (printHex)
  815. printf ("%02X\n", val) ;
  816. else
  817. printf ("%d\n", val) ;
  818. }
  819. /*
  820. * doRead:
  821. * Read a pin and return the value
  822. *********************************************************************************
  823. */
  824. void doRead (int argc, char *argv [])
  825. {
  826. int pin, val ;
  827. if (argc != 3)
  828. {
  829. fprintf (stderr, "Usage: %s read pin\n", argv [0]) ;
  830. exit (1) ;
  831. }
  832. pin = atoi (argv [2]) ;
  833. val = digitalRead (pin) ;
  834. printf ("%s\n", val == 0 ? "0" : "1") ;
  835. }
  836. /*
  837. * doAread:
  838. * Read an analog pin and return the value
  839. *********************************************************************************
  840. */
  841. void doAread (int argc, char *argv [])
  842. {
  843. if (argc != 3)
  844. {
  845. fprintf (stderr, "Usage: %s aread pin\n", argv [0]) ;
  846. exit (1) ;
  847. }
  848. printf ("%d\n", analogRead (atoi (argv [2]))) ;
  849. }
  850. /*
  851. * doToggle:
  852. * Toggle an IO pin
  853. *********************************************************************************
  854. */
  855. void doToggle (int argc, char *argv [])
  856. {
  857. int pin ;
  858. if (argc != 3)
  859. {
  860. fprintf (stderr, "Usage: %s toggle pin\n", argv [0]) ;
  861. exit (1) ;
  862. }
  863. pin = atoi (argv [2]) ;
  864. digitalWrite (pin, !digitalRead (pin)) ;
  865. }
  866. /*
  867. * doBlink:
  868. * Blink an IO pin
  869. *********************************************************************************
  870. */
  871. void doBlink (int argc, char *argv [])
  872. {
  873. int pin ;
  874. if (argc != 3)
  875. {
  876. fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ;
  877. exit (1) ;
  878. }
  879. pin = atoi (argv [2]) ;
  880. pinMode (pin, OUTPUT) ;
  881. for (;;)
  882. {
  883. digitalWrite (pin, !digitalRead (pin)) ;
  884. delay (500) ;
  885. }
  886. }
  887. /*
  888. * doPwmTone:
  889. * Output a tone in a PWM pin
  890. *********************************************************************************
  891. */
  892. void doPwmTone (int argc, char *argv [])
  893. {
  894. int pin, freq ;
  895. if (argc != 4)
  896. {
  897. fprintf (stderr, "Usage: %s pwmTone <pin> <freq>\n", argv [0]) ;
  898. exit (1) ;
  899. }
  900. pin = atoi (argv [2]) ;
  901. freq = atoi (argv [3]) ;
  902. pwmToneWrite (pin, freq) ;
  903. }
  904. /*
  905. * doClock:
  906. * Output a clock on a pin
  907. *********************************************************************************
  908. */
  909. void doClock (int argc, char *argv [])
  910. {
  911. int pin, freq ;
  912. if (argc != 4)
  913. {
  914. fprintf (stderr, "Usage: %s clock <pin> <freq>\n", argv [0]) ;
  915. exit (1) ;
  916. }
  917. pin = atoi (argv [2]) ;
  918. freq = atoi (argv [3]) ;
  919. gpioClockSet (pin, freq) ;
  920. }
  921. /*
  922. * doPwm:
  923. * Output a PWM value on a pin
  924. *********************************************************************************
  925. */
  926. void doPwm (int argc, char *argv [])
  927. {
  928. int pin, val ;
  929. if (argc != 4)
  930. {
  931. fprintf (stderr, "Usage: %s pwm <pin> <value>\n", argv [0]) ;
  932. exit (1) ;
  933. }
  934. pin = atoi (argv [2]) ;
  935. val = atoi (argv [3]) ;
  936. pwmWrite (pin, val) ;
  937. }
  938. /*
  939. * doPwmMode: doPwmRange: doPwmClock:
  940. * Change the PWM mode, range and clock divider values
  941. *********************************************************************************
  942. */
  943. static void doPwmMode (int mode)
  944. {
  945. pwmSetMode (mode) ;
  946. }
  947. static void doPwmRange (int argc, char *argv [])
  948. {
  949. unsigned int range ;
  950. if (argc != 3)
  951. {
  952. fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
  953. exit (1) ;
  954. }
  955. range = (unsigned int)strtoul (argv [2], NULL, 10) ;
  956. if (range == 0)
  957. {
  958. fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
  959. exit (1) ;
  960. }
  961. pwmSetRange (range) ;
  962. }
  963. static void doPwmClock (int argc, char *argv [])
  964. {
  965. unsigned int clock ;
  966. if (argc != 3)
  967. {
  968. fprintf (stderr, "Usage: %s pwmc <clock>\n", argv [0]) ;
  969. exit (1) ;
  970. }
  971. clock = (unsigned int)strtoul (argv [2], NULL, 10) ;
  972. if ((clock < 1) || (clock > 4095))
  973. {
  974. fprintf (stderr, "%s: clock must be between 0 and 4096\n", argv [0]) ;
  975. exit (1) ;
  976. }
  977. pwmSetClock (clock) ;
  978. }
  979. /*
  980. * doVersion:
  981. * Handle the ever more complicated version command and print out
  982. * some usefull information.
  983. *********************************************************************************
  984. */
  985. static void doVersion (char *argv [])
  986. {
  987. int model, rev, mem, maker, warranty ;
  988. struct stat statBuf ;
  989. char name [80] ;
  990. FILE *fd ;
  991. int vMaj, vMin ;
  992. wiringPiVersion (&vMaj, &vMin) ;
  993. printf ("gpio version: %d.%d\n", vMaj, vMin) ;
  994. printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
  995. printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
  996. printf ("For details type: %s -warranty\n", argv [0]) ;
  997. printf ("\n") ;
  998. piBoardId (&model, &rev, &mem, &maker, &warranty) ;
  999. printf ("Raspberry Pi Details:\n") ;
  1000. printf (" Type: %s, Revision: %s, Memory: %dMB, Maker: %s %s\n",
  1001. piModelNames [model], piRevisionNames [rev], piMemorySize [mem], piMakerNames [maker], warranty ? "[Out of Warranty]" : "") ;
  1002. // Check for device tree
  1003. if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ...
  1004. printf (" * Device tree is enabled.\n") ;
  1005. if (stat ("/proc/device-tree/model", &statBuf) == 0) // Output Kernel idea of board type
  1006. {
  1007. if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL)
  1008. {
  1009. fgets (name, 80, fd) ;
  1010. fclose (fd) ;
  1011. printf (" *--> %s\n", name) ;
  1012. }
  1013. }
  1014. if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO
  1015. printf (" * This Raspberry Pi supports user-level GPIO access.\n") ;
  1016. else
  1017. printf (" * Root or sudo required for GPIO access.\n") ;
  1018. }
  1019. /*
  1020. * main:
  1021. * Start here
  1022. *********************************************************************************
  1023. */
  1024. int main (int argc, char *argv [])
  1025. {
  1026. int i ;
  1027. if (getenv ("WIRINGPI_DEBUG") != NULL)
  1028. {
  1029. printf ("gpio: wiringPi debug mode enabled\n") ;
  1030. wiringPiDebug = TRUE ;
  1031. }
  1032. if (argc == 1)
  1033. {
  1034. fprintf (stderr, "%s\n", usage) ;
  1035. return 1 ;
  1036. }
  1037. // Help
  1038. if (strcasecmp (argv [1], "-h") == 0)
  1039. {
  1040. printf ("%s: %s\n", argv [0], usage) ;
  1041. return 0 ;
  1042. }
  1043. // Version & Warranty
  1044. // Wish I could remember why I have both -R and -V ...
  1045. if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0))
  1046. {
  1047. printf ("%d\n", piGpioLayout ()) ;
  1048. return 0 ;
  1049. }
  1050. // Version and information
  1051. if (strcmp (argv [1], "-v") == 0)
  1052. {
  1053. doVersion (argv) ;
  1054. return 0 ;
  1055. }
  1056. if (strcasecmp (argv [1], "-warranty") == 0)
  1057. {
  1058. printf ("gpio version: %s\n", VERSION) ;
  1059. printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
  1060. printf ("\n") ;
  1061. printf (" This program is free software; you can redistribute it and/or modify\n") ;
  1062. printf (" it under the terms of the GNU Leser General Public License as published\n") ;
  1063. printf (" by the Free Software Foundation, either version 3 of the License, or\n") ;
  1064. printf (" (at your option) any later version.\n") ;
  1065. printf ("\n") ;
  1066. printf (" This program is distributed in the hope that it will be useful,\n") ;
  1067. printf (" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
  1068. printf (" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") ;
  1069. printf (" GNU Lesser General Public License for more details.\n") ;
  1070. printf ("\n") ;
  1071. printf (" You should have received a copy of the GNU Lesser General Public License\n") ;
  1072. printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
  1073. printf ("\n") ;
  1074. return 0 ;
  1075. }
  1076. if (geteuid () != 0)
  1077. {
  1078. fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
  1079. return 1 ;
  1080. }
  1081. // Initial test for /sys/class/gpio operations:
  1082. /**/ if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; }
  1083. else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; }
  1084. else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; }
  1085. else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }
  1086. else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argv [0]) ; return 0 ; }
  1087. // Check for load command:
  1088. if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; }
  1089. if (strcasecmp (argv [1], "unload" ) == 0) { doUnLoad (argc, argv) ; return 0 ; }
  1090. // Check for usb power command
  1091. if (strcasecmp (argv [1], "usbp" ) == 0) { doUsbP (argc, argv) ; return 0 ; }
  1092. // Gertboard commands
  1093. if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; }
  1094. if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; }
  1095. // Check for allreadall command, force Gpio mode
  1096. if (strcasecmp (argv [1], "allreadall") == 0)
  1097. {
  1098. wiringPiSetupGpio () ;
  1099. doAllReadall () ;
  1100. return 0 ;
  1101. }
  1102. // Check for -g argument
  1103. /**/ if (strcasecmp (argv [1], "-g") == 0)
  1104. {
  1105. wiringPiSetupGpio () ;
  1106. for (i = 2 ; i < argc ; ++i)
  1107. argv [i - 1] = argv [i] ;
  1108. --argc ;
  1109. wpMode = WPI_MODE_GPIO ;
  1110. }
  1111. // Check for -1 argument
  1112. else if (strcasecmp (argv [1], "-1") == 0)
  1113. {
  1114. wiringPiSetupPhys () ;
  1115. for (i = 2 ; i < argc ; ++i)
  1116. argv [i - 1] = argv [i] ;
  1117. --argc ;
  1118. wpMode = WPI_MODE_PHYS ;
  1119. }
  1120. // Check for -p argument for PiFace
  1121. else if (strcasecmp (argv [1], "-p") == 0)
  1122. {
  1123. piFaceSetup (200) ;
  1124. for (i = 2 ; i < argc ; ++i)
  1125. argv [i - 1] = argv [i] ;
  1126. --argc ;
  1127. wpMode = WPI_MODE_PIFACE ;
  1128. }
  1129. // Check for -z argument so we don't actually initialise wiringPi
  1130. else if (strcasecmp (argv [1], "-z") == 0)
  1131. {
  1132. for (i = 2 ; i < argc ; ++i)
  1133. argv [i - 1] = argv [i] ;
  1134. --argc ;
  1135. wpMode = WPI_MODE_UNINITIALISED ;
  1136. }
  1137. // Default to wiringPi mode
  1138. else
  1139. {
  1140. wiringPiSetup () ;
  1141. wpMode = WPI_MODE_PINS ;
  1142. }
  1143. // Check for -x argument to load in a new extension
  1144. // -x extension:base:args
  1145. // Can load many modules, but unless daemon mode we can only send one
  1146. // command at a time.
  1147. while (strcasecmp (argv [1], "-x") == 0)
  1148. {
  1149. if (argc < 3)
  1150. {
  1151. fprintf (stderr, "%s: -x missing extension command.\n", argv [0]) ;
  1152. exit (EXIT_FAILURE) ;
  1153. }
  1154. if (!loadWPiExtension (argv [0], argv [2], TRUE))
  1155. {
  1156. fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ;
  1157. exit (EXIT_FAILURE) ;
  1158. }
  1159. // Shift args down by 2
  1160. for (i = 3 ; i < argc ; ++i)
  1161. argv [i - 2] = argv [i] ;
  1162. argc -= 2 ;
  1163. }
  1164. if (argc <= 1)
  1165. {
  1166. fprintf (stderr, "%s: no command given\n", argv [0]) ;
  1167. exit (EXIT_FAILURE) ;
  1168. }
  1169. // Core wiringPi functions
  1170. /**/ if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ;
  1171. else if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ;
  1172. else if (strcasecmp (argv [1], "write" ) == 0) doWrite (argc, argv) ;
  1173. else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ;
  1174. else if (strcasecmp (argv [1], "awrite" ) == 0) doAwrite (argc, argv) ;
  1175. else if (strcasecmp (argv [1], "aread" ) == 0) doAread (argc, argv) ;
  1176. // GPIO Nicies
  1177. else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ;
  1178. else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ;
  1179. // Pi Specifics
  1180. else if (strcasecmp (argv [1], "pwm-bal" ) == 0) doPwmMode (PWM_MODE_BAL) ;
  1181. else if (strcasecmp (argv [1], "pwm-ms" ) == 0) doPwmMode (PWM_MODE_MS) ;
  1182. else if (strcasecmp (argv [1], "pwmr" ) == 0) doPwmRange (argc, argv) ;
  1183. else if (strcasecmp (argv [1], "pwmc" ) == 0) doPwmClock (argc, argv) ;
  1184. else if (strcasecmp (argv [1], "pwmTone" ) == 0) doPwmTone (argc, argv) ;
  1185. else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ;
  1186. else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ;
  1187. else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ;
  1188. else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ;
  1189. else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect (argc, argv) ;
  1190. else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ;
  1191. else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ;
  1192. else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ;
  1193. else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ;
  1194. else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ;
  1195. else if (strcasecmp (argv [1], "clock" ) == 0) doClock (argc, argv) ;
  1196. else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ;
  1197. else
  1198. {
  1199. fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
  1200. exit (EXIT_FAILURE) ;
  1201. }
  1202. return 0 ;
  1203. }