Untested serial implementation for windows
This commit is contained in:
parent
be0e8a997c
commit
4eaac6d822
9 changed files with 213 additions and 70 deletions
41
Makefile
41
Makefile
|
|
@ -1,27 +1,30 @@
|
||||||
TARGET_OS=LINUX
|
OS=LINUX
|
||||||
|
|
||||||
CFLAGS=-Wall -MMD -pthread -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=199309L
|
|
||||||
|
|
||||||
SRCS=$(wildcard $(DIR_SRC)/*.c)
|
|
||||||
OBJS=$(addprefix $(DIR_OBJ)/,$(addsuffix .o,$(basename $(SRCS))))
|
|
||||||
DEPS=$(addprefix $(DIR_OBJ)/,$(addsuffix .d,$(basename $(SRCS))))
|
|
||||||
|
|
||||||
ifeq ($(TARGET_OS), LINUX)
|
|
||||||
CC=clang
|
|
||||||
else
|
|
||||||
CC=x86_64-w64-mingw32-gcc
|
|
||||||
CFLAGS+=-Llib/PDCurses/wincon -Llib/PDCurses
|
|
||||||
DEPS+=PDCurses
|
|
||||||
endif
|
|
||||||
|
|
||||||
LDFLAGS=-lpthread -lncurses
|
|
||||||
|
|
||||||
DIR_SRC=src
|
DIR_SRC=src
|
||||||
DIR_BUILD=build
|
DIR_BUILD=build
|
||||||
DIR_OBJ=$(DIR_BUILD)/obj
|
DIR_OBJ=$(DIR_BUILD)/obj
|
||||||
DIR_BIN=$(DIR_BUILD)/bin
|
DIR_BIN=$(DIR_BUILD)/bin
|
||||||
|
|
||||||
|
CFLAGS=-Wall -MMD -pthread -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=199309L
|
||||||
|
LIB_DEPS=
|
||||||
|
LIB_OBJS=
|
||||||
|
|
||||||
|
SRCS=$(wildcard $(DIR_SRC)/*.c)
|
||||||
|
OBJS=$(addprefix $(DIR_OBJ)/,$(addsuffix .o,$(basename $(SRCS))))
|
||||||
|
DEPS=$(addprefix $(DIR_OBJ)/,$(addsuffix .d,$(basename $(SRCS))))
|
||||||
|
|
||||||
|
ifeq ($(OS), LINUX)
|
||||||
|
CC=clang
|
||||||
|
LDFLAGS=-lncurses -lpthread
|
||||||
TARGET=$(DIR_BIN)/bytenuts
|
TARGET=$(DIR_BIN)/bytenuts
|
||||||
|
else
|
||||||
|
CC=x86_64-w64-mingw32-gcc
|
||||||
|
CFLAGS+=-Ilib/PDCurses/wincon/ -Ilib/PDCurses/
|
||||||
|
LDFLAGS=-lpthread -static
|
||||||
|
LIB_DEPS+=PDCurses
|
||||||
|
LIB_OBJS+=lib/PDCurses/wincon/*.o
|
||||||
|
TARGET=$(DIR_BIN)/bytenuts.exe
|
||||||
|
endif
|
||||||
|
|
||||||
DEBUG ?= 0
|
DEBUG ?= 0
|
||||||
ifeq ($(DEBUG), 1)
|
ifeq ($(DEBUG), 1)
|
||||||
|
|
@ -40,10 +43,10 @@ install:
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f /usr/local/bin/bytenuts
|
rm -f /usr/local/bin/bytenuts
|
||||||
|
|
||||||
$(TARGET): $(OBJS)
|
$(TARGET): $(OBJS) $(LIB_DEPS)
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
@echo "link and compile for $@"
|
@echo "link and compile for $@"
|
||||||
@$(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJS)
|
@$(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJS) $(LIB_OBJS)
|
||||||
|
|
||||||
$(DIR_OBJ)/$(DIR_SRC)/%.o: $(DIR_SRC)/%.c
|
$(DIR_OBJ)/$(DIR_SRC)/%.o: $(DIR_SRC)/%.c
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,16 @@ bytenuts_run(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
bytenuts.serial_fd = serial_open(bytenuts.config.serial_path, bytenuts.config.baud);
|
bytenuts.serial_fd = serial_open(bytenuts.config.serial_path, bytenuts.config.baud);
|
||||||
if (bytenuts.serial_fd < 0) {
|
if (bytenuts.serial_fd == SERIAL_INVALID) {
|
||||||
|
printf(
|
||||||
|
"Failed to open serial port \"%s\"\r\n",
|
||||||
|
bytenuts.config.serial_path
|
||||||
|
);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Opened \"%s\"\r\n", bytenuts.config.serial_path);
|
||||||
|
|
||||||
#ifndef __MINGW32__
|
#ifndef __MINGW32__
|
||||||
/* use pseudo-terminals for testing purposes */
|
/* use pseudo-terminals for testing purposes */
|
||||||
if (!strcmp(bytenuts.config.serial_path, "/dev/ptmx")) {
|
if (!strcmp(bytenuts.config.serial_path, "/dev/ptmx")) {
|
||||||
|
|
@ -111,11 +117,13 @@ bytenuts_run(int argc, char **argv)
|
||||||
cheerios_start(&bytenuts);
|
cheerios_start(&bytenuts);
|
||||||
ingest_start(&bytenuts);
|
ingest_start(&bytenuts);
|
||||||
|
|
||||||
|
#ifndef __MINGW32__
|
||||||
if (!strcmp(bytenuts.config.serial_path, "/dev/ptmx")) {
|
if (!strcmp(bytenuts.config.serial_path, "/dev/ptmx")) {
|
||||||
char info[128];
|
char info[128];
|
||||||
snprintf(info, sizeof(info), "Opened PTY port %s", ptsname(bytenuts.serial_fd));
|
snprintf(info, sizeof(info), "Opened PTY port %s", ptsname(bytenuts.serial_fd));
|
||||||
cheerios_info(info);
|
cheerios_info(info);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (bytenuts.resume) {
|
if (bytenuts.resume) {
|
||||||
load_state();
|
load_state();
|
||||||
|
|
@ -157,7 +165,7 @@ bytenuts_kill()
|
||||||
delwin(bytenuts.out_win);
|
delwin(bytenuts.out_win);
|
||||||
endwin();
|
endwin();
|
||||||
|
|
||||||
close(bytenuts.serial_fd);
|
serial_close(bytenuts.serial_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -302,10 +310,17 @@ parse_args(int argc, char **argv)
|
||||||
/* setup default options first */
|
/* setup default options first */
|
||||||
bytenuts.config = CONFIG_DEFAULT;
|
bytenuts.config = CONFIG_DEFAULT;
|
||||||
{
|
{
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
char *home = getenv("HOMEPATH");
|
||||||
|
char path[] = "\\.config\\bytenuts\\config";
|
||||||
|
bytenuts.config.config_path = malloc(strlen(home) + strlen(path) + 4);
|
||||||
|
sprintf(bytenuts.config.config_path, "C:\\%s%s", home, path);
|
||||||
|
#else
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
char path[] = "/.config/bytenuts/config";
|
char path[] = "/.config/bytenuts/config";
|
||||||
bytenuts.config.config_path = malloc(strlen(home) + strlen(path) + 1);
|
bytenuts.config.config_path = malloc(strlen(home) + strlen(path) + 1);
|
||||||
sprintf(bytenuts.config.config_path, "%s%s", home, path);
|
sprintf(bytenuts.config.config_path, "%s%s", home, path);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < argc - 1; i++) {
|
for (int i = 1; i < argc - 1; i++) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#else
|
#else
|
||||||
# include <ncurses.h>
|
# include <ncurses.h>
|
||||||
#endif
|
#endif
|
||||||
#include <poll.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -54,14 +53,14 @@ cheerios_start(bytenuts_t *bytenuts)
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
name_len = snprintf(
|
name_len = snprintf(
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
"%s/.config/bytenuts/outbuf.%d.log",
|
"%s/.config/bytenuts/outbuf.%lld.log",
|
||||||
home, pid
|
home, (long long)pid
|
||||||
);
|
);
|
||||||
cheerios.backup_filename = calloc(1, name_len + 1);
|
cheerios.backup_filename = calloc(1, name_len + 1);
|
||||||
snprintf(
|
snprintf(
|
||||||
cheerios.backup_filename, name_len + 1,
|
cheerios.backup_filename, name_len + 1,
|
||||||
"%s/.config/bytenuts/outbuf.%d.log",
|
"%s/.config/bytenuts/outbuf.%lld.log",
|
||||||
home, pid
|
home, (long long)pid
|
||||||
);
|
);
|
||||||
cheerios.backup = fopen(cheerios.backup_filename, "w");
|
cheerios.backup = fopen(cheerios.backup_filename, "w");
|
||||||
}
|
}
|
||||||
|
|
@ -161,9 +160,22 @@ cheerios_stop()
|
||||||
int
|
int
|
||||||
cheerios_input(const char *buf, size_t len)
|
cheerios_input(const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
size_t len_left = len;
|
||||||
|
size_t p = 0;
|
||||||
|
|
||||||
pthread_mutex_lock(&cheerios.lock);
|
pthread_mutex_lock(&cheerios.lock);
|
||||||
write(cheerios.ser_fd, buf, len);
|
while (len_left > 0) {
|
||||||
|
ssize_t tmp = serial_write(cheerios.ser_fd, &buf[p], len_left);
|
||||||
|
|
||||||
|
if (tmp < 0) {
|
||||||
pthread_mutex_unlock(&cheerios.lock);
|
pthread_mutex_unlock(&cheerios.lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len_left -= tmp;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&cheerios.lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,6 +307,7 @@ cheerios_getmaxy()
|
||||||
{
|
{
|
||||||
int y, x;
|
int y, x;
|
||||||
getmaxyx(cheerios.output, y, x);
|
getmaxyx(cheerios.output, y, x);
|
||||||
|
(void)x;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,6 +316,7 @@ cheerios_getmaxx()
|
||||||
{
|
{
|
||||||
int y, x;
|
int y, x;
|
||||||
getmaxyx(cheerios.output, y, x);
|
getmaxyx(cheerios.output, y, x);
|
||||||
|
(void)y;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -325,7 +339,6 @@ cheerios_thread(void *arg)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
ssize_t read_ret = 0;
|
ssize_t read_ret = 0;
|
||||||
struct pollfd fds;
|
|
||||||
|
|
||||||
while (cheerios.running) {
|
while (cheerios.running) {
|
||||||
pthread_mutex_lock(&cheerios.lock);
|
pthread_mutex_lock(&cheerios.lock);
|
||||||
|
|
@ -334,17 +347,7 @@ cheerios_thread(void *arg)
|
||||||
pthread_cond_wait(&cheerios.cond, &cheerios.lock);
|
pthread_cond_wait(&cheerios.cond, &cheerios.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
fds.fd = cheerios.ser_fd;
|
read_ret = serial_read(cheerios.ser_fd, buf, sizeof(buf));
|
||||||
fds.events = POLLIN;
|
|
||||||
fds.revents = 0;
|
|
||||||
|
|
||||||
if (poll(&fds, 1, 1) == 0) {
|
|
||||||
pthread_mutex_unlock(&cheerios.lock);
|
|
||||||
nanosleep(&(struct timespec){ 0, 100000 }, NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
read_ret = read(cheerios.ser_fd, buf, sizeof(buf));
|
|
||||||
if (read_ret > 0) {
|
if (read_ret > 0) {
|
||||||
insert_buf(&cheerios.lines, buf, read_ret);
|
insert_buf(&cheerios.lines, buf, read_ret);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
src/ingest.c
11
src/ingest.c
|
|
@ -59,14 +59,14 @@ ingest_start(bytenuts_t *bytenuts)
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
name_len = snprintf(
|
name_len = snprintf(
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
"%s/.config/bytenuts/inbuf.%d.log",
|
"%s/.config/bytenuts/inbuf.%lld.log",
|
||||||
HOME, pid
|
HOME, (long long)pid
|
||||||
);
|
);
|
||||||
ingest.history_filename = calloc(1, name_len + 1);
|
ingest.history_filename = calloc(1, name_len + 1);
|
||||||
snprintf(
|
snprintf(
|
||||||
ingest.history_filename, name_len + 1,
|
ingest.history_filename, name_len + 1,
|
||||||
"%s/.config/bytenuts/inbuf.%d.log",
|
"%s/.config/bytenuts/inbuf.%lld.log",
|
||||||
HOME, pid
|
HOME, (long long)pid
|
||||||
);
|
);
|
||||||
|
|
||||||
ingest.history_fd = fopen(ingest.history_filename, "w");
|
ingest.history_fd = fopen(ingest.history_filename, "w");
|
||||||
|
|
@ -209,7 +209,6 @@ ingest_set_history(char **history, int history_len)
|
||||||
static void *
|
static void *
|
||||||
ingest_thread(void *arg)
|
ingest_thread(void *arg)
|
||||||
{
|
{
|
||||||
int esc_flag;
|
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
memset(ingest.inbuf, 0, sizeof(ingest.inbuf));
|
memset(ingest.inbuf, 0, sizeof(ingest.inbuf));
|
||||||
|
|
@ -218,8 +217,6 @@ ingest_thread(void *arg)
|
||||||
bytenuts_set_status(STATUS_INGEST, "normal");
|
bytenuts_set_status(STATUS_INGEST, "normal");
|
||||||
|
|
||||||
while (ingest.running) {
|
while (ingest.running) {
|
||||||
esc_flag = 0;
|
|
||||||
|
|
||||||
pthread_mutex_lock(ingest.term_lock);
|
pthread_mutex_lock(ingest.term_lock);
|
||||||
ch = wgetch(ingest.input);
|
ch = wgetch(ingest.input);
|
||||||
pthread_mutex_unlock(ingest.term_lock);
|
pthread_mutex_unlock(ingest.term_lock);
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,20 @@
|
||||||
|
|
||||||
#include "bytenuts.h"
|
#include "bytenuts.h"
|
||||||
|
|
||||||
|
#ifndef __MINGW32__
|
||||||
static void sigint_handler(int s);
|
static void sigint_handler(int s);
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
#ifndef __MINGW32__
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
act.sa_handler = sigint_handler;
|
act.sa_handler = sigint_handler;
|
||||||
sigemptyset(&act.sa_mask);
|
sigemptyset(&act.sa_mask);
|
||||||
act.sa_flags = 0;
|
act.sa_flags = 0;
|
||||||
sigaction(SIGINT, &act, NULL);
|
sigaction(SIGINT, &act, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (bytenuts_run(argc, argv)) {
|
if (bytenuts_run(argc, argv)) {
|
||||||
bytenuts_stop();
|
bytenuts_stop();
|
||||||
|
|
@ -23,9 +27,11 @@ main(int argc, char **argv)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __MINGW32__
|
||||||
static void
|
static void
|
||||||
sigint_handler(int s)
|
sigint_handler(int s)
|
||||||
{
|
{
|
||||||
bytenuts_kill();
|
bytenuts_kill();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
||||||
132
src/serial.c
132
src/serial.c
|
|
@ -3,15 +3,18 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
|
||||||
serial_t
|
serial_t
|
||||||
serial_open(const char *comport, long bps)
|
serial_open(const char *comport, long bps)
|
||||||
{
|
{
|
||||||
DCB dcb = { 0 };
|
/* referred to: https://github.com/waynix/SPinGW/tree/master */
|
||||||
HANDLE serial = CreateFile(
|
HANDLE serial = CreateFile(
|
||||||
comport,
|
comport,
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
|
@ -21,15 +24,112 @@ serial_open(const char *comport, long bps)
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
DCB serial_params = { 0 };
|
||||||
|
COMMTIMEOUTS timeouts = { 0 };
|
||||||
|
|
||||||
if (serial == INVALID_HANDLE_VALUE) {
|
if (serial == INVALID_HANDLE_VALUE) {
|
||||||
|
return SERIAL_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_params.DCBlength = sizeof(serial_params);
|
||||||
|
if (!GetCommState(serial, &serial_params)) {
|
||||||
|
return SERIAL_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8n1 */
|
||||||
|
serial_params.BaudRate = bps;
|
||||||
|
serial_params.ByteSize = 8;
|
||||||
|
serial_params.StopBits = 1;
|
||||||
|
serial_params.Parity = NOPARITY;
|
||||||
|
|
||||||
|
if (!SetCommState(serial, &serial_params)) {
|
||||||
|
return SERIAL_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeouts.ReadIntervalTimeout = 0;
|
||||||
|
timeouts.ReadTotalTimeoutConstant = 0;
|
||||||
|
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||||
|
timeouts.WriteTotalTimeoutConstant = 0;
|
||||||
|
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||||
|
|
||||||
|
if (!SetCommTimeouts(serial, &timeouts)) {
|
||||||
|
return SERIAL_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
serial_read(serial_t serial, void *buf, size_t len)
|
||||||
|
{
|
||||||
|
DWORD ret = 0;
|
||||||
|
|
||||||
|
if (!ReadFile(serial, buf, len, &ret, NULL)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO
|
return ret;
|
||||||
* reference: https://github.com/waynix/SPinGW/tree/master */
|
|
||||||
return serial;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
serial_read_to(serial_t serial, void *buf, size_t len, unsigned int to_ms)
|
||||||
|
{
|
||||||
|
DWORD ret = -1;
|
||||||
|
size_t p = 0;
|
||||||
|
size_t len_left = len;
|
||||||
|
|
||||||
|
while (to_ms > 0) {
|
||||||
|
DWORD tmp = 0;
|
||||||
|
|
||||||
|
if (!ReadFile(serial, &((uint8_t *)buf)[p], len_left, &tmp, NULL)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp > 0) {
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = tmp;
|
||||||
|
} else {
|
||||||
|
ret += tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
len_left -= tmp;
|
||||||
|
p += tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len_left == 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sleep 1ms */
|
||||||
|
nanosleep(&(struct timespec){ 0, 1000000 }, NULL);
|
||||||
|
to_ms--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
serial_write(serial_t serial, const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
DWORD ret = 0;
|
||||||
|
|
||||||
|
if (!WriteFile(serial, buf, len, &ret, NULL)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
serial_close(serial_t serial)
|
||||||
|
{
|
||||||
|
return (CloseHandle(serial) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# include <termios.h>
|
# include <termios.h>
|
||||||
# include <poll.h>
|
# include <poll.h>
|
||||||
|
|
@ -46,7 +146,7 @@ serial_open(const char *path, long bps)
|
||||||
|
|
||||||
fd = open(path, O_RDWR | O_NOCTTY | O_NDELAY);
|
fd = open(path, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
return -1;
|
return SERIAL_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcgetattr(fd, &otio);
|
tcgetattr(fd, &otio);
|
||||||
|
|
@ -88,25 +188,37 @@ serial_open(const char *path, long bps)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
ssize_t
|
||||||
serial_read(serial_t serial, void *buf, size_t len)
|
serial_read(serial_t serial, void *buf, size_t len)
|
||||||
|
{
|
||||||
|
return serial_read_to(serial, buf, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
serial_read_to(serial_t serial, void *buf, size_t len, unsigned int to_ms)
|
||||||
{
|
{
|
||||||
struct pollfd fds;
|
struct pollfd fds;
|
||||||
fds.fd = serial;
|
fds.fd = serial;
|
||||||
fds.events = POLLIN;
|
fds.events = POLLIN;
|
||||||
fds.revents = 0;
|
fds.revents = 0;
|
||||||
|
|
||||||
if (poll(&fds, 1, 1) == 0) {
|
if (poll(&fds, 1, to_ms) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)read(serial, buf, len);
|
return read(serial, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
serial_write(serial_t serial, const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
return write(serial, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
serial_write(serial_t serial, void *buf, size_t len)
|
serial_close(serial_t serial)
|
||||||
{
|
{
|
||||||
return (int)write(serial, buf, len);
|
return close(serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static speed_t
|
static speed_t
|
||||||
|
|
|
||||||
20
src/serial.h
20
src/serial.h
|
|
@ -8,8 +8,24 @@ typedef HANDLE serial_t;
|
||||||
typedef int serial_t;
|
typedef int serial_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SERIAL_INVALID (serial_t)(-1)
|
||||||
|
|
||||||
|
/* Open a serial port with the given speed and return a handle that can be used
|
||||||
|
* in the other serial APIs*/
|
||||||
serial_t serial_open(const char *path, long bps);
|
serial_t serial_open(const char *path, long bps);
|
||||||
int serial_read(serial_t serial, void *buf, size_t len);
|
|
||||||
int serial_write(serial_t serial, void *buf, size_t len);
|
/* Read up to len bytes (non-blocking), length read is returned */
|
||||||
|
ssize_t serial_read(serial_t serial, void *buf, size_t len);
|
||||||
|
|
||||||
|
/* Read up to len bytes, or until to_ms milliseconds have elapsed, length read
|
||||||
|
* is returned */
|
||||||
|
ssize_t serial_read_to(serial_t serial, void *buf, size_t len, unsigned int to_ms);
|
||||||
|
|
||||||
|
/* Write len bytes onto the serial port, actual number of bytes written is
|
||||||
|
* returned */
|
||||||
|
ssize_t serial_write(serial_t serial, const void *buf, size_t len);
|
||||||
|
|
||||||
|
/* Close the serial file */
|
||||||
|
int serial_close(serial_t serial);
|
||||||
|
|
||||||
#endif /* _SERIAL_H_ */
|
#endif /* _SERIAL_H_ */
|
||||||
|
|
|
||||||
21
src/xmodem.c
21
src/xmodem.c
|
|
@ -1,4 +1,3 @@
|
||||||
#include <poll.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -8,7 +7,7 @@
|
||||||
|
|
||||||
#include "xmodem.h"
|
#include "xmodem.h"
|
||||||
|
|
||||||
int _xmodem_wait(int fd, uint8_t *ret, int timeout_ms);
|
int _xmodem_wait(serial_t fd, uint8_t *ret, int timeout_ms);
|
||||||
|
|
||||||
uint16_t _xmodem_crc(const uint8_t *buf, size_t len);
|
uint16_t _xmodem_crc(const uint8_t *buf, size_t len);
|
||||||
uint8_t _xmodem_csum(const uint8_t *buf, size_t len);
|
uint8_t _xmodem_csum(const uint8_t *buf, size_t len);
|
||||||
|
|
@ -16,7 +15,7 @@ void _xmodem_status_print(size_t sent, size_t total);
|
||||||
|
|
||||||
int
|
int
|
||||||
xmodem_send(
|
xmodem_send(
|
||||||
int dest_fd,
|
serial_t dest_fd,
|
||||||
int in_fd,
|
int in_fd,
|
||||||
size_t sz,
|
size_t sz,
|
||||||
int block_sz,
|
int block_sz,
|
||||||
|
|
@ -106,7 +105,7 @@ xmodem_send(
|
||||||
goto end_of_transmission;
|
goto end_of_transmission;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write(dest_fd, buf, buf_sz) != buf_sz){
|
if (serial_write(dest_fd, buf, buf_sz) != buf_sz){
|
||||||
return XMODEM_ERR_WRITE;
|
return XMODEM_ERR_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +137,7 @@ end_of_transmission:
|
||||||
return XMODEM_ERR_TIMEOUT;
|
return XMODEM_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
write(dest_fd, &(uint8_t){XMODEM_EOT}, 1);
|
serial_write(dest_fd, &(uint8_t){XMODEM_EOT}, 1);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!_xmodem_wait(dest_fd, &ack_char, XMODEM_TIMEOUT) &&
|
!_xmodem_wait(dest_fd, &ack_char, XMODEM_TIMEOUT) &&
|
||||||
|
|
@ -154,20 +153,12 @@ end_of_transmission:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_xmodem_wait(int fd, uint8_t *ret, int timeout_ms)
|
_xmodem_wait(serial_t fd, uint8_t *ret, int timeout_ms)
|
||||||
{
|
{
|
||||||
struct pollfd pfd;
|
if (serial_read_to(fd, ret, 1, timeout_ms) != 1) {
|
||||||
|
|
||||||
pfd.fd = fd;
|
|
||||||
pfd.events = POLLIN;
|
|
||||||
pfd.revents = 0;
|
|
||||||
|
|
||||||
if (poll(&pfd, 1, timeout_ms) <= 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
read(fd, ret, 1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
* length of `block_sz`.
|
* length of `block_sz`.
|
||||||
*/
|
*/
|
||||||
int xmodem_send(
|
int xmodem_send(
|
||||||
int dest_fd,
|
serial_t dest_fd,
|
||||||
int in_fd,
|
int in_fd,
|
||||||
size_t sz,
|
size_t sz,
|
||||||
int block_sz,
|
int block_sz,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue