Browse Source

Merge branch 'master' of git://git.drogon.net/wiringPi

pull/37/merge
Phil Howard 7 years ago
parent
commit
c947643601
29 changed files with 2205 additions and 93 deletions
  1. +1
    -1
      VERSION
  2. +8
    -0
      build
  3. +1
    -1
      debian-template/wiringPi/DEBIAN/control
  4. +1
    -1
      examples/Makefile
  5. +61
    -0
      examples/blink8-drcn.c
  6. +1
    -1
      gpio/Makefile
  7. +19
    -9
      gpio/gpio.1
  8. +15
    -2
      gpio/gpio.c
  9. +3
    -1
      gpio/readall.c
  10. +2
    -2
      version.h
  11. +3
    -3
      wiringPi/Makefile
  12. +405
    -0
      wiringPi/drcNet.c
  13. +42
    -0
      wiringPi/drcNet.h
  14. +252
    -0
      wiringPi/rht03.c
  15. +25
    -0
      wiringPi/rht03.h
  16. +29
    -22
      wiringPi/softPwm.c
  17. +70
    -26
      wiringPi/wiringPi.c
  18. +30
    -17
      wiringPi/wiringPi.h
  19. +104
    -7
      wiringPi/wpiExtensions.c
  20. +100
    -0
      wiringPiD/Makefile
  21. +82
    -0
      wiringPiD/daemonise.c
  22. +9
    -0
      wiringPiD/daemonise.h
  23. +44
    -0
      wiringPiD/drcNetCmd.h
  24. +330
    -0
      wiringPiD/network.c
  25. +31
    -0
      wiringPiD/network.h
  26. +126
    -0
      wiringPiD/runRemote.c
  27. +29
    -0
      wiringPiD/runRemote.h
  28. BIN
      wiringPiD/wiringpid
  29. +382
    -0
      wiringPiD/wiringpid.c

+ 1
- 1
VERSION View File

@@ -1 +1 @@
2.39
2.44

+ 8
- 0
build View File

@@ -161,6 +161,14 @@ fi
check_make_ok check_make_ok


# echo # echo
# echo "wiringPi Daemon"
# cd ../wiringPiD
# make -j5
# check_make_ok
# $sudo make install
# check_make_ok

# echo
# echo "Examples" # echo "Examples"
# cd ../examples # cd ../examples
# make # make


+ 1
- 1
debian-template/wiringPi/DEBIAN/control View File

@@ -1,5 +1,5 @@
Package: wiringpi Package: wiringpi
Version: 2.38
Version: 2.44
Section: libraries Section: libraries
Priority: optional Priority: optional
Architecture: armhf Architecture: armhf


+ 1
- 1
examples/Makefile View File

@@ -33,7 +33,7 @@ INCLUDE = -I/usr/local/include
CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe


LDFLAGS = -L/usr/local/lib LDFLAGS = -L/usr/local/lib
LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm
LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt


# Should not alter anything below this line # Should not alter anything below this line
############################################################################### ###############################################################################


+ 61
- 0
examples/blink8-drcn.c View File

@@ -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. <projects@drogon.net>
***********************************************************************
* 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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

#include <stdio.h>
#include <wiringPi.h>
#include <drcNet.h>

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) ;
}
}
}

+ 1
- 1
gpio/Makefile View File

@@ -37,7 +37,7 @@ INCLUDE = -I$(DESTDIR)$(PREFIX)/include
CFLAGS = $(DEBUG) -Wall -Wextra $(INCLUDE) -Winline -pipe CFLAGS = $(DEBUG) -Wall -Wextra $(INCLUDE) -Winline -pipe


LDFLAGS = -L$(DESTDIR)$(PREFIX)/lib 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 # May not need to alter anything below this line
############################################################################### ###############################################################################


+ 19
- 9
gpio/gpio.1 View File

