10 #define NMRA_MAX_NARGS 10
12 typedef struct ManualRetransmitNode ManualRetransmitNode;
13 struct ManualRetransmitNode {
14 ManualRetransmitNode *back, *next;
20 #define bogus_volatile /*empty*/
24 #define bogus_volatile volatile
28 struct NmraParseEncodeCaller {
30 unsigned long arg[NMRA_MAX_NARGS];
34 unsigned long nmra_argnumber(NmraParseEncodeCaller *pec, int argi) {
35 return pec->arg[argi];
38 void nmra_problem(NmraParseEncodeCaller *pec, const char *problem) {
39 badcmd(pec->ps,problem);
43 static int cmd_nmra_command(ParseState *ps, RetransmitNode *rn) {
47 bogus_volatile int argc, checksum;
48 NmraParseEncodeCaller pec;
53 switch (ps->remain[0]) {
54 case '_': ps->remain++; return ps_needhextoend(ps, rn->d, &rn->l);
55 case '=': hex=1; checksum=1; break;
56 case ':': hex=1; checksum=0; break;
57 default: hex=0; checksum=1; break;
62 nmra.l= NMRA_PACKET_MAX - checksum;
63 if (!ps_needhextoend(ps, nmra.d, &nmra.l))
66 if (!ps_needword(ps)) return 0;
68 lcmdarg= ps->lthisword;
73 if (argc >= NMRA_MAX_NARGS) {
74 badcmd(ps,"far too many nmra args");
78 errno=0; pec.arg[argc++]= strtoul(ps->thisword, &ep, 0);
79 if (errno || ep != ps->thisword + ps->lthisword)
80 { badcmd(ps,"bad numeric argument for nmra"); return 0; }
85 nmra_parse_encode(&nmra, cmdarg,lcmdarg, argc, &pec);
88 nmra_addchecksum(&nmra);
90 nmra_encodeforpic(&nmra, rn->d, &rn->l);
94 static void cmd_nmra(ParseState *ps, const CmdInfo *ci) {
95 static struct { ManualRetransmitNode *head, *tail; } mrns;
97 ManualRetransmitNode *mrn;
98 RetransmitNode *rn, rn_buf;
100 if (ps->remain && ps->remain[0]=='*') {
105 mrname= ps->thisword+1;
106 lmrname= ps->lthisword-1;
109 !(mrn->lname == lmrname &&
110 !memcmp(mrn->name, mrname, lmrname));
113 retransmit_cancel(&mrn->rn);
115 mrn= mmalloc(sizeof(*mrn));
116 mrn->name= mmalloc(lmrname);
117 memcpy(mrn->name, mrname, lmrname);
126 badcmd(ps,"nmra must have slot to cancel or data to send");
134 rn= mrn ? &mrn->rn : &rn_buf;
135 rn->l= sizeof(rn->d);
137 if (!cmd_nmra_command(ps, rn)) {
138 if (mrn) { free(mrn->name); free(mrn); }
143 retransmit_queue(&mrn->rn);
145 serial_transmit(rn->d, rn->l);
148 static void cmd_noop(ParseState *ps, const CmdInfo *ci) {
149 oprintf(&ps->cl->ch,"noop successful\n");
152 const CmdInfo toplevel_cmds[]= {
153 { "nmra", cmd_nmra, },
154 /* eg nmra [*[slot]] speed28 3 13 1 */
155 /* eg nmra [*[slot]] =0348 */
156 /* eg nmra [*[slot]] :03484b */
157 /* eg nmra [*[slot]] _7f7f00644197 */
158 /* eg nmra [*[slot]] */
160 { "pic-raw" , cmd_pic_raw, 1, },
161 { "pic", cmd_pic }, /* eg pic point 3 */
163 { "noop", cmd_noop },