chiark / gitweb /
commented-out idents
[trains.git] / parport / parport-ctl.c
1 /**/
2
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <limits.h>
7 #include <string.h>
8 #include <ctype.h>
9
10 #include <sys/ioctl.h>
11 #include <sys/time.h>
12 #include <linux/ppdev.h>
13 #include <linux/parport.h>
14
15 static const struct numvalinfo {
16   const char *name;
17   int num;
18 } ioctlinfos[] = {
19 #define A(x) { #x , PP##x },
20   A(CLAIM)
21   A(EXCL)
22   A(RELEASE)
23   A(YIELD)
24   A(NEGOT)
25   A(SETMODE)
26   A(GETMODE)
27   A(GETTIME)
28   A(GETMODES)
29   A(SETFLAGS)
30   A(WCONTROL)
31   A(RCONTROL)
32   A(FCONTROL)
33   A(RSTATUS)
34   A(DATADIR)
35   A(WDATA)
36   A(RDATA)
37   A(CLRIRQ)
38   A(WCTLONIRQ)
39 #undef A
40   { 0 }
41 };
42
43 #define FIND(v, a, d) do{                                               \
44     for ((v)= a; (v)->name && strcasecmp(arg,(v)->name); (v)++);        \
45     if (!(v)->name) badusage("unknown " d);                             \
46   }while(0)
47
48 static const struct numvalinfo modeinfos[] = {
49 #define A(x) { #x , IEEE1284_MODE_##x },
50   A(COMPAT)
51   A(NIBBLE)
52   A(BYTE)
53   A(EPP)
54   A(ECP)
55 #undef A
56   { 0 }
57 };
58
59 static union parm {
60   int i;
61   struct timeval tv;
62   unsigned char uc;
63   struct ppdev_frob_struct fs;
64 } parm;
65
66 static const struct typeinfo {
67   const char *name;
68   void (*parse)(const char *const **argv);
69   void (*print)(void);
70 } typeinfos[];
71
72 static const void badusage(const char *what) {
73   const struct typeinfo *ti;
74   const struct numvalinfo *ioi;
75   const char *p;
76   
77   fprintf(stderr,"bad usage: %s\n"
78           "usage: parport-ctl <&parport ioctl"
79           " [output-type [input-type [input-args ...]]]\n"
80           "ioctls:", what);
81   for (ioi= ioctlinfos; ioi->name; ioi++) {
82     fputc(' ',stderr);
83     for (p= ioi->name; *p; p++)
84       fputc(tolower((unsigned char)*p),stderr);
85   }
86   fprintf(stderr,"\ntypes:");
87   for (ti= typeinfos; ti->name; ti++)
88     fprintf(stderr," %s",ti->name);
89   fputc('\n',stderr);
90   exit(126);
91 }
92
93 static const char *pa_1arg(const char *const **argv) {
94   const char *arg= *(*argv)++;
95   if (!arg) badusage("input type needs a value");
96   return arg;
97 }             
98
99 static long pa_int(const char *const **argv) {
100   const char *arg= pa_1arg(argv);
101   char *ep;
102   long l;
103
104   l= strtol(arg,&ep,0);
105   if (ep==arg || *ep) badusage("syntactically incorrect numeric input value");
106   return l;
107 }
108 static unsigned char pa_uc(const char *const **argv) {
109   long l= pa_int(argv);
110   if (l<-128 || l>255) badusage("input unsigned char out of range");
111   return (unsigned long)l;
112 }
113   
114 static void parse_none(const char *const **argv) { }
115 static void parse_int(const char *const **argv) {
116   long l= pa_int(argv);
117   if (l<INT_MIN || l>INT_MAX) badusage("input int out of range");
118   parm.i= l;
119 }
120 static void parse_uc(const char *const **argv) {
121   parm.uc= pa_uc(argv);
122 }
123 static void parse_ppdfs(const char *const **argv) {
124   parm.fs.mask= pa_uc(argv);
125   parm.fs.val= pa_uc(argv);
126 }
127 static void parse_mode(const char *const **argv) {
128   const char *arg= pa_1arg(argv);
129   const struct numvalinfo *mi;
130   FIND(mi, modeinfos, "mode name");
131   parm.i= mi->num;
132 }
133
134 static void print_none(void) { }
135 static void print_set(void) { }
136 static void print_int(void) { printf("%d\n",parm.i); }
137 static void print_uc(void) { printf("0x%02x\n",parm.uc); }
138 static void print_hex(void) {
139   const unsigned char *p;
140   for (p= (void*)&parm;
141        p < (const unsigned char*)(&parm + 1);
142        p++)
143     printf("0x%02x",*p);
144   putchar('\n');
145 }
146 static void print_mode(void) {
147   const struct numvalinfo *mi;
148   for (mi= modeinfos; mi->name && mi->num != parm.i; mi++);
149   if (mi->name) printf("%s\n",mi->name);
150   else printf("unknown mode 0x%x\n",parm.i);
151 }
152 static void print_dump(void) {
153   const struct typeinfo *ti;
154   for (ti= typeinfos; ti->name; ti++) {
155     if (!ti->print || ti->print==print_dump || ti->print==print_none) continue;
156     printf("%s\t", ti->name);
157     ti->print();
158   }
159 }
160
161 static const struct typeinfo typeinfos[] = {
162 #define T(x) { #x, parse_##x, print_##x },
163 #define TI(x) { #x, parse_##x, 0 },
164 #define TO(x) { #x, 0, print_##x },
165   T(none)
166   T(int)
167   T(uc)
168   T(mode)
169   TI(ppdfs)
170   TO(set)
171   TO(hex)
172   TO(dump)
173   { 0 }
174 };
175
176 #define FINDT(v, d, n) do {                             \
177     FIND((v), typeinfos, "type for " d);                \
178     if (!(v)->n) badusage("unsupported type for " d);   \
179   }while(0)
180     
181 int main(int argc, const char *const *argv) {
182   const struct numvalinfo *ioi;
183   const struct typeinfo *iti, *oti;
184   const char *arg;
185   int r;
186   
187   if (!*argv++) badusage("need argv[0]");
188   if (!(arg= *argv++)) badusage("need ioctl name");
189   if (arg[0] == '-') badusage("no options supported");
190   FIND(ioi, ioctlinfos, "ioctl name");
191
192   if ((arg= *argv)) {
193     argv++;
194     FINDT(oti, "type for output from ioctl", print);
195   } else {
196     oti= 0;
197   }
198   memset(&parm,0,sizeof(parm));
199   if ((arg= *argv)) {
200     argv++;
201     FINDT(iti, "input to ioctl", parse);
202     iti->parse(&argv);
203   }
204   if (*argv) badusage("too many args");
205
206   r= ioctl(0, ioi->num, &parm);
207   if (r<0) { perror("parport-ctl: ioctl failed"); exit(-1); }
208   if (r>0) { fprintf(stderr,"parport-ctl: ioctl gave %d!\n",r); }
209
210   if (oti) {
211     oti->print();
212     if (ferror(stdout)) { perror("parport-ctl: write stdout"); exit(-1); }
213   }
214   
215   return r>125 ? 125 : r;
216 }