@@ -9,15 +9,15 @@ gpio \- Command-line access to Raspberry Pi's GPIO
.PP .PP
.B gpio .B gpio
.B [ \-g | \-1 ] .B [ \-g | \-1 ]
.B mode/read/write/aread/awrite/wb/pwm/clock ...
.B mode/read/write/aread/awrite/wb/pwm/clock/toggle/blink ...
.PP .PP
.B gpio .B gpio
.B [ \-x extension:params ] .B [ \-x extension:params ]
.B mode/read/write/aread/awrite/pwm/pwmTone ...
.B mode/read/write/aread/awrite/pwm/toggle/blink ...
.PP .PP
.B gpio .B gpio
.B [ \-p ] .B [ \-p ]
.B read/write/toggle/wb
.B read/write/toggle/blink
.B ... .B ...
.PP .PP
.B gpio .B gpio
@@ -119,10 +119,22 @@ Write the given value (0 or 1) to the pin. You need to set the pin
to output mode first. to output mode first.


.TP .TP
.B toggle <pin>
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 <pin>
Blinks the given pin on/off. Press Control-C to exit.

Note: This command explicitly sets the pin to output mode.

.TP
.B aread <pin> .B aread <pin>
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 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 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 <pin> <value> .B awrite <pin> <value>
Write the analog value to the given pin. This needs to be used in 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 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 e.g. gpio -x mcp4802:200:0 awrite 200 128


@@ -234,7 +246,7 @@ absolutely sure you know what you're doing.
high | low high | low


Change the USB current limiter to high (1.2 amps) or low (the default, 600mA) 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 .TP
.B pwm-bal/pwm-ms .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 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. raspi-config program to load/unload the I2C device at boot time.
(or disable the device tree to continue to use this method)


.TP .TP
.B load spi .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 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. raspi-config program to load/unload the SPI device at boot time.
(or disable the device tree to continue to use this method)


.TP .TP
.B gbr .B gbr


+ 15
- 2
gpio/gpio.c View File

@@ -1443,6 +1443,16 @@ int main (int argc, char *argv [])
wpMode = WPI_MODE_PIFACE ; 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 // Default to wiringPi mode


else else
@@ -1460,12 +1470,15 @@ int main (int argc, char *argv [])
{ {
if (argc < 3) 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) ; 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) ; exit (EXIT_FAILURE) ;
}


// Shift args down by 2 // Shift args down by 2




+ 3
- 1
gpio/readall.c View File

@@ -299,6 +299,8 @@ static void plus2header (int model)
printf (" +-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+\n") ; printf (" +-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+\n") ;
else if (model == PI_MODEL_ZERO) else if (model == PI_MODEL_ZERO)
printf (" +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+\n") ; printf (" +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+\n") ;
else if (model == PI_MODEL_ZERO_W)
printf (" +-----+-----+---------+------+---+-Pi ZeroW-+---+------+---------+-----+-----+\n") ;
else if (model == PI_MODEL_2) else if (model == PI_MODEL_2)
printf (" +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+\n") ; printf (" +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+\n") ;
else if (model == PI_MODEL_3) else if (model == PI_MODEL_3)
@@ -346,7 +348,7 @@ void doReadall (void)


/**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B)) /**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B))
abReadall (model, rev) ; abReadall (model, rev) ;
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO))
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W))
piPlusReadall (model) ; piPlusReadall (model) ;
else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3))
allReadall () ; allReadall () ;


+ 2
- 2
version.h View File

@@ -1,3 +1,3 @@
#define VERSION "2.38"
#define VERSION "2.44"
#define VERSION_MAJOR 2 #define VERSION_MAJOR 2
#define VERSION_MINOR 38
#define VERSION_MINOR 44

+ 3
- 3
wiringPi/Makefile View File

@@ -41,7 +41,7 @@ INCLUDE = -I.
DEFS = -D_GNU_SOURCE DEFS = -D_GNU_SOURCE
CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline $(INCLUDE) -pipe -fPIC CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline $(INCLUDE) -pipe -fPIC


LIBS = -lm -lpthread -lrt
LIBS = -lm -lpthread -lrt -lcrypt


############################################################################### ###############################################################################


@@ -57,8 +57,8 @@ SRC = wiringPi.c \
mcp3002.c mcp3004.c mcp4802.c mcp3422.c \ mcp3002.c mcp3004.c mcp4802.c mcp3422.c \
max31855.c max5322.c ads1115.c \ max31855.c max5322.c ads1115.c \
sn3218.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 \ pseudoPins.c \
wpiExtensions.c wpiExtensions.c




+ 405
- 0
wiringPi/drcNet.c View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <crypt.h>


#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 ;
}

+ 42
- 0
wiringPi/drcNet.h View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

/*********
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

+ 252
- 0
wiringPi/rht03.c View File

@@ -0,0 +1,252 @@
/*
* 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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

#include <sys/time.h>
#include <stdio.h>
#include <stdio.h>
#include <time.h>

#include "wiringPi.h"
#include "rht03.h"

/*
* maxDetectLowHighWait:
* Wait for a transition from low to high on the bus
*********************************************************************************
*/

