Pārlūkot izejas kodu

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

pull/37/merge
Phil Howard pirms 7 gadiem
vecāks
revīzija
c947643601
29 mainītis faili ar 2205 papildinājumiem un 93 dzēšanām
  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ārs
      wiringPiD/wiringpid
  29. +382
    -0
      wiringPiD/wiringpid.c

+ 1
- 1
VERSION Parādīt failu

@@ -1 +1 @@
2.39
2.44

+ 8
- 0
build Parādīt failu

@@ -161,6 +161,14 @@ fi
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
# make


+ 1
- 1
debian-template/wiringPi/DEBIAN/control Parādīt failu

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


+ 1
- 1
examples/Makefile Parādīt failu

@@ -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 -lrt

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


+ 61
- 0
examples/blink8-drcn.c Parādīt failu

@@ -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 Parādīt failu

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


+ 19
- 9
gpio/gpio.1 Parādīt failu

@@ -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
@@ -119,10 +119,22 @@ Write the given value (0 or 1) to the pin. You need to set the pin
to output mode first.

.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>
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 <pin> <value>
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


+ 15
- 2
gpio/gpio.c Parādīt failu

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



+ 3
- 1
gpio/readall.c Parādīt failu

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

/**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B))
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) ;
else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3))
allReadall () ;


+ 2
- 2
version.h Parādīt failu

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

+ 3
- 3
wiringPi/Makefile Parādīt failu

@@ -41,7 +41,7 @@ INCLUDE = -I.
DEFS = -D_GNU_SOURCE
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 \
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



+ 405
- 0
wiringPi/drcNet.c Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

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

+ 70
- 26
wiringPi/wiringPi.c Parādīt failu

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

@@ -224,7 +222,7 @@ const char *piModelNames [16] =
"Pi Zero", // 09
"CM3", // 10
"Unknown11", // 11
"Unknown12", // 12
"Pi Zero-W", // 12
"Unknown13", // 13
"Unknown14", // 14
"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)
{
@@ -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 ;
}
@@ -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:
* 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:
* Set an output PWM value
*********************************************************************************
@@ -2144,9 +2187,10 @@ int wiringPiSetup (void)

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



+ 30
- 17
wiringPi/wiringPi.h Parādīt failu

@@ -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
@@ -92,6 +98,7 @@
#define PI_MODEL_3 8
#define PI_MODEL_ZERO 9
#define PI_MODEL_CM3 10
#define PI_MODEL_ZERO_W 12

#define PI_VERSION_1 0
#define PI_VERSION_1_1 1
@@ -140,13 +147,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 +188,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 +215,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)


+ 104
- 7
wiringPi/wpiExtensions.c Parādīt failu

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

@@ -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:
* Analog IO
* max31855:base:spiChan
@@ -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 ;
}

+ 100
- 0
wiringPiD/Makefile Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

@@ -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 Parādīt failu

@@ -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ārs
wiringPiD/wiringpid Parādīt failu


+ 382
- 0
wiringPiD/wiringpid.c Parādīt failu

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

Notiek ielāde…
Atcelt
Saglabāt