gpio.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. /*
  2. * gpio.c:
  3. * Set-UID command-line interface to the Raspberry Pi's GPIO
  4. * Copyright (c) 2012 Gordon Henderson
  5. ***********************************************************************
  6. * This file is part of wiringPi:
  7. * https://projects.drogon.net/raspberry-pi/wiringpi/
  8. *
  9. * wiringPi is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * wiringPi is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with wiringPi. If not, see <http://www.gnu.org/licenses/>.
  21. ***********************************************************************
  22. */
  23. #include <wiringPi.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <stdint.h>
  27. #include <string.h>
  28. #include <unistd.h>
  29. #include <errno.h>
  30. #include <sys/types.h>
  31. #include <fcntl.h>
  32. #define VERSION "1.0"
  33. static int wpMode ;
  34. char *usage = "Usage: gpio -v\n"
  35. " gpio [-g] <read/write/pwm/mode> ...\n"
  36. " gpio [-p] <read/write/mode> ...\n"
  37. " gpio <export/edge/unexport/unexportall/exports> ..." ;
  38. /*
  39. * doExports:
  40. * List all GPIO exports
  41. *********************************************************************************
  42. */
  43. void doExports (void)
  44. {
  45. int fd ;
  46. int i, l, first ;
  47. char fName [128] ;
  48. char buf [16] ;
  49. // Rather crude, but who knows what others are up to...
  50. for (first = 0, i = 0 ; i < 64 ; ++i)
  51. {
  52. // Try to read the direction
  53. sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ;
  54. if ((fd = open (fName, O_RDONLY)) == -1)
  55. continue ;
  56. if (first == 0)
  57. {
  58. ++first ;
  59. printf ("GPIO Pins exported:\n") ;
  60. }
  61. printf ("%4d: ", i) ;
  62. if ((l = read (fd, buf, 16)) == 0)
  63. sprintf (buf, "%s", "?") ;
  64. buf [l] = 0 ;
  65. if ((buf [strlen (buf) - 1]) == '\n')
  66. buf [strlen (buf) - 1] = 0 ;
  67. printf ("%-3s", buf) ;
  68. close (fd) ;
  69. // Try to Read the value
  70. sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ;
  71. if ((fd = open (fName, O_RDONLY)) == -1)
  72. {
  73. printf ("No Value file (huh?)\n") ;
  74. continue ;
  75. }
  76. if ((l = read (fd, buf, 16)) == 0)
  77. sprintf (buf, "%s", "?") ;
  78. buf [l] = 0 ;
  79. if ((buf [strlen (buf) - 1]) == '\n')
  80. buf [strlen (buf) - 1] = 0 ;
  81. printf (" %s", buf) ;
  82. // Read any edge trigger file
  83. sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ;
  84. if ((fd = open (fName, O_RDONLY)) == -1)
  85. {
  86. printf ("\n") ;
  87. continue ;
  88. }
  89. if ((l = read (fd, buf, 16)) == 0)
  90. sprintf (buf, "%s", "?") ;
  91. buf [l] = 0 ;
  92. if ((buf [strlen (buf) - 1]) == '\n')
  93. buf [strlen (buf) - 1] = 0 ;
  94. printf (" %-8s\n", buf) ;
  95. close (fd) ;
  96. }
  97. }
  98. /*
  99. * doExport:
  100. * gpio export pin mode
  101. * This uses the /sys/class/gpio device interface.
  102. *********************************************************************************
  103. */
  104. void doExport (int argc, char *argv [])
  105. {
  106. FILE *fd ;
  107. int pin ;
  108. char *mode ;
  109. char fName [128] ;
  110. uid_t uid ;
  111. gid_t gid ;
  112. if (argc != 4)
  113. {
  114. fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ;
  115. exit (1) ;
  116. }
  117. pin = atoi (argv [2]) ;
  118. mode = argv [3] ;
  119. if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
  120. {
  121. fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
  122. exit (1) ;
  123. }
  124. fprintf (fd, "%d\n", pin) ;
  125. fclose (fd) ;
  126. sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
  127. if ((fd = fopen (fName, "w")) == NULL)
  128. {
  129. fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
  130. exit (1) ;
  131. }
  132. /**/ if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0))
  133. fprintf (fd, "in\n") ;
  134. else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0))
  135. fprintf (fd, "out\n") ;
  136. else
  137. {
  138. fprintf (stderr, "%s: Invalid mode: %s. Should be in or out\n", argv [1], mode) ;
  139. exit (1) ;
  140. }
  141. fclose (fd) ;
  142. // Change ownership so the current user can actually use it!
  143. uid = getuid () ;
  144. gid = getgid () ;
  145. sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
  146. if (chown (fName, uid, gid) != 0)
  147. {
  148. fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
  149. exit (1) ;
  150. }
  151. // Also change ownership of the edge file - if it exists
  152. sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
  153. if (chown (fName, uid, gid) != 0)
  154. {
  155. if (errno != ENOENT) // Silently ignore File not found - older kernel
  156. {
  157. fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
  158. exit (1) ;
  159. }
  160. }
  161. }
  162. /*
  163. * doEdge:
  164. * gpio edge pin mode
  165. * Easy access to changing the edge trigger on a GPIO pin
  166. * This uses the /sys/class/gpio device interface.
  167. *********************************************************************************
  168. */
  169. void doEdge (int argc, char *argv [])
  170. {
  171. FILE *fd ;
  172. int pin ;
  173. char *mode ;
  174. char fName [128] ;
  175. uid_t uid ;
  176. gid_t gid ;
  177. if (argc != 4)
  178. {
  179. fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ;
  180. exit (1) ;
  181. }
  182. pin = atoi (argv [2]) ;
  183. mode = argv [3] ;
  184. // Export the pin and set direction to input
  185. if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL)
  186. {
  187. fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ;
  188. exit (1) ;
  189. }
  190. fprintf (fd, "%d\n", pin) ;
  191. fclose (fd) ;
  192. sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ;
  193. if ((fd = fopen (fName, "w")) == NULL)
  194. {
  195. fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
  196. exit (1) ;
  197. }
  198. fprintf (fd, "in\n") ;
  199. fclose (fd) ;
  200. sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
  201. if ((fd = fopen (fName, "w")) == NULL)
  202. {
  203. fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ;
  204. exit (1) ;
  205. }
  206. /**/ if (strcasecmp (mode, "none") == 0)
  207. fprintf (fd, "none\n") ;
  208. else if (strcasecmp (mode, "rising") == 0)
  209. fprintf (fd, "rising\n") ;
  210. else if (strcasecmp (mode, "falling") == 0)
  211. fprintf (fd, "falling\n") ;
  212. else if (strcasecmp (mode, "both") == 0)
  213. fprintf (fd, "both\n") ;
  214. else
  215. {
  216. fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
  217. exit (1) ;
  218. }
  219. // Change ownership so the current user can actually use it!
  220. uid = getuid () ;
  221. gid = getgid () ;
  222. sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
  223. if (chown (fName, uid, gid) != 0)
  224. {
  225. fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
  226. exit (1) ;
  227. }
  228. // Also change ownership of the edge file
  229. sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
  230. if (chown (fName, uid, gid) != 0)
  231. {
  232. fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
  233. exit (1) ;
  234. }
  235. fclose (fd) ;
  236. }
  237. /*
  238. * doUnexport:
  239. * gpio unexport pin
  240. * This uses the /sys/class/gpio device interface.
  241. *********************************************************************************
  242. */
  243. void doUnexport (int argc, char *argv [])
  244. {
  245. FILE *fd ;
  246. int pin ;
  247. if (argc != 3)
  248. {
  249. fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ;
  250. exit (1) ;
  251. }
  252. pin = atoi (argv [2]) ;
  253. if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
  254. {
  255. fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
  256. exit (1) ;
  257. }
  258. fprintf (fd, "%d\n", pin) ;
  259. fclose (fd) ;
  260. }
  261. /*
  262. * doUnexportAll:
  263. * gpio unexportall
  264. * Un-Export all the GPIO pins.
  265. * This uses the /sys/class/gpio device interface.
  266. *********************************************************************************
  267. */
  268. void doUnexportall (int argc, char *argv [])
  269. {
  270. FILE *fd ;
  271. int pin ;
  272. for (pin = 0 ; pin < 63 ; ++pin)
  273. {
  274. if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
  275. {
  276. fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
  277. exit (1) ;
  278. }
  279. fprintf (fd, "%d\n", pin) ;
  280. fclose (fd) ;
  281. }
  282. }
  283. /*
  284. * doMode:
  285. * gpio mode pin mode ...
  286. *********************************************************************************
  287. */
  288. void doMode (int argc, char *argv [])
  289. {
  290. int pin ;
  291. char *mode ;
  292. if (argc != 4)
  293. {
  294. fprintf (stderr, "Usage: %s mode pin mode\n", argv [0]) ;
  295. exit (1) ;
  296. }
  297. pin = atoi (argv [2]) ;
  298. if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
  299. return ;
  300. mode = argv [3] ;
  301. /**/ if (strcasecmp (mode, "in") == 0)
  302. pinMode (pin, INPUT) ;
  303. else if (strcasecmp (mode, "out") == 0)
  304. pinMode (pin, OUTPUT) ;
  305. else if (strcasecmp (mode, "pwm") == 0)
  306. pinMode (pin, PWM_OUTPUT) ;
  307. else if (strcasecmp (mode, "up") == 0)
  308. pullUpDnControl (pin, PUD_UP) ;
  309. else if (strcasecmp (mode, "down") == 0)
  310. pullUpDnControl (pin, PUD_DOWN) ;
  311. else if (strcasecmp (mode, "tri") == 0)
  312. pullUpDnControl (pin, PUD_OFF) ;
  313. else
  314. {
  315. fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/up/down/tri\n", argv [1], mode) ;
  316. exit (1) ;
  317. }
  318. }
  319. /*
  320. * doWrite:
  321. * gpio write pin value
  322. *********************************************************************************
  323. */
  324. void doWrite (int argc, char *argv [])
  325. {
  326. int pin, val ;
  327. if (argc != 4)
  328. {
  329. fprintf (stderr, "Usage: %s write pin value\n", argv [0]) ;
  330. exit (1) ;
  331. }
  332. pin = atoi (argv [2]) ;
  333. if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
  334. return ;
  335. val = atoi (argv [3]) ;
  336. /**/ if (val == 0)
  337. digitalWrite (pin, LOW) ;
  338. else
  339. digitalWrite (pin, HIGH) ;
  340. }
  341. /*
  342. * doRead:
  343. * Read a pin and return the value
  344. *********************************************************************************
  345. */
  346. void doRead (int argc, char *argv [])
  347. {
  348. int pin, val ;
  349. if (argc != 3)
  350. {
  351. fprintf (stderr, "Usage: %s read pin\n", argv [0]) ;
  352. exit (1) ;
  353. }
  354. pin = atoi (argv [2]) ;
  355. if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
  356. {
  357. printf ("0\n") ;
  358. return ;
  359. }
  360. val = digitalRead (pin) ;
  361. printf ("%s\n", val == 0 ? "0" : "1") ;
  362. }
  363. /*
  364. * doPwm:
  365. * Output a PWM value on a pin
  366. *********************************************************************************
  367. */
  368. void doPwm (int argc, char *argv [])
  369. {
  370. int pin, val ;
  371. if (argc != 4)
  372. {
  373. fprintf (stderr, "Usage: %s pwm <pin> <value>\n", argv [0]) ;
  374. exit (1) ;
  375. }
  376. pin = atoi (argv [2]) ;
  377. if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
  378. return ;
  379. val = atoi (argv [3]) ;
  380. pwmWrite (pin, val) ;
  381. }
  382. /*
  383. * main:
  384. * Start here
  385. *********************************************************************************
  386. */
  387. int main (int argc, char *argv [])
  388. {
  389. int i ;
  390. if (argc == 1)
  391. {
  392. fprintf (stderr, "%s: %s\n", argv [0], usage) ;
  393. return 1 ;
  394. }
  395. if (geteuid () != 0)
  396. {
  397. fprintf (stderr, "%s: Must be root to run\n", argv [0]) ;
  398. return 1 ;
  399. }
  400. if (strcasecmp (argv [1], "-v") == 0)
  401. {
  402. printf ("gpio version: %s\n", VERSION) ;
  403. printf ("Copyright (c) 2012 Gordon Henderson\n") ;
  404. printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
  405. return 0 ;
  406. }
  407. // Initial test for /sys/class/gpio operations:
  408. /**/ if (strcasecmp (argv [1], "exports" ) == 0)
  409. { doExports () ; return 0 ; }
  410. else if (strcasecmp (argv [1], "export" ) == 0)
  411. { doExport (argc, argv) ; return 0 ; }
  412. else if (strcasecmp (argv [1], "edge" ) == 0)
  413. { doEdge (argc, argv) ; return 0 ; }
  414. else if (strcasecmp (argv [1], "unexportall") == 0)
  415. { doUnexportall (argc, argv) ; return 0 ; }
  416. else if (strcasecmp (argv [1], "unexport") == 0)
  417. { doUnexport (argc, argv) ; return 0 ; }
  418. // Check for -g argument
  419. if (strcasecmp (argv [1], "-g") == 0)
  420. {
  421. if (wiringPiSetupGpio () == -1)
  422. {
  423. fprintf (stderr, "%s: Unable to initialise GPIO in GPIO mode.\n", argv [0]) ;
  424. exit (1) ;
  425. }
  426. for (i = 2 ; i < argc ; ++i)
  427. argv [i - 1] = argv [i] ;
  428. --argc ;
  429. wpMode = WPI_MODE_GPIO ;
  430. }
  431. // Check for -p argument for PiFace
  432. else if (strcasecmp (argv [1], "-p") == 0)
  433. {
  434. if (wiringPiSetupPiFaceForGpioProg () == -1)
  435. {
  436. fprintf (stderr, "%s: Unable to initialise PiFace.\n", argv [0]) ;
  437. exit (1) ;
  438. }
  439. for (i = 2 ; i < argc ; ++i)
  440. argv [i - 1] = argv [i] ;
  441. --argc ;
  442. wpMode = WPI_MODE_PIFACE ;
  443. }
  444. // Default to wiringPi mode
  445. else
  446. {
  447. if (wiringPiSetup () == -1)
  448. {
  449. fprintf (stderr, "%s: Unable to initialise GPIO in wiringPi mode\n", argv [0]) ;
  450. exit (1) ;
  451. }
  452. wpMode = WPI_MODE_PINS ;
  453. }
  454. /**/ if (strcasecmp (argv [1], "write" ) == 0)
  455. doWrite (argc, argv) ;
  456. else if (strcasecmp (argv [1], "read" ) == 0)
  457. doRead (argc, argv) ;
  458. else if (strcasecmp (argv [1], "mode" ) == 0)
  459. doMode (argc, argv) ;
  460. else if (strcasecmp (argv [1], "pwm" ) == 0)
  461. doPwm (argc, argv) ;
  462. else
  463. {
  464. fprintf (stderr, "%s: Unknown command: %s. (read/write/pwm/mode expected)\n", argv [0], argv [1]) ;
  465. exit (1) ;
  466. }
  467. return 0 ;
  468. }