blob: 1c23dffe4949c7884cd6a37a08a85c18dfb7ce35 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "gpiodpi.h"
#ifdef __linux__
#include <pty.h>
#elif __APPLE__
#include <util.h>
#endif
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
void *gpiodpi_create(const char *name, int n_bits) {
struct gpiodpi_ctx *ctx =
(struct gpiodpi_ctx *)calloc(1, sizeof(struct gpiodpi_ctx));
assert(ctx);
// n_bits > 32 requires more sophisticated handling of svBitVecVal which we
// currently don't do.
assert(n_bits <= 32 && "n_bits must be <= 32");
ctx->n_bits = n_bits;
char cwd[PATH_MAX];
char *cwd_rv;
cwd_rv = getcwd(cwd, sizeof(cwd));
assert(cwd_rv != NULL);
int rv;
rv = snprintf(ctx->fifo_pathname, PATH_MAX, "%s/%s", cwd, name);
assert(rv <= PATH_MAX && rv > 0);
rv = mkfifo(ctx->fifo_pathname, 0644); // writes are not supported currently
if (rv != 0) {
fprintf(stderr, "GPIO: Unable to create FIFO at %s: %s\n",
ctx->fifo_pathname, strerror(errno));
return NULL;
}
ctx->fifo_fd = open(ctx->fifo_pathname, O_RDWR);
if (ctx->fifo_fd < 0) {
fprintf(stderr, "GPIO: Unable to open FIFO at %s: %s\n", ctx->fifo_pathname,
strerror(errno));
return NULL;
}
printf(
"\n"
"GPIO: FIFO pipe created at %s for %d bit wide GPIO. Run\n"
"$ cat %s\n"
"to observe the output.\n",
ctx->fifo_pathname, ctx->n_bits, ctx->fifo_pathname);
return (void *)ctx;
}
void gpiodpi_device_to_host(void *ctx_void, svBitVecVal *gpio_data,
svBitVecVal *gpio_oe) {
struct gpiodpi_ctx *ctx = (struct gpiodpi_ctx *)ctx_void;
assert(ctx);
// n_bits > 32 requires more sophisticated handling of svBitVecVal which we
// currently don't do (loop through the array of 32 bit values).
assert(ctx->n_bits <= 32 && "n_bits must be <= 32");
char gpio_str[32 + 1];
for (int i = 0; i < ctx->n_bits; i++) {
gpio_str[ctx->n_bits - i - 1] = !!(gpio_data[0] & (1 << i)) + '0';
}
gpio_str[ctx->n_bits] = '\n';
ssize_t written = write(ctx->fifo_fd, gpio_str, ctx->n_bits + 1);
assert(written == ctx->n_bits + 1);
}
void gpiodpi_close(void *ctx_void) {
struct gpiodpi_ctx *ctx = (struct gpiodpi_ctx *)ctx_void;
if (!ctx) {
return;
}
int rv;
rv = close(ctx->fifo_fd);
if (rv != 0) {
printf("GPIO: Failed to close FIFO: %s\n", strerror(errno));
}
rv = unlink(ctx->fifo_pathname);
if (rv != 0) {
printf("GPIO: Failed to unlink FIFO file at %s: %s\n", ctx->fifo_pathname,
strerror(errno));
}
free(ctx);
}