Gordons Projects

--> Projects Top-Level GIT

62a92d773c2522ee7d3b45d60f9aa2634434c4a0
[wiringPi] / wiringPi / wpiExtensions.c
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
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <stdarg.h>
32 #include <ctype.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <fcntl.h>
38
39 #include <wiringPi.h>
40
41 #include "mcp23008.h"
42 #include "mcp23016.h"
43 #include "mcp23017.h"
44 #include "mcp23s08.h"
45 #include "mcp23s17.h"
46 #include "sr595.h"
47 #include "pcf8574.h"
48 #include "pcf8591.h"
49 #include "mcp3002.h"
50 #include "mcp3004.h"
51 #include "mcp4802.h"
52 #include "mcp3422.h"
53 #include "max31855.h"
54 #include "max5322.h"
55 #include "ads1115.h"
56 #include "sn3218.h"
57 #include "drcSerial.h"
58
59 #include "wpiExtensions.h"
60
61 extern int wiringPiDebug ;
62
63 static int verbose ;
64 static char errorMessage [1024] ;
65
66
67 // Local structure to hold details
68
69 struct extensionFunctionStruct
70 {
71   const char *name ;
72   int   (*function)(char *progName, int pinBase, char *params) ;
73 } ;
74
75
76 /*
77  * verbError:
78  *      Convenient error handling
79  *********************************************************************************
80  */
81
82 static void verbError (const char *message, ...)
83 {
84   va_list argp ;
85   va_start (argp, message) ;
86     vsnprintf (errorMessage, 1023, message, argp) ;
87   va_end (argp) ;
88
89   if (verbose)
90     fprintf (stderr, "%s\n", errorMessage) ;
91 }
92
93
94 /*
95  * extractInt:
96  *      Check & return an integer at the given location (prefixed by a :)
97  *********************************************************************************
98  */
99
100 static char *extractInt (char *progName, char *p, int *num)
101 {
102   if (*p != ':')
103   {
104     verbError ("%s: colon expected", progName) ;
105     return NULL ;
106   }
107
108   ++p ;
109
110   if (!isdigit (*p))
111   {
112     verbError ("%s: digit expected", progName) ;
113     return NULL ;
114   }
115
116   *num = strtol (p, NULL, 0) ;
117
118 // Increment p, but we need to check for hex 0x
119
120   if ((*p == '0') && (*(p + 1) == 'x'))
121     p +=2 ;
122
123   while (isxdigit (*p))
124     ++p ;
125
126   return p ;
127 }
128
129
130 /*
131  * extractStr:
132  *      Check & return a string at the given location (prefixed by a :)
133  *********************************************************************************
134  */
135
136 static char *extractStr (char *progName, char *p, char **str)
137 {
138   char *q, *r ;
139
140   if (*p != ':')
141   {
142     verbError ("%s: colon expected", progName) ;
143     return NULL ;
144   }
145
146   ++p ;
147
148   if (!isprint (*p))
149   {
150     verbError ("%s: character expected", progName) ;
151     return NULL ;
152   }
153
154   q = p ;
155   while ((*q != 0) && (*q != ':'))
156     ++q ;
157
158   *str = r = calloc (q - p + 2, 1) ;    // Zeros it
159
160   while (p != q)
161     *r++ = *p++ ;
162     
163   return p ;
164 }
165
166
167
168 /*
169  * doExtensionMcp23008:
170  *      MCP23008 - 8-bit I2C GPIO expansion chip
171  *      mcp23002:base:i2cAddr
172  *********************************************************************************
173  */
174
175 static int doExtensionMcp23008 (char *progName, int pinBase, char *params)
176 {
177   int i2c ;
178
179   if ((params = extractInt (progName, params, &i2c)) == NULL)
180     return FALSE ;
181
182   if ((i2c < 0x01) || (i2c > 0x77))
183   {
184     verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
185     return FALSE ;
186   }
187
188   mcp23008Setup (pinBase, i2c) ;
189
190   return TRUE ;
191 }
192
193
194 /*
195  * doExtensionMcp23016:
196  *      MCP230016- 16-bit I2C GPIO expansion chip
197  *      mcp23016:base:i2cAddr
198  *********************************************************************************
199  */
200
201 static int doExtensionMcp23016 (char *progName, int pinBase, char *params)
202 {
203   int i2c ;
204
205   if ((params = extractInt (progName, params, &i2c)) == NULL)
206     return FALSE ;
207
208   if ((i2c < 0x03) || (i2c > 0x77))
209   {
210     verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
211     return FALSE ;
212   }
213
214   mcp23016Setup (pinBase, i2c) ;
215
216   return TRUE ;
217 }
218
219
220 /*
221  * doExtensionMcp23017:
222  *      MCP230017- 16-bit I2C GPIO expansion chip
223  *      mcp23017:base:i2cAddr
224  *********************************************************************************
225  */
226
227 static int doExtensionMcp23017 (char *progName, int pinBase, char *params)
228 {
229   int i2c ;
230
231   if ((params = extractInt (progName, params, &i2c)) == NULL)
232     return FALSE ;
233
234   if ((i2c < 0x03) || (i2c > 0x77))
235   {
236     verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
237     return FALSE ;
238   }
239
240   mcp23017Setup (pinBase, i2c) ;
241
242   return TRUE ;
243 }
244
245
246 /*
247  * doExtensionMcp23s08:
248  *      MCP23s08 - 8-bit SPI GPIO expansion chip
249  *      mcp23s08:base:spi:port
250  *********************************************************************************
251  */
252
253 static int doExtensionMcp23s08 (char *progName, int pinBase, char *params)
254 {
255   int spi, port ;
256
257   if ((params = extractInt (progName, params, &spi)) == NULL)
258     return FALSE ;
259
260   if ((spi < 0) || (spi > 1))
261   {
262     verbError ("%s: SPI address (%d) out of range", progName, spi) ;
263     return FALSE ;
264   }
265
266   if ((params = extractInt (progName, params, &port)) == NULL)
267     return FALSE ;
268
269   if ((port < 0) || (port > 7))
270   {
271     verbError ("%s: port address (%d) out of range", progName, port) ;
272     return FALSE ;
273   }
274
275   mcp23s08Setup (pinBase, spi, port) ;
276
277   return TRUE ;
278 }
279
280
281 /*
282  * doExtensionMcp23s17:
283  *      MCP23s17 - 16-bit SPI GPIO expansion chip
284  *      mcp23s17:base:spi:port
285  *********************************************************************************
286  */
287
288 static int doExtensionMcp23s17 (char *progName, int pinBase, char *params)
289 {
290   int spi, port ;
291
292   if ((params = extractInt (progName, params, &spi)) == NULL)
293     return FALSE ;
294
295   if ((spi < 0) || (spi > 1))
296   {
297     verbError ("%s: SPI address (%d) out of range", progName, spi) ;
298     return FALSE ;
299   }
300
301   if ((params = extractInt (progName, params, &port)) == NULL)
302     return FALSE ;
303
304   if ((port < 0) || (port > 7))
305   {
306     verbError ("%s: port address (%d) out of range", progName, port) ;
307     return FALSE ;
308   }
309
310   mcp23s17Setup (pinBase, spi, port) ;
311
312   return TRUE ;
313 }
314
315
316 /*
317  * doExtensionSr595:
318  *      Shift Register 74x595
319  *      sr595:base:pins:data:clock:latch
320  *********************************************************************************
321  */
322
323 static int doExtensionSr595 (char *progName, int pinBase, char *params)
324 {
325   int pins, data, clock, latch ;
326
327 // Extract pins
328
329   if ((params = extractInt (progName, params, &pins)) == NULL)
330     return FALSE ;
331
332   if ((pins < 8) || (pins > 32))
333   {
334     verbError ("%s: pin count (%d) out of range - 8-32 expected.", progName, pins) ;
335     return FALSE ;
336   }
337
338   if ((params = extractInt (progName, params, &data)) == NULL)
339     return FALSE ;
340
341   if ((params = extractInt (progName, params, &clock)) == NULL)
342     return FALSE ;
343
344   if ((params = extractInt (progName, params, &latch)) == NULL)
345     return FALSE ;
346
347   sr595Setup (pinBase, pins, data, clock, latch) ;
348
349   return TRUE ;
350 }
351
352
353 /*
354  * doExtensionPcf8574:
355  *      Digital IO (Crude!)
356  *      pcf8574:base:i2cAddr
357  *********************************************************************************
358  */
359
360 static int doExtensionPcf8574 (char *progName, int pinBase, char *params)
361 {
362   int i2c ;
363
364   if ((params = extractInt (progName, params, &i2c)) == NULL)
365     return FALSE ;
366
367   if ((i2c < 0x03) || (i2c > 0x77))
368   {
369     verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
370     return FALSE ;
371   }
372
373   pcf8574Setup (pinBase, i2c) ;
374
375   return TRUE ;
376 }
377
378
379 /*
380  * doExtensionAds1115:
381  *      Analog Input
382  *      ads1115:base:i2cAddr
383  *********************************************************************************
384  */
385
386 static int doExtensionAds1115 (char *progName, int pinBase, char *params)
387 {
388   int i2c ;
389
390   if ((params = extractInt (progName, params, &i2c)) == NULL)
391     return FALSE ;
392
393   if ((i2c < 0x03) || (i2c > 0x77))
394   {
395     verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
396     return FALSE ;
397   }
398
399   ads1115Setup (pinBase, i2c) ;
400
401   return TRUE ;
402 }
403
404
405 /*
406  * doExtensionPcf8591:
407  *      Analog IO
408  *      pcf8591:base:i2cAddr
409  *********************************************************************************
410  */
411
412 static int doExtensionPcf8591 (char *progName, int pinBase, char *params)
413 {
414   int i2c ;
415
416   if ((params = extractInt (progName, params, &i2c)) == NULL)
417     return FALSE ;
418
419   if ((i2c < 0x03) || (i2c > 0x77))
420   {
421     verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
422     return FALSE ;
423   }
424
425   pcf8591Setup (pinBase, i2c) ;
426
427   return TRUE ;
428 }
429
430
431 /*
432  * doExtensionMax31855:
433  *      Analog IO
434  *      max31855:base:spiChan
435  *********************************************************************************
436  */
437
438 static int doExtensionMax31855 (char *progName, int pinBase, char *params)
439 {
440   int spi ;
441
442   if ((params = extractInt (progName, params, &spi)) == NULL)
443     return FALSE ;
444
445   if ((spi < 0) || (spi > 1))
446   {
447     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
448     return FALSE ;
449   }
450
451   max31855Setup (pinBase, spi) ;
452
453   return TRUE ;
454 }
455
456
457 /*
458  * doExtensionMcp3002:
459  *      Analog IO
460  *      mcp3002:base:spiChan
461  *********************************************************************************
462  */
463
464 static int doExtensionMcp3002 (char *progName, int pinBase, char *params)
465 {
466   int spi ;
467
468   if ((params = extractInt (progName, params, &spi)) == NULL)
469     return FALSE ;
470
471   if ((spi < 0) || (spi > 1))
472   {
473     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
474     return FALSE ;
475   }
476
477   mcp3002Setup (pinBase, spi) ;
478
479   return TRUE ;
480 }
481
482
483 /*
484  * doExtensionMcp3004:
485  *      Analog IO
486  *      mcp3004:base:spiChan
487  *********************************************************************************
488  */
489
490 static int doExtensionMcp3004 (char *progName, int pinBase, char *params)
491 {
492   int spi ;
493
494   if ((params = extractInt (progName, params, &spi)) == NULL)
495     return FALSE ;
496
497   if ((spi < 0) || (spi > 1))
498   {
499     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
500     return FALSE ;
501   }
502
503   mcp3004Setup (pinBase, spi) ;
504
505   return TRUE ;
506 }
507
508
509 /*
510  * doExtensionMax5322:
511  *      Analog O
512  *      max5322:base:spiChan
513  *********************************************************************************
514  */
515
516 static int doExtensionMax5322 (char *progName, int pinBase, char *params)
517 {
518   int spi ;
519
520   if ((params = extractInt (progName, params, &spi)) == NULL)
521     return FALSE ;
522
523   if ((spi < 0) || (spi > 1))
524   {
525     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
526     return FALSE ;
527   }
528
529   max5322Setup (pinBase, spi) ;
530
531   return TRUE ;
532 }
533
534
535 /*
536  * doExtensionMcp4802:
537  *      Analog IO
538  *      mcp4802:base:spiChan
539  *********************************************************************************
540  */
541
542 static int doExtensionMcp4802 (char *progName, int pinBase, char *params)
543 {
544   int spi ;
545
546   if ((params = extractInt (progName, params, &spi)) == NULL)
547     return FALSE ;
548
549   if ((spi < 0) || (spi > 1))
550   {
551     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
552     return FALSE ;
553   }
554
555   mcp4802Setup (pinBase, spi) ;
556
557   return TRUE ;
558 }
559
560
561 /*
562  * doExtensionSn3218:
563  *      Analog Output (LED Driver)
564  *      sn3218:base
565  *********************************************************************************
566  */
567
568 static int doExtensionSn3218 (char *progName, int pinBase, char *params)
569 {
570   sn3218Setup (pinBase) ;
571   return TRUE ;
572 }
573
574
575 /*
576  * doExtensionMcp3422:
577  *      Analog IO
578  *      mcp3422:base:i2cAddr
579  *********************************************************************************
580  */
581
582 static int doExtensionMcp3422 (char *progName, int pinBase, char *params)
583 {
584   int i2c, sampleRate, gain ;
585
586   if ((params = extractInt (progName, params, &i2c)) == NULL)
587     return FALSE ;
588
589   if ((i2c < 0x03) || (i2c > 0x77))
590   {
591     verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
592     return FALSE ;
593   }
594
595   if ((params = extractInt (progName, params, &sampleRate)) == NULL)
596     return FALSE ;
597
598   if ((sampleRate < 0) || (sampleRate > 3))
599   {
600     verbError ("%s: sample rate (%d) out of range", progName, sampleRate) ;
601     return FALSE ;
602   }
603
604   if ((params = extractInt (progName, params, &gain)) == NULL)
605     return FALSE ;
606
607   if ((gain < 0) || (gain > 3))
608   {
609     verbError ("%s: gain (%d) out of range", progName, gain) ;
610     return FALSE ;
611   }
612
613   mcp3422Setup (pinBase, i2c, sampleRate, gain) ;
614
615   return TRUE ;
616 }
617
618
619 /*
620  * doExtensionDrcS:
621  *      Interface to a DRC Serial system
622  *      drcs:base:pins:serialPort:baud
623  *********************************************************************************
624  */
625
626 static int doExtensionDrcS (char *progName, int pinBase, char *params)
627 {
628   char *port ;
629   int pins, baud ;
630
631   if ((params = extractInt (progName, params, &pins)) == NULL)
632     return FALSE ;
633
634   if ((pins < 1) || (pins > 100))
635   {
636     verbError ("%s: pins (%d) out of range (2-100)", progName, pins) ;
637     return FALSE ;
638   }
639   
640   if ((params = extractStr (progName, params, &port)) == NULL)
641     return FALSE ;
642
643   if (strlen (port) == 0)
644   {
645     verbError ("%s: serial port device name required", progName) ;
646     return FALSE ;
647   }
648
649   if ((params = extractInt (progName, params, &baud)) == NULL)
650     return FALSE ;
651
652   if ((baud < 1) || (baud > 4000000))
653   {
654     verbError ("%s: baud rate (%d) out of range", progName, baud) ;
655     return FALSE ;
656   }
657
658   drcSetupSerial (pinBase, pins, port, baud) ;
659
660   return TRUE ;
661 }
662
663
664
665 /*
666  * Function list
667  *********************************************************************************
668  */
669
670 static struct extensionFunctionStruct extensionFunctions [] = 
671 {
672   { "mcp23008",         &doExtensionMcp23008    },
673   { "mcp23016",         &doExtensionMcp23016    },
674   { "mcp23017",         &doExtensionMcp23017    },
675   { "mcp23s08",         &doExtensionMcp23s08    },
676   { "mcp23s17",         &doExtensionMcp23s17    },
677   { "sr595",            &doExtensionSr595       },
678   { "pcf8574",          &doExtensionPcf8574     },
679   { "pcf8591",          &doExtensionPcf8591     },
680   { "mcp3002",          &doExtensionMcp3002     },
681   { "mcp3004",          &doExtensionMcp3004     },
682   { "mcp4802",          &doExtensionMcp4802     },
683   { "mcp3422",          &doExtensionMcp3422     },
684   { "max31855",         &doExtensionMax31855    },
685   { "ads1115",          &doExtensionAds1115     },
686   { "max5322",          &doExtensionMax5322     },
687   { "sn3218",           &doExtensionSn3218      },
688   { "drcs",             &doExtensionDrcS        },
689   { NULL,               NULL                    },
690 } ;
691
692
693 /*
694  * loadWPiExtension:
695  *      Load in a wiringPi extension
696  *      The extensionData always starts with the name, a colon then the pinBase
697  *      number. Other parameters after that are decoded by the module in question.
698  *********************************************************************************
699  */
700
701 int loadWPiExtension (char *progName, char *extensionData, int printErrors)
702 {
703   char *p ;
704   char *extension = extensionData ;
705   struct extensionFunctionStruct *extensionFn ;
706   unsigned pinBase = 0 ;
707
708   verbose = printErrors ;
709
710 // Get the extension name by finding the first colon
711
712   p = extension ;
713   while (*p != ':')
714   {
715     if (!*p)    // ran out of characters
716     {
717       verbError ("%s: extension name not terminated by a colon", progName) ;
718       return FALSE ;
719     }
720     ++p ;
721   }
722   *p++ = 0 ;
723
724 // Simple ATOI code
725
726   if (!isdigit (*p))
727   {
728     verbError ("%s: decimal pinBase number expected after extension name", progName) ;
729     return FALSE ;
730   }
731
732   while (isdigit (*p))
733   {
734     if (pinBase > 2147483647) // 2^31-1 ... Lets be realistic here...
735     {
736       verbError ("%s: pinBase too large", progName) ;
737       return FALSE ;
738     }
739
740     pinBase = pinBase * 10 + (*p - '0') ;
741     ++p ;
742   }
743
744   if (pinBase < 64)
745   {
746     verbError ("%s: pinBase (%d) too small. Minimum is 64.", progName, pinBase) ;
747     return FALSE ;
748   }
749
750 // Search for extensions:
751
752   for (extensionFn = extensionFunctions ; extensionFn->name != NULL ; ++extensionFn)
753   {
754     if (strcmp (extensionFn->name, extension) == 0)
755       return extensionFn->function (progName, pinBase, p) ;
756   }
757
758   verbError ("%s: extension %s not found", progName, extension) ;
759   return FALSE ;
760 }