Add serial communication program

This commit is contained in:
Mark 2020-01-22 15:02:03 +02:00
parent 294db2e403
commit 8f715f5885
2 changed files with 130 additions and 1 deletions

View File

@ -22,7 +22,8 @@ STAGE_BIN=$(STAGE)/init \
$(STAGE)/bin/mkdir \
$(STAGE)/bin/login \
$(STAGE)/bin/ase \
$(STAGE)/bin/su
$(STAGE)/bin/su \
$(STAGE)/bin/com
sh_OBJS=$(O)/sh/sh.o \
$(O)/sh/readline.o \
$(O)/sh/builtin.o \

128
core/bin/com.c Normal file
View File

@ -0,0 +1,128 @@
#include <sys/select.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
// TODO: baud rate support in kernel
static int ready = 0, there_fd;
static struct termios here_tc, here_tc_old;
static struct termios there_tc, there_tc_old;
static void sig_handler(int signum) {
// Restore old termios
if (ready) {
printf("Interrupted\n");
tcsetattr(STDIN_FILENO, TCSANOW, &here_tc_old);
tcsetattr(there_fd, TCSANOW, &there_tc_old);
}
exit(0);
}
int main(int argc, char **argv) {
if (argc != 2) {
printf("Usage: com /dev/ttySn\n");
return -1;
}
signal(SIGINT, sig_handler);
char buf[512];
fd_set fds;
ssize_t len;
int res;
if ((there_fd = open(argv[1], O_RDWR, 0)) < 0) {
perror(argv[1]);
return -1;
}
if (tcgetattr(STDIN_FILENO, &here_tc_old)) {
perror("stdin");
close(there_fd);
return -1;
}
if (tcgetattr(there_fd, &there_tc_old) != 0) {
perror(argv[1]);
close(there_fd);
return -1;
}
ready = 1;
// Make them both raw
memcpy(&here_tc, &here_tc_old, sizeof(struct termios));
memcpy(&there_tc, &there_tc_old, sizeof(struct termios));
here_tc.c_iflag &= ~ICANON;
here_tc.c_lflag &= ~ECHO;
there_tc.c_iflag &= ~ICANON;
there_tc.c_lflag &= ~ECHO;
res = -1;
if (tcsetattr(STDIN_FILENO, TCSANOW, &here_tc) != 0) {
perror("stdin");
goto cleanup;
}
if (tcsetattr(there_fd, TCSANOW, &there_tc) != 0) {
perror(argv[1]);
goto cleanup;
}
while (1) {
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(there_fd, &fds);
if ((res = select(there_fd + 1, &fds, NULL, NULL, NULL)) < 0) {
goto cleanup;
}
if (FD_ISSET(STDIN_FILENO, &fds)) {
if ((len = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) {
if (len != 0) {
perror("read()");
res = -1;
}
goto cleanup;
}
if (write(there_fd, buf, len) != len) {
perror("write()");
res = -1;
goto cleanup;
}
}
if (FD_ISSET(there_fd, &fds)) {
if ((len = read(there_fd, buf, sizeof(buf))) <= 0) {
if (len == 0) {
printf("Remote side hang up\n");
} else {
perror("read()");
res = -1;
}
goto cleanup;
}
if (write(STDOUT_FILENO, buf, len) != len) {
perror("write()");
res = -1;
goto cleanup;
}
}
}
res = 0;
cleanup:
tcsetattr(there_fd, TCSANOW, &there_tc_old);
tcsetattr(STDIN_FILENO, TCSANOW, &here_tc_old);
close(there_fd);
ready = 0;
return 0;
}