Signed-off-by: sndnvaps <sndnvaps@gmail.com>pull/48/head
@@ -19,13 +19,6 @@ then run the ldconfig command. | |||
sudo ldconfig | |||
If you want to install a static library, you may need to do this manually: | |||
cd wiringPi | |||
make static | |||
sudo make install-static | |||
To un-install wiringPi: | |||
./build uninstall | |||
@@ -1,3 +1,13 @@ | |||
Note | |||
==== | |||
This is an unofficial mirror of WiringPi to support ports (Python/Ruby/etc). | |||
Please do not email Gordon if you have issues, he will not be able to help. | |||
Pull-requests are not currently accepted, since this is a mirror. | |||
For support, comments, questions, etc please join the WiringPi Discord channel: https://discord.gg/SM4WUVG | |||
wiringPi README | |||
=============== | |||
@@ -1 +1 @@ | |||
2.32 | |||
2.46 |
@@ -6,7 +6,7 @@ | |||
# Copyright (c) 2012-2015 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# 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 | |||
@@ -64,6 +64,9 @@ if [ x$1 = "xclean" ]; then | |||
echo -n "PiGlow: " ; make clean | |||
cd ../scrollPhat | |||
echo -n "scrollPhat: " ; make clean | |||
cd ../.. | |||
echo -n "Deb: " ; rm -f debian-template/wiringpi*.deb | |||
echo | |||
exit | |||
fi | |||
@@ -161,6 +164,14 @@ fi | |||
check_make_ok | |||
# echo | |||
# echo "wiringPi Daemon" | |||
# cd ../wiringPiD | |||
# make -j5 | |||
# check_make_ok | |||
# $sudo make install | |||
# check_make_ok | |||
# echo | |||
# echo "Examples" | |||
# cd ../examples | |||
# make | |||
@@ -1,5 +1,5 @@ | |||
Package: wiringpi | |||
Version: 2.32 | |||
Version: 2.46 | |||
Section: libraries | |||
Priority: optional | |||
Architecture: armhf | |||
@@ -7,4 +7,4 @@ Depends: libc6 | |||
Maintainer: Gordon Henderson <projects@drogon.net> | |||
Description: The wiringPi libraries, headers and gpio command | |||
Libraries to allow GPIO access on a Raspberry Pi from C and C++ | |||
programs as well as from the command-line | |||
and BASIC programs as well as from the command-line |
@@ -0,0 +1,140 @@ | |||
# | |||
# Makefile: | |||
# wiringPi device - A "wiring" library for the Raspberry Pi | |||
# | |||
# Copyright (c) 2012-2016 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/>. | |||
################################################################################# | |||
VERSION=$(shell cat ../VERSION) | |||
DESTDIR?=/usr | |||
PREFIX?=/local | |||
LDCONFIG?=ldconfig | |||
ifneq ($V,1) | |||
Q ?= @ | |||
endif | |||
STATIC=libwiringPiDev.a | |||
DYNAMIC=libwiringPiDev.so.$(VERSION) | |||
#DEBUG = -g -O0 | |||
DEBUG = -O2 | |||
CC = gcc | |||
INCLUDE = -I. | |||
DEFS = -D_GNU_SOURCE | |||
CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Winline $(INCLUDE) -pipe -fPIC | |||
LIBS = | |||
############################################################################### | |||
SRC = ds1302.c maxdetect.c piNes.c \ | |||
gertboard.c piFace.c \ | |||
lcd128x64.c lcd.c \ | |||
scrollPhat.c \ | |||
piGlow.c | |||
OBJ = $(SRC:.c=.o) | |||
HEADERS = ds1302.h gertboard.h lcd128x64.h lcd.h maxdetect.h piFace.h piGlow.h piNes.h\ | |||
scrollPhat.h | |||
all: $(DYNAMIC) | |||
static: $(STATIC) | |||
$(STATIC): $(OBJ) | |||
$Q echo "[Link (Static)]" | |||
$Q ar rcs $(STATIC) $(OBJ) | |||
$Q ranlib $(STATIC) | |||
# @size $(STATIC) | |||
$(DYNAMIC): $(OBJ) | |||
$Q echo "[Link (Dynamic)]" | |||
$Q $(CC) -shared -Wl,-soname,libwiringPiDev.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPiDev.so.$(VERSION) -lpthread $(OBJ) | |||
.c.o: | |||
$Q echo [Compile] $< | |||
$Q $(CC) -c $(CFLAGS) $< -o $@ | |||
.PHONY: clean | |||
clean: | |||
$Q echo "[Clean]" | |||
$Q rm -f $(OBJ) $(OBJ_I2C) *~ core tags Makefile.bak libwiringPiDev.* | |||
.PHONY: tags | |||
tags: $(SRC) | |||
$Q echo [ctags] | |||
$Q ctags $(SRC) | |||
.PHONY: install | |||
install: $(DYNAMIC) | |||
$Q echo "[Install Headers]" | |||
$Q install -m 0755 -d $(DESTDIR)$(PREFIX)/include | |||
$Q install -m 0644 $(HEADERS) $(DESTDIR)$(PREFIX)/include | |||
$Q echo "[Install Dynamic Lib]" | |||
$Q install -m 0755 -d $(DESTDIR)$(PREFIX)/lib | |||
$Q install -m 0755 libwiringPiDev.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libwiringPiDev.so.$(VERSION) | |||
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPiDev.so.$(VERSION) $(DESTDIR)/lib/libwiringPiDev.so | |||
$Q $(LDCONFIG) | |||
.PHONY: install-static | |||
install-static: $(STATIC) | |||
$Q echo "[Install Headers]" | |||
$Q install -m 0755 -d $(DESTDIR)$(PREFIX)/include | |||
$Q install -m 0644 $(HEADERS) $(DESTDIR)$(PREFIX)/include | |||
$Q echo "[Install Static Lib]" | |||
$Q install -m 0755 -d $(DESTDIR)$(PREFIX)/lib | |||
$Q install -m 0755 libwiringPiDev.a $(DESTDIR)$(PREFIX)/lib | |||
.PHONY: install-deb | |||
install-deb: $(DYNAMIC) | |||
$Q echo "[Install Headers: deb]" | |||
$Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/include | |||
$Q install -m 0644 $(HEADERS) ~/wiringPi/debian-template/wiringPi/usr/include | |||
$Q echo "[Install Dynamic Lib: deb]" | |||
install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/lib | |||
install -m 0755 libwiringPiDev.so.$(VERSION) ~/wiringPi/debian-template/wiringPi/usr/lib/libwiringPiDev.so.$(VERSION) | |||
ln -sf ~/wiringPi/debian-template/wiringPi/usr/lib/libwiringPiDev.so.$(VERSION) ~/wiringPi/debian-template/wiringPi/usr/lib/libwiringPiDev.so | |||
.PHONY: uninstall | |||
uninstall: | |||
$Q echo "[UnInstall]" | |||
$Q cd $(DESTDIR)$(PREFIX)/include/ && rm -f $(HEADERS) | |||
$Q cd $(DESTDIR)$(PREFIX)/lib/ && rm -f libwiringPiDev.* | |||
$Q $(LDCONFIG) | |||
.PHONY: depend | |||
depend: | |||
makedepend -Y $(SRC) | |||
# DO NOT DELETE | |||
ds1302.o: ds1302.h | |||
maxdetect.o: maxdetect.h | |||
piNes.o: piNes.h | |||
gertboard.o: gertboard.h | |||
piFace.o: piFace.h | |||
lcd128x64.o: font.h lcd128x64.h | |||
lcd.o: lcd.h | |||
scrollPhat.o: scrollPhatFont.h scrollPhat.h | |||
piGlow.o: piGlow.h |
@@ -101,7 +101,7 @@ int gertboardAnalogRead (const int chan) | |||
wiringPiSPIDataRW (SPI_A2D, spiData, 2) ; | |||
return ((spiData [0] << 7) | (spiData [1] >> 1)) & 0x3FF ; | |||
return ((spiData [0] << 8) | (spiData [1] >> 1)) & 0x3FF ; | |||
} | |||
@@ -1,7 +1,6 @@ | |||
/* | |||
* piFace.: | |||
* Arduino compatable (ish) Wiring library for the Raspberry Pi | |||
* Copyright (c) 2012-2013 Gordon Henderson | |||
* Copyright (c) 2012-2016 Gordon Henderson | |||
* | |||
* This file to interface with the PiFace peripheral device which | |||
* has an MCP23S17 GPIO device connected via the SPI bus. | |||
@@ -1,6 +1,6 @@ | |||
# | |||
# Makefile: | |||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||
# wiringPi - A "wiring" library for the Raspberry Pi | |||
# https://projects.drogon.net/wiring-pi | |||
# | |||
# Copyright (c) 2012-2015 Gordon Henderson | |||
@@ -33,7 +33,7 @@ INCLUDE = -I/usr/local/include | |||
CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe | |||
LDFLAGS = -L/usr/local/lib | |||
LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm | |||
LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt | |||
# Should not alter anything below this line | |||
############################################################################### | |||
@@ -1,12 +1,12 @@ | |||
# | |||
# Makefile: | |||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||
# wiringPi - A "wiring" library for the Raspberry Pi | |||
# https://projects.drogon.net/wiring-pi | |||
# | |||
# Copyright (c) 2012 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# 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 | |||
@@ -1,12 +1,12 @@ | |||
# | |||
# Makefile: | |||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||
# wiringPi - A "wiring" library for the Raspberry Pi | |||
# https://projects.drogon.net/wiring-pi | |||
# | |||
# Copyright (c) 2012-2015 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# 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 | |||
@@ -0,0 +1,61 @@ | |||
/* | |||
* blink-thread.c: | |||
* Standard "blink" program in wiringPi. Blinks an LED connected | |||
* to the first GPIO pin. | |||
* | |||
* 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> | |||
// LED Pin - wiringPi pin 0 is BCM_GPIO 17. | |||
#define LED 0 | |||
PI_THREAD (blinky) | |||
{ | |||
for (;;) | |||
{ | |||
digitalWrite (LED, HIGH) ; // On | |||
delay (500) ; // mS | |||
digitalWrite (LED, LOW) ; // Off | |||
delay (500) ; | |||
} | |||
} | |||
int main (void) | |||
{ | |||
printf ("Raspberry Pi blink\n") ; | |||
wiringPiSetup () ; | |||
pinMode (LED, OUTPUT) ; | |||
piThreadCreate (blinky) ; | |||
for (;;) | |||
{ | |||
printf ("Hello, world\n") ; | |||
delay (600) ; | |||
} | |||
return 0 ; | |||
} |
@@ -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) ; | |||
} | |||
} | |||
} |
@@ -25,7 +25,6 @@ | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include <wiringPi.h> | |||
#include <sys/time.h> | |||
@@ -34,17 +33,13 @@ | |||
int main() | |||
{ | |||
int x ; | |||
struct timeval t1, t2 ; | |||
struct timeval t1, t2, t3 ; | |||
int t ; | |||
int max, min ; | |||
int del ; | |||
int underRuns, overRuns, exactRuns, total ; | |||
int underRuns, overRuns, exactRuns, bogusRuns, total ; | |||
int descheds ; | |||
if (wiringPiSetup () == -1) | |||
return 1 ; | |||
piHiPri (10) ; sleep (1) ; | |||
// Baseline test | |||
@@ -58,21 +53,22 @@ int main() | |||
{ | |||
underRuns = overRuns = exactRuns = total = 0 ; | |||
descheds = 0 ; | |||
max = del ; | |||
min = del ; | |||
max = 0 ; | |||
min = 999 ; | |||
for (x = 0 ; x < CYCLES ; ++x) | |||
{ | |||
for (;;) // Repeat this if we get a delay over 999uS | |||
{ // -> High probability Linux has deschedulled us | |||
gettimeofday (&t1, NULL) ; | |||
delayMicroseconds (del) ; | |||
usleep (del) ; | |||
// delayMicroseconds (del) ; | |||
gettimeofday (&t2, NULL) ; | |||
if (t2.tv_usec < t1.tv_usec) // Counter wrapped | |||
t = (1000000 + t2.tv_usec) - t1.tv_usec; | |||
else | |||
t = t2.tv_usec - t1.tv_usec ; | |||
timersub (&t2, &t1, &t3) ; | |||
t = t3.tv_usec ; | |||
if (t > 999) | |||
{ | |||
++descheds ; | |||
@@ -82,25 +78,24 @@ int main() | |||
break ; | |||
} | |||
if (t == del) | |||
++exactRuns ; | |||
else if (t < del) | |||
++underRuns ; | |||
else if (t > del) | |||
++overRuns ; | |||
if (t > max) | |||
{ | |||
max = t ; | |||
++overRuns ; | |||
} | |||
else if (t < min) | |||
{ | |||
min = t ; | |||
++underRuns ; | |||
} | |||
else | |||
++exactRuns ; | |||
total += t ; | |||
} | |||
printf ("Delay: %3d. Min: %3d, Max: %3d, Unders: %3d, Overs: %3d, Exacts: %3d, Average: %3d, Descheds: %2d\n", | |||
del, min, max, underRuns, overRuns, exactRuns, total / CYCLES, descheds) ; | |||
fflush (stdout) ; | |||
delay (1) ; | |||
usleep (1000) ; | |||
} | |||
return 0 ; | |||
@@ -1,12 +1,12 @@ | |||
# | |||
# Makefile: | |||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||
# wiringPi - A "wiring" library for the Raspberry Pi | |||
# https://projects.drogon.net/wiring-pi | |||
# | |||
# Copyright (c) 2012-2013 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# 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 | |||
@@ -1,12 +1,12 @@ | |||
# | |||
# Makefile: | |||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||
# wiringPi - A "wiring" library for the Raspberry Pi | |||
# https://projects.drogon.net/wiring-pi | |||
# | |||
# Copyright (c) 2012-2015 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# 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 | |||
@@ -0,0 +1,103 @@ | |||
# | |||
# Makefile: | |||
# The gpio command: | |||
# A swiss-army knige of GPIO shenanigans. | |||
# https://projects.drogon.net/wiring-pi | |||
# | |||
# Copyright (c) 2012-2016 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 = gpio.c readall.c | |||
OBJ = $(SRC:.c=.o) | |||
all: gpio | |||
version.h: ../VERSION | |||
$Q echo Need to run newVersion above. | |||
gpio: $(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) gpio *~ core tags *.bak | |||
.PHONY: tags | |||
tags: $(SRC) | |||
$Q echo [ctags] | |||
$Q ctags $(SRC) | |||
.PHONY: install | |||
install: gpio | |||
$Q echo "[Install]" | |||
$Q cp gpio $(DESTDIR)$(PREFIX)/bin | |||
ifneq ($(WIRINGPI_SUID),0) | |||
$Q chown root.root $(DESTDIR)$(PREFIX)/bin/gpio | |||
$Q chmod 4755 $(DESTDIR)$(PREFIX)/bin/gpio | |||
endif | |||
$Q mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1 | |||
$Q cp gpio.1 $(DESTDIR)$(PREFIX)/share/man/man1 | |||
.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/usr/share/man/man1 | |||
$Q install -m 0644 gpio.1 ~/wiringPi/debian-template/wiringPi/usr/share/man/man1 | |||
.PHONY: uninstall | |||
uninstall: | |||
$Q echo "[UnInstall]" | |||
$Q rm -f $(DESTDIR)$(PREFIX)/bin/gpio | |||
$Q rm -f $(DESTDIR)$(PREFIX)/share/man/man1/gpio.1 | |||
.PHONY: depend | |||
depend: | |||
makedepend -Y $(SRC) | |||
# DO NOT DELETE | |||
gpio.o: ../version.h |
@@ -1,4 +1,4 @@ | |||
.TH GPIO 1 "September 2015" wiringPi "Command-Line access to Raspberry Pi's GPIO" | |||
.TH GPIO 1 "March 2018" wiringPi "Command-Line access to Raspberry Pi's GPIO" | |||
.SH NAME | |||
gpio \- Command-line access to Raspberry Pi's GPIO | |||
@@ -9,15 +9,20 @@ gpio \- Command-line access to Raspberry Pi's GPIO | |||
.PP | |||
.B gpio | |||
.B [ \-g | \-1 ] | |||
.B mode/read/write/aread/awrite/wb/pwm/clock ... | |||
.B mode/read/write/aread/awrite/wb/pwm/pwnTone/clock/toggle/blink ... | |||
.PP | |||
.B gpio | |||
.B [ \-x extension:params ] | |||
.B mode/read/write/aread/awrite/pwm/pwmTone ... | |||
.B mode/read/write/aread/awrite/pwm/toggle/blink ... | |||
.PP | |||
.B gpio | |||
.B [ \-p ] | |||
.B read/write/toggle/wb | |||
.B read/write/toggle/blink | |||
.B ... | |||
.PP | |||
.B gpio | |||
.B [ \-p ] | |||
.B pwnTone pin frequency | |||
.B ... | |||
.PP | |||
.B gpio | |||
@@ -119,10 +124,22 @@ Write the given value (0 or 1) to the pin. You need to set the pin | |||
to output mode first. | |||
.TP | |||
.B toggle <pin> | |||
Changes the state of a GPIO pin; 0 to 1, or 1 to 0. | |||
Note unlike the blink command, the pin must be in output mode first. | |||
.TP | |||
.B blink <pin> | |||
Blinks the given pin on/off. Press Control-C to exit. | |||
Note: This command explicitly sets the pin to output mode. | |||
.TP | |||
.B aread <pin> | |||
Read the analog value of the given pin. This needs to be uses in | |||
Read the analog value of the given pin. This needs to be used in | |||
conjunction with a -x flag to add in an extension that handles analog | |||
inputs. respective logic levels. | |||
inputs. | |||
e.g. gpio -x mcp3002:200:0 aread 200 | |||
@@ -132,7 +149,7 @@ will read the first analog input on an mcp3002 SPI ADC chip. | |||
.B awrite <pin> <value> | |||
Write the analog value to the given pin. This needs to be used in | |||
conjunction with a -x flag to add in an extension that handles analog | |||
inputs. respective logic levels. | |||
inputs. | |||
e.g. gpio -x mcp4802:200:0 awrite 200 128 | |||
@@ -234,7 +251,7 @@ absolutely sure you know what you're doing. | |||
high | low | |||
Change the USB current limiter to high (1.2 amps) or low (the default, 600mA) | |||
This is only applicable to the model B+ | |||
This is only applicable to the Model B+ and the Model B, v2. | |||
.TP | |||
.B pwm-bal/pwm-ms | |||
@@ -245,32 +262,6 @@ Change the PWM mode to balanced (the default) or mark:space ratio (traditional) | |||
Change the PWM range register. The default is 1024. | |||
.TP | |||
.B load i2c [baudrate] | |||
This loads the i2c or drivers into the kernel and changes the permissions | |||
on the associated /dev/ entries so that the current user has access to | |||
them. Optionally it will set the I2C baudrate to that supplied in Kb/sec | |||
(or as close as the Pi can manage) The default speed is 100Kb/sec. | |||
Note: On recent kernels with the device tree enabled you should use the | |||
raspi-config program to load/unload the I2C device at boot time. | |||
(or disable the device tree to continue to use this method) | |||
.TP | |||
.B load spi | |||
This loads the spi drivers into the kernel and changes the permissions | |||
on the associated /dev/ entries so that the current user has access to | |||
them. It used to have the ability to change the buffer size from the | |||
default of 4096 bytes to an arbitrary value, however for some time the | |||
Pi Foundation have compiled the SPI device driver into the kernel and | |||
this has fixed the buffer size. The way to change it now is to edit | |||
the /boot/cmdline.txt file and add on spdev.bufsiz=8192 to set it to | |||
e.g. 8192 bytes then reboot. | |||
Note: On recent kernels with the device tree enabled you should use the | |||
raspi-config program to load/unload the SPI device at boot time. | |||
(or disable the device tree to continue to use this method) | |||
.TP | |||
.B gbr | |||
channel | |||
@@ -350,7 +341,7 @@ Please report bugs to <projects@drogon.net> | |||
.SH COPYRIGHT | |||
Copyright (c) 2012-2015 Gordon Henderson | |||
Copyright (c) 2012-2018 Gordon Henderson | |||
This is free software; see the source for copying conditions. There is NO | |||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |||
@@ -2,7 +2,7 @@ | |||
* gpio.c: | |||
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry | |||
* Pi's GPIO. | |||
* Copyright (c) 2012-2015 Gordon Henderson | |||
* Copyright (c) 2012-2018 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -40,7 +40,7 @@ | |||
#include <gertboard.h> | |||
#include <piFace.h> | |||
#include "version.h" | |||
#include "../version.h" | |||
extern int wiringPiDebug ; | |||
@@ -48,7 +48,7 @@ extern int wiringPiDebug ; | |||
extern void doReadall (void) ; | |||
extern void doAllReadall (void) ; | |||
extern void doPins (void) ; | |||
extern void doQmode (int argc, char *argv []) ; | |||
#ifndef TRUE | |||
# define TRUE (1==1) | |||
@@ -56,16 +56,21 @@ extern void doPins (void) ; | |||
#endif | |||
#define PI_USB_POWER_CONTROL 38 | |||
#define I2CDETECT "/usr/sbin/i2cdetect" | |||
#define I2CDETECT "i2cdetect" | |||
#define MODPROBE "modprobe" | |||
#define RMMOD "rmmod" | |||
int wpMode ; | |||
char *usage = "Usage: gpio -v\n" | |||
" gpio -h\n" | |||
" gpio [-g|-1] [-x extension:params] ...\n" | |||
" gpio [-g|-1] ...\n" | |||
" gpio [-d] ...\n" | |||
" [-x extension:params] [[ -x ...]] ...\n" | |||
" gpio [-p] <read/write/wb> ...\n" | |||
" gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n" | |||
" gpio readall/reset\n" | |||
" gpio <mode/read/write/aread/awritewb/pwm/pwmTone/clock> ...\n" | |||
" gpio <toggle/blink> <pin>\n" | |||
" gpio readall\n" | |||
" gpio unexportall/exports\n" | |||
" gpio export/edge/unexport ...\n" | |||
" gpio wfi <pin> <mode>\n" | |||
@@ -76,6 +81,8 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio load spi/i2c\n" | |||
" gpio unload spi/i2c\n" | |||
" gpio i2cd/i2cdetect\n" | |||
" gpio rbx/rbd\n" | |||
" gpio wb <value>\n" | |||
" gpio usbp high/low\n" | |||
" gpio gbr <channel>\n" | |||
" gpio gbw <channel> <value>" ; // No trailing newline needed here. | |||
@@ -103,6 +110,45 @@ static int decodePin (const char *str) | |||
/* | |||
* findExecutable: | |||
* Code to locate the path to the given executable. We have a fixed list | |||
* of locations to try which completely overrides any $PATH environment. | |||
* This may be detrimental, however it avoids the reliance on $PATH | |||
* which may be a security issue when this program is run a set-uid-root. | |||
********************************************************************************* | |||
*/ | |||
static const char *searchPath [] = | |||
{ | |||
"/sbin", | |||
"/usr/sbin", | |||
"/bin", | |||
"/usr/bin", | |||
NULL, | |||
} ; | |||
static char *findExecutable (const char *progName) | |||
{ | |||
static char *path = NULL ; | |||
int len = strlen (progName) ; | |||
int i = 0 ; | |||
struct stat statBuf ; | |||
for (i = 0 ; searchPath [i] != NULL ; ++i) | |||
{ | |||
path = malloc (strlen (searchPath [i]) + len + 2) ; | |||
sprintf (path, "%s/%s", searchPath [i], progName) ; | |||
if (stat (path, &statBuf) == 0) | |||
return path ; | |||
free (path) ; | |||
} | |||
return NULL ; | |||
} | |||
/* | |||
* changeOwner: | |||
* Change the ownership of the file to the real userId of the calling | |||
* program so we can access it. | |||
@@ -175,9 +221,7 @@ static void checkDevTree (char *argv []) | |||
fprintf (stderr, | |||
"%s: Unable to load/unload modules as this Pi has the device tree enabled.\n" | |||
" You need to run the raspi-config program (as root) and select the\n" | |||
" modules (SPI or I2C) that you wish to load/unload there and reboot.\n" | |||
" There is more information here:\n" | |||
" https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=97314\n", argv [0]) ; | |||
" modules (SPI or I2C) that you wish to load/unload there and reboot.\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
} | |||
@@ -230,15 +274,18 @@ static void doLoad (int argc, char *argv []) | |||
else | |||
_doLoadUsage (argv) ; | |||
if (findExecutable ("modprobe") == NULL) | |||
printf ("No found\n") ; | |||
if (!moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "/sbin/modprobe %s%s", module1, args1) ; | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ; | |||
system (cmd) ; | |||
} | |||
if (!moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "/sbin/modprobe %s%s", module2, args2) ; | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ; | |||
system (cmd) ; | |||
} | |||
@@ -292,13 +339,13 @@ static void doUnLoad (int argc, char *argv []) | |||
if (moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "/sbin/rmmod %s", module1) ; | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ; | |||
system (cmd) ; | |||
} | |||
if (moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "/sbin/rmmod %s", module2) ; | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ; | |||
system (cmd) ; | |||
} | |||
} | |||
@@ -310,13 +357,12 @@ static void doUnLoad (int argc, char *argv []) | |||
********************************************************************************* | |||
*/ | |||
static void doI2Cdetect (int argc, char *argv []) | |||
static void doI2Cdetect (UNU int argc, char *argv []) | |||
{ | |||
int port = piBoardRev () == 1 ? 0 : 1 ; | |||
char command [128] ; | |||
struct stat statBuf ; | |||
int port = piGpioLayout () == 1 ? 0 : 1 ; | |||
char *c, *command ; | |||
if (stat (I2CDETECT, &statBuf) < 0) | |||
if ((c = findExecutable (I2CDETECT)) == NULL) | |||
{ | |||
fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ; | |||
return ; | |||
@@ -328,7 +374,8 @@ static void doI2Cdetect (int argc, char *argv []) | |||
return ; | |||
} | |||
sprintf (command, "%s -y %d", I2CDETECT, port) ; | |||
command = malloc (strlen (c) + 16) ; | |||
sprintf (command, "%s -y %d", c, port) ; | |||
if (system (command) < 0) | |||
fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ; | |||
@@ -341,7 +388,7 @@ static void doI2Cdetect (int argc, char *argv []) | |||
********************************************************************************* | |||
*/ | |||
static void doExports (int argc, char *argv []) | |||
static void doExports (UNU int argc, UNU char *argv []) | |||
{ | |||
int fd ; | |||
int i, l, first ; | |||
@@ -667,7 +714,7 @@ void doUnexportall (char *progName) | |||
********************************************************************************* | |||
*/ | |||
static void doReset (char *progName) | |||
static void doReset (UNU char *progName) | |||
{ | |||
printf ("GPIO Reset is dangerous and has been removed from the gpio command.\n") ; | |||
printf (" - Please write a shell-script to reset the GPIO pins into the state\n") ; | |||
@@ -943,7 +990,7 @@ static void doAwrite (int argc, char *argv []) | |||
/* | |||
* doWriteByte: | |||
* gpio write value | |||
* gpio wb value | |||
********************************************************************************* | |||
*/ | |||
@@ -964,6 +1011,30 @@ static void doWriteByte (int argc, char *argv []) | |||
/* | |||
* doReadByte: | |||
* gpio rbx|rbd value | |||
********************************************************************************* | |||
*/ | |||
static void doReadByte (int argc, char *argv [], int printHex) | |||
{ | |||
int val ; | |||
if (argc != 2) | |||
{ | |||
fprintf (stderr, "Usage: %s rbx|rbd\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
val = digitalReadByte () ; | |||
if (printHex) | |||
printf ("%02X\n", val) ; | |||
else | |||
printf ("%d\n", val) ; | |||
} | |||
/* | |||
* doRead: | |||
* Read a pin and return the value | |||
********************************************************************************* | |||
@@ -1027,6 +1098,34 @@ void doToggle (int argc, char *argv []) | |||
/* | |||
* doBlink: | |||
* Blink an IO pin | |||
********************************************************************************* | |||
*/ | |||
void doBlink (int argc, char *argv []) | |||
{ | |||
int pin ; | |||
if (argc != 3) | |||
{ | |||
fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
pin = atoi (argv [2]) ; | |||
pinMode (pin, OUTPUT) ; | |||
for (;;) | |||
{ | |||
digitalWrite (pin, !digitalRead (pin)) ; | |||
delay (500) ; | |||
} | |||
} | |||
/* | |||
* doPwmTone: | |||
* Output a tone in a PWM pin | |||
********************************************************************************* | |||
@@ -1162,9 +1261,14 @@ static void doVersion (char *argv []) | |||
{ | |||
int model, rev, mem, maker, warranty ; | |||
struct stat statBuf ; | |||
char name [80] ; | |||
FILE *fd ; | |||
int vMaj, vMin ; | |||
printf ("gpio version: %s\n", VERSION) ; | |||
printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ; | |||
wiringPiVersion (&vMaj, &vMin) ; | |||
printf ("gpio version: %d.%d\n", vMaj, vMin) ; | |||
printf ("Copyright (c) 2012-2018 Gordon Henderson\n") ; | |||
printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; | |||
printf ("For details type: %s -warranty\n", argv [0]) ; | |||
printf ("\n") ; | |||
@@ -1179,12 +1283,18 @@ static void doVersion (char *argv []) | |||
if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | |||
printf (" * Device tree is enabled.\n") ; | |||
if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO | |||
if (stat ("/proc/device-tree/model", &statBuf) == 0) // Output Kernel idea of board type | |||
{ | |||
printf (" * This Raspberry Pi supports user-level GPIO access.\n") ; | |||
printf (" -> See the man-page for more details\n") ; | |||
printf (" -> ie. export WIRINGPI_GPIOMEM=1\n") ; | |||
if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL) | |||
{ | |||
fgets (name, 80, fd) ; | |||
fclose (fd) ; | |||
printf (" *--> %s\n", name) ; | |||
} | |||
} | |||
if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO | |||
printf (" * This Raspberry Pi supports user-level GPIO access.\n") ; | |||
else | |||
printf (" * Root or sudo required for GPIO access.\n") ; | |||
} | |||
@@ -1208,8 +1318,11 @@ int main (int argc, char *argv []) | |||
if (argc == 1) | |||
{ | |||
fprintf (stderr, "%s\n", usage) ; | |||
return 1 ; | |||
fprintf (stderr, | |||
"%s: At your service!\n" | |||
" Type: gpio -h for full details and\n" | |||
" gpio readall for a quick printout of your connector details\n", argv [0]) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
// Help | |||
@@ -1217,7 +1330,7 @@ int main (int argc, char *argv []) | |||
if (strcasecmp (argv [1], "-h") == 0) | |||
{ | |||
printf ("%s: %s\n", argv [0], usage) ; | |||
return 0 ; | |||
exit (EXIT_SUCCESS) ; | |||
} | |||
// Version & Warranty | |||
@@ -1225,8 +1338,8 @@ int main (int argc, char *argv []) | |||
if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0)) | |||
{ | |||
printf ("%d\n", piBoardRev ()) ; | |||
return 0 ; | |||
printf ("%d\n", piGpioLayout ()) ; | |||
exit (EXIT_SUCCESS) ; | |||
} | |||
// Version and information | |||
@@ -1234,13 +1347,13 @@ int main (int argc, char *argv []) | |||
if (strcmp (argv [1], "-v") == 0) | |||
{ | |||
doVersion (argv) ; | |||
return 0 ; | |||
exit (EXIT_SUCCESS) ; | |||
} | |||
if (strcasecmp (argv [1], "-warranty") == 0) | |||
{ | |||
printf ("gpio version: %s\n", VERSION) ; | |||
printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ; | |||
printf ("Copyright (c) 2012-2018 Gordon Henderson\n") ; | |||
printf ("\n") ; | |||
printf (" This program is free software; you can redistribute it and/or modify\n") ; | |||
printf (" it under the terms of the GNU Leser General Public License as published\n") ; | |||
@@ -1255,13 +1368,13 @@ int main (int argc, char *argv []) | |||
printf (" You should have received a copy of the GNU Lesser General Public License\n") ; | |||
printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ; | |||
printf ("\n") ; | |||
return 0 ; | |||
exit (EXIT_SUCCESS) ; | |||
} | |||
if (geteuid () != 0) | |||
{ | |||
fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ; | |||
return 1 ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
// Initial test for /sys/class/gpio operations: | |||
@@ -1331,6 +1444,16 @@ int main (int argc, char *argv []) | |||
wpMode = WPI_MODE_PIFACE ; | |||
} | |||
// Check for -z argument so we don't actually initialise wiringPi | |||
else if (strcasecmp (argv [1], "-z") == 0) | |||
{ | |||
for (i = 2 ; i < argc ; ++i) | |||
argv [i - 1] = argv [i] ; | |||
--argc ; | |||
wpMode = WPI_MODE_UNINITIALISED ; | |||
} | |||
// Default to wiringPi mode | |||
else | |||
@@ -1340,17 +1463,25 @@ int main (int argc, char *argv []) | |||
} | |||
// Check for -x argument to load in a new extension | |||
// -x extension:base:args | |||
// Can load many modules, but unless daemon mode we can only send one | |||
// command at a time. | |||
if (strcasecmp (argv [1], "-x") == 0) | |||
while (strcasecmp (argv [1], "-x") == 0) | |||
{ | |||
if (argc < 3) | |||
{ | |||
fprintf (stderr, "%s: -x missing extension specification.\n", argv [0]) ; | |||
fprintf (stderr, "%s: -x missing extension command.\n", argv [0]) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
if (!loadWPiExtension (argv [0], argv [2], TRUE)) // Prints its own error messages | |||
if (!loadWPiExtension (argv [0], argv [2], TRUE)) | |||
{ | |||
fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
// Shift args down by 2 | |||
for (i = 3 ; i < argc ; ++i) | |||
argv [i - 2] = argv [i] ; | |||
@@ -1375,6 +1506,7 @@ int main (int argc, char *argv []) | |||
// GPIO Nicies | |||
else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ; | |||
else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ; | |||
// Pi Specifics | |||
@@ -1386,11 +1518,14 @@ int main (int argc, char *argv []) | |||
else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ; | |||
else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ; | |||
else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ; | |||
else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ; | |||
else if (strcasecmp (argv [1], "pins" ) == 0) doReadall () ; | |||
else if (strcasecmp (argv [1], "qmode" ) == 0) doQmode (argc, argv) ; | |||
else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect (argc, argv) ; | |||
else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ; | |||
else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ; | |||
else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ; | |||
else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ; | |||
else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ; | |||
else if (strcasecmp (argv [1], "clock" ) == 0) doClock (argc, argv) ; | |||
else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; | |||
else | |||
@@ -1398,5 +1533,6 @@ int main (int argc, char *argv []) | |||
fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
return 0 ; | |||
} |
@@ -5,7 +5,7 @@ | |||
# Copyright (c) 2013-2015 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# 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 | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* readall.c: | |||
* The readall functions - getting a bit big, so split them out. | |||
* Copyright (c) 2012-2015 Gordon Henderson | |||
* Copyright (c) 2012-2018 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -118,7 +118,7 @@ static char *physNames [64] = | |||
NULL, | |||
" 3.3v", "5v ", | |||
" SDA.1", "5V ", | |||
" SDA.1", "5v ", | |||
" SCL.1", "0v ", | |||
"GPIO. 7", "TxD ", | |||
" 0v", "RxD ", | |||
@@ -287,22 +287,26 @@ void abReadall (int model, int rev) | |||
/* | |||
* piPlusReadall: | |||
* Read all the pins on the model A+ or the B+ | |||
* Read all the pins on the model A+ or the B+ or actually, all 40-pin Pi's | |||
********************************************************************************* | |||
*/ | |||
static void plus2header (int model) | |||
{ | |||
/**/ if (model == PI_MODEL_AP) | |||
printf (" +-----+-----+---------+------+---+--A Plus--+---+------+---------+-----+-----+\n") ; | |||
printf (" +-----+-----+---------+------+---+---Pi A+--+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_BP) | |||
printf (" +-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+\n") ; | |||
printf (" +-----+-----+---------+------+---+---Pi B+--+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_ZERO) | |||
printf (" +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_ZERO_W) | |||
printf (" +-----+-----+---------+------+---+-Pi ZeroW-+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_2) | |||
printf (" +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_3) | |||
printf (" +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_3P) | |||
printf (" +-----+-----+---------+------+---+---Pi 3+--+---+------+---------+-----+-----+\n") ; | |||
else | |||
printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; | |||
} | |||
@@ -346,14 +350,18 @@ void doReadall (void) | |||
/**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B)) | |||
abReadall (model, rev) ; | |||
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO)) | |||
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || | |||
(model == PI_MODEL_2) || | |||
(model == PI_MODEL_3) || (model == PI_MODEL_3P) || | |||
(model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W)) | |||
piPlusReadall (model) ; | |||
else if (model == PI_MODEL_CM) | |||
else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) | |||
allReadall () ; | |||
else | |||
printf ("Oops - unable to determine board type... model: %d\n", model) ; | |||
} | |||
/* | |||
* doAllReadall: | |||
* Force reading of all pins regardless of Pi model | |||
@@ -364,3 +372,24 @@ void doAllReadall (void) | |||
{ | |||
allReadall () ; | |||
} | |||
/* | |||
* doQmode: | |||
* Query mode on a pin | |||
********************************************************************************* | |||
*/ | |||
void doQmode (int argc, char *argv []) | |||
{ | |||
int pin ; | |||
if (argc != 3) | |||
{ | |||
fprintf (stderr, "Usage: %s qmode pin\n", argv [0]) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
pin = atoi (argv [2]) ; | |||
printf ("%s\n", alts [getAlt (pin)]) ; | |||
} |
@@ -5,7 +5,7 @@ | |||
# in-turn. | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# 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 | |||
@@ -1 +0,0 @@ | |||
#define VERSION "2.32" |
@@ -7,7 +7,7 @@ | |||
# Copyright (c) 2012-2015 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# 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 | |||
@@ -25,8 +25,12 @@ | |||
echo Updating to version: `cat VERSION` | |||
rm -f gpio/version.h | |||
echo "#define VERSION \"`cat VERSION`\"" > gpio/version.h | |||
rm -f version.h | |||
vMaj=`cut -d. -f1 VERSION` | |||
vMin=`cut -d. -f2 VERSION` | |||
echo "#define VERSION \"`cat VERSION`\"" > version.h | |||
echo "#define VERSION_MAJOR $vMaj" >> version.h | |||
echo "#define VERSION_MINOR $vMin" >> version.h | |||
rm -f debian-template/wiringPi/DEBIAN/control | |||
cat > debian-template/wiringPi/DEBIAN/control <<EOF | |||
@@ -39,5 +43,5 @@ Depends: libc6 | |||
Maintainer: Gordon Henderson <projects@drogon.net> | |||
Description: The wiringPi libraries, headers and gpio command | |||
Libraries to allow GPIO access on a Raspberry Pi from C and C++ | |||
programs as well as from the command-line | |||
and BASIC programs as well as from the command-line | |||
EOF |
@@ -0,0 +1,5 @@ | |||
#!/bin/sh | |||
# update - update source files from master on yakko | |||
rsync -aHx --exclude='*.o' --exclude='*~' -v --delete gordon@yakko:rpi/git/wiringPi/ . |
@@ -0,0 +1,3 @@ | |||
#define VERSION "2.46" | |||
#define VERSION_MAJOR 2 | |||
#define VERSION_MINOR 46 |
@@ -0,0 +1,165 @@ | |||
# | |||
# Makefile: | |||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||
# | |||
# Copyright (c) 2012-2015 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/>. | |||
################################################################################# | |||
VERSION=$(shell cat ../VERSION) | |||
DESTDIR?=/usr | |||
PREFIX?=/local | |||
LDCONFIG?=ldconfig | |||
ifneq ($V,1) | |||
Q ?= @ | |||
endif | |||
STATIC=libwiringPi.a | |||
DYNAMIC=libwiringPi.so.$(VERSION) | |||
#DEBUG = -g -O0 | |||
DEBUG = -O2 | |||
CC = gcc | |||
INCLUDE = -I. | |||
DEFS = -D_GNU_SOURCE | |||
CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline $(INCLUDE) -pipe -fPIC | |||
#CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Wconversion -Winline $(INCLUDE) -pipe -fPIC | |||
LIBS = -lm -lpthread -lrt -lcrypt | |||
############################################################################### | |||
SRC = wiringPi.c \ | |||
wiringSerial.c wiringShift.c \ | |||
piHiPri.c piThread.c \ | |||
wiringPiSPI.c wiringPiI2C.c \ | |||
softPwm.c softTone.c \ | |||
mcp23008.c mcp23016.c mcp23017.c \ | |||
mcp23s08.c mcp23s17.c \ | |||
sr595.c \ | |||
pcf8574.c pcf8591.c \ | |||
mcp3002.c mcp3004.c mcp4802.c mcp3422.c \ | |||
max31855.c max5322.c ads1115.c \ | |||
sn3218.c \ | |||
bmp180.c htu21d.c ds18b20.c rht03.c \ | |||
drcSerial.c drcNet.c \ | |||
pseudoPins.c \ | |||
wpiExtensions.c | |||
HEADERS = $(shell ls *.h) | |||
OBJ = $(SRC:.c=.o) | |||
all: $(DYNAMIC) | |||
.PHONY: static | |||
static: | |||
$Q cat noMoreStatic | |||
$(DYNAMIC): $(OBJ) | |||
$Q echo "[Link (Dynamic)]" | |||
$Q $(CC) -shared -Wl,-soname,libwiringPi.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPi.so.$(VERSION) $(LIBS) $(OBJ) | |||
.c.o: | |||
$Q echo [Compile] $< | |||
$Q $(CC) -c $(CFLAGS) $< -o $@ | |||
.PHONY: clean | |||
clean: | |||
$Q echo "[Clean]" | |||
$Q rm -f $(OBJ) $(OBJ_I2C) *~ core tags Makefile.bak libwiringPi.* | |||
.PHONY: tags | |||
tags: $(SRC) | |||
$Q echo [ctags] | |||
$Q ctags $(SRC) | |||
.PHONY: install | |||
install: $(DYNAMIC) | |||
$Q echo "[Install Headers]" | |||
$Q install -m 0755 -d $(DESTDIR)$(PREFIX)/include | |||
$Q install -m 0644 $(HEADERS) $(DESTDIR)$(PREFIX)/include | |||
$Q echo "[Install Dynamic Lib]" | |||
$Q install -m 0755 -d $(DESTDIR)$(PREFIX)/lib | |||
$Q install -m 0755 libwiringPi.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) | |||
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so | |||
$Q $(LDCONFIG) | |||
.PHONY: install-deb | |||
install-deb: $(DYNAMIC) | |||
$Q echo "[Install Headers: deb]" | |||
$Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/include | |||
$Q install -m 0644 $(HEADERS) ~/wiringPi/debian-template/wiringPi/usr/include | |||
$Q echo "[Install Dynamic Lib: deb]" | |||
install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/lib | |||
install -m 0755 libwiringPi.so.$(VERSION) ~/wiringPi/debian-template/wiringPi/usr/lib/libwiringPi.so.$(VERSION) | |||
ln -sf ~/wiringPi/debian-template/wiringPi/usr/lib/libwiringPi.so.$(VERSION) ~/wiringPi/debian-template/wiringPi/usr/lib/libwiringPi.so | |||
.PHONY: uninstall | |||
uninstall: | |||
$Q echo "[UnInstall]" | |||
$Q cd $(DESTDIR)$(PREFIX)/include/ && rm -f $(HEADERS) | |||
$Q cd $(DESTDIR)$(PREFIX)/lib/ && rm -f libwiringPi.* | |||
$Q $(LDCONFIG) | |||
.PHONY: depend | |||
depend: | |||
makedepend -Y $(SRC) $(SRC_I2C) | |||
# DO NOT DELETE | |||
wiringPi.o: softPwm.h softTone.h wiringPi.h ../version.h | |||
wiringSerial.o: wiringSerial.h | |||
wiringShift.o: wiringPi.h wiringShift.h | |||
piHiPri.o: wiringPi.h | |||
piThread.o: wiringPi.h | |||
wiringPiSPI.o: wiringPi.h wiringPiSPI.h | |||
wiringPiI2C.o: wiringPi.h wiringPiI2C.h | |||
softPwm.o: wiringPi.h softPwm.h | |||
softTone.o: wiringPi.h softTone.h | |||
mcp23008.o: wiringPi.h wiringPiI2C.h mcp23x0817.h mcp23008.h | |||
mcp23016.o: wiringPi.h wiringPiI2C.h mcp23016.h mcp23016reg.h | |||
mcp23017.o: wiringPi.h wiringPiI2C.h mcp23x0817.h mcp23017.h | |||
mcp23s08.o: wiringPi.h wiringPiSPI.h mcp23x0817.h mcp23s08.h | |||
mcp23s17.o: wiringPi.h wiringPiSPI.h mcp23x0817.h mcp23s17.h | |||
sr595.o: wiringPi.h sr595.h | |||
pcf8574.o: wiringPi.h wiringPiI2C.h pcf8574.h | |||
pcf8591.o: wiringPi.h wiringPiI2C.h pcf8591.h | |||
mcp3002.o: wiringPi.h wiringPiSPI.h mcp3002.h | |||
mcp3004.o: wiringPi.h wiringPiSPI.h mcp3004.h | |||
mcp4802.o: wiringPi.h wiringPiSPI.h mcp4802.h | |||
mcp3422.o: wiringPi.h wiringPiI2C.h mcp3422.h | |||
max31855.o: wiringPi.h wiringPiSPI.h max31855.h | |||
max5322.o: wiringPi.h wiringPiSPI.h max5322.h | |||
ads1115.o: wiringPi.h wiringPiI2C.h ads1115.h | |||
sn3218.o: wiringPi.h wiringPiI2C.h sn3218.h | |||
bmp180.o: wiringPi.h wiringPiI2C.h bmp180.h | |||
htu21d.o: wiringPi.h wiringPiI2C.h htu21d.h | |||
ds18b20.o: wiringPi.h ds18b20.h | |||
drcSerial.o: wiringPi.h wiringSerial.h drcSerial.h | |||
pseudoPins.o: wiringPi.h pseudoPins.h | |||
wpiExtensions.o: wiringPi.h mcp23008.h mcp23016.h mcp23017.h mcp23s08.h | |||
wpiExtensions.o: mcp23s17.h sr595.h pcf8574.h pcf8591.h mcp3002.h mcp3004.h | |||
wpiExtensions.o: mcp4802.h mcp3422.h max31855.h max5322.h ads1115.h sn3218.h | |||
wpiExtensions.o: drcSerial.h pseudoPins.h bmp180.h htu21d.h ds18b20.h | |||
wpiExtensions.o: wpiExtensions.h |
@@ -228,7 +228,7 @@ static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int data) | |||
{ | |||
if ( (data < 0) || (data > 7) ) // Use default if out of range | |||
data = 4 ; | |||
node->data0 = dataRates [data] ; | |||
node->data1 = dataRates [data] ; // Bugfix 0-1 by "Eric de jong (gm)" <ericdejong@gmx.net> - Thanks. | |||
} | |||
} | |||
@@ -0,0 +1,237 @@ | |||
/* | |||
* bmp180.c: | |||
* Extend wiringPi with the BMP180 I2C Pressure and Temperature | |||
* sensor. This is used in the Pi Weather Station | |||
* Copyright (c) 2016 Gordon Henderson | |||
* | |||
* Information from the document held at: | |||
* http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf | |||
* was very useful when building this code. | |||
* | |||
*********************************************************************** | |||
* 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 <unistd.h> | |||
#include <stdint.h> | |||
#include <stdio.h> | |||
#include <math.h> | |||
#include "wiringPi.h" | |||
#include "wiringPiI2C.h" | |||
#include "bmp180.h" | |||
#undef DEBUG | |||
#define I2C_ADDRESS 0x77 | |||
#define BMP180_OSS 0 | |||
// Static calibration data | |||
// The down-side of this is that there can only be one BMP180 in | |||
// a system - which is practice isn't an issue as it's I2C | |||
// address is fixed. | |||
static int16_t AC1, AC2, AC3 ; | |||
static uint16_t AC4, AC5, AC6 ; | |||
static int16_t VB1, VB2 ; | |||
static int16_t MB, MC, MD ; | |||
static double c5, c6, mc, md, x0, x1, x2, yy0, yy1, yy2, p0, p1, p2 ; | |||
// Pressure & Temp variables | |||
uint32_t cPress, cTemp ; | |||
static int altitude ; | |||
/* | |||
* read16: | |||
* Quick hack to read the 16-bit data with the correct endian | |||
********************************************************************************* | |||
*/ | |||
uint16_t read16 (int fd, int reg) | |||
{ | |||
return (wiringPiI2CReadReg8 (fd, reg) << 8) | wiringPiI2CReadReg8 (fd, reg + 1) ; | |||
} | |||
/* | |||
* bmp180ReadTempPress: | |||
* Does the hard work of reading the sensor | |||
********************************************************************************* | |||
*/ | |||
static void bmp180ReadTempPress (int fd) | |||
{ | |||
double fTemp, fPress ; | |||
double tu, a ; | |||
double pu, s, x, y, z ; | |||
uint8_t data [4] ; | |||
// Start a temperature sensor reading | |||
wiringPiI2CWriteReg8 (fd, 0xF4, 0x2E) ; | |||
delay (5) ; | |||
// Read the raw data | |||
data [0] = wiringPiI2CReadReg8 (fd, 0xF6) ; | |||
data [1] = wiringPiI2CReadReg8 (fd, 0xF7) ; | |||
// And calculate... | |||
tu = (data [0] * 256.0) + data [1] ; | |||
a = c5 * (tu - c6) ; | |||
fTemp = a + (mc / (a + md)) ; | |||
cTemp = (int)rint (((100.0 * fTemp) + 0.5) / 10.0) ; | |||
#ifdef DEBUG | |||
printf ("fTemp: %f, cTemp: %6d\n", fTemp, cTemp) ; | |||
#endif | |||
// Start a pressure snsor reading | |||
wiringPiI2CWriteReg8 (fd, 0xF4, 0x34 | (BMP180_OSS << 6)) ; | |||
delay (5) ; | |||
// Read the raw data | |||
data [0] = wiringPiI2CReadReg8 (fd, 0xF6) ; | |||
data [1] = wiringPiI2CReadReg8 (fd, 0xF7) ; | |||
data [2] = wiringPiI2CReadReg8 (fd, 0xF8) ; | |||
// And calculate... | |||
pu = ((double)data [0] * 256.0) + (double)data [1] + ((double)data [2] / 256.0) ; | |||
s = fTemp - 25.0 ; | |||
x = (x2 * pow (s, 2.0)) + (x1 * s) + x0 ; | |||
y = (yy2 * pow (s, 2.0)) + (yy1 * s) + yy0 ; | |||
z = (pu - x) / y ; | |||
fPress = (p2 * pow (z, 2.0)) + (p1 * z) + p0 ; | |||
cPress = (int)rint (((100.0 * fPress) + 0.5) / 10.0) ; | |||
#ifdef DEBUG | |||
printf ("fPress: %f, cPress: %6d\n", fPress, cPress) ; | |||
#endif | |||
} | |||
/* | |||
* myAnalogWrite: | |||
* Write to a fake register to represent the height above sea level | |||
* so that the peudo millibar register can read the pressure in mB | |||
********************************************************************************* | |||
*/ | |||
static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) | |||
{ | |||
int chan = pin - node->pinBase ; | |||
if (chan == 0) | |||
altitude = value ; | |||
} | |||
/* | |||
* myAnalogRead: | |||
********************************************************************************* | |||
*/ | |||
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) | |||
{ | |||
int chan = pin - node->pinBase ; | |||
bmp180ReadTempPress (node->fd) ; | |||
/**/ if (chan == 0) // Read Temperature | |||
return cTemp ; | |||
else if (chan == 1) // Pressure | |||
return cPress ; | |||
else if (chan == 2) // Pressure in mB | |||
return cPress / pow (1 - ((double)altitude / 44330.0), 5.255) ; | |||
else | |||
return -9999 ; | |||
} | |||
/* | |||
* bmp180Setup: | |||
* Create a new instance of a PCF8591 I2C GPIO interface. We know it | |||
* has 4 pins, (4 analog inputs and 1 analog output which we'll shadow | |||
* input 0) so all we need to know here is the I2C address and the | |||
* user-defined pin base. | |||
********************************************************************************* | |||
*/ | |||
int bmp180Setup (const int pinBase) | |||
{ | |||
double c3, c4, b1 ; | |||
int fd ; | |||
struct wiringPiNodeStruct *node ; | |||
if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0) | |||
return FALSE ; | |||
node = wiringPiNewNode (pinBase, 4) ; | |||
node->fd = fd ; | |||
node->analogRead = myAnalogRead ; | |||
node->analogWrite = myAnalogWrite ; | |||
// Read calibration data | |||
AC1 = read16 (fd, 0xAA) ; | |||
AC2 = read16 (fd, 0xAC) ; | |||
AC3 = read16 (fd, 0xAE) ; | |||
AC4 = read16 (fd, 0xB0) ; | |||
AC5 = read16 (fd, 0xB2) ; | |||
AC6 = read16 (fd, 0xB4) ; | |||
VB1 = read16 (fd, 0xB6) ; | |||
VB2 = read16 (fd, 0xB8) ; | |||
MB = read16 (fd, 0xBA) ; | |||
MC = read16 (fd, 0xBC) ; | |||
MD = read16 (fd, 0xBE) ; | |||
// Calculate coefficients | |||
c3 = 160.0 * pow (2.0, -15.0) * AC3 ; | |||
c4 = pow (10.0, -3.0) * pow(2.0,-15.0) * AC4 ; | |||
b1 = pow (160.0, 2.0) * pow(2.0,-30.0) * VB1 ; | |||
c5 = (pow (2.0, -15.0) / 160.0) * AC5 ; | |||
c6 = AC6 ; | |||
mc = (pow (2.0, 11.0) / pow(160.0,2.0)) * MC ; | |||
md = MD / 160.0 ; | |||
x0 = AC1 ; | |||
x1 = 160.0 * pow (2.0, -13.0) * AC2 ; | |||
x2 = pow (160.0, 2.0) * pow(2.0,-25.0) * VB2 ; | |||
yy0 = c4 * pow (2.0, 15.0) ; | |||
yy1 = c4 * c3 ; | |||
yy2 = c4 * b1 ; | |||
p0 = (3791.0 - 8.0) / 1600.0 ; | |||
p1 = 1.0 - 7357.0 * pow (2.0, -20.0) ; | |||
p2 = 3038.0 * 100.0 * pow (2.0, -36.0) ; | |||
return TRUE ; | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* bmp180.h: | |||
* Extend wiringPi with the BMP180 I2C Pressure and Temperature | |||
* sensor. | |||
* Copyright (c) 2016 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/>. | |||
*********************************************************************** | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
extern int bmp180Setup (const int pinBase) ; | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -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 ; | |||
} |
@@ -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 |
@@ -0,0 +1,146 @@ | |||
/* | |||
* ds18b20.c: | |||
* Extend wiringPi with the DS18B20 1-Wire temperature sensor. | |||
* This is used in the Pi Weather Station and many other places. | |||
* Copyright (c) 2016 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 <malloc.h> | |||
#include <ctype.h> | |||
#include "wiringPi.h" | |||
#include "ds18b20.h" | |||
#define W1_PREFIX "/sys/bus/w1/devices/28-" | |||
#define W1_POSTFIX "/w1_slave" | |||
/* | |||
* myAnalogRead: | |||
********************************************************************************* | |||
*/ | |||
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) | |||
{ | |||
int chan = pin - node->pinBase ; | |||
int fd = node->fd ; | |||
char buffer [4096] ; | |||
char *p ; | |||
int temp, sign ; | |||
if (chan != 0) | |||
return -9999 ; | |||
// Rewind the file - we're keeping it open to keep things going | |||
// smoothly | |||
lseek (fd, 0, SEEK_SET) ; | |||
// Read the file - we know it's only a couple of lines, so this ought to be | |||
// more than enough | |||
if (read (fd, buffer, 4096) <= 0) // Read nothing, or it failed in some odd way | |||
return -9998 ; | |||
// Look for YES, then t= | |||
if (strstr (buffer, "YES") == NULL) | |||
return -9997 ; | |||
if ((p = strstr (buffer, "t=")) == NULL) | |||
return -9996 ; | |||
// p points to the 't', so we skip over it... | |||
p += 2 ; | |||
// and extract the number | |||
// (without caring about overflow) | |||
if (*p == '-') // Negative number? | |||
{ | |||
sign = -1 ; | |||
++p ; | |||
} | |||
else | |||
sign = 1 ; | |||
temp = 0 ; | |||
while (isdigit (*p)) | |||
{ | |||
temp = temp * 10 + (*p - '0') ; | |||
++p ; | |||
} | |||
// We know it returns temp * 1000, but we only really want temp * 10, so | |||
// do a bit of rounding... | |||
temp = (temp + 50) / 100 ; | |||
return temp * sign ; | |||
} | |||
/* | |||
* ds18b20Setup: | |||
* Create a new instance of a DS18B20 temperature sensor. | |||
********************************************************************************* | |||
*/ | |||
int ds18b20Setup (const int pinBase, const char *deviceId) | |||
{ | |||
int fd ; | |||
struct wiringPiNodeStruct *node ; | |||
char *fileName ; | |||
// Allocate space for the filename | |||
if ((fileName = malloc (strlen (W1_PREFIX) + strlen (W1_POSTFIX) + strlen (deviceId) + 1)) == NULL) | |||
return FALSE ; | |||
sprintf (fileName, "%s%s%s", W1_PREFIX, deviceId, W1_POSTFIX) ; | |||
fd = open (fileName, O_RDONLY) ; | |||
free (fileName) ; | |||
if (fd < 0) | |||
return FALSE ; | |||
// We'll keep the file open, to make access a little faster | |||
// although it's very slow reading these things anyway )-: | |||
node = wiringPiNewNode (pinBase, 1) ; | |||
node->fd = fd ; | |||
node->analogRead = myAnalogRead ; | |||
return TRUE ; | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* bmp180.h: | |||
* Extend wiringPi with the BMP180 I2C Pressure and Temperature | |||
* sensor. | |||
* Copyright (c) 2016 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/>. | |||
*********************************************************************** | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
extern int ds18b20Setup (const int pinBase, const char *serialNum) ; | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -0,0 +1,150 @@ | |||
/* | |||
* htu21d.c: | |||
* Extend wiringPi with the HTU21D I2C humidity and Temperature | |||
* sensor. This is used in the Pi Weather station. | |||
* Copyright (c) 2016 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 <unistd.h> | |||
#include <stdint.h> | |||
#include <stdio.h> | |||
#include <math.h> | |||
#include "wiringPi.h" | |||
#include "wiringPiI2C.h" | |||
#include "htu21d.h" | |||
#define DEBUG | |||
#undef FAKE_SENSOR | |||
#define I2C_ADDRESS 0x40 | |||
int checksum (UNU uint8_t data [4]) | |||
{ | |||
return TRUE ; | |||
} | |||
/* | |||
* myAnalogRead: | |||
********************************************************************************* | |||
*/ | |||
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) | |||
{ | |||
int chan = pin - node->pinBase ; | |||
int fd = node->fd ; | |||
uint8_t data [4] ; | |||
uint32_t sTemp, sHumid ; | |||
double fTemp, fHumid ; | |||
int cTemp, cHumid ; | |||
/**/ if (chan == 0) // Read Temperature | |||
{ | |||
// Send read temperature command: | |||
data [0] = 0xF3 ; | |||
if (write (fd, data, 1) != 1) | |||
return -9999 ; | |||
// Wait then read the data | |||
delay (50) ; | |||
if (read (fd, data, 3) != 3) | |||
return -9998 ; | |||
if (!checksum (data)) | |||
return -9997 ; | |||
// Do the calculation | |||
sTemp = (data [0] << 8) | data [1] ; | |||
fTemp = -48.85 + 175.72 * (double)sTemp / 63356.0 ; | |||
cTemp = (int)rint (((100.0 * fTemp) + 0.5) / 10.0) ; | |||
return cTemp ; | |||
} | |||
else if (chan == 1) // humidity | |||
{ | |||
// Send read humidity command: | |||
data [0] = 0xF5 ; | |||
if (write (fd, data, 1) != 1) | |||
return -9999 ; | |||
// Wait then read the data | |||
delay (50) ; | |||
if (read (fd, data, 3) != 3) | |||
return -9998 ; | |||
if (!checksum (data)) | |||
return -9997 ; | |||
sHumid = (data [0] << 8) | data [1] ; | |||
fHumid = -6.0 + 125.0 * (double)sHumid / 65536.0 ; | |||
cHumid = (int)rint (((100.0 * fHumid) + 0.5) / 10.0) ; | |||
return cHumid ; | |||
} | |||
else | |||
return -9999 ; | |||
} | |||
/* | |||
* htu21dSetup: | |||
* Create a new instance of a HTU21D I2C GPIO interface. | |||
* This chip has a fixed I2C address, so we are not providing any | |||
* allowance to change this. | |||
********************************************************************************* | |||
*/ | |||
int htu21dSetup (const int pinBase) | |||
{ | |||
int fd ; | |||
struct wiringPiNodeStruct *node ; | |||
uint8_t data ; | |||
int status ; | |||
if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0) | |||
return FALSE ; | |||
node = wiringPiNewNode (pinBase, 2) ; | |||
node->fd = fd ; | |||
node->analogRead = myAnalogRead ; | |||
// Send a reset code to it: | |||
data = 0xFE ; | |||
if (write (fd, &data, 1) != 1) | |||
return FALSE ; | |||
delay (15) ; | |||
// Read the status register to check it's really there | |||
status = wiringPiI2CReadReg8 (fd, 0xE7) ; | |||
return (status == 0x02) ? TRUE : FALSE ; | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* htu21d.h: | |||
* Extend wiringPi with the HTU21D I2C Humidity and Temperature | |||
* sensor. | |||
* Copyright (c) 2016 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/>. | |||
*********************************************************************** | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
extern int htu21dSetup (const int pinBase) ; | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -49,7 +49,7 @@ static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) | |||
wiringPiSPIDataRW (node->fd, spiData, 2) ; | |||
return ((spiData [0] << 7) | (spiData [1] >> 1)) & 0x3FF ; | |||
return ((spiData [0] << 8) | (spiData [1] >> 1)) & 0x3FF ; | |||
} | |||
@@ -0,0 +1,20 @@ | |||
wiringPi is no-longer shipped with the ability to statically link it. | |||
Many reasons but the biggest issue is people who have statically linked | |||
wiringPi into their product - for example a Pi UPS device or a Tetris-like | |||
game and not subsequently shipped their modified sources. These people are | |||
no better than common thieves with complete disregard to the conditions | |||
of the LGPL that wiringPi ships with. | |||
Additionally, many think it's a good idea to statically link wiringPi | |||
into their favourite language - like Node, and Java and other itsy bitsy | |||
little things. These people have a complete and utter disregard to what | |||
happens underneath when e.g. the Linux kernel changes on the Pi then | |||
wiringPi stops as it depends on some Pi kernel features, then the poor | |||
user get in-touch with me and I've had over 10,000 emails so-far and | |||
it's now beyond a joke. | |||
DO NOT STATICALLY LINK WIRINGPI. | |||
Gordon Henderson, March 2018. |
@@ -36,7 +36,7 @@ | |||
********************************************************************************* | |||
*/ | |||
static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) | |||
static void myAnalogWrite (struct wiringPiNodeStruct *node, UNU int pin, int value) | |||
{ | |||
unsigned char b [2] ; | |||
b [0] = 0x40 ; | |||
@@ -0,0 +1,95 @@ | |||
/* | |||
* pseudoPins.c: | |||
* Extend wiringPi with a number of pseudo pins which can be | |||
* digitally or analog written/read. | |||
* | |||
* Note: | |||
* Just one set of pseudo pins can exist per Raspberry Pi. | |||
* These pins are shared between all programs running on | |||
* that Raspberry Pi. The values are also persistant as | |||
* they live in shared RAM. This gives you a means for | |||
* temporary variable storing/sharing between programs, | |||
* or for other cunning things I've not thought of yet.. | |||
* | |||
* Copyright (c) 2012-2016 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 SHARED_NAME "wiringPiPseudoPins" | |||
#define PSEUDO_PINS 64 | |||
#include <unistd.h> | |||
#include <sys/types.h> | |||
#include <sys/mman.h> | |||
#include <sys/stat.h> | |||
#include <fcntl.h> | |||
#include <wiringPi.h> | |||
#include "pseudoPins.h" | |||
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) | |||
{ | |||
int *ptr = (int *)node->data0 ; | |||
int myPin = pin - node->pinBase ; | |||
return *(ptr + myPin) ; | |||
} | |||
static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) | |||
{ | |||
int *ptr = (int *)node->data0 ; | |||
int myPin = pin - node->pinBase ; | |||
*(ptr + myPin) = value ; | |||
} | |||
/* | |||
* pseudoPinsSetup: | |||
* Create a new wiringPi device node for the pseudoPins driver | |||
********************************************************************************* | |||
*/ | |||
int pseudoPinsSetup (const int pinBase) | |||
{ | |||
struct wiringPiNodeStruct *node ; | |||
void *ptr ; | |||
node = wiringPiNewNode (pinBase, PSEUDO_PINS) ; | |||
node->fd = shm_open (SHARED_NAME, O_CREAT | O_RDWR, 0666) ; | |||
if (node->fd < 0) | |||
return FALSE ; | |||
if (ftruncate (node->fd, PSEUDO_PINS * sizeof (int)) < 0) | |||
return FALSE ; | |||
ptr = mmap (NULL, PSEUDO_PINS * sizeof (int), PROT_READ | PROT_WRITE, MAP_SHARED, node->fd, 0) ; | |||
node->data0 = (unsigned int)ptr ; | |||
node->analogRead = myAnalogRead ; | |||
node->analogWrite = myAnalogWrite ; | |||
return TRUE ; | |||
} |
@@ -0,0 +1,26 @@ | |||
/* | |||
* pseudoPins.h: | |||
* Extend wiringPi with a number of pseudo pins which can be | |||
* digitally or analog written/read. | |||
* Copyright (c) 2012-2016 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 pseudoPinsSetup (const int pinBase) ; |
@@ -0,0 +1,252 @@ | |||
/* | |||
* rht03.c: | |||
* Extend wiringPi with the rht03 Maxdetect 1-Wire sensor. | |||
* Copyright (c) 2016-2017 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
* | |||
* wiringPi is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Lesser General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* wiringPi is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public | |||
* License along with wiringPi. | |||
* If not, see <http://www.gnu.org/licenses/>. | |||
*********************************************************************** | |||
*/ | |||
#include <sys/time.h> | |||
#include <stdio.h> | |||
#include <stdio.h> | |||
#include <time.h> | |||
#include "wiringPi.h" | |||
#include "rht03.h" | |||
/* | |||
* maxDetectLowHighWait: | |||
* Wait for a transition from low to high on the bus | |||
********************************************************************************* | |||
*/ | |||
static int maxDetectLowHighWait (const int pin) | |||
{ | |||
struct timeval now, timeOut, timeUp ; | |||
// If already high then wait for pin to go low | |||
gettimeofday (&now, NULL) ; | |||
timerclear (&timeOut) ; | |||
timeOut.tv_usec = 1000 ; | |||
timeradd (&now, &timeOut, &timeUp) ; | |||
while (digitalRead (pin) == HIGH) | |||
{ | |||
gettimeofday (&now, NULL) ; | |||
if (timercmp (&now, &timeUp, >)) | |||
return FALSE ; | |||
} | |||
// Wait for it to go HIGH | |||
gettimeofday (&now, NULL) ; | |||
timerclear (&timeOut) ; | |||
timeOut.tv_usec = 1000 ; | |||
timeradd (&now, &timeOut, &timeUp) ; | |||
while (digitalRead (pin) == LOW) | |||
{ | |||
gettimeofday (&now, NULL) ; | |||
if (timercmp (&now, &timeUp, >)) | |||
return FALSE ; | |||
} | |||
return TRUE ; | |||
} | |||
/* | |||
* maxDetectClockByte: | |||
* Read in a single byte from the MaxDetect bus | |||
********************************************************************************* | |||
*/ | |||
static unsigned int maxDetectClockByte (const int pin) | |||
{ | |||
unsigned int byte = 0 ; | |||
int bit ; | |||
for (bit = 0 ; bit < 8 ; ++bit) | |||
{ | |||
if (!maxDetectLowHighWait (pin)) | |||
return 0 ; | |||
// bit starting now - we need to time it. | |||
delayMicroseconds (30) ; | |||
byte <<= 1 ; | |||
if (digitalRead (pin) == HIGH) // It's a 1 | |||
byte |= 1 ; | |||
} | |||
return byte ; | |||
} | |||
/* | |||
* maxDetectRead: | |||
* Read in and return the 4 data bytes from the MaxDetect sensor. | |||
* Return TRUE/FALSE depending on the checksum validity | |||
********************************************************************************* | |||
*/ | |||
static int maxDetectRead (const int pin, unsigned char buffer [4]) | |||
{ | |||
int i ; | |||
unsigned int checksum ; | |||
unsigned char localBuf [5] ; | |||
struct timeval now, then, took ; | |||
// See how long we took | |||
gettimeofday (&then, NULL) ; | |||
// Wake up the RHT03 by pulling the data line low, then high | |||
// Low for 10mS, high for 40uS. | |||
pinMode (pin, OUTPUT) ; | |||
digitalWrite (pin, 0) ; delay (10) ; | |||
digitalWrite (pin, 1) ; delayMicroseconds (40) ; | |||
pinMode (pin, INPUT) ; | |||
// Now wait for sensor to pull pin low | |||
if (!maxDetectLowHighWait (pin)) | |||
return FALSE ; | |||
// and read in 5 bytes (40 bits) | |||
for (i = 0 ; i < 5 ; ++i) | |||
localBuf [i] = maxDetectClockByte (pin) ; | |||
checksum = 0 ; | |||
for (i = 0 ; i < 4 ; ++i) | |||
{ | |||
buffer [i] = localBuf [i] ; | |||
checksum += localBuf [i] ; | |||
} | |||
checksum &= 0xFF ; | |||
// See how long we took | |||
gettimeofday (&now, NULL) ; | |||
timersub (&now, &then, &took) ; | |||
// Total time to do this should be: | |||
// 10mS + 40µS - reset | |||
// + 80µS + 80µS - sensor doing its low -> high thing | |||
// + 40 * (50µS + 27µS (0) or 70µS (1) ) | |||
// = 15010µS | |||
// so if we take more than that, we've had a scheduling interruption and the | |||
// reading is probably bogus. | |||
if ((took.tv_sec != 0) || (took.tv_usec > 16000)) | |||
return FALSE ; | |||
return checksum == localBuf [4] ; | |||
} | |||
/* | |||
* myReadRHT03: | |||
* Read the Temperature & Humidity from an RHT03 sensor | |||
* Values returned are *10, so 123 is 12.3. | |||
********************************************************************************* | |||
*/ | |||
static int myReadRHT03 (const int pin, int *temp, int *rh) | |||
{ | |||
int result ; | |||
unsigned char buffer [4] ; | |||
// Read ... | |||
result = maxDetectRead (pin, buffer) ; | |||
if (!result) | |||
return FALSE ; | |||
*rh = (buffer [0] * 256 + buffer [1]) ; | |||
*temp = (buffer [2] * 256 + buffer [3]) ; | |||
if ((*temp & 0x8000) != 0) // Negative | |||
{ | |||
*temp &= 0x7FFF ; | |||
*temp = -*temp ; | |||
} | |||
// Discard obviously bogus readings - the checksum can't detect a 2-bit error | |||
// (which does seem to happen - no realtime here) | |||
if ((*rh > 999) || (*temp > 800) || (*temp < -400)) | |||
return FALSE ; | |||
return TRUE ; | |||
} | |||
/* | |||
* myAnalogRead: | |||
********************************************************************************* | |||
*/ | |||
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) | |||
{ | |||
int piPin = node->fd ; | |||
int chan = pin - node->pinBase ; | |||
int temp = -9997 ; | |||
int rh = -9997 ; | |||
int try ; | |||
if (chan > 1) | |||
return -9999 ; // Bad parameters | |||
for (try = 0 ; try < 10 ; ++try) | |||
{ | |||
if (myReadRHT03 (piPin, &temp, &rh)) | |||
return chan == 0 ? temp : rh ; | |||
} | |||
return -9998 ; | |||
} | |||
/* | |||
* rht03Setup: | |||
* Create a new instance of an RHT03 temperature sensor. | |||
********************************************************************************* | |||
*/ | |||
int rht03Setup (const int pinBase, const int piPin) | |||
{ | |||
struct wiringPiNodeStruct *node ; | |||
if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin | |||
return FALSE ; | |||
// 2 pins - temperature and humidity | |||
node = wiringPiNewNode (pinBase, 2) ; | |||
node->fd = piPin ; | |||
node->analogRead = myAnalogRead ; | |||
return TRUE ; | |||
} |
@@ -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: | |||
* Provide 2 channels of software driven PWM. | |||
* Copyright (c) 2012-2014 Gordon Henderson | |||
* Provide many channels of software driven PWM. | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -23,17 +23,18 @@ | |||
*/ | |||
#include <stdio.h> | |||
#include <malloc.h> | |||
#include <pthread.h> | |||
#include "wiringPi.h" | |||
#include "softPwm.h" | |||
// MAX_PINS: | |||
// This is more than the number of Pi pins because we can actually softPwm | |||
// pins that are on GPIO expanders. It's not that efficient and more than 1 or | |||
// 2 pins on e.g. (SPI) mcp23s17 won't really be that effective, however... | |||
// This is more than the number of Pi pins because we can actually softPwm. | |||
// Once upon a time I let pins on gpio expanders be softPwm'd, but it's really | |||
// really not a good thing. | |||
#define MAX_PINS 1024 | |||
#define MAX_PINS 64 | |||
// The PWM Frequency is derived from the "pulse time" below. Essentially, | |||
// the frequency is a function of the range and this pulse time. | |||
@@ -44,7 +45,7 @@ | |||
// It's possible to get a higher frequency by lowering the pulse time, | |||
// however CPU uage will skyrocket as wiringPi uses a hard-loop to time | |||
// periods under 100µS - this is because the Linux timer calls are just | |||
// accurate at all, and have an overhead. | |||
// not accurate at all, and have an overhead. | |||
// | |||
// Another way to increase the frequency is to reduce the range - however | |||
// that reduces the overall output accuracy... | |||
@@ -63,7 +64,7 @@ static volatile int newPin = -1 ; | |||
********************************************************************************* | |||
*/ | |||
static PI_THREAD (softPwmThread) | |||
static void *softPwmThread (void *arg) | |||
{ | |||
int pin, mark, space ; | |||
struct sched_param param ; | |||
@@ -71,6 +72,9 @@ static PI_THREAD (softPwmThread) | |||
param.sched_priority = sched_get_priority_max (SCHED_RR) ; | |||
pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; | |||
pin = *((int *)arg) ; | |||
free (arg) ; | |||
pin = newPin ; | |||
newPin = -1 ; | |||
@@ -102,14 +106,15 @@ static PI_THREAD (softPwmThread) | |||
void softPwmWrite (int pin, int value) | |||
{ | |||
pin &= (MAX_PINS - 1) ; | |||
/**/ if (value < 0) | |||
value = 0 ; | |||
else if (value > range [pin]) | |||
value = range [pin] ; | |||
if (pin < MAX_PINS) | |||
{ | |||
/**/ if (value < 0) | |||
value = 0 ; | |||
else if (value > range [pin]) | |||
value = range [pin] ; | |||
marks [pin] = value ; | |||
marks [pin] = value ; | |||
} | |||
} | |||
@@ -123,21 +128,30 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) | |||
{ | |||
int res ; | |||
pthread_t myThread ; | |||
int *passPin ; | |||
if (pin >= MAX_PINS) | |||
return -1 ; | |||
if (range [pin] != 0) // Already running on this pin | |||
return -1 ; | |||
if (range <= 0) | |||
if (pwmRange <= 0) | |||
return -1 ; | |||
passPin = malloc (sizeof (*passPin)) ; | |||
if (passPin == NULL) | |||
return -1 ; | |||
pinMode (pin, OUTPUT) ; | |||
digitalWrite (pin, LOW) ; | |||
pinMode (pin, OUTPUT) ; | |||
marks [pin] = initialValue ; | |||
range [pin] = pwmRange ; | |||
newPin = pin ; | |||
res = pthread_create (&myThread, NULL, softPwmThread, NULL) ; | |||
*passPin = pin ; | |||
newPin = pin ; | |||
res = pthread_create (&myThread, NULL, softPwmThread, (void *)passPin) ; | |||
while (newPin != -1) | |||
delay (1) ; | |||
@@ -156,11 +170,14 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) | |||
void softPwmStop (int pin) | |||
{ | |||
if (range [pin] != 0) | |||
if (pin < MAX_PINS) | |||
{ | |||
pthread_cancel (threads [pin]) ; | |||
pthread_join (threads [pin], NULL) ; | |||
range [pin] = 0 ; | |||
digitalWrite (pin, LOW) ; | |||
if (range [pin] != 0) | |||
{ | |||
pthread_cancel (threads [pin]) ; | |||
pthread_join (threads [pin], NULL) ; | |||
range [pin] = 0 ; | |||
digitalWrite (pin, LOW) ; | |||
} | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
/* | |||
* wiringPi.h: | |||
* Arduino like Wiring library for the Raspberry Pi. | |||
* Copyright (c) 2012-2016 Gordon Henderson | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -26,12 +26,22 @@ | |||
// C doesn't have true/false by default and I can never remember which | |||
// way round they are, so ... | |||
// (and yes, I know about stdbool.h but I like capitals for these and I'm old) | |||
#ifndef TRUE | |||
# define TRUE (1==1) | |||
# define FALSE (!TRUE) | |||
#endif | |||
// GCC warning suppressor | |||
#define UNU __attribute__((unused)) | |||
// Mask for the bottom 64 pins which belong to the Raspberry Pi | |||
// The others are available for the other devices | |||
#define PI_GPIO_MASK (0xFFFFFFC0) | |||
// Handy defines | |||
// wiringPi modes | |||
@@ -77,16 +87,19 @@ | |||
// Pi model types and version numbers | |||
// Intended for the GPIO program Use at your own risk. | |||
#define PI_MODEL_A 0 | |||
#define PI_MODEL_B 1 | |||
#define PI_MODEL_AP 2 | |||
#define PI_MODEL_BP 3 | |||
#define PI_MODEL_2 4 | |||
#define PI_ALPHA 5 | |||
#define PI_MODEL_CM 6 | |||
#define PI_MODEL_07 7 | |||
#define PI_MODEL_3 8 | |||
#define PI_MODEL_ZERO 9 | |||
#define PI_MODEL_A 0 | |||
#define PI_MODEL_B 1 | |||
#define PI_MODEL_AP 2 | |||
#define PI_MODEL_BP 3 | |||
#define PI_MODEL_2 4 | |||
#define PI_ALPHA 5 | |||
#define PI_MODEL_CM 6 | |||
#define PI_MODEL_07 7 | |||
#define PI_MODEL_3 8 | |||
#define PI_MODEL_ZERO 9 | |||
#define PI_MODEL_CM3 10 | |||
#define PI_MODEL_ZERO_W 12 | |||
#define PI_MODEL_3P 13 | |||
#define PI_VERSION_1 0 | |||
#define PI_VERSION_1_1 1 | |||
@@ -95,7 +108,7 @@ | |||
#define PI_MAKER_SONY 0 | |||
#define PI_MAKER_EGOMAN 1 | |||
#define PI_MAKER_MBEST 2 | |||
#define PI_MAKER_EMBEST 2 | |||
#define PI_MAKER_UNKNOWN 3 | |||
extern const char *piModelNames [16] ; | |||
@@ -108,7 +121,7 @@ extern const int piMemorySize [ 8] ; | |||
// Threads | |||
#define PI_THREAD(X) void *X (void *dummy) | |||
#define PI_THREAD(X) void *X (UNU void *dummy) | |||
// Failure modes | |||
@@ -135,19 +148,30 @@ struct wiringPiNodeStruct | |||
unsigned int data2 ; // ditto | |||
unsigned int data3 ; // ditto | |||
void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ; | |||
void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ; | |||
int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ; | |||
void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||
void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||
int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ; | |||
void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||
void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ; | |||
void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ; | |||
int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ; | |||
//unsigned int (*digitalRead8) (struct wiringPiNodeStruct *node, int pin) ; | |||
void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||
// void (*digitalWrite8) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||
void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||
int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ; | |||
void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||
struct wiringPiNodeStruct *next ; | |||
} ; | |||
extern struct wiringPiNodeStruct *wiringPiNodes ; | |||
// Export variables for the hardware pointers | |||
extern volatile unsigned int *_wiringPiGpio ; | |||
extern volatile unsigned int *_wiringPiPwm ; | |||
extern volatile unsigned int *_wiringPiClk ; | |||
extern volatile unsigned int *_wiringPiPads ; | |||
extern volatile unsigned int *_wiringPiTimer ; | |||
extern volatile unsigned int *_wiringPiTimerIrqRaw ; | |||
// Function prototypes | |||
// c++ wrappers thanks to a comment by Nick Lott | |||
@@ -168,19 +192,22 @@ extern int wiringPiFailure (int fatal, const char *message, ...) ; | |||
extern struct wiringPiNodeStruct *wiringPiFindNode (int pin) ; | |||
extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) ; | |||
extern void wiringPiVersion (int *major, int *minor) ; | |||
extern int wiringPiSetup (void) ; | |||
extern int wiringPiSetupSys (void) ; | |||
extern int wiringPiSetupGpio (void) ; | |||
extern int wiringPiSetupPhys (void) ; | |||
extern void pinModeAlt (int pin, int mode) ; | |||
extern void pinMode (int pin, int mode) ; | |||
extern void pullUpDnControl (int pin, int pud) ; | |||
extern int digitalRead (int pin) ; | |||
extern void digitalWrite (int pin, int value) ; | |||
extern void pwmWrite (int pin, int value) ; | |||
extern int analogRead (int pin) ; | |||
extern void analogWrite (int pin, int value) ; | |||
extern void pinModeAlt (int pin, int mode) ; | |||
extern void pinMode (int pin, int mode) ; | |||
extern void pullUpDnControl (int pin, int pud) ; | |||
extern int digitalRead (int pin) ; | |||
extern void digitalWrite (int pin, int value) ; | |||
extern unsigned int digitalRead8 (int pin) ; | |||
extern void digitalWrite8 (int pin, int value) ; | |||
extern void pwmWrite (int pin, int value) ; | |||
extern int analogRead (int pin) ; | |||
extern void analogWrite (int pin, int value) ; | |||
// PiFace specifics | |||
// (Deprecated) | |||
@@ -190,19 +217,22 @@ extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio | |||
// On-Board Raspberry Pi hardware specific stuff | |||
extern int piBoardRev (void) ; | |||
extern int piGpioLayout (void) ; | |||
extern int piBoardRev (void) ; // Deprecated | |||
extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; | |||
extern int wpiPinToGpio (int wpiPin) ; | |||
extern int physPinToGpio (int physPin) ; | |||
extern void setPadDrive (int group, int value) ; | |||
extern int getAlt (int pin) ; | |||
extern void pwmToneWrite (int pin, int freq) ; | |||
extern void digitalWriteByte (int value) ; | |||
extern unsigned int digitalReadByte (void) ; | |||
extern void pwmSetMode (int mode) ; | |||
extern void pwmSetRange (unsigned int range) ; | |||
extern void pwmSetClock (int divisor) ; | |||
extern void gpioClockSet (int pin, int freq) ; | |||
extern unsigned int digitalReadByte (void) ; | |||
extern unsigned int digitalReadByte2 (void) ; | |||
extern void digitalWriteByte (int value) ; | |||
extern void digitalWriteByte2 (int value) ; | |||
// Interrupts | |||
// (Also Pi hardware specific) | |||
@@ -52,6 +52,7 @@ | |||
#include <string.h> | |||
#include <fcntl.h> | |||
#include <sys/ioctl.h> | |||
#include <asm/ioctl.h> | |||
#include "wiringPi.h" | |||
#include "wiringPiI2C.h" | |||
@@ -221,7 +222,7 @@ int wiringPiI2CSetup (const int devId) | |||
int rev ; | |||
const char *device ; | |||
rev = piBoardRev () ; | |||
rev = piGpioLayout () ; | |||
if (rev == 1) | |||
device = "/dev/i2c-0" ; | |||
@@ -28,6 +28,7 @@ | |||
#include <errno.h> | |||
#include <string.h> | |||
#include <sys/ioctl.h> | |||
#include <asm/ioctl.h> | |||
#include <linux/spi/spidev.h> | |||
#include "wiringPi.h" | |||
@@ -38,10 +39,10 @@ | |||
// The SPI bus parameters | |||
// Variables as they need to be passed as pointers later on | |||
const static char *spiDev0 = "/dev/spidev0.0" ; | |||
const static char *spiDev1 = "/dev/spidev0.1" ; | |||
const static uint8_t spiBPW = 8 ; | |||
const static uint16_t spiDelay = 0 ; | |||
static const char *spiDev0 = "/dev/spidev0.0" ; | |||
static const char *spiDev1 = "/dev/spidev0.1" ; | |||
static const uint8_t spiBPW = 8 ; | |||
static const uint16_t spiDelay = 0 ; | |||
static uint32_t spiSpeeds [2] ; | |||
static int spiFds [2] ; | |||
@@ -49,24 +49,36 @@ int serialOpen (const char *device, const int baud) | |||
switch (baud) | |||
{ | |||
case 50: myBaud = B50 ; break ; | |||
case 75: myBaud = B75 ; break ; | |||
case 110: myBaud = B110 ; break ; | |||
case 134: myBaud = B134 ; break ; | |||
case 150: myBaud = B150 ; break ; | |||
case 200: myBaud = B200 ; break ; | |||
case 300: myBaud = B300 ; break ; | |||
case 600: myBaud = B600 ; break ; | |||
case 1200: myBaud = B1200 ; break ; | |||
case 1800: myBaud = B1800 ; break ; | |||
case 2400: myBaud = B2400 ; break ; | |||
case 4800: myBaud = B4800 ; break ; | |||
case 9600: myBaud = B9600 ; break ; | |||
case 19200: myBaud = B19200 ; break ; | |||
case 38400: myBaud = B38400 ; break ; | |||
case 57600: myBaud = B57600 ; break ; | |||
case 115200: myBaud = B115200 ; break ; | |||
case 230400: myBaud = B230400 ; break ; | |||
case 50: myBaud = B50 ; break ; | |||
case 75: myBaud = B75 ; break ; | |||
case 110: myBaud = B110 ; break ; | |||
case 134: myBaud = B134 ; break ; | |||
case 150: myBaud = B150 ; break ; | |||
case 200: myBaud = B200 ; break ; | |||
case 300: myBaud = B300 ; break ; | |||
case 600: myBaud = B600 ; break ; | |||
case 1200: myBaud = B1200 ; break ; | |||
case 1800: myBaud = B1800 ; break ; | |||
case 2400: myBaud = B2400 ; break ; | |||
case 4800: myBaud = B4800 ; break ; | |||
case 9600: myBaud = B9600 ; break ; | |||
case 19200: myBaud = B19200 ; break ; | |||
case 38400: myBaud = B38400 ; break ; | |||
case 57600: myBaud = B57600 ; break ; | |||
case 115200: myBaud = B115200 ; break ; | |||
case 230400: myBaud = B230400 ; break ; | |||
case 460800: myBaud = B460800 ; break ; | |||
case 500000: myBaud = B500000 ; break ; | |||
case 576000: myBaud = B576000 ; break ; | |||
case 921600: myBaud = B921600 ; break ; | |||
case 1000000: myBaud = B1000000 ; break ; | |||
case 1152000: myBaud = B1152000 ; break ; | |||
case 1500000: myBaud = B1500000 ; break ; | |||
case 2000000: myBaud = B2000000 ; break ; | |||
case 2500000: myBaud = B2500000 ; break ; | |||
case 3000000: myBaud = B3000000 ; break ; | |||
case 3500000: myBaud = B3500000 ; break ; | |||
case 4000000: myBaud = B4000000 ; break ; | |||
default: | |||
return -2 ; | |||
@@ -96,7 +108,7 @@ int serialOpen (const char *device, const int baud) | |||
options.c_cc [VMIN] = 0 ; | |||
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) | |||
tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ; | |||
tcsetattr (fd, TCSANOW, &options) ; | |||
ioctl (fd, TIOCMGET, &status); | |||
@@ -55,6 +55,13 @@ | |||
#include "ads1115.h" | |||
#include "sn3218.h" | |||
#include "drcSerial.h" | |||
#include "drcNet.h" | |||
#include "../wiringPiD/drcNetCmd.h" | |||
#include "pseudoPins.h" | |||
#include "bmp180.h" | |||
#include "htu21d.h" | |||
#include "ds18b20.h" | |||
#include "rht03.h" | |||
#include "wpiExtensions.h" | |||
@@ -130,12 +137,16 @@ static char *extractInt (char *progName, char *p, int *num) | |||
/* | |||
* extractStr: | |||
* Check & return a string at the given location (prefixed by a :) | |||
* Note: The string can be enclosed in []'s to escape colons. This is | |||
* so we can handle IPv6 addresses which contain colons and the []'s is | |||
* a common way to prepresent them. | |||
********************************************************************************* | |||
*/ | |||
static char *extractStr (char *progName, char *p, char **str) | |||
{ | |||
char *q, *r ; | |||
int quoted = FALSE ; | |||
if (*p != ':') | |||
{ | |||
@@ -145,21 +156,38 @@ static char *extractStr (char *progName, char *p, char **str) | |||
++p ; | |||
if (!isprint (*p)) | |||
if (*p == '[') | |||
{ | |||
quoted = TRUE ; | |||
++p ; | |||
} | |||
if (!isprint (*p)) // Is this needed? | |||
{ | |||
verbError ("%s: character expected", progName) ; | |||
return NULL ; | |||
} | |||
q = p ; | |||
while ((*q != 0) && (*q != ':')) | |||
++q ; | |||
if (quoted) | |||
{ | |||
while ((*q != 0) && (*q != ']')) | |||
++q ; | |||
} | |||
else | |||
{ | |||
while ((*q != 0) && (*q != ':')) | |||
++q ; | |||
} | |||
*str = r = calloc (q - p + 2, 1) ; // Zeros it | |||
while (p != q) | |||
*r++ = *p++ ; | |||
if (quoted) // Skip over the ] to the : | |||
++p ; | |||
return p ; | |||
} | |||
@@ -429,6 +457,87 @@ static int doExtensionPcf8591 (char *progName, int pinBase, char *params) | |||
/* | |||
* doExtensionPseudoPins: | |||
* 64 Memory resident pseudo pins | |||
* pseudoPins:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionPseudoPins (UNU char *progName, int pinBase, UNU char *params) | |||
{ | |||
pseudoPinsSetup (pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionBmp180: | |||
* Analog Temp + Pressure | |||
* bmp180:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionBmp180 (UNU char *progName, int pinBase, UNU char *params) | |||
{ | |||
bmp180Setup (pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionHtu21d: | |||
* Analog humidity + Pressure | |||
* htu21d:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionHtu21d (UNU char *progName, int pinBase, UNU char *params) | |||
{ | |||
htu21dSetup (pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionDs18b20: | |||
* 1-Wire Temperature | |||
* htu21d:base:serialNum | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionDs18b20 (char *progName, int pinBase, char *params) | |||
{ | |||
char *serialNum ; | |||
if ((params = extractStr (progName, params, &serialNum)) == NULL) | |||
return FALSE ; | |||
return ds18b20Setup (pinBase, serialNum) ; | |||
} | |||
/* | |||
* doExtensionRht03: | |||
* Maxdetect 1-Wire Temperature & Humidity | |||
* rht03:base:piPin | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionRht03 (char *progName, int pinBase, char *params) | |||
{ | |||
int piPin ; | |||
if ((params = extractInt (progName, params, &piPin)) == NULL) | |||
return FALSE ; | |||
return rht03Setup (pinBase, piPin) ; | |||
} | |||
/* | |||
* doExtensionMax31855: | |||
* Analog IO | |||
* max31855:base:spiChan | |||
@@ -565,7 +674,7 @@ static int doExtensionMcp4802 (char *progName, int pinBase, char *params) | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionSn3218 (char *progName, int pinBase, char *params) | |||
static int doExtensionSn3218 (UNU char *progName, int pinBase, UNU char *params) | |||
{ | |||
sn3218Setup (pinBase) ; | |||
return TRUE ; | |||
@@ -631,9 +740,9 @@ static int doExtensionDrcS (char *progName, int pinBase, char *params) | |||
if ((params = extractInt (progName, params, &pins)) == NULL) | |||
return FALSE ; | |||
if ((pins < 1) || (pins > 100)) | |||
if ((pins < 1) || (pins > 1000)) | |||
{ | |||
verbError ("%s: pins (%d) out of range (2-100)", progName, pins) ; | |||
verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ; | |||
return FALSE ; | |||
} | |||
@@ -661,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 | |||
@@ -677,6 +839,11 @@ static struct extensionFunctionStruct extensionFunctions [] = | |||
{ "sr595", &doExtensionSr595 }, | |||
{ "pcf8574", &doExtensionPcf8574 }, | |||
{ "pcf8591", &doExtensionPcf8591 }, | |||
{ "bmp180", &doExtensionBmp180 }, | |||
{ "pseudoPins", &doExtensionPseudoPins }, | |||
{ "htu21d", &doExtensionHtu21d }, | |||
{ "ds18b20", &doExtensionDs18b20 }, | |||
{ "rht03", &doExtensionRht03 }, | |||
{ "mcp3002", &doExtensionMcp3002 }, | |||
{ "mcp3004", &doExtensionMcp3004 }, | |||
{ "mcp4802", &doExtensionMcp4802 }, | |||
@@ -686,6 +853,7 @@ static struct extensionFunctionStruct extensionFunctions [] = | |||
{ "max5322", &doExtensionMax5322 }, | |||
{ "sn3218", &doExtensionSn3218 }, | |||
{ "drcs", &doExtensionDrcS }, | |||
{ "drcn", &doExtensionDrcNet }, | |||
{ NULL, NULL }, | |||
} ; | |||
@@ -703,7 +871,7 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors) | |||
char *p ; | |||
char *extension = extensionData ; | |||
struct extensionFunctionStruct *extensionFn ; | |||
unsigned pinBase = 0 ; | |||
int pinBase = 0 ; | |||
verbose = printErrors ; | |||
@@ -755,6 +923,6 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors) | |||
return extensionFn->function (progName, pinBase, p) ; | |||
} | |||
verbError ("%s: extension %s not found", progName, extension) ; | |||
fprintf (stderr, "%s: extension %s not found", progName, extension) ; | |||
return FALSE ; | |||
} |
@@ -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 |
@@ -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) ; | |||
} | |||
} |
@@ -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) ; |
@@ -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 ; | |||
@@ -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 ; | |||
} |
@@ -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) ; |
@@ -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 ; | |||
} | |||
} | |||
} |
@@ -1,7 +1,8 @@ | |||
/* | |||
* pins.c: | |||
* Just display a handy Pi pinnout diagram. | |||
* Copyright (c) 2012-2015 Gordon Henderson | |||
* 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/ | |||
@@ -21,13 +22,8 @@ | |||
*********************************************************************** | |||
*/ | |||
// Globals | |||
#include <stdio.h> | |||
void doPins (void) | |||
{ | |||
printf ("The pins command has been deprecated - sorry. Please use the\n") ; | |||
printf (" gpio readall\n") ; | |||
printf ("command to get a list of the pinnouts for your Pi.\n") ; | |||
} | |||
extern int noLocalPins ; | |||
extern void runRemoteCommands (int fd) ; |
@@ -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 ; | |||
} |