$(LINK)
hostside: hostside.o serialio.o client.o obc.o commands.o \
- nmra.o encode.o retransmit.o -loop
+ nmra.o encode.o retransmit.o output.o -loop
$(LINK)
layoutinfo.h: ../layout/ours.layout-data.c Makefile
Protocol over new hostside stdin:
+ Example (always the same msg):
+ P> nmra [*<slot>] [<nmra-command [<nmra-args>...]] nmra speed28 3 13 1
+ P> nmra [*<slot>] [=<nmra-bytes>] nmra =0348
+ P> nmra [*<slot>] [:<nmra-bytes-with-csum>] nmra :03484b
+ P> nmra [*<slot>] [_<pic-literal-bytes>] nmra _7f7f00644197
+ in each case *<slot> indicates that the message should be put in
+ the retransmission cycle, and cancels any previous message with the
+ same *<slot>. <slot> may be empty.
+ P> nmra *<slot>
+ cancels the relevant retransmission.
- P> nmra-x <nmra-command> [<nmra-args>...]
- P> nmra-1 <nmra-command> [<nmra-args>...]
- P> xmit-x <nmra-data-hex>...
- P> xmit-1 <nmra-data-hex>...
- *-1 means transmit it once
- *-x means put it in the transmission cycle; to cancel,
- ask for nmra-x idle
+ Example (always the same msg):
+ P> pic =<pic-bytes> pic =a003
+ P> pic <pic-command> [<pic-args...] pic point 3
+ the latter for commands with no `...' in README.protocol only
+
+ Keen readers will observe that
+ pic =<pic-bytes> and
+ nmra _<pic-bytes>
+ do exactly the same.
- P> pic <pic-command> [<pic-args>...]
- P> raw <pic-command-data-hex>...
- eg pic point 3 == raw a003
- for commands with no `...' in README.protocol only
P> polarity <bit-string-in-hex>....
where, eg, with 14 segments,
[ 1] [111 1111] reversible
0x02 0x3c hex values
023c hex data string
+ Up< pic-out <hex-bytes...>
+ Up< pic-in <hex-bytes...>
+
U< count <type> <number-in-decimal>
eg count polarity 14
U< pic detect 1|0 <S>
#include <stdlib.h>
#include "hostside.h"
+#include "../layout/dlist.h"
+
+struct ClientList clients;
void vbadcmd(ParseState *ps, const char *fmt, va_list al) {
oprintf(&ps->cl->ch,"error ");
return OOP_CONTINUE;
}
-static void new_client(int fd, OutBufferError error, char *desc) {
+static void new_client(int fd, OutBufferError error,
+ char *desc, const char *default_selectors) {
Client *cl;
int r;
cl= mmalloc(sizeof(*cl));
+ cl->selectors= mstrdup(default_selectors);
cl->ch.desc= desc;
cl->ch.fd= fd;
cl->ch.error= error;
client_ifok, cl,
client_iferr, cl);
if (r) diee("oop_rd_read");
+
+ LIST_LINK_TAIL(clients, cl);
}
static void stdin_error(OutBufferChain *ch, const char *e1, const char *e2) {
}
void stdin_client(void) {
- new_client(0, stdin_error, (char*)"stdin");
+ new_client(0, stdin_error, (char*)"stdin", "p");
}
}
const CmdInfo toplevel_cmds[]= {
- { "nmra", cmd_nmra, },
- /* eg nmra [*[slot]] speed28 3 13 1 */
- /* eg nmra [*[slot]] =0348 */
- /* eg nmra [*[slot]] :03484b */
- /* eg nmra [*[slot]] _7f7f00644197 */
- /* eg nmra [*[slot]] */
#if 0
- { "pic-raw" , cmd_pic_raw, 1, },
- { "pic", cmd_pic }, /* eg pic point 3 */
+ { "pic", cmd_pic }, /* eg pic point 3 */
#endif
- { "noop", cmd_noop },
+ { "nmra", cmd_nmra, },
+ { "noop", cmd_noop },
{ 0 }
};
void diem(void) __attribute__((noreturn));
void serial_open(const char *device);
-void serial_transmit(const Byte *command, int length);
+void serial_transmit_now(const Byte *command, int length);
void *mmalloc(size_t sz);
-
+char *mstrdupl(const char *s, int l);
+char *mstrdup(const char *s);
+
extern int serial_fd, serial_fudge_delay;
/*---------- nmra parsing, nmra.c et al ----------*/
};
void obc_init(OutBufferChain *ch);
+
void ovprintf(OutBufferChain *ch, const char *fmt, va_list al)
__attribute__((format(printf,2,0)));
void oprintf(OutBufferChain *ch, const char *msg, ...)
__attribute__((format(printf,2,3)));
void owrite(OutBufferChain *ch, const char *data, int l);
+/*---------- from output.c ----------*/
+
+typedef char Selector;
+
+void oovprintf(Selector sel, const char *fmt, va_list al)
+ __attribute__((format(printf,2,0)));
+void ooprintf(Selector sel, const char *fmt, ...)
+ __attribute__((format(printf,2,3)));
+void oowrite(Selector sel, const char *data, int l);
+
+void serial_transmit(const Byte *command, int length);
+
+void output_hex(Selector sel, const char *work,
+ const Byte *command, int length);
+
/*---------- from hostside.c ----------*/
extern oop_source *events;
/*---------- from client.c ----------*/
+struct ClientList { Client *head, *tail; };
+extern struct ClientList clients;
+
struct Client {
OutBufferChain ch;
+ Client *back, *next;
+ char *selectors;
oop_read *rd;
};
static void xmit_command(void) {
dump("xmit_command", buf.d, buf.l);
- serial_transmit(buf.d, buf.l);
+ serial_transmit_now(buf.d, buf.l);
}
static void xmit_nmra_raw(void) {
dump("xmit_nmra_raw", buf.d, buf.l);
nmra_encodeforpic(&buf, encoded, &lencoded);
- serial_transmit(encoded, lencoded);
+ serial_transmit_now(encoded, lencoded);
}
static void xmit_nmra_bytes(void) {
--- /dev/null
+/*
+ * transmissions to clients
+ */
+
+#include <string.h>
+#include <stdarg.h>
+
+#include "hostside.h"
+
+#define FOR_OOS(s) do{ \
+ Client *cl, *next_cl; \
+ for (cl= clients.head; \
+ cl; \
+ cl= next_cl) { \
+ OutBufferChain *ch= &cl->ch; \
+ next_cl= cl->next; \
+ if (!strchr(cl->selectors, sel)) continue; \
+ s; \
+ } \
+ }while(0)
+
+void oovprintf(Selector sel, const char *fmt, va_list al) {
+ FOR_OOS( ovprintf(ch, fmt, al) );
+}
+
+void ooprintf(Selector sel, const char *fmt, ...)
+ { va_list al; va_start(al,fmt); oovprintf(sel,fmt,al); va_end(al); }
+
+void oowrite(Selector sel, const char *data, int l) {
+ FOR_OOS( owrite(ch, data, l) );
+}
+
+void output_hex(Selector sel, const char *word,
+ const Byte *command, int length) {
+ ooprintf(sel, "%s", word);
+ while (length) {
+ ooprintf(sel, " %02x", *command++);
+ length--;
+ }
+ ooprintf(sel, "\n");
+}
+
+void serial_transmit(const Byte *command, int length) {
+ output_hex('p', "trace-pic-out", command,length);
+ serial_transmit_now(command, length);
+}
return p;
}
+char *mstrdupl(const char *s, int l) {
+ char *p;
+ p= mmalloc(l+1);
+ memcpy(p,s,l);
+ p[l]= 0;
+ return p;
+}
+
+char *mstrdup(const char *s) { return mstrdupl(s,strlen(s)); }
+
void serial_open(const char *device) {
assert(serial_fd==-1);
if (serial_fd<0) diee(device);
}
-void serial_transmit(const Byte *command, int length) {
+void serial_transmit_now(const Byte *command, int length) {
int r;
assert(length <= COMMAND_ENCODED_MAX);