RasPiGPIOController/src/main.c

100 lines
3.4 KiB
C

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