static int maxDetectLowHighWait (const int pin)
{
struct timeval now, timeOut, timeUp ;

// If already high then wait for pin to go low

gettimeofday (&now, NULL) ;
timerclear (&timeOut) ;
timeOut.tv_usec = 1000 ;
timeradd (&now, &timeOut, &timeUp) ;

while (digitalRead (pin) == HIGH)
{
gettimeofday (&now, NULL) ;
if (timercmp (&now, &timeUp, >))
return FALSE ;
}

// Wait for it to go HIGH

gettimeofday (&now, NULL) ;
timerclear (&timeOut) ;
timeOut.tv_usec = 1000 ;
timeradd (&now, &timeOut, &timeUp) ;

while (digitalRead (pin) == LOW)
{
gettimeofday (&now, NULL) ;
if (timercmp (&now, &timeUp, >))
return FALSE ;
}

return TRUE ;
}


/*
* maxDetectClockByte:
* Read in a single byte from the MaxDetect bus
*********************************************************************************
*/

static unsigned int maxDetectClockByte (const int pin)
{
unsigned int byte = 0 ;
int bit ;

for (bit = 0 ; bit < 8 ; ++bit)
{
if (!maxDetectLowHighWait (pin))
return 0 ;

// bit starting now - we need to time it.

delayMicroseconds (30) ;
byte <<= 1 ;
if (digitalRead (pin) == HIGH) // It's a 1
byte |= 1 ;
}

return byte ;
}


/*
* maxDetectRead:
* Read in and return the 4 data bytes from the MaxDetect sensor.
* Return TRUE/FALSE depending on the checksum validity
*********************************************************************************
*/

static int maxDetectRead (const int pin, unsigned char buffer [4])
{
int i ;
unsigned int checksum ;
unsigned char localBuf [5] ;
struct timeval now, then, took ;

// See how long we took

gettimeofday (&then, NULL) ;

// Wake up the RHT03 by pulling the data line low, then high
// Low for 10mS, high for 40uS.

pinMode (pin, OUTPUT) ;
digitalWrite (pin, 0) ; delay (10) ;
digitalWrite (pin, 1) ; delayMicroseconds (40) ;
pinMode (pin, INPUT) ;

// Now wait for sensor to pull pin low

if (!maxDetectLowHighWait (pin))
return FALSE ;

// and read in 5 bytes (40 bits)

for (i = 0 ; i < 5 ; ++i)
localBuf [i] = maxDetectClockByte (pin) ;

checksum = 0 ;
for (i = 0 ; i < 4 ; ++i)
{
buffer [i] = localBuf [i] ;
checksum += localBuf [i] ;
}
checksum &= 0xFF ;

// See how long we took
gettimeofday (&now, NULL) ;
timersub (&now, &then, &took) ;

// Total time to do this should be:
// 10mS + 40µS - reset
// + 80µS + 80µS - sensor doing its low -> high thing
// + 40 * (50µS + 27µS (0) or 70µS (1) )
// = 15010µS
// so if we take more than that, we've had a scheduling interruption and the
// reading is probably bogus.

if ((took.tv_sec != 0) || (took.tv_usec > 16000))
return FALSE ;

return checksum == localBuf [4] ;
}


