Gordons Projects

--> Projects Top-Level GIT

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