| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| #include "uartdpi.h" |
| |
| #ifdef __linux__ |
| #include <pty.h> |
| #elif __APPLE__ |
| #include <util.h> |
| #endif |
| |
| #include <assert.h> |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| void *uartdpi_create(const char *name) { |
| struct uartdpi_ctx *ctx = |
| (struct uartdpi_ctx *)malloc(sizeof(struct uartdpi_ctx)); |
| assert(ctx); |
| |
| int rv; |
| |
| struct termios tty; |
| cfmakeraw(&tty); |
| |
| rv = openpty(&ctx->master, &ctx->slave, 0, &tty, 0); |
| assert(rv != -1); |
| |
| rv = ttyname_r(ctx->slave, ctx->ptyname, 64); |
| assert(rv == 0 && "ttyname_r failed"); |
| |
| int cur_flags = fcntl(ctx->master, F_GETFL, 0); |
| assert(cur_flags != -1 && "Unable to read current flags."); |
| int new_flags = fcntl(ctx->master, F_SETFL, cur_flags | O_NONBLOCK); |
| assert(new_flags != -1 && "Unable to set FD flags"); |
| |
| printf( |
| "\n" |
| "UART: Created %s for %s. Connect to it with any terminal program, e.g.\n" |
| "$ screen %s\n", |
| ctx->ptyname, name, ctx->ptyname); |
| |
| return (void *)ctx; |
| } |
| |
| int uartdpi_can_read(void *ctx_void) { |
| struct uartdpi_ctx *ctx = (struct uartdpi_ctx *)ctx_void; |
| |
| int rv = read(ctx->master, &ctx->tmp_read, 1); |
| return (rv == 1); |
| } |
| |
| char uartdpi_read(void *ctx_void) { |
| struct uartdpi_ctx *ctx = (struct uartdpi_ctx *)ctx_void; |
| |
| return ctx->tmp_read; |
| } |
| |
| void uartdpi_write(void *ctx_void, char c) { |
| struct uartdpi_ctx *ctx = (struct uartdpi_ctx *)ctx_void; |
| |
| int rv = write(ctx->master, &c, 1); |
| assert(rv == 1 && "write() failed."); |
| } |