/*
* 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 ;
}

+ 25
- 0
wiringPi/rht03.h View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

extern int rht03Setup (const int pinBase, const int devicePin) ;

+ 29
- 22
wiringPi/softPwm.c View File

@@ -1,7 +1,7 @@
/* /*
* softPwm.c: * 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: * This file is part of wiringPi:
* https://projects.drogon.net/raspberry-pi/wiringpi/ * https://projects.drogon.net/raspberry-pi/wiringpi/
@@ -30,11 +30,11 @@
#include "softPwm.h" #include "softPwm.h"


// MAX_PINS: // 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 PWM Frequency is derived from the "pulse time" below. Essentially,
// the frequency is a function of the range and this pulse time. // 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, // 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 // 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 // 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 // Another way to increase the frequency is to reduce the range - however
// that reduces the overall output accuracy... // that reduces the overall output accuracy...
@@ -106,14 +106,15 @@ static void *softPwmThread (void *arg)


void softPwmWrite (int pin, int value) void softPwmWrite (int pin, int value)
{ {
pin &= (MAX_PINS - 1) ;
/**/ if (value < 0)
value = 0 ;
else if (value > range [pin])
value = range [pin] ;
if (pin < MAX_PINS)
{
/**/ 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 ; pthread_t myThread ;
int *passPin ; int *passPin ;


if (pin >= MAX_PINS)
return -1 ;

if (range [pin] != 0) // Already running on this pin if (range [pin] != 0) // Already running on this pin
return -1 ; return -1 ;


@@ -139,15 +143,15 @@ int softPwmCreate (int pin, int initialValue, int pwmRange)
if (passPin == NULL) if (passPin == NULL)
return -1 ; return -1 ;


pinMode (pin, OUTPUT) ;
digitalWrite (pin, LOW) ; digitalWrite (pin, LOW) ;
pinMode (pin, OUTPUT) ;


marks [pin] = initialValue ; marks [pin] = initialValue ;
range [pin] = pwmRange ; range [pin] = pwmRange ;


*passPin = pin ; *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) while (newPin != -1)
delay (1) ; delay (1) ;
@@ -166,11 +170,14 @@ int softPwmCreate (int pin, int initialValue, int pwmRange)


void softPwmStop (int pin) 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) ;
}
} }
} }

+ 70
- 26
wiringPi/wiringPi.c View File

@@ -84,10 +84,8 @@
#define ENV_GPIOMEM "WIRINGPI_GPIOMEM" #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 ; struct wiringPiNodeStruct *wiringPiNodes = NULL ;


