mirror of
https://github.com/clockworkpi/WiringPi.git
synced 2025-12-12 16:08:49 +01:00
Bumped the version to 2.40 - correctly this time, I hope.
Added fixed for a few minor things. pin driver for rht03/dht type sensors. Network stuff is experimental - for now.
This commit is contained in:
parent
e687f3f2c6
commit
70fa99a127
8
build
8
build
@ -160,6 +160,14 @@ fi
|
|||||||
$sudo make install
|
$sudo make install
|
||||||
check_make_ok
|
check_make_ok
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "wiringPi Daemon"
|
||||||
|
cd ../wiringPiD
|
||||||
|
make -j5
|
||||||
|
check_make_ok
|
||||||
|
$sudo make install
|
||||||
|
check_make_ok
|
||||||
|
|
||||||
# echo
|
# echo
|
||||||
# echo "Examples"
|
# echo "Examples"
|
||||||
# cd ../examples
|
# cd ../examples
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
Package: wiringpi
|
Package: wiringpi
|
||||||
Version: 2.38
|
Version: 2.40
|
||||||
Section: libraries
|
Section: libraries
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Architecture: armhf
|
Architecture: armhf
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
# Should not alter anything below this line
|
# Should not alter anything below this line
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|||||||
61
examples/blink8-drcn.c
Normal file
61
examples/blink8-drcn.c
Normal 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) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|||||||
28
gpio/gpio.1
28
gpio/gpio.1
@ -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
|
||||||
@ -118,11 +118,23 @@ respective logic levels.
|
|||||||
Write the given value (0 or 1) to the pin. You need to set the pin
|
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
|
||||||
|
.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
|
.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
|
||||||
|
|||||||
17
gpio/gpio.c
17
gpio/gpio.c
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
#define VERSION "2.38"
|
#define VERSION "2.40"
|
||||||
#define VERSION_MAJOR 2
|
#define VERSION_MAJOR 2
|
||||||
#define VERSION_MINOR 38
|
#define VERSION_MINOR 40
|
||||||
|
|||||||
@ -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 \
|
bmp180.c htu21d.c ds18b20.c rht03.c \
|
||||||
drcSerial.c \
|
drcSerial.c drcNet.c \
|
||||||
pseudoPins.c \
|
pseudoPins.c \
|
||||||
wpiExtensions.c
|
wpiExtensions.c
|
||||||
|
|
||||||
|
|||||||
405
wiringPi/drcNet.c
Normal file
405
wiringPi/drcNet.c
Normal 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
wiringPi/drcNet.h
Normal file
42
wiringPi/drcNet.h
Normal 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
|
||||||
126
wiringPi/rht03.c
Normal file
126
wiringPi/rht03.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* rht03.c:
|
||||||
|
* Extend wiringPi with the rht03 Maxdetect 1-Wire sensor.
|
||||||
|
* Copyright (c) 2016-2017 Gordon Henderson
|
||||||
|
***********************************************************************
|
||||||
|
* This file is part of wiringPi:
|
||||||
|
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||||||
|
*
|
||||||
|
* wiringPi is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* wiringPi is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with wiringPi.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
***********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include <sys/types.h>
|
||||||
|
//#include <sys/stat.h>
|
||||||
|
//#include <fcntl.h>
|
||||||
|
|
||||||
|
//#include <unistd.h>
|
||||||
|
//#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
//#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
//#include <ctype.h>
|
||||||
|
|
||||||
|
#include "wiringPi.h"
|
||||||
|
#include "../devLib/maxdetect.h"
|
||||||
|
|
||||||
|
#include "rht03.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* myReadRHT03:
|
||||||
|
* Read the Temperature & Humidity from an RHT03 sensor
|
||||||
|
* Values returned are *10, so 123 is 12.3.
|
||||||
|
*********************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int myReadRHT03 (const int pin, int *temp, int *rh)
|
||||||
|
{
|
||||||
|
int result ;
|
||||||
|
unsigned char buffer [4] ;
|
||||||
|
|
||||||
|
// Read ...
|
||||||
|
|
||||||
|
result = maxDetectRead (pin, buffer) ;
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return FALSE ;
|
||||||
|
|
||||||
|
*rh = (buffer [0] * 256 + buffer [1]) ;
|
||||||
|
*temp = (buffer [2] * 256 + buffer [3]) ;
|
||||||
|
|
||||||
|
if ((*temp & 0x8000) != 0) // Negative
|
||||||
|
{
|
||||||
|
*temp &= 0x7FFF ;
|
||||||
|
*temp = -*temp ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard obviously bogus readings - the checksum can't detect a 2-bit error
|
||||||
|
// (which does seem to happen - no realtime here)
|
||||||
|
|
||||||
|
if ((*rh > 999) || (*temp > 800) || (*temp < -400))
|
||||||
|
return FALSE ;
|
||||||
|
|
||||||
|
return TRUE ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* myAnalogRead:
|
||||||
|
*********************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
|
||||||
|
{
|
||||||
|
int piPin = node->fd ;
|
||||||
|
int chan = pin - node->pinBase ;
|
||||||
|
int temp = -9997 ;
|
||||||
|
int rh = -9997 ;
|
||||||
|
int try ;
|
||||||
|
|
||||||
|
if (chan > 1)
|
||||||
|
return -9999 ; // Bad parameters
|
||||||
|
|
||||||
|
for (try = 0 ; try < 10 ; ++try)
|
||||||
|
{
|
||||||
|
if (myReadRHT03 (piPin, &temp, &rh))
|
||||||
|
return chan == 0 ? temp : rh ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -9998 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rht03Setup:
|
||||||
|
* Create a new instance of an RHT03 temperature sensor.
|
||||||
|
*********************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
int rht03Setup (const int pinBase, const int piPin)
|
||||||
|
{
|
||||||
|
struct wiringPiNodeStruct *node ;
|
||||||
|
|
||||||
|
if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin
|
||||||
|
return FALSE ;
|
||||||
|
|
||||||
|
// 2 pins - temperature and humidity
|
||||||
|
|
||||||
|
node = wiringPiNewNode (pinBase, 2) ;
|
||||||
|
|
||||||
|
node->fd = piPin ;
|
||||||
|
node->analogRead = myAnalogRead ;
|
||||||
|
|
||||||
|
return TRUE ;
|
||||||
|
}
|
||||||
25
wiringPi/rht03.h
Normal file
25
wiringPi/rht03.h
Normal 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) ;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* softPwm.c:
|
* softPwm.c:
|
||||||
* Provide 2 channels of software driven PWM.
|
* Provide many channels of software driven PWM.
|
||||||
* Copyright (c) 2012-2014 Gordon Henderson
|
* 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
|
// 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
|
// Once upon a time I let pins on gpio expanders be softPwm'd, but it's really
|
||||||
// 2 pins on e.g. (SPI) mcp23s17 won't really be that effective, however...
|
// 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,8 +106,8 @@ static void *softPwmThread (void *arg)
|
|||||||
|
|
||||||
void softPwmWrite (int pin, int value)
|
void softPwmWrite (int pin, int value)
|
||||||
{
|
{
|
||||||
pin &= (MAX_PINS - 1) ;
|
if (pin < MAX_PINS)
|
||||||
|
{
|
||||||
/**/ if (value < 0)
|
/**/ if (value < 0)
|
||||||
value = 0 ;
|
value = 0 ;
|
||||||
else if (value > range [pin])
|
else if (value > range [pin])
|
||||||
@ -115,6 +115,7 @@ void softPwmWrite (int pin, int value)
|
|||||||
|
|
||||||
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,8 +143,8 @@ 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 ;
|
||||||
@ -165,6 +169,8 @@ int softPwmCreate (int pin, int initialValue, int pwmRange)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void softPwmStop (int pin)
|
void softPwmStop (int pin)
|
||||||
|
{
|
||||||
|
if (pin < MAX_PINS)
|
||||||
{
|
{
|
||||||
if (range [pin] != 0)
|
if (range [pin] != 0)
|
||||||
{
|
{
|
||||||
@ -174,3 +180,4 @@ void softPwmStop (int pin)
|
|||||||
digitalWrite (pin, LOW) ;
|
digitalWrite (pin, LOW) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -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
|
// Extend wiringPi with other pin-based devices and keep track of
|
||||||
// The others are available for the other devices
|
// them in this structure
|
||||||
|
|
||||||
#define PI_GPIO_MASK (0xFFFFFFC0)
|
|
||||||
|
|
||||||
struct wiringPiNodeStruct *wiringPiNodes = NULL ;
|
struct wiringPiNodeStruct *wiringPiNodes = NULL ;
|
||||||
|
|
||||||
@ -1246,6 +1244,8 @@ struct wiringPiNodeStruct *wiringPiFindNode (int pin)
|
|||||||
|
|
||||||
static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { 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 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 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 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 void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; }
|
||||||
@ -1277,7 +1277,9 @@ struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
|
|||||||
node->pinMode = pinModeDummy ;
|
node->pinMode = pinModeDummy ;
|
||||||
node->pullUpDnControl = pullUpDnControlDummy ;
|
node->pullUpDnControl = pullUpDnControlDummy ;
|
||||||
node->digitalRead = digitalReadDummy ;
|
node->digitalRead = digitalReadDummy ;
|
||||||
|
//node->digitalRead8 = digitalRead8Dummy ;
|
||||||
node->digitalWrite = digitalWriteDummy ;
|
node->digitalWrite = digitalWriteDummy ;
|
||||||
|
//node->digitalWrite8 = digitalWrite8Dummy ;
|
||||||
node->pwmWrite = pwmWriteDummy ;
|
node->pwmWrite = pwmWriteDummy ;
|
||||||
node->analogRead = analogReadDummy ;
|
node->analogRead = analogReadDummy ;
|
||||||
node->analogWrite = analogWriteDummy ;
|
node->analogWrite = analogWriteDummy ;
|
||||||
@ -1492,6 +1494,27 @@ int digitalRead (int pin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* digitalRead8:
|
||||||
|
* Read 8-bits (a byte) from given start pin.
|
||||||
|
*********************************************************************************
|
||||||
|
|
||||||
|
unsigned int digitalRead8 (int pin)
|
||||||
|
{
|
||||||
|
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
||||||
|
|
||||||
|
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
||||||
|
return 0 ;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((node = wiringPiFindNode (pin)) == NULL)
|
||||||
|
return LOW ;
|
||||||
|
return node->digitalRead8 (node, pin) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* digitalWrite:
|
* digitalWrite:
|
||||||
* Set an output bit
|
* Set an output bit
|
||||||
@ -1535,6 +1558,26 @@ void digitalWrite (int pin, int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* digitalWrite8:
|
||||||
|
* Set an output 8-bit byte on the device from the given pin number
|
||||||
|
*********************************************************************************
|
||||||
|
|
||||||
|
void digitalWrite8 (int pin, int value)
|
||||||
|
{
|
||||||
|
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
||||||
|
|
||||||
|
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
||||||
|
return ;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((node = wiringPiFindNode (pin)) != NULL)
|
||||||
|
node->digitalWrite8 (node, pin, value) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pwmWrite:
|
* pwmWrite:
|
||||||
* Set an output PWM value
|
* Set an output PWM value
|
||||||
|
|||||||
@ -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
|
||||||
@ -143,7 +149,9 @@ struct wiringPiNodeStruct
|
|||||||
void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ;
|
void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ;
|
||||||
void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ;
|
void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ;
|
||||||
int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ;
|
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 (*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) ;
|
void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
|
||||||
int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ;
|
int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ;
|
||||||
void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
|
void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
|
||||||
@ -184,6 +192,8 @@ extern void pinMode (int pin, int mode) ;
|
|||||||
extern void pullUpDnControl (int pin, int pud) ;
|
extern void pullUpDnControl (int pin, int pud) ;
|
||||||
extern int digitalRead (int pin) ;
|
extern int digitalRead (int pin) ;
|
||||||
extern void digitalWrite (int pin, int value) ;
|
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 void pwmWrite (int pin, int value) ;
|
||||||
extern int analogRead (int pin) ;
|
extern int analogRead (int pin) ;
|
||||||
extern void analogWrite (int pin, int value) ;
|
extern void analogWrite (int pin, int value) ;
|
||||||
@ -204,12 +214,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)
|
||||||
|
|||||||
@ -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 ;
|
||||||
|
if (quoted)
|
||||||
|
{
|
||||||
|
while ((*q != 0) && (*q != ']'))
|
||||||
|
++q ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
while ((*q != 0) && (*q != ':'))
|
while ((*q != 0) && (*q != ':'))
|
||||||
++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 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,6 +519,24 @@ static int doExtensionDs18b20 (char *progName, int pinBase, char *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* doExtensionRht03:
|
||||||
|
* Maxdetect 1-Wire Temperature & Humidity
|
||||||
|
* rht03:base:piPin
|
||||||
|
*********************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int doExtensionRht03 (char *progName, int pinBase, char *params)
|
||||||
|
{
|
||||||
|
int piPin ;
|
||||||
|
|
||||||
|
if ((params = extractInt (progName, params, &piPin)) == NULL)
|
||||||
|
return FALSE ;
|
||||||
|
|
||||||
|
return rht03Setup (pinBase, piPin) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* doExtensionMax31855:
|
* doExtensionMax31855:
|
||||||
* Analog IO
|
* Analog IO
|
||||||
@ -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
wiringPiD/Makefile
Normal file
100
wiringPiD/Makefile
Normal 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
wiringPiD/daemonise.c
Normal file
82
wiringPiD/daemonise.c
Normal 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
wiringPiD/daemonise.h
Normal file
9
wiringPiD/daemonise.h
Normal 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
wiringPiD/drcNetCmd.h
Normal file
44
wiringPiD/drcNetCmd.h
Normal 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
wiringPiD/network.c
Normal file
330
wiringPiD/network.c
Normal 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
wiringPiD/network.h
Normal file
31
wiringPiD/network.h
Normal 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
wiringPiD/runRemote.c
Normal file
126
wiringPiD/runRemote.c
Normal 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
wiringPiD/runRemote.h
Normal file
29
wiringPiD/runRemote.h
Normal 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
Executable file
BIN
wiringPiD/wiringpid
Executable file
Binary file not shown.
382
wiringPiD/wiringpid.c
Normal file
382
wiringPiD/wiringpid.c
Normal 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…
x
Reference in New Issue
Block a user