chiark / gitweb /
Merge and end branch-hostside-wip-2008-01-25 PROPERLY; cvs up -j branch-hostside...
[trains.git] / hostside / main.c
1 /*
2  * simple test harness for now
3  * asserts on usage errors
4  * see README for usage info
5
6  * usage:
7  *    ./hostside /dev/ttySn DATA               nmra
8  *    ./hostside /dev/ttySn DATA command       already encoded - raw transmit
9  * DATA is an even number of hex digits in a single arg
10  */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <assert.h>
15 #include <stdlib.h>
16 #include <limits.h>
17 #include <unistd.h>
18 #include <errno.h>
19
20 #include "common.h"
21
22 const char *progname= "hostside-old";
23 static FILE *dump_stream= 0;
24
25 static int repeat_delay= -1, iterations= -1;
26 static const char *serial_port;
27
28 static Nmra buf;
29
30 void die_hook(void) { }
31 void die_vprintf_hook(const char *fmt, va_list al) { }
32
33 static void pahex(const char **argv) {
34   const char *data_string;
35   char hbuf[3], *ep;
36   int i, l;
37   Byte *c;
38
39   c= buf.d;
40
41   while ((data_string= *argv++)) {
42     l= strlen(data_string);
43     if (l&1) badusage("hex argument odd length");
44     l >>= 1;
45   
46     for (i=0; i<l; i++) {
47       if (c >= buf.d + sizeof(buf.d)) badusage("too much hex");
48
49       hbuf[0]= data_string[i*2];
50       hbuf[1]= data_string[i*2+1];
51       hbuf[2]= 0;
52       *c++= strtoul(hbuf,&ep,16); 
53       if (ep!=&hbuf[2]) badusage("bad hex in hex argument");
54     }
55   }
56   buf.l= c - buf.d;
57 }
58
59 struct NmraParseEncodeCaller {
60   const char *const *argv;
61 };
62
63 unsigned long nmra_argnumber(NmraParseEncodeCaller *pec, int argi) {
64   const char *arg;
65   char *ep;
66   unsigned long l;
67
68   arg= pec->argv[argi];
69   errno=0; l= strtoul(arg,&ep,0);
70   if (errno || *ep || ep==arg) badusage("bad numeric arg value");
71   return l;
72 }
73
74 void nmra_problem(NmraParseEncodeCaller *pec, const char *problem) {
75   badusage(problem);
76 }
77
78 static void dump(const char *what, const Byte *data, int length) {
79   if (!dump_stream) return;
80   fprintf(dump_stream,"%-25s %3d  ",what,length);
81   while (length>0) {
82     fprintf(dump_stream," %02x", *data);
83     data++;
84     length--;
85   }
86   fprintf(dump_stream,"\n");
87 }
88
89 static void xmit_command(void) {
90   dump("xmit_command", buf.d, buf.l);
91   serial_transmit_now(buf.d, buf.l);
92 }
93
94 static void xmit_nmra_raw(void) {
95   PicInsn pi;
96   
97   dump("xmit_nmra_raw", buf.d, buf.l);
98   nmra_encodeforpic(&buf, &pi);
99   serial_transmit_now(pi.d, pi.l);
100 }
101
102 static void xmit_nmra_bytes(void) {
103   int l;
104   l= buf.l;
105   nmra_addchecksum(&buf);
106   xmit_nmra_raw();
107   buf.l= l;
108 }
109
110 int main(int argc, const char **argv) {
111   void (*xmitter)(void);
112   const char *arg;
113
114   if (!*argv++) badusage("need argv[0]");
115   
116   while ((arg=*argv++) && *arg=='-') {
117     arg++;
118     switch (*arg++) {
119     case 's': serial_port=             arg;  break;
120     case 'i': iterations=         atoi(arg); break;
121     case 'f': serial_fudge_delay= atoi(arg); break;
122     case 'w': repeat_delay=       atoi(arg); break;
123     case 'd': dump_stream= stdout; goto noarg;
124     default: badusage("uknown option");
125     noarg: if (*arg) badusage("option with value where forbidden");
126     }
127   }
128
129   if (!serial_port) badusage("need serial port option");
130
131   if (!arg) badusage("need arg");
132
133   #define BARE(f)                               \
134   if (!strcmp(arg,#f)) {                        \
135     pahex(argv);                                \
136     xmitter= xmit_##f;                          \
137   } else
138   BARE(command)
139   BARE(nmra_raw)
140   BARE(nmra_bytes)
141   #undef BARE
142   {
143     NmraParseEncodeCaller pec;
144     pec.argv= argv;
145     for (argc=0; argv[argc]; argc++);
146     nmra_parse_encode(&buf, arg, strlen(arg), argc, &pec);
147     xmitter= xmit_nmra_bytes;
148   }
149
150   serial_open(serial_port);
151
152   for (;;) {
153     xmitter();
154     
155     if (repeat_delay < 0) break;
156     if (iterations >= 0 && !iterations--) break;
157     if (repeat_delay > 0) usleep(repeat_delay);
158   }
159
160   return 0;
161 }