Gordons Projects

--> Projects Top-Level GIT

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