From 8427263c79754f907e6abefcb8e941a2736abade Mon Sep 17 00:00:00 2001 From: ian Date: Mon, 30 May 2005 01:32:03 +0000 Subject: [PATCH] new "hostside" wip has an event loop --- hostside/.cvsignore | 1 + hostside/Makefile | 10 +-- hostside/README | 6 +- hostside/hostside.c | 213 ++++++++++++++++++++++++++++++++++++++++++++ hostside/hostside.h | 23 ++++- hostside/serialio.c | 11 +-- 6 files changed, 250 insertions(+), 14 deletions(-) create mode 100644 hostside/hostside.c diff --git a/hostside/.cvsignore b/hostside/.cvsignore index 52a5ddf..d8fc992 100644 --- a/hostside/.cvsignore +++ b/hostside/.cvsignore @@ -1,4 +1,5 @@ hostside +hostside-old safety t layoutinfo.h diff --git a/hostside/Makefile b/hostside/Makefile index 545a991..117bd49 100644 --- a/hostside/Makefile +++ b/hostside/Makefile @@ -3,14 +3,14 @@ include ../common.make include ../cprogs.make -TARGETS= hostside #safety -CFLAGS= -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes \ - -Wpointer-arith -Wwrite-strings -g $(OPTIMISE) -OPTIMISE= -O2 +TARGETS= hostside hostside-old all: $(TARGETS) -hostside: serialio.o nmra.o main.o encode.o +hostside-old: serialio.o nmra.o main.o encode.o + $(LINK) + +hostside: hostside.o serialio.o -loop $(LINK) layoutinfo.h: ../layout/ours.layout-data.c Makefile diff --git a/hostside/README b/hostside/README index 8f8e7f8..5fc572c 100644 --- a/hostside/README +++ b/hostside/README @@ -36,14 +36,14 @@ Protocol over new hostside stdin: P> nmra-x [...] P> nmra-1 [...] - P> nmra-raw-x ... - P> nmra-raw-1 ... + P> xmit-x ... + P> xmit-1 ... *-1 means transmit it once *-x means put it in the transmission cycle; to cancel, ask for nmra-x idle - P> raw ... P> pic [...] + P> raw ... eg pic point 3 == raw a003 for commands with no `...' in README.protocol only P> polarity .... diff --git a/hostside/hostside.c b/hostside/hostside.c new file mode 100644 index 0000000..414e769 --- /dev/null +++ b/hostside/hostside.c @@ -0,0 +1,213 @@ +/**/ + +#include +#include +#include +#include +#include + +#include +#include + +#include "../layout/dlist.h" +#include "hostside.h" + +oop_source *events; +FILE *dump_stream= 0; + +typedef struct OutBuffer OutBuffer; +struct OutBuffer { + OutBuffer *back, *next; + char *m; + int l; +}; +typedef struct OutBufferChain OutBufferChain; +struct OutBufferChain { + const char *what; + int fd; + int done_of_head; + struct { OutBuffer *head, *tail; } obs; +}; +static OutBufferChain stdin_ochain= { "stdin", 0 }; +static OutBufferChain serial_ochain= { "serial", -1 }; + +static void *ochain_writeable(oop_source *evts, int fd, + oop_event evt, void *ch_v) { + OutBufferChain *ch= ch_v; + OutBuffer *ob; + int r; + + assert(fd == ch->fd); + assert(evt == OOP_WRITE); + + for (;;) { + ob= ch->obs.head; + if (!ob) { + events->cancel_fd(events, fd, OOP_WRITE); + events->cancel_fd(events, fd, OOP_EXCEPTION); + return OOP_CONTINUE; + } + if (ch->done_of_head == ob->l) { + LIST_UNLINK(ch->obs, ob); + free(ob); + free(ob->m); + ch->done_of_head= 0; + continue; + } + r= write(ch->fd, ob->m + ch->done_of_head, ob->l - ch->done_of_head); + if (r==-1) { + if (errno==EINTR) continue; + if (errno==EWOULDBLOCK) return OOP_CONTINUE; + diee(ch->what); + } + assert(r>=0); + ch->done_of_head += r; + assert(ch->done_of_head <= ob->l); + } +} + +static void *ochain_exception(oop_source *evts, int fd, + oop_event evt, void *ch_v) { + OutBufferChain *ch= ch_v; + die(ch->what); +} + +static void ochain_addlink(OutBufferChain *ch, OutBuffer *ob) { + if (!ch->obs.head) { + events->on_fd(events, ch->fd, OOP_WRITE, ochain_writeable, ch); + events->on_fd(events, ch->fd, OOP_EXCEPTION, ochain_exception, ch); + } + LIST_LINK_TAIL(ch->obs, ob); +} + +static void ovprintf(const char *fmt, va_list al) + __attribute__((format(printf,1,0))); +static void ovprintf(const char *fmt, va_list al) { + OutBuffer *ob; + + ob= malloc(sizeof(*ob)); if (!ob) diem(); + ob->l= vasprintf(&ob->m, fmt, al); if (ob->l <= 0) diem(); + ochain_addlink(&stdin_ochain, ob); +} + +static void oprintf(const char *msg, ...) __attribute__((format(printf,1,2))); +static void oprintf(const char *msg, ...) { + va_list al; + va_start(al,msg); + ovprintf(msg,al); + va_end(al); +} + +static void badcmd(const char *how) { + oprintf("error %s\n",how); +} + +static void cmd_noop(ParseState *ps, const CmdInfo *ci) { + oprintf("noop successful\n"); +} + +static const CmdInfo toplevel_cmds[]= { +#if 0 + { "nmra-x", cmd_nmra_x }, + { "nmra-1", cmd_nmra_1 }, + { "xmit-x", cmd_xmit_x }, + { "xmit-1", cmd_xmit_1 }, + { "pic", cmd_pic }, + { "raw", cmd_raw }, +#endif + { "noop", cmd_noop }, + { 0 } +}; + +static int ps_needword(ParseState *ps) { + const char *space; + if (!ps->remain) { badcmd("too few args"); return 0; } + space= strchr(ps->remain, ' '); + ps->thisword= ps->remain; + if (space) { + ps->lthisword= space - ps->thisword; + ps->remain= space + 1; + } else { + ps->lthisword= strlen(ps->remain); + ps->remain= 0; + } + return 1; +} + +static const CmdInfo *ps_lookup(ParseState *ps, const CmdInfo *inf) { + for (; + inf->name; + inf++) + if (ps->lthisword == strlen(inf->name) && + !memcmp(ps->thisword, inf->name, ps->lthisword)) + return inf; + return 0; +} + +static const CmdInfo *ps_needword_lookup(ParseState *ps, const CmdInfo *infs) { + if (!ps_needword(ps)) return 0; + return ps_lookup(ps,infs); +} + +static void *stdin_iferr(oop_source *evts, oop_read *stdin_read, + oop_rd_event evt, const char *errmsg, int errnoval, + const char *data, size_t recsz, void *u0) + __attribute__((noreturn)); +static void *stdin_iferr(oop_source *evts, oop_read *stdin_read, + oop_rd_event evt, const char *errmsg, int errnoval, + const char *data, size_t recsz, void *u0) { + fprintf(stderr,"stdin %s\n", + oop_rd_errmsg(stdin_read, evt, errnoval, OOP_RD_STYLE_GETLINE)); + exit(4); +} + +static void *stdin_ifok(oop_source *evts, oop_read *stdin_read, + oop_rd_event evt, const char *errmsg, int errnoval, + const char *data, size_t recsz, void *u0) { + ParseState ps; + const CmdInfo *ci; + + if (evt == OOP_RD_EOF) + exit(0); + if (evt != OOP_RD_OK) + stdin_iferr(evts,stdin_read,evt,errmsg,errnoval,data,recsz,u0); + + ps.remain= data; + ci= ps_needword_lookup(&ps, toplevel_cmds); + if (!ci) { badcmd("unknown command"); return OOP_CONTINUE; } + ci->fn(&ps,ci); + return OOP_CONTINUE; +} + +static void *serial_readable(oop_source *evts, int fd, + oop_event evt, void *u0) { + abort(); +} + +const char *device; + +int main(int argc, const char **argv) { + oop_read *stdin_source; + oop_source_sys *sys_events; + int r; + + device= argv[1]; + if (!device) device= "/dev/ttyS0"; + + serial_open(device); + r= oop_fd_nonblock(serial_fd, 1); if (r) diee("nonblock(serial_fd,1)"); + serial_ochain.fd= serial_fd; + + sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new"); + events= oop_sys_source(sys_events); assert(events); + + stdin_source= oop_rd_new_fd(events, 0, 0,0); + if (!stdin_source) diee("oop_rd_new_fd(,0,,)"); + r= oop_rd_read(stdin_source, OOP_RD_STYLE_GETLINE, 1024, + stdin_ifok, 0, stdin_iferr, 0); + if (r) diee("oop_rd_read(stdin_source,...)"); + + events->on_fd(events, serial_fd, OOP_READ, serial_readable, 0); + oop_sys_run(sys_events); + abort(); +} diff --git a/hostside/hostside.h b/hostside/hostside.h index 26e1a0a..f3d63bf 100644 --- a/hostside/hostside.h +++ b/hostside/hostside.h @@ -4,9 +4,30 @@ #define HOSTSIDE_H #include +#include typedef unsigned char Byte; + +typedef struct ParseState ParseState; +struct ParseState { + const char *remain; + const char *thisword; + int lthisword; +}; + +typedef struct CmdInfo CmdInfo; +struct CmdInfo { + const char *name; + void (*fn)(ParseState *ps, const CmdInfo *ci); +}; + +extern oop_source *events; +void die(const char *m) __attribute__((noreturn)); +void diee(const char *m) __attribute__((noreturn)); +void diem(void) __attribute__((noreturn)); + + #define COMMAND_ENCODED_MAX 16 #define NMRA_PACKET_MAX ((COMMAND_ENCODED_MAX*7 - 14) / 8) @@ -25,6 +46,6 @@ void dump(const char *what, const Byte *data, int length); void sysfatal(const char *m); void serial_open(const char *device); -extern int serial_fudge_delay; +extern int serial_fd, serial_fudge_delay; #endif /*HOSTSIDE_H*/ diff --git a/hostside/serialio.c b/hostside/serialio.c index fae0f97..5d964ea 100644 --- a/hostside/serialio.c +++ b/hostside/serialio.c @@ -12,16 +12,17 @@ #include "hostside.h" int serial_fudge_delay= 0; +int serial_fd= -1; -static int serial_fd= -1; - -void sysfatal(const char *m) { perror(m); exit(12); } +void die(const char *m) { fprintf(stderr,"%s\n",m); exit(8); } +void diee(const char *m) { perror(m); exit(12); } +void diem(void) { perror("malloc failed"); exit(16); } void serial_open(const char *device) { assert(serial_fd==-1); serial_fd= open(device,O_RDWR); - if (serial_fd<0) sysfatal(device); + if (serial_fd<0) diee(device); } void dump(const char *what, const Byte *data, int length) { @@ -46,7 +47,7 @@ void xmit_command(const Byte *command, int length) { serial_fudge_delay ? 1 : length); if (r==-1) { if (errno == EINTR) continue; - sysfatal("command_transmit"); + diee("command_transmit"); } assert(r<=length); command += r; -- 2.30.2