Initial commit

This commit is contained in:
Alex 2020-08-13 09:06:17 +02:00
commit 5af2be7e5b
Signed by: caskd
GPG Key ID: F92BA85F61F4C173
6 changed files with 215 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build/

19
CMakeLists.txt Normal file
View File

@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.16)
project(relaycontrol LANGUAGES C)
set(CFLAGS "${CFLAGS} -Wall -Wextra -pedantic -Wformat-overflow=2 -Wformat-security -Winit-self -Wstrict-overflow=2 -Wstringop-overflow=2 -Walloc-zero -Wduplicated-branches -Wduplicated-cond -Wtrampolines -Wfloat-equal -Wshadow -Wunsafe-loop-optimizations -Wparentheses -fanalyzer -fstack-protector")
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
if (CMAKE_BUILD_TYPE EQUAL "Debug")
set(CFLAGS "${CFLAGS} -Og")
elseif (CMAKE_BUILD_TYPE EQUAL "Release")
set(CFLAGS "${CFLAGS} -O2 -Werror")
endif()
add_executable(relaycntl
src/main.c
)
set_property(TARGET relaycntl PROPERTY C_STANDARD 99)
install(TARGETS relaycntl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

13
LICENSE Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

25
README.md Normal file
View File

@ -0,0 +1,25 @@
# Raspberry PI General Purpose Input/Output Controller
This is a simple GPIO pin controller for UNIX-like kernels/systems.
## Requirements
- CMake
- ANSI C compiler
- UNIX standard library
## Building
First, generate the build files with CMake:
```
cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
```
Second, install the binary:
```
cd build/
sudo make install
```
## License
WTFPL

99
src/main.c Normal file
View File

@ -0,0 +1,99 @@
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#define GPIO_IFACE_MISSING = -1
#define GPIO_PIN_EXP_FAIL = -2
#define GPIO_DIR_CONT_FAIL = -3
#define GPIO_SWITCH_FAIL = -4
#define GPIO_PIN_UNX_NF = -5
#define GPIO_PIN_UNX_FAIL = -6
#define GPIO_PREFIX "/sys/class/gpio/"
#define GPIO_EXPORT "export"
#define GPIO_UNEXPORT "unexport"
#define MAX_PATHLEN 512
#define PRINTERRANDRET(mesg, varfmt, var) \
{ \
fprintf(stderr, "%s \"%" varfmt "\". %s (%i)\n", mesg, var, strerror(errno), errno); \
return 1; \
}
ssize_t exportPin(signed int pinno);
ssize_t setPinDirection(signed int pinno, char* value);
ssize_t setPinValue(signed int pinno, int value);
int main(int argc, char* argv[])
{
int pinno = (argc > 1) ? atoi(argv[1]) : 0;
bool value = (argc > 2) ? atoi(argv[2]) : 0;
if (pinno != exportPin(pinno))
return -1;
if (pinno != setPinDirection(pinno, "out"))
return -1;
if (pinno != setPinValue(pinno, value))
return -1;
return 0;
}
ssize_t exportPin(signed int pinno)
{
if (chdir(GPIO_PREFIX) != 0)
PRINTERRANDRET("Failed to change directory to", "s", GPIO_PREFIX);
char buffer[MAX_PATHLEN];
int fd;
ssize_t nbytes;
if ((fd = open(GPIO_EXPORT, O_WRONLY)) < 0)
PRINTERRANDRET("Failed to open export", "s", GPIO_EXPORT);
if ((nbytes = snprintf(buffer, MAX_PATHLEN, "%i", pinno)) <= 0)
PRINTERRANDRET("Couldn't format pin number as string", "i", pinno);
if (write(fd, buffer, nbytes) != nbytes && errno != EBUSY)
PRINTERRANDRET("Couldn't write pin number to the exporter", "i", pinno);
if (close(fd) != 0)
PRINTERRANDRET("Couldn't close exporter", "i", pinno);
return pinno;
}
ssize_t setPinDirection(signed int pinno, char* value)
{
if (chdir(GPIO_PREFIX) != 0)
PRINTERRANDRET("Failed to change directory to", "s", GPIO_PREFIX);
char buffer[MAX_PATHLEN];
int fd;
ssize_t nbytes;
if ((nbytes = snprintf(buffer, MAX_PATHLEN, "gpio%i/direction", pinno)) <= 0)
PRINTERRANDRET("Couldn't format pin path as string", "i", pinno);
if ((fd = open(buffer, O_WRONLY)) < 0)
PRINTERRANDRET("Failed to open pin path.", "s", GPIO_EXPORT);
if (write(fd, value, strlen(value)) != nbytes && errno != EBUSY)
PRINTERRANDRET("Couldn't write pin direction", "i", pinno);
if (close(fd) != 0)
PRINTERRANDRET("Couldn't close pin direction file", "i", pinno);
return pinno;
}
ssize_t setPinValue(signed int pinno, int value)
{
if (chdir(GPIO_PREFIX) != 0)
PRINTERRANDRET("Failed to change directory to", "s", GPIO_PREFIX);
char buffer[MAX_PATHLEN];
int fd;
ssize_t nbytes;
if ((nbytes = snprintf(buffer, MAX_PATHLEN, "gpio%i/value", pinno)) <= 0)
PRINTERRANDRET("Couldn't format pin path as string", "i", pinno);
if ((fd = open(buffer, O_WRONLY)) < 0)
PRINTERRANDRET("Failed to open pin path.", "s", GPIO_EXPORT);
if ((nbytes = snprintf(buffer, MAX_PATHLEN, "%i", value)) <= 0)
PRINTERRANDRET("Couldn't format pin value as string", "i", value);
if (write(fd, buffer, nbytes) != nbytes && errno != EBUSY)
PRINTERRANDRET("Couldn't write pin value", "i", pinno);
if (close(fd) != 0)
PRINTERRANDRET("Couldn't close pin value file", "i", pinno);
return pinno;
}

58
src/main.py Normal file
View File

@ -0,0 +1,58 @@
import time
import sys
import errno
GPIO_IFACE_MISSING = -1
GPIO_PIN_EXP_FAIL = -2
GPIO_DIR_CONT_FAIL = -3
GPIO_SWITCH_FAIL = -4
GPIO_PIN_UNX_NF = -5
GPIO_PIN_UNX_FAIL = -6
PINLISTMISS = -1
PINLISTTOKFAIL = -2
def preparePin(pinno):
try: x = open('/sys/class/gpio/export', 'w')
except:
return GPIO_IFACE_MISSING
else:
try:
x.write(f'{pinno}')
x.close()
except OSError as e:
if (e.errno != errno.EBUSY): # Busy devices are already exported
return GPIO_PIN_EXP_FAIL
return
for i in range(0,5):
try: g = open(f'/sys/class/gpio/gpio{pinno}/direction', 'w')
except:
if (i == 4):
return GPIO_DIR_CONT_FAIL
else: time.sleep(1)
else:
try: g.write('out')
except:
g.close()
return GPIO_SWITCH_FAIL
else:
g.close()
break
def closePin(pinno):
try: x = open('/sys/class/gpio/unexport', 'w')
except: return GPIO_PIN_UNX_NF
else:
try: x.write(pinno)
except: return GPIO_PIN_UNX_FAIL
finally: x.close()
try: preparePin(sys.argv[1])
except GPIO_SWITCH_FAIL: print(f'GPIO Pin direction couldn\'t be switched to out. {sys.argv[1]}')
except GPIO_DIR_CONT_FAIL: print(f'GPIO Pin control couldn\'t be opened. {sys.argv[1]}')
except GPIO_PIN_EXP_FAIL: print(f'GPIO Pin couldn\'t be exported. P: {sys.argv[1]}')
except GPIO_IFACE_MISSING: print(f'GPIO Export interface couldn\'t be opened. {sys.argv[1]}')
with open(f'/sys/class/gpio/gpio{sys.argv[1]}/value', 'w') as x:
if (len(sys.argv) == 3): x.write(sys.argv[2])
else: x.write('0')