Signed-off-by: sndnvaps <sndnvaps@gmail.com>pull/48/head
@@ -19,13 +19,6 @@ then run the ldconfig command. | |||||
sudo ldconfig | 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: | To un-install wiringPi: | ||||
./build uninstall | ./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 | wiringPi README | ||||
=============== | =============== | ||||
@@ -1 +1 @@ | |||||
2.32 | |||||
2.46 |
@@ -6,7 +6,7 @@ | |||||
# Copyright (c) 2012-2015 Gordon Henderson | # Copyright (c) 2012-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # 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 | echo -n "PiGlow: " ; make clean | ||||
cd ../scrollPhat | cd ../scrollPhat | ||||
echo -n "scrollPhat: " ; make clean | echo -n "scrollPhat: " ; make clean | ||||
cd ../.. | |||||
echo -n "Deb: " ; rm -f debian-template/wiringpi*.deb | |||||
echo | |||||
exit | exit | ||||
fi | fi | ||||
@@ -161,6 +164,14 @@ fi | |||||
check_make_ok | check_make_ok | ||||
# echo | # echo | ||||
# echo "wiringPi Daemon" | |||||
# cd ../wiringPiD | |||||
# make -j5 | |||||
# check_make_ok | |||||
# $sudo make install | |||||
# check_make_ok | |||||
# echo | |||||
# echo "Examples" | # echo "Examples" | ||||
# cd ../examples | # cd ../examples | ||||
# make | # make | ||||
@@ -1,5 +1,5 @@ | |||||
Package: wiringpi | Package: wiringpi | ||||
Version: 2.32 | |||||
Version: 2.46 | |||||
Section: libraries | Section: libraries | ||||
Priority: optional | Priority: optional | ||||
Architecture: armhf | Architecture: armhf | ||||
@@ -7,4 +7,4 @@ Depends: libc6 | |||||
Maintainer: Gordon Henderson <projects@drogon.net> | Maintainer: Gordon Henderson <projects@drogon.net> | ||||
Description: The wiringPi libraries, headers and gpio command | Description: The wiringPi libraries, headers and gpio command | ||||
Libraries to allow GPIO access on a Raspberry Pi from C and C++ | 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) ; | 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.: | * 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 | * This file to interface with the PiFace peripheral device which | ||||
* has an MCP23S17 GPIO device connected via the SPI bus. | * has an MCP23S17 GPIO device connected via the SPI bus. | ||||
@@ -1,6 +1,6 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2015 Gordon Henderson | # Copyright (c) 2012-2015 Gordon Henderson | ||||
@@ -33,7 +33,7 @@ INCLUDE = -I/usr/local/include | |||||
CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe | CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe | ||||
LDFLAGS = -L/usr/local/lib | LDFLAGS = -L/usr/local/lib | ||||
LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm | |||||
LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt | |||||
# Should not alter anything below this line | # Should not alter anything below this line | ||||
############################################################################### | ############################################################################### | ||||
@@ -1,12 +1,12 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012 Gordon Henderson | # Copyright (c) 2012 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -1,12 +1,12 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2015 Gordon Henderson | # Copyright (c) 2012-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # 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 <stdio.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <wiringPi.h> | |||||
#include <sys/time.h> | #include <sys/time.h> | ||||
@@ -34,17 +33,13 @@ | |||||
int main() | int main() | ||||
{ | { | ||||
int x ; | int x ; | ||||
struct timeval t1, t2 ; | |||||
struct timeval t1, t2, t3 ; | |||||
int t ; | int t ; | ||||
int max, min ; | int max, min ; | ||||
int del ; | int del ; | ||||
int underRuns, overRuns, exactRuns, total ; | |||||
int underRuns, overRuns, exactRuns, bogusRuns, total ; | |||||
int descheds ; | int descheds ; | ||||
if (wiringPiSetup () == -1) | |||||
return 1 ; | |||||
piHiPri (10) ; sleep (1) ; | |||||
// Baseline test | // Baseline test | ||||
@@ -58,21 +53,22 @@ int main() | |||||
{ | { | ||||
underRuns = overRuns = exactRuns = total = 0 ; | underRuns = overRuns = exactRuns = total = 0 ; | ||||
descheds = 0 ; | descheds = 0 ; | ||||
max = del ; | |||||
min = del ; | |||||
max = 0 ; | |||||
min = 999 ; | |||||
for (x = 0 ; x < CYCLES ; ++x) | for (x = 0 ; x < CYCLES ; ++x) | ||||
{ | { | ||||
for (;;) // Repeat this if we get a delay over 999uS | for (;;) // Repeat this if we get a delay over 999uS | ||||
{ // -> High probability Linux has deschedulled us | { // -> High probability Linux has deschedulled us | ||||
gettimeofday (&t1, NULL) ; | gettimeofday (&t1, NULL) ; | ||||
delayMicroseconds (del) ; | |||||
usleep (del) ; | |||||
// delayMicroseconds (del) ; | |||||
gettimeofday (&t2, NULL) ; | 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) | if (t > 999) | ||||
{ | { | ||||
++descheds ; | ++descheds ; | ||||
@@ -82,25 +78,24 @@ int main() | |||||
break ; | break ; | ||||
} | } | ||||
if (t == del) | |||||
++exactRuns ; | |||||
else if (t < del) | |||||
++underRuns ; | |||||
else if (t > del) | |||||
++overRuns ; | |||||
if (t > max) | if (t > max) | ||||
{ | |||||
max = t ; | max = t ; | ||||
++overRuns ; | |||||
} | |||||
else if (t < min) | else if (t < min) | ||||
{ | |||||
min = t ; | min = t ; | ||||
++underRuns ; | |||||
} | |||||
else | |||||
++exactRuns ; | |||||
total += t ; | total += t ; | ||||
} | } | ||||
printf ("Delay: %3d. Min: %3d, Max: %3d, Unders: %3d, Overs: %3d, Exacts: %3d, Average: %3d, Descheds: %2d\n", | 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) ; | del, min, max, underRuns, overRuns, exactRuns, total / CYCLES, descheds) ; | ||||
fflush (stdout) ; | fflush (stdout) ; | ||||
delay (1) ; | |||||
usleep (1000) ; | |||||
} | } | ||||
return 0 ; | return 0 ; | ||||
@@ -1,12 +1,12 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2013 Gordon Henderson | # Copyright (c) 2012-2013 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -1,12 +1,12 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2015 Gordon Henderson | # Copyright (c) 2012-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # 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 | .SH NAME | ||||
gpio \- Command-line access to Raspberry Pi's GPIO | gpio \- Command-line access to Raspberry Pi's GPIO | ||||
@@ -9,15 +9,20 @@ gpio \- Command-line access to Raspberry Pi's GPIO | |||||
.PP | .PP | ||||
.B gpio | .B gpio | ||||
.B [ \-g | \-1 ] | .B [ \-g | \-1 ] | ||||
.B mode/read/write/aread/awrite/wb/pwm/clock ... | |||||
.B mode/read/write/aread/awrite/wb/pwm/pwnTone/clock/toggle/blink ... | |||||
.PP | .PP | ||||
.B gpio | .B gpio | ||||
.B [ \-x extension:params ] | .B [ \-x extension:params ] | ||||
.B mode/read/write/aread/awrite/pwm/pwmTone ... | |||||
.B mode/read/write/aread/awrite/pwm/toggle/blink ... | |||||
.PP | .PP | ||||
.B gpio | .B gpio | ||||
.B [ \-p ] | .B [ \-p ] | ||||
.B read/write/toggle/wb | |||||
.B read/write/toggle/blink | |||||
.B ... | |||||
.PP | |||||
.B gpio | |||||
.B [ \-p ] | |||||
.B pwnTone pin frequency | |||||
.B ... | .B ... | ||||
.PP | .PP | ||||
.B gpio | .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. | to output mode first. | ||||
.TP | .TP | ||||
.B toggle <pin> | |||||
Changes the state of a GPIO pin; 0 to 1, or 1 to 0. | |||||
Note unlike the blink command, the pin must be in output mode first. | |||||
.TP | |||||
.B blink <pin> | |||||
Blinks the given pin on/off. Press Control-C to exit. | |||||
Note: This command explicitly sets the pin to output mode. | |||||
.TP | |||||
.B aread <pin> | .B aread <pin> | ||||
Read the analog value of the given pin. This needs to be uses in | |||||
Read the analog value of the given pin. This needs to be used in | |||||
conjunction with a -x flag to add in an extension that handles analog | conjunction with a -x flag to add in an extension that handles analog | ||||
inputs. respective logic levels. | |||||
inputs. | |||||
e.g. gpio -x mcp3002:200:0 aread 200 | e.g. gpio -x mcp3002:200:0 aread 200 | ||||
@@ -132,7 +149,7 @@ will read the first analog input on an mcp3002 SPI ADC chip. | |||||
.B awrite <pin> <value> | .B awrite <pin> <value> | ||||
Write the analog value to the given pin. This needs to be used in | Write the analog value to the given pin. This needs to be used in | ||||
conjunction with a -x flag to add in an extension that handles analog | conjunction with a -x flag to add in an extension that handles analog | ||||
inputs. respective logic levels. | |||||
inputs. | |||||
e.g. gpio -x mcp4802:200:0 awrite 200 128 | e.g. gpio -x mcp4802:200:0 awrite 200 128 | ||||
@@ -234,7 +251,7 @@ absolutely sure you know what you're doing. | |||||
high | low | high | low | ||||
Change the USB current limiter to high (1.2 amps) or low (the default, 600mA) | Change the USB current limiter to high (1.2 amps) or low (the default, 600mA) | ||||
This is only applicable to the model B+ | |||||
This is only applicable to the Model B+ and the Model B, v2. | |||||
.TP | .TP | ||||
.B pwm-bal/pwm-ms | .B pwm-bal/pwm-ms | ||||
@@ -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. | Change the PWM range register. The default is 1024. | ||||
.TP | .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 | .B gbr | ||||
channel | channel | ||||
@@ -350,7 +341,7 @@ Please report bugs to <projects@drogon.net> | |||||
.SH COPYRIGHT | .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 | This is free software; see the source for copying conditions. There is NO | ||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
@@ -2,7 +2,7 @@ | |||||
* gpio.c: | * gpio.c: | ||||
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry | * Swiss-Army-Knife, Set-UID command-line interface to the Raspberry | ||||
* Pi's GPIO. | * Pi's GPIO. | ||||
* Copyright (c) 2012-2015 Gordon Henderson | |||||
* Copyright (c) 2012-2018 Gordon Henderson | |||||
*********************************************************************** | *********************************************************************** | ||||
* This file is part of wiringPi: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | * https://projects.drogon.net/raspberry-pi/wiringpi/ | ||||
@@ -40,7 +40,7 @@ | |||||
#include <gertboard.h> | #include <gertboard.h> | ||||
#include <piFace.h> | #include <piFace.h> | ||||
#include "version.h" | |||||
#include "../version.h" | |||||
extern int wiringPiDebug ; | extern int wiringPiDebug ; | ||||
@@ -48,7 +48,7 @@ extern int wiringPiDebug ; | |||||
extern void doReadall (void) ; | extern void doReadall (void) ; | ||||
extern void doAllReadall (void) ; | extern void doAllReadall (void) ; | ||||
extern void doPins (void) ; | |||||
extern void doQmode (int argc, char *argv []) ; | |||||
#ifndef TRUE | #ifndef TRUE | ||||
# define TRUE (1==1) | # define TRUE (1==1) | ||||
@@ -56,16 +56,21 @@ extern void doPins (void) ; | |||||
#endif | #endif | ||||
#define PI_USB_POWER_CONTROL 38 | #define PI_USB_POWER_CONTROL 38 | ||||
#define I2CDETECT "/usr/sbin/i2cdetect" | |||||
#define I2CDETECT "i2cdetect" | |||||
#define MODPROBE "modprobe" | |||||
#define RMMOD "rmmod" | |||||
int wpMode ; | int wpMode ; | ||||
char *usage = "Usage: gpio -v\n" | char *usage = "Usage: gpio -v\n" | ||||
" gpio -h\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 [-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 unexportall/exports\n" | ||||
" gpio export/edge/unexport ...\n" | " gpio export/edge/unexport ...\n" | ||||
" gpio wfi <pin> <mode>\n" | " gpio wfi <pin> <mode>\n" | ||||
@@ -76,6 +81,8 @@ char *usage = "Usage: gpio -v\n" | |||||
" gpio load spi/i2c\n" | " gpio load spi/i2c\n" | ||||
" gpio unload spi/i2c\n" | " gpio unload spi/i2c\n" | ||||
" gpio i2cd/i2cdetect\n" | " gpio i2cd/i2cdetect\n" | ||||
" gpio rbx/rbd\n" | |||||
" gpio wb <value>\n" | |||||
" gpio usbp high/low\n" | " gpio usbp high/low\n" | ||||
" gpio gbr <channel>\n" | " gpio gbr <channel>\n" | ||||
" gpio gbw <channel> <value>" ; // No trailing newline needed here. | " 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: | * changeOwner: | ||||
* Change the ownership of the file to the real userId of the calling | * Change the ownership of the file to the real userId of the calling | ||||
* program so we can access it. | * program so we can access it. | ||||
@@ -175,9 +221,7 @@ static void checkDevTree (char *argv []) | |||||
fprintf (stderr, | fprintf (stderr, | ||||
"%s: Unable to load/unload modules as this Pi has the device tree enabled.\n" | "%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" | " 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) ; | exit (1) ; | ||||
} | } | ||||
} | } | ||||
@@ -230,15 +274,18 @@ static void doLoad (int argc, char *argv []) | |||||
else | else | ||||
_doLoadUsage (argv) ; | _doLoadUsage (argv) ; | ||||
if (findExecutable ("modprobe") == NULL) | |||||
printf ("No found\n") ; | |||||
if (!moduleLoaded (module1)) | if (!moduleLoaded (module1)) | ||||
{ | { | ||||
sprintf (cmd, "/sbin/modprobe %s%s", module1, args1) ; | |||||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ; | |||||
system (cmd) ; | system (cmd) ; | ||||
} | } | ||||
if (!moduleLoaded (module2)) | if (!moduleLoaded (module2)) | ||||
{ | { | ||||
sprintf (cmd, "/sbin/modprobe %s%s", module2, args2) ; | |||||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ; | |||||
system (cmd) ; | system (cmd) ; | ||||
} | } | ||||
@@ -292,13 +339,13 @@ static void doUnLoad (int argc, char *argv []) | |||||
if (moduleLoaded (module1)) | if (moduleLoaded (module1)) | ||||
{ | { | ||||
sprintf (cmd, "/sbin/rmmod %s", module1) ; | |||||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ; | |||||
system (cmd) ; | system (cmd) ; | ||||
} | } | ||||
if (moduleLoaded (module2)) | if (moduleLoaded (module2)) | ||||
{ | { | ||||
sprintf (cmd, "/sbin/rmmod %s", module2) ; | |||||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ; | |||||
system (cmd) ; | 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)) ; | fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ; | ||||
return ; | return ; | ||||
@@ -328,7 +374,8 @@ static void doI2Cdetect (int argc, char *argv []) | |||||
return ; | return ; | ||||
} | } | ||||
sprintf (command, "%s -y %d", I2CDETECT, port) ; | |||||
command = malloc (strlen (c) + 16) ; | |||||
sprintf (command, "%s -y %d", c, port) ; | |||||
if (system (command) < 0) | if (system (command) < 0) | ||||
fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ; | 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 fd ; | ||||
int i, l, first ; | 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 ("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") ; | 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: | * 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: | * doRead: | ||||
* Read a pin and return the value | * 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: | * doPwmTone: | ||||
* Output a tone in a PWM pin | * Output a tone in a PWM pin | ||||
********************************************************************************* | ********************************************************************************* | ||||
@@ -1162,9 +1261,14 @@ static void doVersion (char *argv []) | |||||
{ | { | ||||
int model, rev, mem, maker, warranty ; | int model, rev, mem, maker, warranty ; | ||||
struct stat statBuf ; | 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 ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; | ||||
printf ("For details type: %s -warranty\n", argv [0]) ; | printf ("For details type: %s -warranty\n", argv [0]) ; | ||||
printf ("\n") ; | printf ("\n") ; | ||||
@@ -1179,12 +1283,18 @@ static void doVersion (char *argv []) | |||||
if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | ||||
printf (" * Device tree is enabled.\n") ; | 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 | else | ||||
printf (" * Root or sudo required for GPIO access.\n") ; | printf (" * Root or sudo required for GPIO access.\n") ; | ||||
} | } | ||||
@@ -1208,8 +1318,11 @@ int main (int argc, char *argv []) | |||||
if (argc == 1) | 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 | // Help | ||||
@@ -1217,7 +1330,7 @@ int main (int argc, char *argv []) | |||||
if (strcasecmp (argv [1], "-h") == 0) | if (strcasecmp (argv [1], "-h") == 0) | ||||
{ | { | ||||
printf ("%s: %s\n", argv [0], usage) ; | printf ("%s: %s\n", argv [0], usage) ; | ||||
return 0 ; | |||||
exit (EXIT_SUCCESS) ; | |||||
} | } | ||||
// Version & Warranty | // Version & Warranty | ||||
@@ -1225,8 +1338,8 @@ int main (int argc, char *argv []) | |||||
if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0)) | 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 | // Version and information | ||||
@@ -1234,13 +1347,13 @@ int main (int argc, char *argv []) | |||||
if (strcmp (argv [1], "-v") == 0) | if (strcmp (argv [1], "-v") == 0) | ||||
{ | { | ||||
doVersion (argv) ; | doVersion (argv) ; | ||||
return 0 ; | |||||
exit (EXIT_SUCCESS) ; | |||||
} | } | ||||
if (strcasecmp (argv [1], "-warranty") == 0) | if (strcasecmp (argv [1], "-warranty") == 0) | ||||
{ | { | ||||
printf ("gpio version: %s\n", VERSION) ; | 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 ("\n") ; | ||||
printf (" This program is free software; you can redistribute it and/or modify\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") ; | 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 (" 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 (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ; | ||||
printf ("\n") ; | printf ("\n") ; | ||||
return 0 ; | |||||
exit (EXIT_SUCCESS) ; | |||||
} | } | ||||
if (geteuid () != 0) | if (geteuid () != 0) | ||||
{ | { | ||||
fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [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: | // Initial test for /sys/class/gpio operations: | ||||
@@ -1331,6 +1444,16 @@ int main (int argc, char *argv []) | |||||
wpMode = WPI_MODE_PIFACE ; | wpMode = WPI_MODE_PIFACE ; | ||||
} | } | ||||
// Check for -z argument so we don't actually initialise wiringPi | |||||
else if (strcasecmp (argv [1], "-z") == 0) | |||||
{ | |||||
for (i = 2 ; i < argc ; ++i) | |||||
argv [i - 1] = argv [i] ; | |||||
--argc ; | |||||
wpMode = WPI_MODE_UNINITIALISED ; | |||||
} | |||||
// Default to wiringPi mode | // Default to wiringPi mode | ||||
else | else | ||||
@@ -1340,17 +1463,25 @@ int main (int argc, char *argv []) | |||||
} | } | ||||
// Check for -x argument to load in a new extension | // 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) | if (argc < 3) | ||||
{ | { | ||||
fprintf (stderr, "%s: -x missing extension specification.\n", argv [0]) ; | |||||
fprintf (stderr, "%s: -x missing extension command.\n", argv [0]) ; | |||||
exit (EXIT_FAILURE) ; | exit (EXIT_FAILURE) ; | ||||
} | } | ||||
if (!loadWPiExtension (argv [0], argv [2], TRUE)) // Prints its own error messages | |||||
if (!loadWPiExtension (argv [0], argv [2], TRUE)) | |||||
{ | |||||
fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ; | |||||
exit (EXIT_FAILURE) ; | exit (EXIT_FAILURE) ; | ||||
} | |||||
// Shift args down by 2 | |||||
for (i = 3 ; i < argc ; ++i) | for (i = 3 ; i < argc ; ++i) | ||||
argv [i - 2] = argv [i] ; | argv [i - 2] = argv [i] ; | ||||
@@ -1375,6 +1506,7 @@ int main (int argc, char *argv []) | |||||
// GPIO Nicies | // GPIO Nicies | ||||
else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ; | else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ; | ||||
else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ; | |||||
// Pi Specifics | // 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], "drive" ) == 0) doPadDrive (argc, argv) ; | ||||
else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ; | else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ; | ||||
else if (strcasecmp (argv [1], "nreadall" ) == 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], "i2cdetect") == 0) doI2Cdetect (argc, argv) ; | ||||
else if (strcasecmp (argv [1], "i2cd" ) == 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], "reset" ) == 0) doReset (argv [0]) ; | ||||
else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ; | 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], "clock" ) == 0) doClock (argc, argv) ; | ||||
else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; | else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; | ||||
else | else | ||||
@@ -1398,5 +1533,6 @@ int main (int argc, char *argv []) | |||||
fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ; | fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ; | ||||
exit (EXIT_FAILURE) ; | exit (EXIT_FAILURE) ; | ||||
} | } | ||||
return 0 ; | return 0 ; | ||||
} | } |
@@ -5,7 +5,7 @@ | |||||
# Copyright (c) 2013-2015 Gordon Henderson | # Copyright (c) 2013-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* readall.c: | * readall.c: | ||||
* The readall functions - getting a bit big, so split them out. | * 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: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | * https://projects.drogon.net/raspberry-pi/wiringpi/ | ||||
@@ -118,7 +118,7 @@ static char *physNames [64] = | |||||
NULL, | NULL, | ||||
" 3.3v", "5v ", | " 3.3v", "5v ", | ||||
" SDA.1", "5V ", | |||||
" SDA.1", "5v ", | |||||
" SCL.1", "0v ", | " SCL.1", "0v ", | ||||
"GPIO. 7", "TxD ", | "GPIO. 7", "TxD ", | ||||
" 0v", "RxD ", | " 0v", "RxD ", | ||||
@@ -287,22 +287,26 @@ void abReadall (int model, int rev) | |||||
/* | /* | ||||
* piPlusReadall: | * 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) | static void plus2header (int model) | ||||
{ | { | ||||
/**/ if (model == PI_MODEL_AP) | /**/ if (model == PI_MODEL_AP) | ||||
printf (" +-----+-----+---------+------+---+--A Plus--+---+------+---------+-----+-----+\n") ; | |||||
printf (" +-----+-----+---------+------+---+---Pi A+--+---+------+---------+-----+-----+\n") ; | |||||
else if (model == PI_MODEL_BP) | else if (model == PI_MODEL_BP) | ||||
printf (" +-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+\n") ; | |||||
printf (" +-----+-----+---------+------+---+---Pi B+--+---+------+---------+-----+-----+\n") ; | |||||
else if (model == PI_MODEL_ZERO) | else if (model == PI_MODEL_ZERO) | ||||
printf (" +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+\n") ; | printf (" +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+\n") ; | ||||
else if (model == PI_MODEL_ZERO_W) | |||||
printf (" +-----+-----+---------+------+---+-Pi ZeroW-+---+------+---------+-----+-----+\n") ; | |||||
else if (model == PI_MODEL_2) | else if (model == PI_MODEL_2) | ||||
printf (" +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+\n") ; | printf (" +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+\n") ; | ||||
else if (model == PI_MODEL_3) | else if (model == PI_MODEL_3) | ||||
printf (" +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+\n") ; | printf (" +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+\n") ; | ||||
else if (model == PI_MODEL_3P) | |||||
printf (" +-----+-----+---------+------+---+---Pi 3+--+---+------+---------+-----+-----+\n") ; | |||||
else | else | ||||
printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; | printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; | ||||
} | } | ||||
@@ -346,14 +350,18 @@ void doReadall (void) | |||||
/**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B)) | /**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B)) | ||||
abReadall (model, rev) ; | abReadall (model, rev) ; | ||||
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO)) | |||||
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || | |||||
(model == PI_MODEL_2) || | |||||
(model == PI_MODEL_3) || (model == PI_MODEL_3P) || | |||||
(model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W)) | |||||
piPlusReadall (model) ; | piPlusReadall (model) ; | ||||
else if (model == PI_MODEL_CM) | |||||
else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) | |||||
allReadall () ; | allReadall () ; | ||||
else | else | ||||
printf ("Oops - unable to determine board type... model: %d\n", model) ; | printf ("Oops - unable to determine board type... model: %d\n", model) ; | ||||
} | } | ||||
/* | /* | ||||
* doAllReadall: | * doAllReadall: | ||||
* Force reading of all pins regardless of Pi model | * Force reading of all pins regardless of Pi model | ||||
@@ -364,3 +372,24 @@ void doAllReadall (void) | |||||
{ | { | ||||
allReadall () ; | 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. | # in-turn. | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # 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 | # Copyright (c) 2012-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -25,8 +25,12 @@ | |||||
echo Updating to version: `cat VERSION` | 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 | rm -f debian-template/wiringPi/DEBIAN/control | ||||
cat > debian-template/wiringPi/DEBIAN/control <<EOF | cat > debian-template/wiringPi/DEBIAN/control <<EOF | ||||
@@ -39,5 +43,5 @@ Depends: libc6 | |||||
Maintainer: Gordon Henderson <projects@drogon.net> | Maintainer: Gordon Henderson <projects@drogon.net> | ||||
Description: The wiringPi libraries, headers and gpio command | Description: The wiringPi libraries, headers and gpio command | ||||
Libraries to allow GPIO access on a Raspberry Pi from C and C++ | 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 | 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 | if ( (data < 0) || (data > 7) ) // Use default if out of range | ||||
data = 4 ; | 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) ; | 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] ; | unsigned char b [2] ; | ||||
b [0] = 0x40 ; | 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: | * softPwm.c: | ||||
* Provide 2 channels of software driven PWM. | |||||
* Copyright (c) 2012-2014 Gordon Henderson | |||||
* Provide many channels of software driven PWM. | |||||
* Copyright (c) 2012-2017 Gordon Henderson | |||||
*********************************************************************** | *********************************************************************** | ||||
* This file is part of wiringPi: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | * https://projects.drogon.net/raspberry-pi/wiringpi/ | ||||
@@ -23,17 +23,18 @@ | |||||
*/ | */ | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <malloc.h> | |||||
#include <pthread.h> | #include <pthread.h> | ||||
#include "wiringPi.h" | #include "wiringPi.h" | ||||
#include "softPwm.h" | #include "softPwm.h" | ||||
// MAX_PINS: | // MAX_PINS: | ||||
// This is more than the number of Pi pins because we can actually softPwm | |||||
// pins that are on GPIO expanders. It's not that efficient and more than 1 or | |||||
// 2 pins on e.g. (SPI) mcp23s17 won't really be that effective, however... | |||||
// This is more than the number of Pi pins because we can actually softPwm. | |||||
// Once upon a time I let pins on gpio expanders be softPwm'd, but it's really | |||||
// really not a good thing. | |||||
#define MAX_PINS 1024 | |||||
#define MAX_PINS 64 | |||||
// The PWM Frequency is derived from the "pulse time" below. Essentially, | // The PWM Frequency is derived from the "pulse time" below. Essentially, | ||||
// the frequency is a function of the range and this pulse time. | // the frequency is a function of the range and this pulse time. | ||||
@@ -44,7 +45,7 @@ | |||||
// It's possible to get a higher frequency by lowering the pulse time, | // It's possible to get a higher frequency by lowering the pulse time, | ||||
// however CPU uage will skyrocket as wiringPi uses a hard-loop to time | // however CPU uage will skyrocket as wiringPi uses a hard-loop to time | ||||
// periods under 100µS - this is because the Linux timer calls are just | // periods under 100µS - this is because the Linux timer calls are just | ||||
// accurate at all, and have an overhead. | |||||
// not accurate at all, and have an overhead. | |||||
// | // | ||||
// Another way to increase the frequency is to reduce the range - however | // Another way to increase the frequency is to reduce the range - however | ||||
// that reduces the overall output accuracy... | // that reduces the overall output accuracy... | ||||
@@ -63,7 +64,7 @@ static volatile int newPin = -1 ; | |||||
********************************************************************************* | ********************************************************************************* | ||||
*/ | */ | ||||
static PI_THREAD (softPwmThread) | |||||
static void *softPwmThread (void *arg) | |||||
{ | { | ||||
int pin, mark, space ; | int pin, mark, space ; | ||||
struct sched_param param ; | struct sched_param param ; | ||||
@@ -71,6 +72,9 @@ static PI_THREAD (softPwmThread) | |||||
param.sched_priority = sched_get_priority_max (SCHED_RR) ; | param.sched_priority = sched_get_priority_max (SCHED_RR) ; | ||||
pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; | pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; | ||||
pin = *((int *)arg) ; | |||||
free (arg) ; | |||||
pin = newPin ; | pin = newPin ; | ||||
newPin = -1 ; | newPin = -1 ; | ||||
@@ -102,14 +106,15 @@ static PI_THREAD (softPwmThread) | |||||
void softPwmWrite (int pin, int value) | void softPwmWrite (int pin, int value) | ||||
{ | { | ||||
pin &= (MAX_PINS - 1) ; | |||||
/**/ if (value < 0) | |||||
value = 0 ; | |||||
else if (value > range [pin]) | |||||
value = range [pin] ; | |||||
if (pin < MAX_PINS) | |||||
{ | |||||
/**/ if (value < 0) | |||||
value = 0 ; | |||||
else if (value > range [pin]) | |||||
value = range [pin] ; | |||||
marks [pin] = value ; | |||||
marks [pin] = value ; | |||||
} | |||||
} | } | ||||
@@ -123,21 +128,30 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) | |||||
{ | { | ||||
int res ; | int res ; | ||||
pthread_t myThread ; | pthread_t myThread ; | ||||
int *passPin ; | |||||
if (pin >= MAX_PINS) | |||||
return -1 ; | |||||
if (range [pin] != 0) // Already running on this pin | if (range [pin] != 0) // Already running on this pin | ||||
return -1 ; | return -1 ; | ||||
if (range <= 0) | |||||
if (pwmRange <= 0) | |||||
return -1 ; | |||||
passPin = malloc (sizeof (*passPin)) ; | |||||
if (passPin == NULL) | |||||
return -1 ; | return -1 ; | ||||
pinMode (pin, OUTPUT) ; | |||||
digitalWrite (pin, LOW) ; | digitalWrite (pin, LOW) ; | ||||
pinMode (pin, OUTPUT) ; | |||||
marks [pin] = initialValue ; | marks [pin] = initialValue ; | ||||
range [pin] = pwmRange ; | range [pin] = pwmRange ; | ||||
newPin = pin ; | |||||
res = pthread_create (&myThread, NULL, softPwmThread, NULL) ; | |||||
*passPin = pin ; | |||||
newPin = pin ; | |||||
res = pthread_create (&myThread, NULL, softPwmThread, (void *)passPin) ; | |||||
while (newPin != -1) | while (newPin != -1) | ||||
delay (1) ; | delay (1) ; | ||||
@@ -156,11 +170,14 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) | |||||
void softPwmStop (int pin) | void softPwmStop (int pin) | ||||
{ | { | ||||
if (range [pin] != 0) | |||||
if (pin < MAX_PINS) | |||||
{ | { | ||||
pthread_cancel (threads [pin]) ; | |||||
pthread_join (threads [pin], NULL) ; | |||||
range [pin] = 0 ; | |||||
digitalWrite (pin, LOW) ; | |||||
if (range [pin] != 0) | |||||
{ | |||||
pthread_cancel (threads [pin]) ; | |||||
pthread_join (threads [pin], NULL) ; | |||||
range [pin] = 0 ; | |||||
digitalWrite (pin, LOW) ; | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* wiringPi.h: | * wiringPi.h: | ||||
* Arduino like Wiring library for the Raspberry Pi. | * 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: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/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 | // C doesn't have true/false by default and I can never remember which | ||||
// way round they are, so ... | // way round they are, so ... | ||||
// (and yes, I know about stdbool.h but I like capitals for these and I'm old) | |||||
#ifndef TRUE | #ifndef TRUE | ||||
# define TRUE (1==1) | # define TRUE (1==1) | ||||
# define FALSE (!TRUE) | # define FALSE (!TRUE) | ||||
#endif | #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 | // Handy defines | ||||
// wiringPi modes | // wiringPi modes | ||||
@@ -77,16 +87,19 @@ | |||||
// Pi model types and version numbers | // Pi model types and version numbers | ||||
// Intended for the GPIO program Use at your own risk. | // 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 0 | ||||
#define PI_VERSION_1_1 1 | #define PI_VERSION_1_1 1 | ||||
@@ -95,7 +108,7 @@ | |||||
#define PI_MAKER_SONY 0 | #define PI_MAKER_SONY 0 | ||||
#define PI_MAKER_EGOMAN 1 | #define PI_MAKER_EGOMAN 1 | ||||
#define PI_MAKER_MBEST 2 | |||||
#define PI_MAKER_EMBEST 2 | |||||
#define PI_MAKER_UNKNOWN 3 | #define PI_MAKER_UNKNOWN 3 | ||||
extern const char *piModelNames [16] ; | extern const char *piModelNames [16] ; | ||||
@@ -108,7 +121,7 @@ extern const int piMemorySize [ 8] ; | |||||
// Threads | // Threads | ||||
#define PI_THREAD(X) void *X (void *dummy) | |||||
#define PI_THREAD(X) void *X (UNU void *dummy) | |||||
// Failure modes | // Failure modes | ||||
@@ -135,19 +148,30 @@ struct wiringPiNodeStruct | |||||
unsigned int data2 ; // ditto | unsigned int data2 ; // ditto | ||||
unsigned int data3 ; // ditto | unsigned int data3 ; // ditto | ||||
void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ; | |||||
void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ; | |||||
int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ; | |||||
void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||||
void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||||
int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ; | |||||
void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||||
void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ; | |||||
void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ; | |||||
int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ; | |||||
//unsigned int (*digitalRead8) (struct wiringPiNodeStruct *node, int pin) ; | |||||
void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||||
// void (*digitalWrite8) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||||
void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||||
int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ; | |||||
void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ; | |||||
struct wiringPiNodeStruct *next ; | struct wiringPiNodeStruct *next ; | ||||
} ; | } ; | ||||
extern struct wiringPiNodeStruct *wiringPiNodes ; | 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 | // Function prototypes | ||||
// c++ wrappers thanks to a comment by Nick Lott | // 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 *wiringPiFindNode (int pin) ; | ||||
extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) ; | extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) ; | ||||
extern void wiringPiVersion (int *major, int *minor) ; | |||||
extern int wiringPiSetup (void) ; | extern int wiringPiSetup (void) ; | ||||
extern int wiringPiSetupSys (void) ; | extern int wiringPiSetupSys (void) ; | ||||
extern int wiringPiSetupGpio (void) ; | extern int wiringPiSetupGpio (void) ; | ||||
extern int wiringPiSetupPhys (void) ; | extern int wiringPiSetupPhys (void) ; | ||||
extern void pinModeAlt (int pin, int mode) ; | |||||
extern void pinMode (int pin, int mode) ; | |||||
extern void pullUpDnControl (int pin, int pud) ; | |||||
extern int digitalRead (int pin) ; | |||||
extern void digitalWrite (int pin, int value) ; | |||||
extern void pwmWrite (int pin, int value) ; | |||||
extern int analogRead (int pin) ; | |||||
extern void analogWrite (int pin, int value) ; | |||||
extern void pinModeAlt (int pin, int mode) ; | |||||
extern void pinMode (int pin, int mode) ; | |||||
extern void pullUpDnControl (int pin, int pud) ; | |||||
extern int digitalRead (int pin) ; | |||||
extern void digitalWrite (int pin, int value) ; | |||||
extern unsigned int digitalRead8 (int pin) ; | |||||
extern void digitalWrite8 (int pin, int value) ; | |||||
extern void pwmWrite (int pin, int value) ; | |||||
extern int analogRead (int pin) ; | |||||
extern void analogWrite (int pin, int value) ; | |||||
// PiFace specifics | // PiFace specifics | ||||
// (Deprecated) | // (Deprecated) | ||||
@@ -190,19 +217,22 @@ extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio | |||||
// On-Board Raspberry Pi hardware specific stuff | // 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 void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; | ||||
extern int wpiPinToGpio (int wpiPin) ; | extern int wpiPinToGpio (int wpiPin) ; | ||||
extern int physPinToGpio (int physPin) ; | extern int physPinToGpio (int physPin) ; | ||||
extern void setPadDrive (int group, int value) ; | extern void setPadDrive (int group, int value) ; | ||||
extern int getAlt (int pin) ; | extern int getAlt (int pin) ; | ||||
extern void pwmToneWrite (int pin, int freq) ; | extern void pwmToneWrite (int pin, int freq) ; | ||||
extern void digitalWriteByte (int value) ; | |||||
extern unsigned int digitalReadByte (void) ; | |||||
extern void pwmSetMode (int mode) ; | extern void pwmSetMode (int mode) ; | ||||
extern void pwmSetRange (unsigned int range) ; | extern void pwmSetRange (unsigned int range) ; | ||||
extern void pwmSetClock (int divisor) ; | extern void pwmSetClock (int divisor) ; | ||||
extern void gpioClockSet (int pin, int freq) ; | extern void gpioClockSet (int pin, int freq) ; | ||||
extern unsigned int digitalReadByte (void) ; | |||||
extern unsigned int digitalReadByte2 (void) ; | |||||
extern void digitalWriteByte (int value) ; | |||||
extern void digitalWriteByte2 (int value) ; | |||||
// Interrupts | // Interrupts | ||||
// (Also Pi hardware specific) | // (Also Pi hardware specific) | ||||
@@ -52,6 +52,7 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <asm/ioctl.h> | |||||
#include "wiringPi.h" | #include "wiringPi.h" | ||||
#include "wiringPiI2C.h" | #include "wiringPiI2C.h" | ||||
@@ -221,7 +222,7 @@ int wiringPiI2CSetup (const int devId) | |||||
int rev ; | int rev ; | ||||
const char *device ; | const char *device ; | ||||
rev = piBoardRev () ; | |||||
rev = piGpioLayout () ; | |||||
if (rev == 1) | if (rev == 1) | ||||
device = "/dev/i2c-0" ; | device = "/dev/i2c-0" ; | ||||
@@ -28,6 +28,7 @@ | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <asm/ioctl.h> | |||||
#include <linux/spi/spidev.h> | #include <linux/spi/spidev.h> | ||||
#include "wiringPi.h" | #include "wiringPi.h" | ||||
@@ -38,10 +39,10 @@ | |||||
// The SPI bus parameters | // The SPI bus parameters | ||||
// Variables as they need to be passed as pointers later on | // 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 uint32_t spiSpeeds [2] ; | ||||
static int spiFds [2] ; | static int spiFds [2] ; | ||||
@@ -49,24 +49,36 @@ int serialOpen (const char *device, const int baud) | |||||
switch (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: | default: | ||||
return -2 ; | return -2 ; | ||||
@@ -96,7 +108,7 @@ int serialOpen (const char *device, const int baud) | |||||
options.c_cc [VMIN] = 0 ; | options.c_cc [VMIN] = 0 ; | ||||
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) | options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) | ||||
tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ; | |||||
tcsetattr (fd, TCSANOW, &options) ; | |||||
ioctl (fd, TIOCMGET, &status); | ioctl (fd, TIOCMGET, &status); | ||||
@@ -55,6 +55,13 @@ | |||||
#include "ads1115.h" | #include "ads1115.h" | ||||
#include "sn3218.h" | #include "sn3218.h" | ||||
#include "drcSerial.h" | #include "drcSerial.h" | ||||
#include "drcNet.h" | |||||
#include "../wiringPiD/drcNetCmd.h" | |||||
#include "pseudoPins.h" | |||||
#include "bmp180.h" | |||||
#include "htu21d.h" | |||||
#include "ds18b20.h" | |||||
#include "rht03.h" | |||||
#include "wpiExtensions.h" | #include "wpiExtensions.h" | ||||
@@ -130,12 +137,16 @@ static char *extractInt (char *progName, char *p, int *num) | |||||
/* | /* | ||||
* extractStr: | * extractStr: | ||||
* Check & return a string at the given location (prefixed by a :) | * Check & return a string at the given location (prefixed by a :) | ||||
* Note: The string can be enclosed in []'s to escape colons. This is | |||||
* so we can handle IPv6 addresses which contain colons and the []'s is | |||||
* a common way to prepresent them. | |||||
********************************************************************************* | ********************************************************************************* | ||||
*/ | */ | ||||
static char *extractStr (char *progName, char *p, char **str) | static char *extractStr (char *progName, char *p, char **str) | ||||
{ | { | ||||
char *q, *r ; | char *q, *r ; | ||||
int quoted = FALSE ; | |||||
if (*p != ':') | if (*p != ':') | ||||
{ | { | ||||
@@ -145,21 +156,38 @@ static char *extractStr (char *progName, char *p, char **str) | |||||
++p ; | ++p ; | ||||
if (!isprint (*p)) | |||||
if (*p == '[') | |||||
{ | |||||
quoted = TRUE ; | |||||
++p ; | |||||
} | |||||
if (!isprint (*p)) // Is this needed? | |||||
{ | { | ||||
verbError ("%s: character expected", progName) ; | verbError ("%s: character expected", progName) ; | ||||
return NULL ; | return NULL ; | ||||
} | } | ||||
q = p ; | q = p ; | ||||
while ((*q != 0) && (*q != ':')) | |||||
++q ; | |||||
if (quoted) | |||||
{ | |||||
while ((*q != 0) && (*q != ']')) | |||||
++q ; | |||||
} | |||||
else | |||||
{ | |||||
while ((*q != 0) && (*q != ':')) | |||||
++q ; | |||||
} | |||||
*str = r = calloc (q - p + 2, 1) ; // Zeros it | *str = r = calloc (q - p + 2, 1) ; // Zeros it | ||||
while (p != q) | while (p != q) | ||||
*r++ = *p++ ; | *r++ = *p++ ; | ||||
if (quoted) // Skip over the ] to the : | |||||
++p ; | |||||
return p ; | return p ; | ||||
} | } | ||||
@@ -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: | * doExtensionMax31855: | ||||
* Analog IO | * Analog IO | ||||
* max31855:base:spiChan | * 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) ; | sn3218Setup (pinBase) ; | ||||
return TRUE ; | return TRUE ; | ||||
@@ -631,9 +740,9 @@ static int doExtensionDrcS (char *progName, int pinBase, char *params) | |||||
if ((params = extractInt (progName, params, &pins)) == NULL) | if ((params = extractInt (progName, params, &pins)) == NULL) | ||||
return FALSE ; | return FALSE ; | ||||
if ((pins < 1) || (pins > 100)) | |||||
if ((pins < 1) || (pins > 1000)) | |||||
{ | { | ||||
verbError ("%s: pins (%d) out of range (2-100)", progName, pins) ; | |||||
verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ; | |||||
return FALSE ; | return FALSE ; | ||||
} | } | ||||
@@ -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 | * Function list | ||||
@@ -677,6 +839,11 @@ static struct extensionFunctionStruct extensionFunctions [] = | |||||
{ "sr595", &doExtensionSr595 }, | { "sr595", &doExtensionSr595 }, | ||||
{ "pcf8574", &doExtensionPcf8574 }, | { "pcf8574", &doExtensionPcf8574 }, | ||||
{ "pcf8591", &doExtensionPcf8591 }, | { "pcf8591", &doExtensionPcf8591 }, | ||||
{ "bmp180", &doExtensionBmp180 }, | |||||
{ "pseudoPins", &doExtensionPseudoPins }, | |||||
{ "htu21d", &doExtensionHtu21d }, | |||||
{ "ds18b20", &doExtensionDs18b20 }, | |||||
{ "rht03", &doExtensionRht03 }, | |||||
{ "mcp3002", &doExtensionMcp3002 }, | { "mcp3002", &doExtensionMcp3002 }, | ||||
{ "mcp3004", &doExtensionMcp3004 }, | { "mcp3004", &doExtensionMcp3004 }, | ||||
{ "mcp4802", &doExtensionMcp4802 }, | { "mcp4802", &doExtensionMcp4802 }, | ||||
@@ -686,6 +853,7 @@ static struct extensionFunctionStruct extensionFunctions [] = | |||||
{ "max5322", &doExtensionMax5322 }, | { "max5322", &doExtensionMax5322 }, | ||||
{ "sn3218", &doExtensionSn3218 }, | { "sn3218", &doExtensionSn3218 }, | ||||
{ "drcs", &doExtensionDrcS }, | { "drcs", &doExtensionDrcS }, | ||||
{ "drcn", &doExtensionDrcNet }, | |||||
{ NULL, NULL }, | { NULL, NULL }, | ||||
} ; | } ; | ||||
@@ -703,7 +871,7 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors) | |||||
char *p ; | char *p ; | ||||
char *extension = extensionData ; | char *extension = extensionData ; | ||||
struct extensionFunctionStruct *extensionFn ; | struct extensionFunctionStruct *extensionFn ; | ||||
unsigned pinBase = 0 ; | |||||
int pinBase = 0 ; | |||||
verbose = printErrors ; | verbose = printErrors ; | ||||
@@ -755,6 +923,6 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors) | |||||
return extensionFn->function (progName, pinBase, p) ; | return extensionFn->function (progName, pinBase, p) ; | ||||
} | } | ||||
verbError ("%s: extension %s not found", progName, extension) ; | |||||
fprintf (stderr, "%s: extension %s not found", progName, extension) ; | |||||
return FALSE ; | return FALSE ; | ||||
} | } |
@@ -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: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/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 ; | |||||
} |