Gordons Projects

--> Projects Top-Level GIT

Pushing to 2.39 as I have have not done the last one rightly...
[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 (UNU char *progName, int pinBase, UNU char *params)
443 {
444   pseudoPinsSetup (pinBase) ;
445
446   return TRUE ;
447 }
448
449
450 /*
451  * doExtensionBmp180:
452  *      Analog Temp + Pressure
453  *      bmp180:base
454  *********************************************************************************
455  */
456
457 static int doExtensionBmp180 (UNU char *progName, int pinBase, UNU char *params)
458 {
459   bmp180Setup (pinBase) ;
460
461   return TRUE ;
462 }
463
464
465 /*
466  * doExtensionHtu21d:
467  *      Analog humidity + Pressure
468  *      htu21d:base
469  *********************************************************************************
470  */
471
472 static int doExtensionHtu21d (UNU char *progName, int pinBase, UNU char *params)
473 {
474   htu21dSetup (pinBase) ;
475
476   return TRUE ;
477 }
478
479
480 /*
481  * doExtensionDs18b20:
482  *      1-Wire Temperature
483  *      htu21d:base:serialNum
484  *********************************************************************************
485  */
486
487 static int doExtensionDs18b20 (char *progName, int pinBase, char *params)
488 {
489   char *serialNum ;
490
491   if ((params = extractStr (progName, params, &serialNum)) == NULL)
492     return FALSE ;
493
494   return ds18b20Setup (pinBase, serialNum) ;
495 }
496
497
498 /*
499  * doExtensionMax31855:
500  *      Analog IO
501  *      max31855:base:spiChan
502  *********************************************************************************
503  */
504
505 static int doExtensionMax31855 (char *progName, int pinBase, char *params)
506 {
507   int spi ;
508
509   if ((params = extractInt (progName, params, &spi)) == NULL)
510     return FALSE ;
511
512   if ((spi < 0) || (spi > 1))
513   {
514     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
515     return FALSE ;
516   }
517
518   max31855Setup (pinBase, spi) ;
519
520   return TRUE ;
521 }
522
523
524 /*
525  * doExtensionMcp3002:
526  *      Analog IO
527  *      mcp3002:base:spiChan
528  *********************************************************************************
529  */
530
531 static int doExtensionMcp3002 (char *progName, int pinBase, char *params)
532 {
533   int spi ;
534
535   if ((params = extractInt (progName, params, &spi)) == NULL)
536     return FALSE ;
537
538   if ((spi < 0) || (spi > 1))
539   {
540     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
541     return FALSE ;
542   }
543
544   mcp3002Setup (pinBase, spi) ;
545
546   return TRUE ;
547 }
548
549
550 /*
551  * doExtensionMcp3004:
552  *      Analog IO
553  *      mcp3004:base:spiChan
554  *********************************************************************************
555  */
556
557 static int doExtensionMcp3004 (char *progName, int pinBase, char *params)
558 {
559   int spi ;
560
561   if ((params = extractInt (progName, params, &spi)) == NULL)
562     return FALSE ;
563
564   if ((spi < 0) || (spi > 1))
565   {
566     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
567     return FALSE ;
568   }
569
570   mcp3004Setup (pinBase, spi) ;
571
572   return TRUE ;
573 }
574
575
576 /*
577  * doExtensionMax5322:
578  *      Analog O
579  *      max5322:base:spiChan
580  *********************************************************************************
581  */
582
583 static int doExtensionMax5322 (char *progName, int pinBase, char *params)
584 {
585   int spi ;
586
587   if ((params = extractInt (progName, params, &spi)) == NULL)
588     return FALSE ;
589
590   if ((spi < 0) || (spi > 1))
591   {
592     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
593     return FALSE ;
594   }
595
596   max5322Setup (pinBase, spi) ;
597
598   return TRUE ;
599 }
600
601
602 /*
603  * doExtensionMcp4802:
604  *      Analog IO
605  *      mcp4802:base:spiChan
606  *********************************************************************************
607  */
608
609 static int doExtensionMcp4802 (char *progName, int pinBase, char *params)
610 {
611   int spi ;
612
613   if ((params = extractInt (progName, params, &spi)) == NULL)
614     return FALSE ;
615
616   if ((spi < 0) || (spi > 1))
617   {
618     verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
619     return FALSE ;
620   }
621
622   mcp4802Setup (pinBase, spi) ;
623
624   return TRUE ;
625 }
626
627
628 /*
629  * doExtensionSn3218:
630  *      Analog Output (LED Driver)
631  *      sn3218:base
632  *********************************************************************************
633  */
634
635 static int doExtensionSn3218 (UNU char *progName, int pinBase, UNU char *params)
636 {
637   sn3218Setup (pinBase) ;
638   return TRUE ;
639 }
640
641
642 /*
643  * doExtensionMcp3422:
644  *      Analog IO
645  *      mcp3422:base:i2cAddr
646  *********************************************************************************
647  */
648
649 static int doExtensionMcp3422 (char *progName, int pinBase, char *params)
650 {
651   int i2c, sampleRate, gain ;
652
653   if ((params = extractInt (progName, params, &i2c)) == NULL)
654     return FALSE ;
655
656   if ((i2c < 0x03) || (i2c > 0x77))
657   {
658     verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
659     return FALSE ;
660   }
661
662   if ((params = extractInt (progName, params, &sampleRate)) == NULL)
663     return FALSE ;
664
665   if ((sampleRate < 0) || (sampleRate > 3))
666   {
667     verbError ("%s: sample rate (%d) out of range", progName, sampleRate) ;
668     return FALSE ;
669   }
670
671   if ((params = extractInt (progName, params, &gain)) == NULL)
672     return FALSE ;
673
674   if ((gain < 0) || (gain > 3))
675   {
676     verbError ("%s: gain (%d) out of range", progName, gain) ;
677     return FALSE ;
678   }
679
680   mcp3422Setup (pinBase, i2c, sampleRate, gain) ;
681
682   return TRUE ;
683 }
684
685
686 /*
687  * doExtensionDrcS:
688  *      Interface to a DRC Serial system
689  *      drcs:base:pins:serialPort:baud
690  *********************************************************************************
691  */
692
693 static int doExtensionDrcS (char *progName, int pinBase, char *params)
694 {
695   char *port ;
696   int pins, baud ;
697
698   if ((params = extractInt (progName, params, &pins)) == NULL)
699     return FALSE ;
700
701   if ((pins < 1) || (pins > 100))
702   {
703     verbError ("%s: pins (%d) out of range (2-100)", progName, pins) ;
704     return FALSE ;
705   }
706   
707   if ((params = extractStr (progName, params, &port)) == NULL)
708     return FALSE ;
709
710   if (strlen (port) == 0)
711   {
712     verbError ("%s: serial port device name required", progName) ;
713     return FALSE ;
714   }
715
716   if ((params = extractInt (progName, params, &baud)) == NULL)
717     return FALSE ;
718
719   if ((baud < 1) || (baud > 4000000))
720   {
721     verbError ("%s: baud rate (%d) out of range", progName, baud) ;
722     return FALSE ;
723   }
724
725   drcSetupSerial (pinBase, pins, port, baud) ;
726
727   return TRUE ;
728 }
729
730
731
732 /*
733  * Function list
734  *********************************************************************************
735  */
736
737 static struct extensionFunctionStruct extensionFunctions [] = 
738 {
739   { "mcp23008",         &doExtensionMcp23008    },
740   { "mcp23016",         &doExtensionMcp23016    },
741   { "mcp23017",         &doExtensionMcp23017    },
742   { "mcp23s08",         &doExtensionMcp23s08    },
743   { "mcp23s17",         &doExtensionMcp23s17    },
744   { "sr595",            &doExtensionSr595       },
745   { "pcf8574",          &doExtensionPcf8574     },
746   { "pcf8591",          &doExtensionPcf8591     },
747   { "bmp180",           &doExtensionBmp180      },
748   { "pseudoPins",       &doExtensionPseudoPins  },
749   { "htu21d",           &doExtensionHtu21d      },
750   { "ds18b20",          &doExtensionDs18b20     },
751   { "mcp3002",          &doExtensionMcp3002     },
752   { "mcp3004",          &doExtensionMcp3004     },
753   { "mcp4802",          &doExtensionMcp4802     },
754   { "mcp3422",          &doExtensionMcp3422     },
755   { "max31855",         &doExtensionMax31855    },
756   { "ads1115",          &doExtensionAds1115     },
757   { "max5322",          &doExtensionMax5322     },
758   { "sn3218",           &doExtensionSn3218      },
759   { "drcs",             &doExtensionDrcS        },
760   { NULL,               NULL                    },
761 } ;
762
763
764 /*
765  * loadWPiExtension:
766  *      Load in a wiringPi extension
767  *      The extensionData always starts with the name, a colon then the pinBase
768  *      number. Other parameters after that are decoded by the module in question.
769  *********************************************************************************
770  */
771
772 int loadWPiExtension (char *progName, char *extensionData, int printErrors)
773 {
774   char *p ;
775   char *extension = extensionData ;
776   struct extensionFunctionStruct *extensionFn ;
777   unsigned pinBase = 0 ;
778
779   verbose = printErrors ;
780
781 // Get the extension name by finding the first colon
782
783   p = extension ;
784   while (*p != ':')
785   {
786     if (!*p)    // ran out of characters
787     {
788       verbError ("%s: extension name not terminated by a colon", progName) ;
789       return FALSE ;
790     }
791     ++p ;
792   }
793   *p++ = 0 ;
794
795 // Simple ATOI code
796
797   if (!isdigit (*p))
798   {
799     verbError ("%s: decimal pinBase number expected after extension name", progName) ;
800     return FALSE ;
801   }
802
803   while (isdigit (*p))
804   {
805     if (pinBase > 2147483647) // 2^31-1 ... Lets be realistic here...
806     {
807       verbError ("%s: pinBase too large", progName) ;
808       return FALSE ;
809     }
810
811     pinBase = pinBase * 10 + (*p - '0') ;
812     ++p ;
813   }
814
815   if (pinBase < 64)
816   {
817     verbError ("%s: pinBase (%d) too small. Minimum is 64.", progName, pinBase) ;
818     return FALSE ;
819   }
820
821 // Search for extensions:
822
823   for (extensionFn = extensionFunctions ; extensionFn->name != NULL ; ++extensionFn)
824   {
825     if (strcmp (extensionFn->name, extension) == 0)
826       return extensionFn->function (progName, pinBase, p) ;
827   }
828
829   verbError ("%s: extension %s not found", progName, extension) ;
830   return FALSE ;
831 }