From 70fa99a127ff150ee2b0975afe5be9547ddb44e3 Mon Sep 17 00:00:00 2001 From: Gordon Henderson Date: Mon, 27 Feb 2017 19:51:32 +0000 Subject: [PATCH] Bumped the version to 2.40 - correctly this time, I hope. Added fixed for a few minor things. pin driver for rht03/dht type sensors. Network stuff is experimental - for now. --- VERSION | 2 +- build | 8 + debian-template/wiringPi/DEBIAN/control | 2 +- examples/Makefile | 2 +- examples/blink8-drcn.c | 61 ++++ gpio/Makefile | 2 +- gpio/gpio.1 | 28 +- gpio/gpio.c | 17 +- version.h | 4 +- wiringPi/Makefile | 4 +- wiringPi/drcNet.c | 405 ++++++++++++++++++++++++ wiringPi/drcNet.h | 42 +++ wiringPi/rht03.c | 126 ++++++++ wiringPi/rht03.h | 25 ++ wiringPi/softPwm.c | 51 +-- wiringPi/wiringPi.c | 87 +++-- wiringPi/wiringPi.h | 46 ++- wiringPi/wpiExtensions.c | 111 ++++++- wiringPiD/Makefile | 100 ++++++ wiringPiD/daemonise.c | 82 +++++ wiringPiD/daemonise.h | 9 + wiringPiD/drcNetCmd.h | 44 +++ wiringPiD/network.c | 330 +++++++++++++++++++ wiringPiD/network.h | 31 ++ wiringPiD/runRemote.c | 126 ++++++++ wiringPiD/runRemote.h | 29 ++ wiringPiD/wiringpid | Bin 0 -> 18721 bytes wiringPiD/wiringpid.c | 382 ++++++++++++++++++++++ 28 files changed, 2069 insertions(+), 87 deletions(-) create mode 100644 examples/blink8-drcn.c create mode 100644 wiringPi/drcNet.c create mode 100644 wiringPi/drcNet.h create mode 100644 wiringPi/rht03.c create mode 100644 wiringPi/rht03.h create mode 100644 wiringPiD/Makefile create mode 100644 wiringPiD/daemonise.c create mode 100644 wiringPiD/daemonise.h create mode 100644 wiringPiD/drcNetCmd.h create mode 100644 wiringPiD/network.c create mode 100644 wiringPiD/network.h create mode 100644 wiringPiD/runRemote.c create mode 100644 wiringPiD/runRemote.h create mode 100755 wiringPiD/wiringpid create mode 100644 wiringPiD/wiringpid.c diff --git a/VERSION b/VERSION index 23f3620..4bdd32f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.39 +2.40 diff --git a/build b/build index b42a25a..070ea3f 100755 --- a/build +++ b/build @@ -160,6 +160,14 @@ fi $sudo make install check_make_ok + echo + echo "wiringPi Daemon" + cd ../wiringPiD + make -j5 + check_make_ok + $sudo make install + check_make_ok + # echo # echo "Examples" # cd ../examples diff --git a/debian-template/wiringPi/DEBIAN/control b/debian-template/wiringPi/DEBIAN/control index 80cd3f8..75cedfa 100644 --- a/debian-template/wiringPi/DEBIAN/control +++ b/debian-template/wiringPi/DEBIAN/control @@ -1,5 +1,5 @@ Package: wiringpi -Version: 2.38 +Version: 2.40 Section: libraries Priority: optional Architecture: armhf diff --git a/examples/Makefile b/examples/Makefile index d6195b3..4725d85 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -33,7 +33,7 @@ INCLUDE = -I/usr/local/include CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe LDFLAGS = -L/usr/local/lib -LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm +LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt # Should not alter anything below this line ############################################################################### diff --git a/examples/blink8-drcn.c b/examples/blink8-drcn.c new file mode 100644 index 0000000..96c775b --- /dev/null +++ b/examples/blink8-drcn.c @@ -0,0 +1,61 @@ +/* + * blink8-drcn.c: + * Simple sequence over the first 8 GPIO pins - LEDs + * Aimed at the Ladder board, but it's fairly generic. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +int main (void) +{ + int i, led ; + + printf ("Raspberry Pi - 8-LED Sequencer\n") ; + printf ("==============================\n") ; + printf ("\n") ; + printf ("Connect LEDs to the first 8 GPIO pins and watch ...\n") ; + + int pinBase = 100 ; + +// wiringPiSetup () ; + drcSetupNet (pinBase, 100, "192.168.254.21", "6124", "123456") ; + + for (i = 0 ; i < 8 ; ++i) + pinMode (i + pinBase, OUTPUT) ; + + for (;;) + { + for (led = 0 ; led < 8 ; ++led) + { + digitalWrite (led + pinBase, 1) ; + delay (10) ; + } + + for (led = 0 ; led < 8 ; ++led) + { + digitalWrite (led + pinBase, 0) ; + delay (10) ; + } + } +} diff --git a/gpio/Makefile b/gpio/Makefile index 9152ea8..f41a005 100644 --- a/gpio/Makefile +++ b/gpio/Makefile @@ -37,7 +37,7 @@ INCLUDE = -I$(DESTDIR)$(PREFIX)/include CFLAGS = $(DEBUG) -Wall -Wextra $(INCLUDE) -Winline -pipe LDFLAGS = -L$(DESTDIR)$(PREFIX)/lib -LIBS = -lwiringPi -lwiringPiDev -lpthread -lrt -lm +LIBS = -lwiringPi -lwiringPiDev -lpthread -lrt -lm -lcrypt # May not need to alter anything below this line ############################################################################### diff --git a/gpio/gpio.1 b/gpio/gpio.1 index e5fe181..e5490d6 100644 --- a/gpio/gpio.1 +++ b/gpio/gpio.1 @@ -9,15 +9,15 @@ gpio \- Command-line access to Raspberry Pi's GPIO .PP .B gpio .B [ \-g | \-1 ] -.B mode/read/write/aread/awrite/wb/pwm/clock ... +.B mode/read/write/aread/awrite/wb/pwm/clock/toggle/blink ... .PP .B gpio .B [ \-x extension:params ] -.B mode/read/write/aread/awrite/pwm/pwmTone ... +.B mode/read/write/aread/awrite/pwm/toggle/blink ... .PP .B gpio .B [ \-p ] -.B read/write/toggle/wb +.B read/write/toggle/blink .B ... .PP .B gpio @@ -118,11 +118,23 @@ respective logic levels. Write the given value (0 or 1) to the pin. You need to set the pin to output mode first. +.TP +.B toggle +Changes the state of a GPIO pin; 0 to 1, or 1 to 0. + +Note unlike the blink command, the pin must be in output mode first. + +.TP +.B blink +Blinks the given pin on/off. Press Control-C to exit. + +Note: This command explicitly sets the pin to output mode. + .TP .B aread -Read the analog value of the given pin. This needs to be uses in +Read the analog value of the given pin. This needs to be used in conjunction with a -x flag to add in an extension that handles analog -inputs. respective logic levels. +inputs. e.g. gpio -x mcp3002:200:0 aread 200 @@ -132,7 +144,7 @@ will read the first analog input on an mcp3002 SPI ADC chip. .B awrite Write the analog value to the given pin. This needs to be used in conjunction with a -x flag to add in an extension that handles analog -inputs. respective logic levels. +inputs. e.g. gpio -x mcp4802:200:0 awrite 200 128 @@ -234,7 +246,7 @@ absolutely sure you know what you're doing. high | low Change the USB current limiter to high (1.2 amps) or low (the default, 600mA) -This is only applicable to the model B+ +This is only applicable to the Model B+ and the Model B, v2. .TP .B pwm-bal/pwm-ms @@ -253,7 +265,6 @@ them. Optionally it will set the I2C baudrate to that supplied in Kb/sec Note: On recent kernels with the device tree enabled you should use the raspi-config program to load/unload the I2C device at boot time. -(or disable the device tree to continue to use this method) .TP .B load spi @@ -268,7 +279,6 @@ e.g. 8192 bytes then reboot. Note: On recent kernels with the device tree enabled you should use the raspi-config program to load/unload the SPI device at boot time. -(or disable the device tree to continue to use this method) .TP .B gbr diff --git a/gpio/gpio.c b/gpio/gpio.c index 3327308..6fd71f8 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -1443,6 +1443,16 @@ int main (int argc, char *argv []) wpMode = WPI_MODE_PIFACE ; } +// Check for -z argument so we don't actually initialise wiringPi + + else if (strcasecmp (argv [1], "-z") == 0) + { + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + wpMode = WPI_MODE_UNINITIALISED ; + } + // Default to wiringPi mode else @@ -1460,12 +1470,15 @@ int main (int argc, char *argv []) { if (argc < 3) { - fprintf (stderr, "%s: -x missing extension specification.\n", argv [0]) ; + fprintf (stderr, "%s: -x missing extension command.\n", argv [0]) ; exit (EXIT_FAILURE) ; } - if (!loadWPiExtension (argv [0], argv [2], TRUE)) // Prints its own error messages + if (!loadWPiExtension (argv [0], argv [2], TRUE)) + { + fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ; exit (EXIT_FAILURE) ; + } // Shift args down by 2 diff --git a/version.h b/version.h index fde08f3..2c359b6 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "2.38" +#define VERSION "2.40" #define VERSION_MAJOR 2 -#define VERSION_MINOR 38 +#define VERSION_MINOR 40 diff --git a/wiringPi/Makefile b/wiringPi/Makefile index 13d006f..0a1283f 100644 --- a/wiringPi/Makefile +++ b/wiringPi/Makefile @@ -57,8 +57,8 @@ SRC = wiringPi.c \ mcp3002.c mcp3004.c mcp4802.c mcp3422.c \ max31855.c max5322.c ads1115.c \ sn3218.c \ - bmp180.c htu21d.c ds18b20.c \ - drcSerial.c \ + bmp180.c htu21d.c ds18b20.c rht03.c \ + drcSerial.c drcNet.c \ pseudoPins.c \ wpiExtensions.c diff --git a/wiringPi/drcNet.c b/wiringPi/drcNet.c new file mode 100644 index 0000000..0964ff7 --- /dev/null +++ b/wiringPi/drcNet.c @@ -0,0 +1,405 @@ +/* + * drcNet.h: + * Extend wiringPi with the DRC Network protocol (e.g. to another Pi) + * Copyright (c) 2016-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "wiringPi.h" +#include "drcNet.h" +#include "../wiringPiD/drcNetCmd.h" + + +/* + * remoteReadline: + * Read in a line of data from the remote server, ending with a newline + * character which is not stored. Returns the length or < 0 on + * any sort of failure. + ********************************************************************************* + */ + +static int remoteReadline (int fd, char *buf, int max) +{ + int len = 0 ; + char c ; + + for (;;) + { + if (read (fd, &c, 1) < 1) + return -1 ; + + if (c == '\n') + return len ; + + *buf++ = c ; + if (++len == max) + return len ; + } +} + + +/* + * getChallenge: + * Read in lines from the remote site until we get one identified + * as the challenge. This line contains the password salt. + ********************************************************************************* + */ + +static char *getChallenge (int fd) +{ + static char buf [1024] ; + int num ; + + for (;;) + { + if ((num = remoteReadline (fd, buf, 1023)) < 0) + return NULL ; + buf [num] = 0 ; + + if (strncmp (buf, "Challenge ", 10) == 0) + return &buf [10] ; + } +} + + +/* + * authenticate: + * Read in the challenge from the server, use it to encrypt our password + * and send it back to the server. Wait for a reply back from the server + * to say that we're good to go. + * The server will simply disconnect on a bad response. No 3 chances here. + ********************************************************************************* + */ + +static int authenticate (int fd, const char *pass) +{ + char *challenge ; + char *encrypted ; + char salted [1024] ; + + if ((challenge = getChallenge (fd)) == NULL) + return -1 ; + + sprintf (salted, "$6$%s$", challenge) ; + encrypted = crypt (pass, salted) ; + +// This is an assertion, or sanity check on my part... +// The '20' comes from the $6$ then the 16 characters of the salt, +// then the terminating $. + + if (strncmp (encrypted, salted, 20) != 0) + { + errno = EBADE ; + return -1 ; + } + +// 86 characters is the length of the SHA-256 hash + + if (write (fd, encrypted + 20, 86) == 86) + return 0 ; + else + return -1 ; +} + + +/* + * _drcSetupNet: + * Do the hard work of establishing a network connection and authenticating + * the password. + ********************************************************************************* + */ + +int _drcSetupNet (const char *ipAddress, const char *port, const char *password) +{ + struct addrinfo hints; + struct addrinfo *result, *rp ; + struct in6_addr serveraddr ; + int remoteFd ; + +// Start by seeing if we've been given a (textual) numeric IP address +// which will save lookups in getaddrinfo() + + memset (&hints, 0, sizeof (hints)) ; + hints.ai_flags = AI_NUMERICSERV ; + hints.ai_family = AF_UNSPEC ; + hints.ai_socktype = SOCK_STREAM ; + hints.ai_protocol = 0 ; + + if (inet_pton (AF_INET, ipAddress, &serveraddr) == 1) // Valid IPv4 + { + hints.ai_family = AF_INET ; + hints.ai_flags |= AI_NUMERICHOST ; + } + else + { + if (inet_pton (AF_INET6, ipAddress, &serveraddr) == 1) // Valid IPv6 + { + hints.ai_family = AF_INET6 ; + hints.ai_flags |= AI_NUMERICHOST ; + } + } + +// Now use getaddrinfo() with the newly supplied hints + + if (getaddrinfo (ipAddress, port, &hints, &result) != 0) + return -1 ; + +// Now try each address in-turn until we get one that connects... + + for (rp = result; rp != NULL; rp = rp->ai_next) + { + if ((remoteFd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0) + continue ; + + if (connect (remoteFd, rp->ai_addr, rp->ai_addrlen) < 0) + continue ; + + if (authenticate (remoteFd, password) < 0) + { + close (remoteFd) ; + errno = EACCES ; // Permission denied + return -1 ; + } + else + return remoteFd ; + } + + errno = EHOSTUNREACH ; // Host unreachable - may not be right, but good enough + return -1 ; // Nothing connected +} + + +/* + * myPinMode: + * Change the pin mode on the remote DRC device + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_PIN_MODE ; + cmd.data = mode ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myPullUpDnControl: + ********************************************************************************* + */ + +static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_PULL_UP_DN ; + cmd.data = mode ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_DIGITAL_WRITE ; + cmd.data = value ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myDigitalWrite8: + ********************************************************************************* + +static void myDigitalWrite8 (struct wiringPiNodeStruct *node, int pin, int value) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_DIGITAL_WRITE8 ; + cmd.data = value ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + */ + + +/* + * myAnalogWrite: + ********************************************************************************* + */ + +static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_ANALOG_WRITE ; + cmd.data = value ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myPwmWrite: + ********************************************************************************* + */ + +static void myPwmWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_PWM_WRITE ; + cmd.data = value ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_ANALOG_READ ; + cmd.data = 0 ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; + + return cmd.data ; +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_DIGITAL_READ ; + cmd.data = 0 ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; + + return cmd.data ; +} + + +/* + * myDigitalRead8: + ********************************************************************************* + +static unsigned int myDigitalRead8 (struct wiringPiNodeStruct *node, int pin) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_DIGITAL_READ8 ; + cmd.data = 0 ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; + + return cmd.data ; +} + */ + + +/* + * drcNet: + * Create a new instance of an DRC GPIO interface. + * Could be a variable nunber of pins here - we might not know in advance. + ********************************************************************************* + */ + +int drcSetupNet (const int pinBase, const int numPins, const char *ipAddress, const char *port, const char *password) +{ + int fd, len ; + struct wiringPiNodeStruct *node ; + + if ((fd = _drcSetupNet (ipAddress, port, password)) < 0) + return FALSE ; + + len = sizeof (struct drcNetComStruct) ; + + if (setsockopt (fd, SOL_SOCKET, SO_RCVLOWAT, (void *)&len, sizeof (len)) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, numPins) ; + + node->fd = fd ; + node->pinMode = myPinMode ; + node->pullUpDnControl = myPullUpDnControl ; + node->analogRead = myAnalogRead ; + node->analogRead = myAnalogRead ; + node->analogWrite = myAnalogWrite ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; +//node->digitalRead8 = myDigitalRead8 ; +//node->digitalWrite8 = myDigitalWrite8 ; + node->pwmWrite = myPwmWrite ; + + return TRUE ; +} diff --git a/wiringPi/drcNet.h b/wiringPi/drcNet.h new file mode 100644 index 0000000..00f9b05 --- /dev/null +++ b/wiringPi/drcNet.h @@ -0,0 +1,42 @@ +/* + * drcNet.h: + * Extend wiringPi with the DRC Network protocol (e.g. to another Pi) + * Copyright (c) 2016-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +/********* +struct drcNetStruct +{ + uint32_t pin ; + uint32_t cmd ; + uint32_t data ; +} ; +**************/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int drcSetupNet (const int pinBase, const int numPins, const char *ipAddress, const char *port, const char *password) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/rht03.c b/wiringPi/rht03.c new file mode 100644 index 0000000..9fa5702 --- /dev/null +++ b/wiringPi/rht03.c @@ -0,0 +1,126 @@ +/* + * rht03.c: + * Extend wiringPi with the rht03 Maxdetect 1-Wire sensor. + * Copyright (c) 2016-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +//#include +//#include +//#include + +//#include +//#include +#include +//#include +#include +//#include + +#include "wiringPi.h" +#include "../devLib/maxdetect.h" + +#include "rht03.h" + + +/* + * myReadRHT03: + * Read the Temperature & Humidity from an RHT03 sensor + * Values returned are *10, so 123 is 12.3. + ********************************************************************************* + */ + +static int myReadRHT03 (const int pin, int *temp, int *rh) +{ + int result ; + unsigned char buffer [4] ; + +// Read ... + + result = maxDetectRead (pin, buffer) ; + + if (!result) + return FALSE ; + + *rh = (buffer [0] * 256 + buffer [1]) ; + *temp = (buffer [2] * 256 + buffer [3]) ; + + if ((*temp & 0x8000) != 0) // Negative + { + *temp &= 0x7FFF ; + *temp = -*temp ; + } + +// Discard obviously bogus readings - the checksum can't detect a 2-bit error +// (which does seem to happen - no realtime here) + + if ((*rh > 999) || (*temp > 800) || (*temp < -400)) + return FALSE ; + + return TRUE ; +} + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int piPin = node->fd ; + int chan = pin - node->pinBase ; + int temp = -9997 ; + int rh = -9997 ; + int try ; + + if (chan > 1) + return -9999 ; // Bad parameters + + for (try = 0 ; try < 10 ; ++try) + { + if (myReadRHT03 (piPin, &temp, &rh)) + return chan == 0 ? temp : rh ; + } + + return -9998 ; +} + + +/* + * rht03Setup: + * Create a new instance of an RHT03 temperature sensor. + ********************************************************************************* + */ + +int rht03Setup (const int pinBase, const int piPin) +{ + struct wiringPiNodeStruct *node ; + + if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin + return FALSE ; + +// 2 pins - temperature and humidity + + node = wiringPiNewNode (pinBase, 2) ; + + node->fd = piPin ; + node->analogRead = myAnalogRead ; + + return TRUE ; +} diff --git a/wiringPi/rht03.h b/wiringPi/rht03.h new file mode 100644 index 0000000..9523fbf --- /dev/null +++ b/wiringPi/rht03.h @@ -0,0 +1,25 @@ +/* + * rht03.h: + * Extend wiringPi with the rht03 Maxdetect 1-Wire sensor. + * Copyright (c) 2016-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +extern int rht03Setup (const int pinBase, const int devicePin) ; diff --git a/wiringPi/softPwm.c b/wiringPi/softPwm.c index 5999cc0..d99fa00 100644 --- a/wiringPi/softPwm.c +++ b/wiringPi/softPwm.c @@ -1,7 +1,7 @@ /* * softPwm.c: - * Provide 2 channels of software driven PWM. - * Copyright (c) 2012-2014 Gordon Henderson + * Provide many channels of software driven PWM. + * Copyright (c) 2012-2017 Gordon Henderson *********************************************************************** * This file is part of wiringPi: * https://projects.drogon.net/raspberry-pi/wiringpi/ @@ -30,11 +30,11 @@ #include "softPwm.h" // MAX_PINS: -// This is more than the number of Pi pins because we can actually softPwm -// pins that are on GPIO expanders. It's not that efficient and more than 1 or -// 2 pins on e.g. (SPI) mcp23s17 won't really be that effective, however... +// This is more than the number of Pi pins because we can actually softPwm. +// Once upon a time I let pins on gpio expanders be softPwm'd, but it's really +// really not a good thing. -#define MAX_PINS 1024 +#define MAX_PINS 64 // The PWM Frequency is derived from the "pulse time" below. Essentially, // the frequency is a function of the range and this pulse time. @@ -45,7 +45,7 @@ // It's possible to get a higher frequency by lowering the pulse time, // however CPU uage will skyrocket as wiringPi uses a hard-loop to time // periods under 100µS - this is because the Linux timer calls are just -// accurate at all, and have an overhead. +// not accurate at all, and have an overhead. // // Another way to increase the frequency is to reduce the range - however // that reduces the overall output accuracy... @@ -106,14 +106,15 @@ static void *softPwmThread (void *arg) void softPwmWrite (int pin, int value) { - pin &= (MAX_PINS - 1) ; + if (pin < MAX_PINS) + { + /**/ if (value < 0) + value = 0 ; + else if (value > range [pin]) + value = range [pin] ; - /**/ if (value < 0) - value = 0 ; - else if (value > range [pin]) - value = range [pin] ; - - marks [pin] = value ; + marks [pin] = value ; + } } @@ -129,6 +130,9 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) pthread_t myThread ; int *passPin ; + if (pin >= MAX_PINS) + return -1 ; + if (range [pin] != 0) // Already running on this pin return -1 ; @@ -139,15 +143,15 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) if (passPin == NULL) return -1 ; - pinMode (pin, OUTPUT) ; digitalWrite (pin, LOW) ; + pinMode (pin, OUTPUT) ; marks [pin] = initialValue ; range [pin] = pwmRange ; *passPin = pin ; - newPin = pin ; - res = pthread_create (&myThread, NULL, softPwmThread, (void *)passPin) ; + newPin = pin ; + res = pthread_create (&myThread, NULL, softPwmThread, (void *)passPin) ; while (newPin != -1) delay (1) ; @@ -166,11 +170,14 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) void softPwmStop (int pin) { - if (range [pin] != 0) + if (pin < MAX_PINS) { - pthread_cancel (threads [pin]) ; - pthread_join (threads [pin], NULL) ; - range [pin] = 0 ; - digitalWrite (pin, LOW) ; + if (range [pin] != 0) + { + pthread_cancel (threads [pin]) ; + pthread_join (threads [pin], NULL) ; + range [pin] = 0 ; + digitalWrite (pin, LOW) ; + } } } diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index ba86f41..e018100 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -84,10 +84,8 @@ #define ENV_GPIOMEM "WIRINGPI_GPIOMEM" -// Mask for the bottom 64 pins which belong to the Raspberry Pi -// The others are available for the other devices - -#define PI_GPIO_MASK (0xFFFFFFC0) +// Extend wiringPi with other pin-based devices and keep track of +// them in this structure struct wiringPiNodeStruct *wiringPiNodes = NULL ; @@ -1244,13 +1242,15 @@ struct wiringPiNodeStruct *wiringPiFindNode (int pin) ********************************************************************************* */ -static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { return ; } -static void pullUpDnControlDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) { return ; } -static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return LOW ; } -static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } -static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } -static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) { return 0 ; } -static void analogWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { return ; } +static void pullUpDnControlDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) { return ; } +static unsigned int digitalRead8Dummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return 0 ; } +static void digitalWrite8Dummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return LOW ; } +static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) { return 0 ; } +static void analogWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) { @@ -1272,17 +1272,19 @@ struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) if (node == NULL) (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ; - node->pinBase = pinBase ; - node->pinMax = pinBase + numPins - 1 ; - node->pinMode = pinModeDummy ; - node->pullUpDnControl = pullUpDnControlDummy ; - node->digitalRead = digitalReadDummy ; - node->digitalWrite = digitalWriteDummy ; - node->pwmWrite = pwmWriteDummy ; - node->analogRead = analogReadDummy ; - node->analogWrite = analogWriteDummy ; - node->next = wiringPiNodes ; - wiringPiNodes = node ; + node->pinBase = pinBase ; + node->pinMax = pinBase + numPins - 1 ; + node->pinMode = pinModeDummy ; + node->pullUpDnControl = pullUpDnControlDummy ; + node->digitalRead = digitalReadDummy ; +//node->digitalRead8 = digitalRead8Dummy ; + node->digitalWrite = digitalWriteDummy ; +//node->digitalWrite8 = digitalWrite8Dummy ; + node->pwmWrite = pwmWriteDummy ; + node->analogRead = analogReadDummy ; + node->analogWrite = analogWriteDummy ; + node->next = wiringPiNodes ; + wiringPiNodes = node ; return node ; } @@ -1492,6 +1494,27 @@ int digitalRead (int pin) } +/* + * digitalRead8: + * Read 8-bits (a byte) from given start pin. + ********************************************************************************* + +unsigned int digitalRead8 (int pin) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + return 0 ; + else + { + if ((node = wiringPiFindNode (pin)) == NULL) + return LOW ; + return node->digitalRead8 (node, pin) ; + } +} + */ + + /* * digitalWrite: * Set an output bit @@ -1535,6 +1558,26 @@ void digitalWrite (int pin, int value) } +/* + * digitalWrite8: + * Set an output 8-bit byte on the device from the given pin number + ********************************************************************************* + +void digitalWrite8 (int pin, int value) +{ + struct wiringPiNodeStruct *node = wiringPiNodes ; + + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + return ; + else + { + if ((node = wiringPiFindNode (pin)) != NULL) + node->digitalWrite8 (node, pin, value) ; + } +} + */ + + /* * pwmWrite: * Set an output PWM value diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 1b50470..0788bf2 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -26,6 +26,7 @@ // C doesn't have true/false by default and I can never remember which // way round they are, so ... +// (and yes, I know about stdbool.h but I like capitals for these and I'm old) #ifndef TRUE # define TRUE (1==1) @@ -36,6 +37,11 @@ #define UNU __attribute__((unused)) +// Mask for the bottom 64 pins which belong to the Raspberry Pi +// The others are available for the other devices + +#define PI_GPIO_MASK (0xFFFFFFC0) + // Handy defines // wiringPi modes @@ -140,13 +146,15 @@ struct wiringPiNodeStruct unsigned int data2 ; // ditto unsigned int data3 ; // ditto - void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ; - void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ; - int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ; - void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; - void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; - int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ; - void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; + void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ; + void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ; + int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ; +//unsigned int (*digitalRead8) (struct wiringPiNodeStruct *node, int pin) ; + void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; +// void (*digitalWrite8) (struct wiringPiNodeStruct *node, int pin, int value) ; + void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; + int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ; + void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; struct wiringPiNodeStruct *next ; } ; @@ -179,14 +187,16 @@ extern int wiringPiSetupSys (void) ; extern int wiringPiSetupGpio (void) ; extern int wiringPiSetupPhys (void) ; -extern void pinModeAlt (int pin, int mode) ; -extern void pinMode (int pin, int mode) ; -extern void pullUpDnControl (int pin, int pud) ; -extern int digitalRead (int pin) ; -extern void digitalWrite (int pin, int value) ; -extern void pwmWrite (int pin, int value) ; -extern int analogRead (int pin) ; -extern void analogWrite (int pin, int value) ; +extern void pinModeAlt (int pin, int mode) ; +extern void pinMode (int pin, int mode) ; +extern void pullUpDnControl (int pin, int pud) ; +extern int digitalRead (int pin) ; +extern void digitalWrite (int pin, int value) ; +extern unsigned int digitalRead8 (int pin) ; +extern void digitalWrite8 (int pin, int value) ; +extern void pwmWrite (int pin, int value) ; +extern int analogRead (int pin) ; +extern void analogWrite (int pin, int value) ; // PiFace specifics // (Deprecated) @@ -204,12 +214,14 @@ extern int physPinToGpio (int physPin) ; extern void setPadDrive (int group, int value) ; extern int getAlt (int pin) ; extern void pwmToneWrite (int pin, int freq) ; -extern void digitalWriteByte (int value) ; -extern unsigned int digitalReadByte (void) ; extern void pwmSetMode (int mode) ; extern void pwmSetRange (unsigned int range) ; extern void pwmSetClock (int divisor) ; extern void gpioClockSet (int pin, int freq) ; +extern unsigned int digitalReadByte (void) ; +extern unsigned int digitalReadByte2 (void) ; +extern void digitalWriteByte (int value) ; +extern void digitalWriteByte2 (int value) ; // Interrupts // (Also Pi hardware specific) diff --git a/wiringPi/wpiExtensions.c b/wiringPi/wpiExtensions.c index 2761945..53fafc0 100644 --- a/wiringPi/wpiExtensions.c +++ b/wiringPi/wpiExtensions.c @@ -55,10 +55,13 @@ #include "ads1115.h" #include "sn3218.h" #include "drcSerial.h" +#include "drcNet.h" +#include "../wiringPiD/drcNetCmd.h" #include "pseudoPins.h" #include "bmp180.h" #include "htu21d.h" #include "ds18b20.h" +#include "rht03.h" #include "wpiExtensions.h" @@ -134,12 +137,16 @@ static char *extractInt (char *progName, char *p, int *num) /* * extractStr: * Check & return a string at the given location (prefixed by a :) + * Note: The string can be enclosed in []'s to escape colons. This is + * so we can handle IPv6 addresses which contain colons and the []'s is + * a common way to prepresent them. ********************************************************************************* */ static char *extractStr (char *progName, char *p, char **str) { char *q, *r ; + int quoted = FALSE ; if (*p != ':') { @@ -149,21 +156,38 @@ static char *extractStr (char *progName, char *p, char **str) ++p ; - if (!isprint (*p)) + if (*p == '[') + { + quoted = TRUE ; + ++p ; + } + + if (!isprint (*p)) // Is this needed? { verbError ("%s: character expected", progName) ; return NULL ; } q = p ; - while ((*q != 0) && (*q != ':')) - ++q ; + if (quoted) + { + while ((*q != 0) && (*q != ']')) + ++q ; + } + else + { + while ((*q != 0) && (*q != ':')) + ++q ; + } *str = r = calloc (q - p + 2, 1) ; // Zeros it while (p != q) *r++ = *p++ ; - + + if (quoted) // Skip over the ] to the : + ++p ; + return p ; } @@ -495,6 +519,24 @@ static int doExtensionDs18b20 (char *progName, int pinBase, char *params) } +/* + * doExtensionRht03: + * Maxdetect 1-Wire Temperature & Humidity + * rht03:base:piPin + ********************************************************************************* + */ + +static int doExtensionRht03 (char *progName, int pinBase, char *params) +{ + int piPin ; + + if ((params = extractInt (progName, params, &piPin)) == NULL) + return FALSE ; + + return rht03Setup (pinBase, piPin) ; +} + + /* * doExtensionMax31855: * Analog IO @@ -698,9 +740,9 @@ static int doExtensionDrcS (char *progName, int pinBase, char *params) if ((params = extractInt (progName, params, &pins)) == NULL) return FALSE ; - if ((pins < 1) || (pins > 100)) + if ((pins < 1) || (pins > 1000)) { - verbError ("%s: pins (%d) out of range (2-100)", progName, pins) ; + verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ; return FALSE ; } @@ -728,6 +770,59 @@ static int doExtensionDrcS (char *progName, int pinBase, char *params) } +/* + * doExtensionDrcNet: + * Interface to a DRC Network system + * drcn:base:pins:ipAddress:port:password + ********************************************************************************* + */ + +static int doExtensionDrcNet (char *progName, int pinBase, char *params) +{ + int pins ; + char *ipAddress, *port, *password ; + char pPort [1024] ; + + if ((params = extractInt (progName, params, &pins)) == NULL) + return FALSE ; + + if ((pins < 1) || (pins > 1000)) + { + verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ; + return FALSE ; + } + + if ((params = extractStr (progName, params, &ipAddress)) == NULL) + return FALSE ; + + if (strlen (ipAddress) == 0) + { + verbError ("%s: ipAddress required", progName) ; + return FALSE ; + } + + if ((params = extractStr (progName, params, &port)) == NULL) + return FALSE ; + + if (strlen (port) == 0) + { + sprintf (pPort, "%d", DEFAULT_SERVER_PORT) ; + port = pPort ; + } + + if ((params = extractStr (progName, params, &password)) == NULL) + return FALSE ; + + if (strlen (password) == 0) + { + verbError ("%s: password required", progName) ; + return FALSE ; + } + + return drcSetupNet (pinBase, pins, ipAddress, port, password) ; +} + + /* * Function list @@ -748,6 +843,7 @@ static struct extensionFunctionStruct extensionFunctions [] = { "pseudoPins", &doExtensionPseudoPins }, { "htu21d", &doExtensionHtu21d }, { "ds18b20", &doExtensionDs18b20 }, + { "rht03", &doExtensionRht03 }, { "mcp3002", &doExtensionMcp3002 }, { "mcp3004", &doExtensionMcp3004 }, { "mcp4802", &doExtensionMcp4802 }, @@ -757,6 +853,7 @@ static struct extensionFunctionStruct extensionFunctions [] = { "max5322", &doExtensionMax5322 }, { "sn3218", &doExtensionSn3218 }, { "drcs", &doExtensionDrcS }, + { "drcn", &doExtensionDrcNet }, { NULL, NULL }, } ; @@ -826,6 +923,6 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors) return extensionFn->function (progName, pinBase, p) ; } - verbError ("%s: extension %s not found", progName, extension) ; + fprintf (stderr, "%s: extension %s not found", progName, extension) ; return FALSE ; } diff --git a/wiringPiD/Makefile b/wiringPiD/Makefile new file mode 100644 index 0000000..6b2cc9e --- /dev/null +++ b/wiringPiD/Makefile @@ -0,0 +1,100 @@ +# +# Makefile: +# The wiringPiD utility: +# https://projects.drogon.net/wiring-pi +# +# Copyright (c) 2012-2017 Gordon Henderson +################################################################################# +# This file is part of wiringPi: +# A "wiring" library for the Raspberry Pi +# +# wiringPi is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# wiringPi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with wiringPi. If not, see . +################################################################################# + +DESTDIR?=/usr +PREFIX?=/local + +ifneq ($V,1) +Q ?= @ +endif + +#DEBUG = -g -O0 +DEBUG = -O2 +CC = gcc +INCLUDE = -I$(DESTDIR)$(PREFIX)/include +CFLAGS = $(DEBUG) -Wall -Wextra $(INCLUDE) -Winline -pipe + +LDFLAGS = -L$(DESTDIR)$(PREFIX)/lib +LIBS = -lwiringPi -lwiringPiDev -lpthread -lrt -lm -lcrypt + +# May not need to alter anything below this line +############################################################################### + +SRC = wiringpid.c network.c runRemote.c daemonise.c + +OBJ = $(SRC:.c=.o) + +all: wiringpid + +wiringpid: $(OBJ) + $Q echo [Link] + $Q $(CC) -o $@ $(OBJ) $(LDFLAGS) $(LIBS) + +.c.o: + $Q echo [Compile] $< + $Q $(CC) -c $(CFLAGS) $< -o $@ + +.PHONY: clean +clean: + $Q echo "[Clean]" + $Q rm -f $(OBJ) wiringpid *~ core tags *.bak + +.PHONY: tags +tags: $(SRC) + $Q echo [ctags] + $Q ctags $(SRC) + +.PHONY: install +install: wiringpid + $Q echo "[Install]" + $Q mkdir -p $(DESTDIR)$(PREFIX)/sbin + $Q cp wiringpid $(DESTDIR)$(PREFIX)/sbin + $Q chown root.root $(DESTDIR)$(PREFIX)/sbin/wiringpid + +# $Q mkdir -p $(DESTDIR)$(PREFIX)/man/man8 +# $Q cp gpio.1 $(DESTDIR)$(PREFIX)/man/man8 + +.PHONY: install-deb +install-deb: gpio + $Q echo "[Install: deb]" + $Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/bin + $Q install -m 0755 gpio ~/wiringPi/debian-template/wiringPi/usr/bin + $Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/man/man1 + $Q install -m 0644 gpio.1 ~/wiringPi/debian-template/wiringPi/man/man1 + +.PHONY: uninstall +uninstall: + $Q echo "[UnInstall]" + $Q rm -f $(DESTDIR)$(PREFIX)/sbin/wiringpid + $Q rm -f $(DESTDIR)$(PREFIX)/man/man8/wiringpid.8 + +.PHONY: depend +depend: + makedepend -Y $(SRC) +# DO NOT DELETE + +wiringpid.o: drcNetCmd.h network.h runRemote.h daemonise.h +network.o: network.h +runRemote.o: drcNetCmd.h network.h runRemote.h +daemonise.o: daemonise.h diff --git a/wiringPiD/daemonise.c b/wiringPiD/daemonise.c new file mode 100644 index 0000000..134a6bb --- /dev/null +++ b/wiringPiD/daemonise.c @@ -0,0 +1,82 @@ +/* + * daemonise.c: + * Fairly generic "Turn the current process into a daemon" code. + * + * Copyright (c) 2016-2017 Gordon Henderson. + ********************************************************************************* + */ + +#include +#include +#include +#include +#include +#include + +#include "daemonise.h" + +void daemonise (const char *pidFile) +{ + pid_t pid ; + int i ; + FILE *fd ; + + syslog (LOG_DAEMON | LOG_INFO, "Becoming daemon") ; + +// Fork from the parent + + if ((pid = fork ()) < 0) + { + syslog (LOG_DAEMON | LOG_ALERT, "Fork no. 1 failed: %m") ; + exit (EXIT_FAILURE) ; + } + + if (pid > 0) // Parent - terminate + exit (EXIT_SUCCESS) ; + +// Now running on the child - become session leader + + if (setsid() < 0) + { + syslog (LOG_DAEMON | LOG_ALERT, "setsid failed: %m") ; + exit (EXIT_FAILURE) ; + } + +// Ignore a few signals + + signal (SIGCHLD, SIG_IGN) ; + signal (SIGHUP, SIG_IGN) ; + +// Fork again + + if ((pid = fork ()) < 0) + { + syslog (LOG_DAEMON | LOG_ALERT, "Fork no. 2 failed: %m") ; + exit (EXIT_FAILURE) ; + } + + if (pid > 0) // parent - terminate + exit (EXIT_SUCCESS) ; + +// Tidying up - reset umask, change to / and close all files + + umask (0) ; + chdir ("/") ; + + for (i = 0 ; i < sysconf (_SC_OPEN_MAX) ; ++i) + close (i) ; + +// Write PID into /var/run + + if (pidFile != NULL) + { + if ((fd = fopen (pidFile, "w")) == NULL) + { + syslog (LOG_DAEMON | LOG_ALERT, "Unable to write PID file: %m") ; + exit (EXIT_FAILURE) ; + } + + fprintf (fd, "%d\n", getpid ()) ; + fclose (fd) ; + } +} diff --git a/wiringPiD/daemonise.h b/wiringPiD/daemonise.h new file mode 100644 index 0000000..8d13319 --- /dev/null +++ b/wiringPiD/daemonise.h @@ -0,0 +1,9 @@ +/* + * daemonise.h: + * Fairly generic "Turn the current process into a daemon" code. + * + * Copyright (c) 2016-2017 Gordon Henderson. + ********************************************************************************* + */ + +extern void daemonise (const char *pidFile) ; diff --git a/wiringPiD/drcNetCmd.h b/wiringPiD/drcNetCmd.h new file mode 100644 index 0000000..23f7dc1 --- /dev/null +++ b/wiringPiD/drcNetCmd.h @@ -0,0 +1,44 @@ +/* + * drcNetCmd.c: + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#define DEFAULT_SERVER_PORT 6124 + +#define DRCN_PIN_MODE 1 +#define DRCN_PULL_UP_DN 2 + +#define DRCN_DIGITAL_WRITE 3 +#define DRCN_DIGITAL_WRITE8 4 +#define DRCN_ANALOG_WRITE 5 +#define DRCN_PWM_WRITE 6 + +#define DRCN_DIGITAL_READ 7 +#define DRCN_DIGITAL_READ8 8 +#define DRCN_ANALOG_READ 9 + + +struct drcNetComStruct +{ + uint32_t pin ; + uint32_t cmd ; + uint32_t data ; +} comDat ; + diff --git a/wiringPiD/network.c b/wiringPiD/network.c new file mode 100644 index 0000000..9f6bb88 --- /dev/null +++ b/wiringPiD/network.c @@ -0,0 +1,330 @@ +/* + * network.c: + * Part of wiringPiD + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "network.h" + +#define TRUE (1==1) +#define FALSE (!TRUE) + +// Local data + +#define SALT_LEN 16 + +static char salt [SALT_LEN + 1] ; +static char *returnedHash = NULL ; +static int serverFd = -1 ; + +// Union for the server Socket Address + +static union +{ + struct sockaddr_in sin ; + struct sockaddr_in6 sin6 ; +} serverSockAddr ; + +// and client address + +static union +{ + struct sockaddr_in sin ; + struct sockaddr_in6 sin6 ; +} clientSockAddr ; + + +/* + * getClientIP: + * Returns a pointer to a static string containing the clients IP address + ********************************************************************************* + */ + +char *getClientIP (void) +{ + char buf [INET6_ADDRSTRLEN] ; + static char ipAddress [1024] ; + + if (clientSockAddr.sin.sin_family == AF_INET) // IPv4 + { + if (snprintf (ipAddress, 1024, "IPv4: %s", + inet_ntop (clientSockAddr.sin.sin_family, (void *)&clientSockAddr.sin.sin_addr, buf, sizeof (buf))) == 1024) + strcpy (ipAddress, "Too long") ; + } + else // IPv6 + { + if (clientSockAddr.sin.sin_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED (&clientSockAddr.sin6.sin6_addr)) + { + if (snprintf (ipAddress, 1024, "IPv4in6: %s", + inet_ntop (clientSockAddr.sin.sin_family, (char *)&clientSockAddr.sin6.sin6_addr, buf, sizeof(buf))) == 1024) + strcpy (ipAddress, "Too long") ; + } + else + { + if (snprintf (ipAddress, 1024, "IPv6: %s", + inet_ntop (clientSockAddr.sin.sin_family, (char *)&clientSockAddr.sin6.sin6_addr, buf, sizeof(buf))) == 1024) + strcpy (ipAddress, "Too long") ; + } + } + + return ipAddress ; +} + + + +/* + * clientPstr: clientPrintf: + * Print over a network socket + ********************************************************************************* + */ + +static int clientPstr (int fd, char *s) +{ + int len = strlen (s) ; + return (write (fd, s, len) == len) ? 0 : -1 ; +} + +static int clientPrintf (const int fd, const char *message, ...) +{ + va_list argp ; + char buffer [1024] ; + + va_start (argp, message) ; + vsnprintf (buffer, 1023, message, argp) ; + va_end (argp) ; + + return clientPstr (fd, buffer) ; +} + + +/* + * sendGreeting: + * Send some text to the client device + ********************************************************************************* + */ + +int sendGreeting (int clientFd) +{ + if (clientPrintf (clientFd, "200 Welcome to wiringPiD - http://wiringpi.com/\n") < 0) + return -1 ; + + return clientPrintf (clientFd, "200 Connecting from: %s\n", getClientIP ()) ; +} + + +/* + * getSalt: + * Create a random 'salt' value for the password encryption process + ********************************************************************************* + */ + +static int getSalt (char drySalt []) +{ + static const char *seaDog = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789/." ; + + unsigned char wetSalt [SALT_LEN] ; + int i, fd ; + + if ((fd = open ("/dev/urandom", O_RDONLY)) < 0) + return fd ; + + if (read (fd, wetSalt, SALT_LEN) != SALT_LEN) + return -1 ; + + close (fd) ; + + for (i = 0 ; i < SALT_LEN ; ++i) + drySalt [i] = seaDog [wetSalt [i] & 63] ; + + drySalt [SALT_LEN] = 0 ; + + return 0 ; +} + + +/* + * sendChallenge: + * Create and send our salt (aka nonce) to the remote device + ********************************************************************************* + */ + +int sendChallenge (int clientFd) +{ + if (getSalt (salt) < 0) + return -1 ; + + return clientPrintf (clientFd, "Challenge %s\n", salt) ; +} + + +/* + * getResponse: + * Read the encrypted password from the remote device. + ********************************************************************************* + */ + + +int getResponse (int clientFd) +{ + char reply [1024] ; + int len ; + +// Being sort of lazy about this. I'm expecting an SHA-512 hash back and these +// are exactly 86 characters long, so no reason not to, I guess... + + len = 86 ; + + if (setsockopt (clientFd, SOL_SOCKET, SO_RCVLOWAT, (void *)&len, sizeof (len)) < 0) + return -1 ; + + len = recv (clientFd, reply, 86, 0) ; + if (len != 86) + return -1 ; + + reply [len] = 0 ; + + if ((returnedHash = malloc (len + 1)) == NULL) + return -1 ; + + strcpy (returnedHash, reply) ; + + return 0 ; +} + + +/* + * passwordMatch: + * See if there's a match. If not, we simply dump them. + ********************************************************************************* + */ + +int passwordMatch (const char *password) +{ + char *encrypted ; + char salted [1024] ; + + sprintf (salted, "$6$%s$", salt) ; + + encrypted = crypt (password, salted) ; + +// 20: $6$ then 16 characters of salt, then $ +// 86 is the length of an SHA-512 hash + + return strncmp (encrypted + 20, returnedHash, 86) == 0 ; +} + + +/* + * setupServer: + * Do what's needed to create a local server socket instance that can listen + * on both IPv4 and IPv6 interfaces. + ********************************************************************************* + */ + +int setupServer (int serverPort) +{ + socklen_t clientSockAddrSize = sizeof (clientSockAddr) ; + + int on = 1 ; + int family ; + socklen_t serverSockAddrSize ; + int clientFd ; + +// Try to create an IPv6 socket + + serverFd = socket (PF_INET6, SOCK_STREAM, 0) ; + +// If it didn't work, then fall-back to IPv4. + + if (serverFd < 0) + { + if ((serverFd = socket (PF_INET, SOCK_STREAM, 0)) < 0) + return -1 ; + + family = AF_INET ; + serverSockAddrSize = sizeof (struct sockaddr_in) ; + } + else // We got an IPv6 socket + { + family = AF_INET6 ; + serverSockAddrSize = sizeof (struct sockaddr_in6) ; + } + + if (setsockopt (serverFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) + return -1 ; + +// Setup the servers socket address - cope with IPv4 and v6. + + memset (&serverSockAddr, 0, sizeof (serverSockAddr)) ; + switch (family) + { + case AF_INET: + serverSockAddr.sin.sin_family = AF_INET ; + serverSockAddr.sin.sin_addr.s_addr = htonl (INADDR_ANY) ; + serverSockAddr.sin.sin_port = htons (serverPort) ; + break; + + case AF_INET6: + serverSockAddr.sin6.sin6_family = AF_INET6 ; + serverSockAddr.sin6.sin6_addr = in6addr_any ; + serverSockAddr.sin6.sin6_port = htons (serverPort) ; + } + +// Bind, listen and accept + + if (bind (serverFd, (struct sockaddr *)&serverSockAddr, serverSockAddrSize) < 0) + return -1 ; + + if (listen (serverFd, 4) < 0) // Really only going to talk to one client at a time... + return -1 ; + + if ((clientFd = accept (serverFd, (struct sockaddr *)&clientSockAddr, &clientSockAddrSize)) < 0) + return -1 ; + + return clientFd ; +} + + +/* + * closeServer: + ********************************************************************************* + */ + +void closeServer (int clientFd) +{ + if (serverFd != -1) close (serverFd) ; + if (clientFd != -1) close (clientFd) ; + serverFd = clientFd = -1 ; +} diff --git a/wiringPiD/network.h b/wiringPiD/network.h new file mode 100644 index 0000000..94c3380 --- /dev/null +++ b/wiringPiD/network.h @@ -0,0 +1,31 @@ +/* + * network.h: + * Part of wiringPiD + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +extern char *getClientIP (void) ; +extern int getResponce (int clientFd) ; +extern int setupServer (int serverPort) ; +extern int sendGreeting (int clientFd) ; +extern int sendChallenge (int clientFd) ; +extern int getResponse (int clientFd) ; +extern int passwordMatch (const char *password) ; +extern void closeServer (int clientFd) ; diff --git a/wiringPiD/runRemote.c b/wiringPiD/runRemote.c new file mode 100644 index 0000000..cd7432b --- /dev/null +++ b/wiringPiD/runRemote.c @@ -0,0 +1,126 @@ +/* + * runRemote.c: + * Run the remote commands passed over the network link. + * + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +//#include + +#include +#include + +#include "drcNetCmd.h" +#include "network.h" +#include "runRemote.h" + + + +int noLocalPins = FALSE ; + + +void runRemoteCommands (int fd) +{ + register uint32_t pin ; + int len ; + struct drcNetComStruct cmd ; + + len = sizeof (struct drcNetComStruct) ; + + if (setsockopt (fd, SOL_SOCKET, SO_RCVLOWAT, (void *)&len, sizeof (len)) < 0) + return ; + + for (;;) + { + if (recv (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) // Probably remote hangup + return ; + + pin = cmd.pin ; + if (noLocalPins && ((pin & PI_GPIO_MASK) == 0)) + { + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + continue ; + } + + switch (cmd.cmd) + { + case DRCN_PIN_MODE: + pinMode (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_PULL_UP_DN: + pullUpDnControl (pin, cmd.data) ; + break ; + + case DRCN_PWM_WRITE: + pwmWrite (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_DIGITAL_WRITE: + digitalWrite (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_DIGITAL_WRITE8: + //digitalWrite8 (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_DIGITAL_READ: + cmd.data = digitalRead (pin) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_DIGITAL_READ8: + //cmd.data = digitalRead8 (pin) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_ANALOG_WRITE: + analogWrite (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_ANALOG_READ: + cmd.data = analogRead (pin) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + } + } + +} diff --git a/wiringPiD/runRemote.h b/wiringPiD/runRemote.h new file mode 100644 index 0000000..57d5018 --- /dev/null +++ b/wiringPiD/runRemote.h @@ -0,0 +1,29 @@ +/* + * runRemote.h: + * Run the remote commands passed over the network link. + * + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +// Globals + +extern int noLocalPins ; + +extern void runRemoteCommands (int fd) ; diff --git a/wiringPiD/wiringpid b/wiringPiD/wiringpid new file mode 100755 index 0000000000000000000000000000000000000000..529e2868b44f2cf2b6a01664f1653c4f28c3067a GIT binary patch literal 18721 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%0DrYL1WH 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 literal 0 HcmV?d00001 diff --git a/wiringPiD/wiringpid.c b/wiringPiD/wiringpid.c new file mode 100644 index 0000000..8dde1cd --- /dev/null +++ b/wiringPiD/wiringpid.c @@ -0,0 +1,382 @@ +/* + * wiringPiD.c: + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "drcNetCmd.h" +#include "network.h" +#include "runRemote.h" +#include "daemonise.h" + + +#define PIDFILE "/var/run/wiringPiD.pid" + + +// Globals + +static const char *usage = "[-h] [-d] [-g | -1 | -z] [[-x extension:pin:params] ...] password" ; +static int doDaemon = FALSE ; + +// + +static void logMsg (const char *message, ...) +{ + va_list argp ; + char buffer [1024] ; + + va_start (argp, message) ; + vsnprintf (buffer, 1023, message, argp) ; + va_end (argp) ; + + if (doDaemon) + syslog (LOG_DAEMON | LOG_INFO, "%s", buffer) ; + else + printf ("%s\n", buffer) ; +} + + +/* + * sigHandler: + * setupSigHandler: + * Somehing has happened that would normally terminate the program so try + * to close down nicely. + ********************************************************************************* + */ + +void sigHandler (int sig) +{ + logMsg ("Exiting on signal %d: %s", sig, strsignal (sig)) ; + (void)unlink (PIDFILE) ; + exit (EXIT_FAILURE) ; +} + +void setupSigHandler (void) +{ + struct sigaction action ; + + sigemptyset (&action.sa_mask) ; + action.sa_flags = 0 ; + +// Ignore what we can + + action.sa_handler = SIG_IGN ; + + sigaction (SIGHUP, &action, NULL) ; + sigaction (SIGTTIN, &action, NULL) ; + sigaction (SIGTTOU, &action, NULL) ; + +// Trap what we can to exit gracefully + + action.sa_handler = sigHandler ; + + sigaction (SIGINT, &action, NULL) ; + sigaction (SIGQUIT, &action, NULL) ; + sigaction (SIGILL, &action, NULL) ; + sigaction (SIGABRT, &action, NULL) ; + sigaction (SIGFPE, &action, NULL) ; + sigaction (SIGSEGV, &action, NULL) ; + sigaction (SIGPIPE, &action, NULL) ; + sigaction (SIGALRM, &action, NULL) ; + sigaction (SIGTERM, &action, NULL) ; + sigaction (SIGUSR1, &action, NULL) ; + sigaction (SIGUSR2, &action, NULL) ; + sigaction (SIGCHLD, &action, NULL) ; + sigaction (SIGTSTP, &action, NULL) ; + sigaction (SIGBUS, &action, NULL) ; +} + + +/* + * The works... + ********************************************************************************* + */ + +int main (int argc, char *argv []) +{ + int clientFd ; + char *p, *password ; + int i ; + int port = DEFAULT_SERVER_PORT ; + int wpiSetup = 0 ; + + if (argc < 2) + { + fprintf (stderr, "Usage: %s %s\n", argv [0], usage) ; + exit (EXIT_FAILURE) ; + } + +// Help? + + if (strcasecmp (argv [1], "-h") == 0) + { + printf ("Usage: %s %s\n", argv [0], usage) ; + return 0 ; + } + +// Daemonize? +// Must come before the other args as e.g. some extensions +// open files which get closed on daemonise... + + if (strcasecmp (argv [1], "-d") == 0) + { + if (geteuid () != 0) + { + fprintf (stderr, "%s: Must be root to run as a daemon.\n", argv [0]) ; + exit (EXIT_FAILURE) ; + } + + doDaemon = TRUE ; + daemonise (PIDFILE) ; + + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + } + +// Scan all other arguments + + while (*argv [1] == '-') + { + +// Look for wiringPi setup arguments: +// Same as the gpio command and rtb. + +// -g - bcm_gpio + + if (strcasecmp (argv [1], "-g") == 0) + { + if (wpiSetup == 0) + { + logMsg ("BCM_GPIO mode selected") ; + wiringPiSetupGpio () ; + } + + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + ++wpiSetup ; + continue ; + } + +// -1 - physical pins + + if (strcasecmp (argv [1], "-1") == 0) + { + if (wpiSetup == 0) + { + logMsg ("GPIO-PHYS mode selected") ; + wiringPiSetupPhys () ; + } + + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + ++wpiSetup ; + continue ; + } + +// -z - no wiringPi - blocks remotes accessing local pins + + if (strcasecmp (argv [1], "-z") == 0) + { + if (wpiSetup == 0) + logMsg ("No GPIO mode selected") ; + + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + noLocalPins = TRUE ; + ++wpiSetup ; + continue ; + } + +// -p to select the port + + if (strcasecmp (argv [1], "-p") == 0) + { + if (argc < 3) + { + logMsg ("-p missing extension port") ; + exit (EXIT_FAILURE) ; + } + + logMsg ("Setting port to: %s", argv [2]) ; + + port = atoi (argv [2]) ; + if ((port < 1) || (port > 65535)) + { + logMsg ("Invalid server port: %d", port) ; + exit (EXIT_FAILURE) ; + } + +// Shift args down by 2 + + for (i = 3 ; i < argc ; ++i) + argv [i - 2] = argv [i] ; + argc -= 2 ; + + continue ; + } + +// Check for -x argument to load in a new extension +// -x extension:base:args +// Can load many modules to extend the daemon. + + if (strcasecmp (argv [1], "-x") == 0) + { + if (argc < 3) + { + logMsg ("-x missing extension name:data:etc.") ; + exit (EXIT_FAILURE) ; + } + + logMsg ("Loading extension: %s", argv [2]) ; + + if (!loadWPiExtension (argv [0], argv [2], TRUE)) + { + logMsg ("Extension load failed: %s", strerror (errno)) ; + exit (EXIT_FAILURE) ; + } + +// Shift args down by 2 + + for (i = 3 ; i < argc ; ++i) + argv [i - 2] = argv [i] ; + argc -= 2 ; + + continue ; + } + + logMsg ("Invalid parameter: %s", argv [1]) ; + exit (EXIT_FAILURE) ; + } + +// Default to wiringPi mode + + if (wpiSetup == 0) + { + logMsg ("WiringPi GPIO mode selected") ; + wiringPiSetup () ; + } + +// Finally, should just be one arg left - the password... + + if (argc != 2) + { + logMsg ("No password supplied") ; + exit (EXIT_FAILURE) ; + } + + if (strlen (argv [1]) < 6) + { + logMsg ("Password too short - at least 6 chars, not %d", strlen (argv [1])) ; + exit (EXIT_FAILURE) ; + } + + if ((password = malloc (strlen (argv [1]) + 1)) == NULL) + { + logMsg ("Out of memory") ; + exit (EXIT_FAILURE) ; + } + strcpy (password, argv [1]) ; + +// Wipe out the password on the command-line in a vague attempt to try to +// hide it from snoopers + + for (p = argv [1] ; *p ; ++p) + *p = ' ' ; + + setupSigHandler () ; + +// Enter our big loop + + for (;;) + { + + if (!doDaemon) + printf ("-=-\nWaiting for a new connection...\n") ; + + if ((clientFd = setupServer (port)) < 0) + { + logMsg ("Unable to setup server: %s", strerror (errno)) ; + exit (EXIT_FAILURE) ; + } + + logMsg ("New connection from: %s.", getClientIP ()) ; + + if (!doDaemon) + printf ("Sending Greeting.\n") ; + + if (sendGreeting (clientFd) < 0) + { + logMsg ("Unable to send greeting message: %s", strerror (errno)) ; + closeServer (clientFd) ; + continue ; + } + + if (!doDaemon) + printf ("Sending Challenge.\n") ; + + if (sendChallenge (clientFd) < 0) + { + logMsg ("Unable to send challenge message: %s", strerror (errno)) ; + closeServer (clientFd) ; + continue ; + } + + if (!doDaemon) + printf ("Waiting for response.\n") ; + + if (getResponse (clientFd) < 0) + { + logMsg ("Connection closed waiting for response: %s", strerror (errno)) ; + closeServer (clientFd) ; + continue ; + } + + if (!passwordMatch (password)) + { + logMsg ("Password failure") ; + closeServer (clientFd) ; + continue ; + } + + logMsg ("Password OK - Starting") ; + + runRemoteCommands (clientFd) ; + closeServer (clientFd) ; + } + + return 0 ; +}