Gordons Projects

--> Projects Top-Level GIT

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