wpiExtensions.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. /*
  2. * extensions.c:
  3. * Originally part of the GPIO program to test, peek, poke and otherwise
  4. * noodle with the GPIO hardware on the Raspberry Pi.
  5. * Now used as a general purpose library to allow systems to dynamically
  6. * add in new devices into wiringPi at program run-time.
  7. * Copyright (c) 2012-2015 Gordon Henderson
  8. ***********************************************************************
  9. * This file is part of wiringPi:
  10. * https://projects.drogon.net/raspberry-pi/wiringpi/
  11. *
  12. * wiringPi is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Lesser General Public License as published by
  14. * the Free Software Foundation, either version 3 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * wiringPi is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Lesser General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Lesser General Public License
  23. * along with wiringPi. If not, see <http://www.gnu.org/licenses/>.
  24. ***********************************************************************
  25. */
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <stdint.h>
  29. #include <stdarg.h>
  30. #include <ctype.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include <errno.h>
  34. #include <sys/types.h>
  35. #include <fcntl.h>
  36. #include <wiringPi.h>
  37. #include "mcp23008.h"
  38. #include "mcp23016.h"
  39. #include "mcp23017.h"
  40. #include "mcp23s08.h"
  41. #include "mcp23s17.h"
  42. #include "sr595.h"
  43. #include "pcf8574.h"
  44. #include "pcf8591.h"
  45. #include "mcp3002.h"
  46. #include "mcp3004.h"
  47. #include "mcp4802.h"
  48. #include "mcp3422.h"
  49. #include "max31855.h"
  50. #include "max5322.h"
  51. #include "ads1115.h"
  52. #include "sn3218.h"
  53. #include "drcSerial.h"
  54. #include "wpiExtensions.h"
  55. extern int wiringPiDebug ;
  56. static int verbose ;
  57. static char errorMessage [1024] ;
  58. #ifndef TRUE
  59. # define TRUE (1==1)
  60. # define FALSE (1==2)
  61. #endif
  62. // Local structure to hold details
  63. struct extensionFunctionStruct
  64. {
  65. const char *name ;
  66. int (*function)(char *progName, int pinBase, char *params) ;
  67. } ;
  68. /*
  69. * verbError:
  70. * Convenient error handling
  71. *********************************************************************************
  72. */
  73. static void verbError (const char *message, ...)
  74. {
  75. va_list argp ;
  76. va_start (argp, message) ;
  77. vsnprintf (errorMessage, 1023, message, argp) ;
  78. va_end (argp) ;
  79. if (verbose)
  80. fprintf (stderr, "%s\n", errorMessage) ;
  81. }
  82. /*
  83. * extractInt:
  84. * Check & return an integer at the given location (prefixed by a :)
  85. *********************************************************************************
  86. */
  87. static char *extractInt (char *progName, char *p, int *num)
  88. {
  89. if (*p != ':')
  90. {
  91. verbError ("%s: colon expected", progName) ;
  92. return NULL ;
  93. }
  94. ++p ;
  95. if (!isdigit (*p))
  96. {
  97. verbError ("%s: digit expected", progName) ;
  98. return NULL ;
  99. }
  100. *num = strtol (p, NULL, 0) ;
  101. while (isdigit (*p))
  102. ++p ;
  103. return p ;
  104. }
  105. /*
  106. * extractStr:
  107. * Check & return a string at the given location (prefixed by a :)
  108. *********************************************************************************
  109. */
  110. static char *extractStr (char *progName, char *p, char **str)
  111. {
  112. char *q, *r ;
  113. if (*p != ':')
  114. {
  115. verbError ("%s: colon expected", progName) ;
  116. return NULL ;
  117. }
  118. ++p ;
  119. if (!isprint (*p))
  120. {
  121. verbError ("%s: character expected", progName) ;
  122. return NULL ;
  123. }
  124. q = p ;
  125. while ((*q != 0) && (*q != ':'))
  126. ++q ;
  127. *str = r = calloc (q - p + 2, 1) ; // Zeros it
  128. while (p != q)
  129. *r++ = *p++ ;
  130. return p ;
  131. }
  132. /*
  133. * doExtensionMcp23008:
  134. * MCP23008 - 8-bit I2C GPIO expansion chip
  135. * mcp23002:base:i2cAddr
  136. *********************************************************************************
  137. */
  138. static int doExtensionMcp23008 (char *progName, int pinBase, char *params)
  139. {
  140. int i2c ;
  141. if ((params = extractInt (progName, params, &i2c)) == NULL)
  142. return FALSE ;
  143. if ((i2c < 0x01) || (i2c > 0x77))
  144. {
  145. verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
  146. return FALSE ;
  147. }
  148. mcp23008Setup (pinBase, i2c) ;
  149. return TRUE ;
  150. }
  151. /*
  152. * doExtensionMcp23016:
  153. * MCP230016- 16-bit I2C GPIO expansion chip
  154. * mcp23016:base:i2cAddr
  155. *********************************************************************************
  156. */
  157. static int doExtensionMcp23016 (char *progName, int pinBase, char *params)
  158. {
  159. int i2c ;
  160. if ((params = extractInt (progName, params, &i2c)) == NULL)
  161. return FALSE ;
  162. if ((i2c < 0x03) || (i2c > 0x77))
  163. {
  164. verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
  165. return FALSE ;
  166. }
  167. mcp23016Setup (pinBase, i2c) ;
  168. return TRUE ;
  169. }
  170. /*
  171. * doExtensionMcp23017:
  172. * MCP230017- 16-bit I2C GPIO expansion chip
  173. * mcp23017:base:i2cAddr
  174. *********************************************************************************
  175. */
  176. static int doExtensionMcp23017 (char *progName, int pinBase, char *params)
  177. {
  178. int i2c ;
  179. if ((params = extractInt (progName, params, &i2c)) == NULL)
  180. return FALSE ;
  181. if ((i2c < 0x03) || (i2c > 0x77))
  182. {
  183. verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
  184. return FALSE ;
  185. }
  186. mcp23017Setup (pinBase, i2c) ;
  187. return TRUE ;
  188. }
  189. /*
  190. * doExtensionMcp23s08:
  191. * MCP23s08 - 8-bit SPI GPIO expansion chip
  192. * mcp23s08:base:spi:port
  193. *********************************************************************************
  194. */
  195. static int doExtensionMcp23s08 (char *progName, int pinBase, char *params)
  196. {
  197. int spi, port ;
  198. if ((params = extractInt (progName, params, &spi)) == NULL)
  199. return FALSE ;
  200. if ((spi < 0) || (spi > 1))
  201. {
  202. verbError ("%s: SPI address (%d) out of range", progName, spi) ;
  203. return FALSE ;
  204. }
  205. if ((params = extractInt (progName, params, &port)) == NULL)
  206. return FALSE ;
  207. if ((port < 0) || (port > 7))
  208. {
  209. verbError ("%s: port address (%d) out of range", progName, port) ;
  210. return FALSE ;
  211. }
  212. mcp23s08Setup (pinBase, spi, port) ;
  213. return TRUE ;
  214. }
  215. /*
  216. * doExtensionMcp23s17:
  217. * MCP23s17 - 16-bit SPI GPIO expansion chip
  218. * mcp23s17:base:spi:port
  219. *********************************************************************************
  220. */
  221. static int doExtensionMcp23s17 (char *progName, int pinBase, char *params)
  222. {
  223. int spi, port ;
  224. if ((params = extractInt (progName, params, &spi)) == NULL)
  225. return FALSE ;
  226. if ((spi < 0) || (spi > 1))
  227. {
  228. verbError ("%s: SPI address (%d) out of range", progName, spi) ;
  229. return FALSE ;
  230. }
  231. if ((params = extractInt (progName, params, &port)) == NULL)
  232. return FALSE ;
  233. if ((port < 0) || (port > 7))
  234. {
  235. verbError ("%s: port address (%d) out of range", progName, port) ;
  236. return FALSE ;
  237. }
  238. mcp23s17Setup (pinBase, spi, port) ;
  239. return TRUE ;
  240. }
  241. /*
  242. * doExtensionSr595:
  243. * Shift Register 74x595
  244. * sr595:base:pins:data:clock:latch
  245. *********************************************************************************
  246. */
  247. static int doExtensionSr595 (char *progName, int pinBase, char *params)
  248. {
  249. int pins, data, clock, latch ;
  250. // Extract pins
  251. if ((params = extractInt (progName, params, &pins)) == NULL)
  252. return FALSE ;
  253. if ((pins < 8) || (pins > 32))
  254. {
  255. verbError ("%s: pin count (%d) out of range - 8-32 expected.", progName, pins) ;
  256. return FALSE ;
  257. }
  258. if ((params = extractInt (progName, params, &data)) == NULL)
  259. return FALSE ;
  260. if ((params = extractInt (progName, params, &clock)) == NULL)
  261. return FALSE ;
  262. if ((params = extractInt (progName, params, &latch)) == NULL)
  263. return FALSE ;
  264. sr595Setup (pinBase, pins, data, clock, latch) ;
  265. return TRUE ;
  266. }
  267. /*
  268. * doExtensionPcf8574:
  269. * Digital IO (Crude!)
  270. * pcf8574:base:i2cAddr
  271. *********************************************************************************
  272. */
  273. static int doExtensionPcf8574 (char *progName, int pinBase, char *params)
  274. {
  275. int i2c ;
  276. if ((params = extractInt (progName, params, &i2c)) == NULL)
  277. return FALSE ;
  278. if ((i2c < 0x03) || (i2c > 0x77))
  279. {
  280. verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
  281. return FALSE ;
  282. }
  283. pcf8574Setup (pinBase, i2c) ;
  284. return TRUE ;
  285. }
  286. /*
  287. * doExtensionAds1115:
  288. * Analog Input
  289. * ads1115:base:i2cAddr
  290. *********************************************************************************
  291. */
  292. static int doExtensionAds1115 (char *progName, int pinBase, char *params)
  293. {
  294. int i2c ;
  295. if ((params = extractInt (progName, params, &i2c)) == NULL)
  296. return FALSE ;
  297. if ((i2c < 0x03) || (i2c > 0x77))
  298. {
  299. verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
  300. return FALSE ;
  301. }
  302. ads1115Setup (pinBase, i2c) ;
  303. return TRUE ;
  304. }
  305. /*
  306. * doExtensionPcf8591:
  307. * Analog IO
  308. * pcf8591:base:i2cAddr
  309. *********************************************************************************
  310. */
  311. static int doExtensionPcf8591 (char *progName, int pinBase, char *params)
  312. {
  313. int i2c ;
  314. if ((params = extractInt (progName, params, &i2c)) == NULL)
  315. return FALSE ;
  316. if ((i2c < 0x03) || (i2c > 0x77))
  317. {
  318. verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
  319. return FALSE ;
  320. }
  321. pcf8591Setup (pinBase, i2c) ;
  322. return TRUE ;
  323. }
  324. /*
  325. * doExtensionMax31855:
  326. * Analog IO
  327. * max31855:base:spiChan
  328. *********************************************************************************
  329. */
  330. static int doExtensionMax31855 (char *progName, int pinBase, char *params)
  331. {
  332. int spi ;
  333. if ((params = extractInt (progName, params, &spi)) == NULL)
  334. return FALSE ;
  335. if ((spi < 0) || (spi > 1))
  336. {
  337. verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
  338. return FALSE ;
  339. }
  340. max31855Setup (pinBase, spi) ;
  341. return TRUE ;
  342. }
  343. /*
  344. * doExtensionMcp3002:
  345. * Analog IO
  346. * mcp3002:base:spiChan
  347. *********************************************************************************
  348. */
  349. static int doExtensionMcp3002 (char *progName, int pinBase, char *params)
  350. {
  351. int spi ;
  352. if ((params = extractInt (progName, params, &spi)) == NULL)
  353. return FALSE ;
  354. if ((spi < 0) || (spi > 1))
  355. {
  356. verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
  357. return FALSE ;
  358. }
  359. mcp3002Setup (pinBase, spi) ;
  360. return TRUE ;
  361. }
  362. /*
  363. * doExtensionMcp3004:
  364. * Analog IO
  365. * mcp3004:base:spiChan
  366. *********************************************************************************
  367. */
  368. static int doExtensionMcp3004 (char *progName, int pinBase, char *params)
  369. {
  370. int spi ;
  371. if ((params = extractInt (progName, params, &spi)) == NULL)
  372. return FALSE ;
  373. if ((spi < 0) || (spi > 1))
  374. {
  375. verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
  376. return FALSE ;
  377. }
  378. mcp3004Setup (pinBase, spi) ;
  379. return TRUE ;
  380. }
  381. /*
  382. * doExtensionMax5322:
  383. * Analog O
  384. * max5322:base:spiChan
  385. *********************************************************************************
  386. */
  387. static int doExtensionMax5322 (char *progName, int pinBase, char *params)
  388. {
  389. int spi ;
  390. if ((params = extractInt (progName, params, &spi)) == NULL)
  391. return FALSE ;
  392. if ((spi < 0) || (spi > 1))
  393. {
  394. verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
  395. return FALSE ;
  396. }
  397. max5322Setup (pinBase, spi) ;
  398. return TRUE ;
  399. }
  400. /*
  401. * doExtensionMcp4802:
  402. * Analog IO
  403. * mcp4802:base:spiChan
  404. *********************************************************************************
  405. */
  406. static int doExtensionMcp4802 (char *progName, int pinBase, char *params)
  407. {
  408. int spi ;
  409. if ((params = extractInt (progName, params, &spi)) == NULL)
  410. return FALSE ;
  411. if ((spi < 0) || (spi > 1))
  412. {
  413. verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
  414. return FALSE ;
  415. }
  416. mcp4802Setup (pinBase, spi) ;
  417. return TRUE ;
  418. }
  419. /*
  420. * doExtensionSn3218:
  421. * Analog Output (LED Driver)
  422. * sn3218:base
  423. *********************************************************************************
  424. */
  425. static int doExtensionSn3218 (char *progName, int pinBase, char *params)
  426. {
  427. sn3218Setup (pinBase) ;
  428. return TRUE ;
  429. }
  430. /*
  431. * doExtensionMcp3422:
  432. * Analog IO
  433. * mcp3422:base:i2cAddr
  434. *********************************************************************************
  435. */
  436. static int doExtensionMcp3422 (char *progName, int pinBase, char *params)
  437. {
  438. int i2c, sampleRate, gain ;
  439. if ((params = extractInt (progName, params, &i2c)) == NULL)
  440. return FALSE ;
  441. if ((i2c < 0x03) || (i2c > 0x77))
  442. {
  443. verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
  444. return FALSE ;
  445. }
  446. if ((params = extractInt (progName, params, &sampleRate)) == NULL)
  447. return FALSE ;
  448. if ((sampleRate < 0) || (sampleRate > 3))
  449. {
  450. verbError ("%s: sample rate (%d) out of range", progName, sampleRate) ;
  451. return FALSE ;
  452. }
  453. if ((params = extractInt (progName, params, &gain)) == NULL)
  454. return FALSE ;
  455. if ((gain < 0) || (gain > 3))
  456. {
  457. verbError ("%s: gain (%d) out of range", progName, gain) ;
  458. return FALSE ;
  459. }
  460. mcp3422Setup (pinBase, i2c, sampleRate, gain) ;
  461. return TRUE ;
  462. }
  463. /*
  464. * doExtensionDrcS:
  465. * Interface to a DRC Serial system
  466. * drcs:base:pins:serialPort:baud
  467. *********************************************************************************
  468. */
  469. static int doExtensionDrcS (char *progName, int pinBase, char *params)
  470. {
  471. char *port ;
  472. int pins, baud ;
  473. if ((params = extractInt (progName, params, &pins)) == NULL)
  474. return FALSE ;
  475. if ((pins < 1) || (pins > 100))
  476. {
  477. verbError ("%s: pins (%d) out of range (2-100)", progName, pins) ;
  478. return FALSE ;
  479. }
  480. if ((params = extractStr (progName, params, &port)) == NULL)
  481. return FALSE ;
  482. if (strlen (port) == 0)
  483. {
  484. verbError ("%s: serial port device name required", progName) ;
  485. return FALSE ;
  486. }
  487. if ((params = extractInt (progName, params, &baud)) == NULL)
  488. return FALSE ;
  489. if ((baud < 1) || (baud > 4000000))
  490. {
  491. verbError ("%s: baud rate (%d) out of range", progName, baud) ;
  492. return FALSE ;
  493. }
  494. drcSetupSerial (pinBase, pins, port, baud) ;
  495. return TRUE ;
  496. }
  497. /*
  498. * Function list
  499. *********************************************************************************
  500. */
  501. static struct extensionFunctionStruct extensionFunctions [] =
  502. {
  503. { "mcp23008", &doExtensionMcp23008 },
  504. { "mcp23016", &doExtensionMcp23016 },
  505. { "mcp23017", &doExtensionMcp23017 },
  506. { "mcp23s08", &doExtensionMcp23s08 },
  507. { "mcp23s17", &doExtensionMcp23s17 },
  508. { "sr595", &doExtensionSr595 },
  509. { "pcf8574", &doExtensionPcf8574 },
  510. { "pcf8591", &doExtensionPcf8591 },
  511. { "mcp3002", &doExtensionMcp3002 },
  512. { "mcp3004", &doExtensionMcp3004 },
  513. { "mcp4802", &doExtensionMcp4802 },
  514. { "mcp3422", &doExtensionMcp3422 },
  515. { "max31855", &doExtensionMax31855 },
  516. { "ads1115", &doExtensionAds1115 },
  517. { "max5322", &doExtensionMax5322 },
  518. { "sn3218", &doExtensionSn3218 },
  519. { "drcs", &doExtensionDrcS },
  520. { NULL, NULL },
  521. } ;
  522. /*
  523. * loadWPiExtension:
  524. * Load in a wiringPi extension
  525. * The extensionData always starts with the name, a colon then the pinBase
  526. * number. Other parameters after that are decoded by the module in question.
  527. *********************************************************************************
  528. */
  529. int loadWPiExtension (char *progName, char *extensionData, int printErrors)
  530. {
  531. char *p ;
  532. char *extension = extensionData ;
  533. struct extensionFunctionStruct *extensionFn ;
  534. int pinBase = 0 ;
  535. verbose = printErrors ;
  536. // Get the extension name by finding the first colon
  537. p = extension ;
  538. while (*p != ':')
  539. {
  540. if (!*p) // ran out of characters
  541. {
  542. verbError ("%s: extension name not terminated by a colon", progName) ;
  543. return FALSE ;
  544. }
  545. ++p ;
  546. }
  547. *p++ = 0 ;
  548. // Simple ATOI code
  549. if (!isdigit (*p))
  550. {
  551. verbError ("%s: pinBase number expected after extension name", progName) ;
  552. return FALSE ;
  553. }
  554. while (isdigit (*p))
  555. {
  556. if (pinBase > 1000000000) // Lets be realistic here...
  557. {
  558. verbError ("%s: pinBase too large", progName) ;
  559. return FALSE ;
  560. }
  561. pinBase = pinBase * 10 + (*p - '0') ;
  562. ++p ;
  563. }
  564. if (pinBase < 64)
  565. {
  566. verbError ("%s: pinBase (%d) too small. Minimum is 64.", progName, pinBase) ;
  567. return FALSE ;
  568. }
  569. // Search for extensions:
  570. for (extensionFn = extensionFunctions ; extensionFn->name != NULL ; ++extensionFn)
  571. {
  572. if (strcmp (extensionFn->name, extension) == 0)
  573. return extensionFn->function (progName, pinBase, p) ;
  574. }
  575. verbError ("%s: extension %s not found", progName, extension) ;
  576. return FALSE ;
  577. }