@@ -224,7 +222,7 @@ const char *piModelNames [16] =
"Pi Zero", // 09 "Pi Zero", // 09
"CM3", // 10 "CM3", // 10
"Unknown11", // 11 "Unknown11", // 11
"Unknown12", // 12
"Pi Zero-W", // 12
"Unknown13", // 13 "Unknown13", // 13
"Unknown14", // 14 "Unknown14", // 14
"Unknown15", // 15 "Unknown15", // 15
@@ -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) struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
{ {
@@ -1272,17 +1272,19 @@ struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
if (node == NULL) if (node == NULL)
(void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ; (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 ; return node ;
} }
@@ -1493,6 +1495,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: * digitalWrite:
* Set an output bit * Set an output bit
********************************************************************************* *********************************************************************************
@@ -1536,6 +1559,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: * pwmWrite:
* Set an output PWM value * Set an output PWM value
********************************************************************************* *********************************************************************************
@@ -2144,9 +2187,10 @@ int wiringPiSetup (void)


switch (model) switch (model)
{ {
case PI_MODEL_A: case PI_MODEL_B:
case PI_MODEL_AP: case PI_MODEL_BP:
case PI_ALPHA: case PI_MODEL_CM: case PI_MODEL_ZERO:
case PI_MODEL_A: case PI_MODEL_B:
case PI_MODEL_AP: case PI_MODEL_BP:
case PI_ALPHA: case PI_MODEL_CM:
case PI_MODEL_ZERO: case PI_MODEL_ZERO_W:
piGpioBase = GPIO_PERI_BASE_OLD ; piGpioBase = GPIO_PERI_BASE_OLD ;
break ; break ;




+ 30
- 17
wiringPi/wiringPi.h View File

@@ -26,6 +26,7 @@


// C doesn't have true/false by default and I can never remember which // C doesn't have true/false by default and I can never remember which
// way round they are, so ... // way round they are, so ...
// (and yes, I know about stdbool.h but I like capitals for these and I'm old)


#ifndef TRUE #ifndef TRUE
# define TRUE (1==1) # define TRUE (1==1)
@@ -36,6 +37,11 @@


#define UNU __attribute__((unused)) #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 // Handy defines


// wiringPi modes // wiringPi modes
@@ -92,6 +98,7 @@
#define PI_MODEL_3 8 #define PI_MODEL_3 8
#define PI_MODEL_ZERO 9 #define PI_MODEL_ZERO 9
#define PI_MODEL_CM3 10 #define PI_MODEL_CM3 10
#define PI_MODEL_ZERO_W 12


#define PI_VERSION_1 0 #define PI_VERSION_1 0
#define PI_VERSION_1_1 1 #define PI_VERSION_1_1 1
@@ -140,13 +147,15 @@ struct wiringPiNodeStruct
unsigned int data2 ; // ditto unsigned int data2 ; // ditto
unsigned int data3 ; // 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 ; struct wiringPiNodeStruct *next ;
} ; } ;
@@ -179,14 +188,16 @@ extern int wiringPiSetupSys (void) ;
extern int wiringPiSetupGpio (void) ; extern int wiringPiSetupGpio (void) ;
extern int wiringPiSetupPhys (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 // PiFace specifics
// (Deprecated) // (Deprecated)
@@ -204,12 +215,14 @@ extern int physPinToGpio (int physPin) ;
extern void setPadDrive (int group, int value) ; extern void setPadDrive (int group, int value) ;
extern int getAlt (int pin) ; extern int getAlt (int pin) ;
extern void pwmToneWrite (int pin, int freq) ; extern void pwmToneWrite (int pin, int freq) ;
extern void digitalWriteByte (int value) ;
extern unsigned int digitalReadByte (void) ;
extern void pwmSetMode (int mode) ; extern void pwmSetMode (int mode) ;
extern void pwmSetRange (unsigned int range) ; extern void pwmSetRange (unsigned int range) ;
extern void pwmSetClock (int divisor) ; extern void pwmSetClock (int divisor) ;
extern void gpioClockSet (int pin, int freq) ; 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 // Interrupts
// (Also Pi hardware specific) // (Also Pi hardware specific)


+ 104
- 7
wiringPi/wpiExtensions.c View File

@@ -55,10 +55,13 @@
#include "ads1115.h" #include "ads1115.h"
#include "sn3218.h" #include "sn3218.h"
#include "drcSerial.h" #include "drcSerial.h"
#include "drcNet.h"
#include "../wiringPiD/drcNetCmd.h"
#include "pseudoPins.h" #include "pseudoPins.h"
#include "bmp180.h" #include "bmp180.h"
#include "htu21d.h" #include "htu21d.h"
#include "ds18b20.h" #include "ds18b20.h"
#include "rht03.h"


#include "wpiExtensions.h" #include "wpiExtensions.h"


@@ -134,12 +137,16 @@ static char *extractInt (char *progName, char *p, int *num)
/* /*
* extractStr: * extractStr:
* Check & return a string at the given location (prefixed by a :) * 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) static char *extractStr (char *progName, char *p, char **str)
{ {
char *q, *r ; char *q, *r ;
int quoted = FALSE ;


if (*p != ':') if (*p != ':')
{ {
@@ -149,21 +156,38 @@ static char *extractStr (char *progName, char *p, char **str)


++p ; ++p ;


if (!isprint (*p))
if (*p == '[')
{
quoted = TRUE ;
++p ;
}

if (!isprint (*p)) // Is this needed?
{ {
verbError ("%s: character expected", progName) ; verbError ("%s: character expected", progName) ;
return NULL ; return NULL ;
} }


q = p ; 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 *str = r = calloc (q - p + 2, 1) ; // Zeros it


while (p != q) while (p != q)
*r++ = *p++ ; *r++ = *p++ ;

if (quoted) // Skip over the ] to the :
++p ;

return p ; return p ;
} }


@@ -496,6 +520,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: * doExtensionMax31855:
* Analog IO * Analog IO
* max31855:base:spiChan * max31855:base:spiChan
@@ -698,9 +740,9 @@ static int doExtensionDrcS (char *progName, int pinBase, char *params)
if ((params = extractInt (progName, params, &pins)) == NULL) if ((params = extractInt (progName, params, &pins)) == NULL)
return FALSE ; 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 ; 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 * Function list
@@ -748,6 +843,7 @@ static struct extensionFunctionStruct extensionFunctions [] =
{ "pseudoPins", &doExtensionPseudoPins }, { "pseudoPins", &doExtensionPseudoPins },
{ "htu21d", &doExtensionHtu21d }, { "htu21d", &doExtensionHtu21d },
{ "ds18b20", &doExtensionDs18b20 }, { "ds18b20", &doExtensionDs18b20 },
{ "rht03", &doExtensionRht03 },
{ "mcp3002", &doExtensionMcp3002 }, { "mcp3002", &doExtensionMcp3002 },
{ "mcp3004", &doExtensionMcp3004 }, { "mcp3004", &doExtensionMcp3004 },
{ "mcp4802", &doExtensionMcp4802 }, { "mcp4802", &doExtensionMcp4802 },
@@ -757,6 +853,7 @@ static struct extensionFunctionStruct extensionFunctions [] =
{ "max5322", &doExtensionMax5322 }, { "max5322", &doExtensionMax5322 },
{ "sn3218", &doExtensionSn3218 }, { "sn3218", &doExtensionSn3218 },
{ "drcs", &doExtensionDrcS }, { "drcs", &doExtensionDrcS },
{ "drcn", &doExtensionDrcNet },
{ NULL, NULL }, { NULL, NULL },
} ; } ;


@@ -826,6 +923,6 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors)
return extensionFn->function (progName, pinBase, p) ; 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 ; return FALSE ;
} }

+ 100
- 0
wiringPiD/Makefile View File

@@ -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 <http://www.gnu.org/licenses/>.
#################################################################################

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

+ 82
- 0
wiringPiD/daemonise.c View File

@@ -0,0 +1,82 @@
/*
* daemonise.c:
* Fairly generic "Turn the current process into a daemon" code.
*
* Copyright (c) 2016-2017 Gordon Henderson.
*********************************************************************************
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <signal.h>
#include <sys/stat.h>

#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) ;
}
}

+ 9
- 0
wiringPiD/daemonise.h View File

@@ -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) ;

+ 44
- 0
wiringPiD/drcNetCmd.h View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

#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 ;


+ 330
- 0
wiringPiD/network.c View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <malloc.h>

#include <fcntl.h>
#include <crypt.h>

#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 ;
}

+ 31
- 0
wiringPiD/network.h View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

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) ;

+ 126
- 0
wiringPiD/runRemote.c View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
//#include <stdarg.h>

#include <wiringPi.h>
#include <wpiExtensions.h>

#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 ;
}
}

}

+ 29
- 0
wiringPiD/runRemote.h View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

// Globals

extern int noLocalPins ;

extern void runRemoteCommands (int fd) ;

BIN
wiringPiD/wiringpid View File


+ 382
- 0
wiringPiD/wiringpid.c View File

@@ -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 <http://www.gnu.org/licenses/>.
***********************************************************************
*/

#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <syslog.h>
#include <signal.h>
#include <errno.h>

#include <wiringPi.h>
#include <wpiExtensions.h>

#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 ;
}

Loading…
Cancel
Save