blob: 80087eebf018a72f1cc5fbe04863d735a8242a71 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
/* Common code for GPIO tools. */
#include <ctype.h>
#include <errno.h>
#include <gpiod.h>
#include <libgen.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/signalfd.h>
#include "tools-common.h"
const char *get_progname(void)
{
return program_invocation_name;
}
void die(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
fprintf(stderr, "%s: ", program_invocation_name);
vfprintf(stderr, fmt, va);
fprintf(stderr, "\n");
va_end(va);
exit(EXIT_FAILURE);
}
void die_perror(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
fprintf(stderr, "%s: ", program_invocation_name);
vfprintf(stderr, fmt, va);
fprintf(stderr, ": %s\n", strerror(errno));
va_end(va);
exit(EXIT_FAILURE);
}
void print_version(void)
{
printf("%s (libgpiod) v%s\n",
program_invocation_short_name, gpiod_version_string());
printf("Copyright (C) 2017-2018 Bartosz Golaszewski\n");
printf("License: LGPLv2.1\n");
printf("This is free software: you are free to change and redistribute it.\n");
printf("There is NO WARRANTY, to the extent permitted by law.\n");
}
int bias_flags(const char *option)
{
if (strcmp(option, "pull-down") == 0)
return GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN;
if (strcmp(option, "pull-up") == 0)
return GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP;
if (strcmp(option, "disable") == 0)
return GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLED;
if (strcmp(option, "as-is") != 0)
die("invalid bias: %s", option);
return 0;
}
void print_bias_help(void)
{
printf("Biases:\n");
printf(" as-is:\tleave bias unchanged\n");
printf(" disable:\tdisable bias\n");
printf(" pull-up:\tenable pull-up\n");
printf(" pull-down:\tenable pull-down\n");
}
int make_signalfd(void)
{
sigset_t sigmask;
int sigfd, rv;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGTERM);
sigaddset(&sigmask, SIGINT);
rv = sigprocmask(SIG_BLOCK, &sigmask, NULL);
if (rv < 0)
die("error masking signals: %s", strerror(errno));
sigfd = signalfd(-1, &sigmask, 0);
if (sigfd < 0)
die("error creating signalfd: %s", strerror(errno));
return sigfd;
}
int chip_dir_filter(const struct dirent *entry)
{
bool is_chip;
char *path;
int ret;
ret = asprintf(&path, "/dev/%s", entry->d_name);
if (ret < 0)
return 0;
is_chip = gpiod_is_gpiochip_device(path);
free(path);
return !!is_chip;
}
struct gpiod_chip *chip_open_by_name(const char *name)
{
struct gpiod_chip *chip;
char *path;
int ret;
ret = asprintf(&path, "/dev/%s", name);
if (ret < 0)
return NULL;
chip = gpiod_chip_open(path);
free(path);
return chip;
}
static struct gpiod_chip *chip_open_by_number(unsigned int num)
{
struct gpiod_chip *chip;
char *path;
int ret;
ret = asprintf(&path, "/dev/gpiochip%u", num);
if (!ret)
return NULL;
chip = gpiod_chip_open(path);
free(path);
return chip;
}
static bool isuint(const char *str)
{
for (; *str && isdigit(*str); str++)
;
return *str == '\0';
}
struct gpiod_chip *chip_open_lookup(const char *device)
{
struct gpiod_chip *chip;
if (isuint(device)) {
chip = chip_open_by_number(strtoul(device, NULL, 10));
} else {
if (strncmp(device, "/dev/", 5))
chip = chip_open_by_name(device);
else
chip = gpiod_chip_open(device);
}
return chip;
}