serial_forwarder: serial parsing
This removes the dependency on libserialport
This commit is contained in:
parent
8623d7cd86
commit
7a0518c35b
11
Makefile
11
Makefile
@ -5,10 +5,8 @@ DEBUG = -g -gdwarf-4
|
|||||||
CFLAGS += -Wall -Werror -Wfatal-errors
|
CFLAGS += -Wall -Werror -Wfatal-errors
|
||||||
CFLAGS += -std=c2x
|
CFLAGS += -std=c2x
|
||||||
CFLAGS += -I$(SDL)/include -D_REENTRANT
|
CFLAGS += -I$(SDL)/include -D_REENTRANT
|
||||||
CFLAGS += -I/usr/local/include
|
|
||||||
CFLAGS += $(shell pkg-config --cflags freetype2)
|
CFLAGS += $(shell pkg-config --cflags freetype2)
|
||||||
LDFLAGS += -L$(SDL)/build -lSDL3 -Wl,-rpath=$(SDL)/build
|
LDFLAGS += -L$(SDL)/build -lSDL3 -Wl,-rpath=$(SDL)/build
|
||||||
LDFLAGS += -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lserialport
|
|
||||||
LDFLAGS += $(shell pkg-config --libs freetype2)
|
LDFLAGS += $(shell pkg-config --libs freetype2)
|
||||||
|
|
||||||
DEPFLAGS = -MMD -MP
|
DEPFLAGS = -MMD -MP
|
||||||
@ -18,12 +16,17 @@ OPT = -O3 -march=native
|
|||||||
OBJS = \
|
OBJS = \
|
||||||
timer.o
|
timer.o
|
||||||
|
|
||||||
all: main
|
SERIAL_FORWARDER_OBJS = \
|
||||||
|
serial_forwarder.o \
|
||||||
|
serial.o \
|
||||||
|
parse_serial.o
|
||||||
|
|
||||||
|
all: serial_forwarder
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CARCH) $(CFLAGS) $(OPT) $(DEBUG) $(DEPFLAGS) -MF ${<}.d -c $< -o $@
|
$(CC) $(CARCH) $(CFLAGS) $(OPT) $(DEBUG) $(DEPFLAGS) -MF ${<}.d -c $< -o $@
|
||||||
|
|
||||||
main: $(OBJS)
|
serial_forwarder: $(SERIAL_FORWARDER_OBJS)
|
||||||
$(CC) $(LDFLAGS) $^ -o $@
|
$(CC) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
-include $(shell find -type f -name '*.d')
|
-include $(shell find -type f -name '*.d')
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "bufsize.h"
|
#include "parse_serial.h"
|
||||||
|
|
||||||
uint8_t const * parse_int(uint8_t const * buf, int * length, int * number, int * digits)
|
uint8_t const * parse_int(uint8_t const * buf, int * length, int * number, int * digits)
|
||||||
{
|
{
|
||||||
@ -27,8 +28,8 @@ uint8_t const * parse_int(uint8_t const * buf, int * length, int * number, int *
|
|||||||
case '8': [[fallthrough]];
|
case '8': [[fallthrough]];
|
||||||
case '9':
|
case '9':
|
||||||
*digits += 1;
|
*digits += 1;
|
||||||
number *= 10;
|
*number *= 10;
|
||||||
number += c - '0';
|
*number += c - '0';
|
||||||
break;
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
break;
|
break;
|
||||||
@ -49,7 +50,7 @@ int parse_time(uint8_t const * const buf, int length, struct stopwatch_time * ti
|
|||||||
uint8_t const * bufi = buf;
|
uint8_t const * bufi = buf;
|
||||||
bufi = parse_int(bufi, &length, &time->integer_value, &time->integer_digits);
|
bufi = parse_int(bufi, &length, &time->integer_value, &time->integer_digits);
|
||||||
|
|
||||||
if (integer_digits == 0) {
|
if (time->integer_digits == 0) {
|
||||||
fprintf(stderr, "invalid integer at `%c`\n", *bufi);
|
fprintf(stderr, "invalid integer at `%c`\n", *bufi);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -62,7 +63,7 @@ int parse_time(uint8_t const * const buf, int length, struct stopwatch_time * ti
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
bufi = parse_int(bufi, &length, &time->fraction_value, &time->fraction_digits);
|
bufi = parse_int(bufi, &length, &time->fraction_value, &time->fraction_digits);
|
||||||
if (integer_digits == 0) {
|
if (time->fraction_digits == 0) {
|
||||||
fprintf(stderr, "invalid fraction at `%c`\n", *bufi);
|
fprintf(stderr, "invalid fraction at `%c`\n", *bufi);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -74,55 +75,65 @@ int min(int a, int b) {
|
|||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct parser_state {
|
bool is_timer_resume(uint8_t const * const buf, int length)
|
||||||
uint8_t buf[BUFSIZE];
|
|
||||||
int offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool is_()
|
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_line(uint8_t * buf, int length,
|
bool handle_line(uint8_t const * const buf, int length,
|
||||||
struct timer_state * timer_state)
|
struct timer_state * timer_state)
|
||||||
{
|
{
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
timer_state->status = COUNTER_RUNNING;
|
timer_state->status = TIMER_RUNNING;
|
||||||
int ret = clock_gettime(CLOCK_MONOTONIC, &timer_state->counter.start);
|
int ret = clock_gettime(CLOCK_MONOTONIC, &timer_state->counter.start);
|
||||||
timer_state->counter.offset.tv_sec = 0;
|
timer_state->counter.offset.tv_sec = 0;
|
||||||
timer_state->counter.offset.tv_nsec = 0;
|
timer_state->counter.offset.tv_nsec = 0;
|
||||||
assert(ret != -1);
|
assert(ret != -1);
|
||||||
} else if (is_) {
|
return true;
|
||||||
|
} else if (is_timer_resume(buf, length)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
int ret = parse_time(buf, length, &timer_state->time);
|
||||||
|
if (ret == 0) {
|
||||||
|
timer_state->status = TIMER_STOPPED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_parse(uint8_t * read_buf, int length,
|
bool handle_parse(uint8_t * read_buf, int length,
|
||||||
struct parser_state * parser_state,
|
struct parser_state * parser_state,
|
||||||
struct timer_state * timer_state)
|
struct timer_state * timer_state)
|
||||||
{
|
{
|
||||||
|
bool have_state_change = false;
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
int copy_length = min(length, BUFSIZE - state->offset);
|
int copy_length = min(length, BUFSIZE - parser_state->offset);
|
||||||
length -= copy_length;
|
length -= copy_length;
|
||||||
memcpy(&state->buf[state->offset], read_buf, copy_length);
|
memcpy(&parser_state->buf[parser_state->offset], read_buf, copy_length);
|
||||||
state->offset += copy_length;
|
parser_state->offset += copy_length;
|
||||||
|
|
||||||
while (state->offset > 0) {
|
while (parser_state->offset > 0) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < state->offset) {
|
while (i < parser_state->offset) {
|
||||||
if (state->buf[i] == '\r') {
|
if (parser_state->buf[i] == '\r') {
|
||||||
fprintf(stderr, "r at %d %d\n", i, state->offset);
|
fprintf(stderr, "r at %d %d\n", i, parser_state->offset);
|
||||||
handle_line(state->buf, i);
|
have_state_change |= handle_line(parser_state->buf, i,
|
||||||
state->offset -= i + 1;
|
timer_state);
|
||||||
assert(state->offset >= 0);
|
parser_state->offset -= i + 1;
|
||||||
memmove(&state->buf[0], &state->buf[i + 1], state->offset);
|
assert(parser_state->offset >= 0);
|
||||||
|
memmove(&parser_state->buf[0], &parser_state->buf[i + 1], parser_state->offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
if (i == state->offset)
|
if (i == parser_state->offset)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return have_state_change;
|
||||||
}
|
}
|
||||||
|
15
parse_serial.h
Normal file
15
parse_serial.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "bufsize.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
struct parser_state {
|
||||||
|
uint8_t buf[BUFSIZE];
|
||||||
|
int offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool handle_parse(uint8_t * read_buf, int length,
|
||||||
|
struct parser_state * parser_state,
|
||||||
|
struct timer_state * timer_state);
|
50
serial.c
Normal file
50
serial.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#define _DEFAULT_SOURCE 1
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
|
int set_terminal_attributes(int fd)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct termios tty;
|
||||||
|
ret = tcgetattr(fd, &tty);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("tcgetattr");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty.c_cflag &= ~PARENB; // no parity
|
||||||
|
tty.c_cflag &= ~CSTOPB; // one stop bit
|
||||||
|
tty.c_cflag &= ~CSIZE; // clear size bits
|
||||||
|
tty.c_cflag |= CS8; // 8 bit
|
||||||
|
tty.c_cflag &= ~CRTSCTS; // disable RTS/CTS hardware flow control
|
||||||
|
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
|
||||||
|
|
||||||
|
tty.c_lflag &= ~ICANON;
|
||||||
|
tty.c_lflag &= ~ECHO; // disable echo
|
||||||
|
tty.c_lflag &= ~ECHOE; // disable erasure
|
||||||
|
tty.c_lflag &= ~ECHONL; // disable new-line echo
|
||||||
|
tty.c_lflag &= ~ISIG; // disable interpretation of INTR, QUIT and SUSP
|
||||||
|
|
||||||
|
tty.c_iflag &= ~(IXON|IXOFF|IXANY); // turn off xon/xoff ctrl
|
||||||
|
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // disable any special handling of received bytes
|
||||||
|
|
||||||
|
tty.c_oflag &= ~OPOST; // prevent special interpretation of output bytes (e.g. newline chars)
|
||||||
|
tty.c_oflag &= ~ONLCR; // prevent conversion of newline to carriage return/line feed
|
||||||
|
|
||||||
|
tty.c_cc[VMIN] = 1;
|
||||||
|
tty.c_cc[VTIME] = 0;
|
||||||
|
|
||||||
|
cfsetospeed(&tty, B1200);
|
||||||
|
cfsetispeed(&tty, B1200);
|
||||||
|
|
||||||
|
ret = tcsetattr(fd, TCSANOW, &tty);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("tcsetattr");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
serial_forwarder
Executable file
BIN
serial_forwarder
Executable file
Binary file not shown.
@ -1,79 +1,23 @@
|
|||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <errno.h>
|
#include <sys/socket.h>
|
||||||
#include <stdbool.h>
|
#include <sys/timerfd.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <libserialport.h>
|
|
||||||
|
|
||||||
#include "bufsize.h"
|
#include "bufsize.h"
|
||||||
|
#include "serial.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "parse_serial.h"
|
||||||
|
|
||||||
#define PORT 4321
|
#define PORT 4321
|
||||||
#define SERIALPORT "/dev/ttyS0"
|
//#define SERIALPORT "/dev/ttyS0"
|
||||||
|
#define SERIALPORT "/dev/ttyUSB0"
|
||||||
int sp_error(const char * s, enum sp_return result)
|
|
||||||
{
|
|
||||||
char * error_message;
|
|
||||||
switch (result) {
|
|
||||||
case SP_ERR_ARG:
|
|
||||||
printf("%s: error: Invalid argument.\n", s);
|
|
||||||
case SP_ERR_FAIL:
|
|
||||||
error_message = sp_last_error_message();
|
|
||||||
printf("%s: error: Failed: %s\n", error_message, s);
|
|
||||||
sp_free_error_message(error_message);
|
|
||||||
case SP_ERR_SUPP:
|
|
||||||
printf("%s: error: Not supported.\n", s);
|
|
||||||
case SP_ERR_MEM:
|
|
||||||
printf("%s: error: Couldn't allocate memory.\n", s);
|
|
||||||
case SP_OK: [[fallthrough]];
|
|
||||||
default:
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_serial(struct sp_port * port)
|
|
||||||
{
|
|
||||||
enum sp_return sp_ret;
|
|
||||||
|
|
||||||
sp_ret = sp_get_port_by_name(SERIALPORT, &port);
|
|
||||||
if (sp_ret != SP_OK) {
|
|
||||||
sp_error("sp_get_port_by_name", sp_ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sp_ret = sp_open(port, SP_MODE_READ_WRITE);
|
|
||||||
if (sp_ret != SP_OK) {
|
|
||||||
sp_error("sp_open", sp_ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sp_ret = sp_set_baudrate(port, 1200);
|
|
||||||
if (sp_ret != SP_OK) {
|
|
||||||
sp_error("sp_set_baudrate", sp_ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sp_ret = sp_set_bits(port, 8);
|
|
||||||
if (sp_ret != SP_OK) {
|
|
||||||
sp_error("sp_set_bits", sp_ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sp_ret = sp_set_parity(port, SP_PARITY_NONE);
|
|
||||||
if (sp_ret != SP_OK) {
|
|
||||||
sp_error("sp_set_parity", sp_ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sp_ret = sp_set_stopbits(port, 1);
|
|
||||||
if (sp_ret != SP_OK) {
|
|
||||||
sp_error("sp_set_stopbits", sp_ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sp_ret = sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE);
|
|
||||||
if (sp_ret != SP_OK) {
|
|
||||||
sp_error("sp_set_flowcontrol", sp_ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int handle_sock(int sock)
|
int handle_sock(int sock)
|
||||||
{
|
{
|
||||||
@ -86,10 +30,10 @@ int handle_sock(int sock)
|
|||||||
ssize_t recv_len = recvfrom(sock, buf, BUFSIZE, 0, (struct sockaddr *)&src_addr, &addrlen);
|
ssize_t recv_len = recvfrom(sock, buf, BUFSIZE, 0, (struct sockaddr *)&src_addr, &addrlen);
|
||||||
if (recv_len == -1) {
|
if (recv_len == -1) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
perror("eagain");
|
perror("sock eagain");
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
perror("recvfrom");
|
perror("recvfrom sock");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,11 +45,85 @@ int handle_sock(int sock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rearm_timer(int timerfd)
|
||||||
|
{
|
||||||
|
struct itimerspec value;
|
||||||
|
value.it_value.tv_sec = 1;
|
||||||
|
value.it_value.tv_nsec = 0;
|
||||||
|
value.it_interval.tv_sec = 0;
|
||||||
|
value.it_interval.tv_nsec = 0;
|
||||||
|
|
||||||
|
int ret = timerfd_settime(timerfd, 0, &value, NULL);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("timerfd_settime");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle_timerfd(int timerfd)
|
||||||
|
{
|
||||||
|
uint64_t expired_count = 0;
|
||||||
|
while (true) {
|
||||||
|
ssize_t len = read(timerfd, &expired_count, (sizeof (expired_count)));
|
||||||
|
if (len == -1) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
fprintf(stderr, "timerfd eagain\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
perror("read timerfd");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(len == (sizeof (expired_count)));
|
||||||
|
printf("len %ld\n", len);
|
||||||
|
}
|
||||||
|
|
||||||
|
rearm_timer(timerfd);
|
||||||
|
printf("do timer stuff\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct receiver_state {
|
struct receiver_state {
|
||||||
uint64_t seq;
|
uint64_t seq;
|
||||||
uint64_t ack_seq;
|
uint64_t ack_seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int handle_serialfd(int timerfd,
|
||||||
|
struct parser_state * parser_state,
|
||||||
|
struct timer_state * timer_state)
|
||||||
|
{
|
||||||
|
uint8_t buf[BUFSIZE];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ssize_t len = read(timerfd, buf, (sizeof (buf)));
|
||||||
|
if (len == -1) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
fprintf(stderr, "serialfd eagain\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
perror("read serialfd");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
fprintf(stderr, "%x ", buf[i]);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
*/
|
||||||
|
bool have_state_change = handle_parse(buf, len,
|
||||||
|
parser_state,
|
||||||
|
timer_state);
|
||||||
|
printf("have_state_change: %d\n", have_state_change);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -127,7 +145,7 @@ int main(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_EVENTS 2
|
#define MAX_EVENTS 5
|
||||||
struct epoll_event events[MAX_EVENTS];
|
struct epoll_event events[MAX_EVENTS];
|
||||||
|
|
||||||
int epollfd = epoll_create1(0);
|
int epollfd = epoll_create1(0);
|
||||||
@ -136,19 +154,67 @@ int main(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct epoll_event ev;
|
{
|
||||||
ev.events = EPOLLIN | EPOLLET;
|
struct epoll_event ev;
|
||||||
ev.data.fd = sock;
|
ev.events = EPOLLIN | EPOLLET;
|
||||||
ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &ev);
|
ev.data.fd = sock;
|
||||||
if (ret == -1) {
|
ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &ev);
|
||||||
perror("epoll_ctl: sock");
|
if (ret == -1) {
|
||||||
|
perror("epoll_ctl: sock");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
||||||
|
if (timerfd == -1) {
|
||||||
|
perror("timerfd_create");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = rearm_timer(timerfd);
|
||||||
|
if (ret == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
struct epoll_event ev;
|
||||||
|
ev.events = EPOLLIN | EPOLLET;
|
||||||
|
ev.data.fd = timerfd;
|
||||||
|
ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("epoll_ctl: timerfd");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int serialfd = open(SERIALPORT, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||||
|
if (serialfd == -1) {
|
||||||
|
perror("open: serialport");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = set_terminal_attributes(serialfd);
|
||||||
|
if (ret == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
struct epoll_event ev;
|
||||||
|
ev.events = EPOLLIN | EPOLLET;
|
||||||
|
ev.data.fd = serialfd;
|
||||||
|
ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, serialfd, &ev);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("epoll_ctl: timerfd");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct parser_state parser_state = {0};
|
||||||
|
struct timer_state timer_state = {0};
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("Wait for datagram\n");
|
printf("Wait for datagram\n");
|
||||||
|
|
||||||
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, 1000);
|
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
|
||||||
if (nfds == -1) {
|
if (nfds == -1) {
|
||||||
perror("epoll_wait");
|
perror("epoll_wait");
|
||||||
return -1;
|
return -1;
|
||||||
@ -159,6 +225,19 @@ int main(void)
|
|||||||
ret = handle_sock(sock);
|
ret = handle_sock(sock);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
} else if (events[n].data.fd == timerfd) {
|
||||||
|
ret = handle_timerfd(timerfd);
|
||||||
|
if (ret == -1)
|
||||||
|
return -1;
|
||||||
|
} else if (events[n].data.fd == serialfd) {
|
||||||
|
fprintf(stderr, "handle_serialfd\n");
|
||||||
|
ret = handle_serialfd(serialfd,
|
||||||
|
&parser_state,
|
||||||
|
&timer_state);
|
||||||
|
if (ret == -1)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
timer.h
16
timer.h
@ -1,13 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
enum counter_status {
|
enum timer_status {
|
||||||
COUNTER_STOPPED,
|
TIMER_STOPPED,
|
||||||
COUNTER_RUNNING,
|
TIMER_RUNNING,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stopwatch_time {
|
struct stopwatch_time {
|
||||||
int32_t whole;
|
int integer_value;
|
||||||
int32_t fraction;
|
int integer_digits;
|
||||||
|
int fraction_value;
|
||||||
|
int fraction_digits;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct running_counter {
|
struct running_counter {
|
||||||
@ -16,7 +20,7 @@ struct running_counter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct timer_state {
|
struct timer_state {
|
||||||
enum counter_status status;
|
enum timer_status status;
|
||||||
struct running_counter counter;
|
struct running_counter counter;
|
||||||
struct stopwatch_time time;
|
struct stopwatch_time time;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user