--- /dev/null
+/**/
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <linux/ppdev.h>
+#include <linux/parport.h>
+
+static const struct numvalinfo {
+ const char *name;
+ int num;
+} ioctlinfos[] = {
+#define A(x) { #x , PP##x },
+ A(CLAIM)
+ A(EXCL)
+ A(RELEASE)
+ A(YIELD)
+ A(NEGOT)
+ A(SETMODE)
+ A(GETMODE)
+ A(GETTIME)
+ A(GETMODES)
+ A(SETFLAGS)
+ A(WCONTROL)
+ A(RCONTROL)
+ A(FCONTROL)
+ A(RSTATUS)
+ A(DATADIR)
+ A(WDATA)
+ A(RDATA)
+ A(CLRIRQ)
+ A(WCTLONIRQ)
+#undef A
+ { 0 }
+};
+
+#define FIND(v, a, d) do{ \
+ for ((v)= a; (v)->name && strcasecmp(arg,(v)->name); (v)++); \
+ if (!(v)->name) badusage("unknown " d); \
+ }while(0)
+
+static const struct numvalinfo modeinfos[] = {
+#define A(x) { #x , IEEE1284_MODE_##x },
+ A(COMPAT)
+ A(NIBBLE)
+ A(BYTE)
+ A(EPP)
+ A(ECP)
+#undef A
+ { 0 }
+};
+
+static union parm {
+ int i;
+ struct timeval tv;
+ unsigned char uc;
+ struct ppdev_frob_struct fs;
+} parm;
+
+static const struct typeinfo {
+ const char *name;
+ void (*parse)(const char *const **argv);
+ void (*print)(void);
+} typeinfos[];
+
+static const void badusage(const char *what) {
+ const struct typeinfo *ti;
+ const struct numvalinfo *ioi;
+ const char *p;
+
+ fprintf(stderr,"bad usage: %s\n"
+ "usage: parport-ctl <&parport ioctl"
+ " [input-type [input-args ...] [output-type]]\n"
+ "ioctls:", what);
+ for (ioi= ioctlinfos; ioi->name; ioi++) {
+ fputc(' ',stderr);
+ for (p= ioi->name; *p; p++)
+ fputc(tolower((unsigned char)*p),stderr);
+ }
+ fprintf(stderr,"\ntypes:");
+ for (ti= typeinfos; ti->name; ti++)
+ fprintf(stderr," %s",ti->name);
+ fputc('\n',stderr);
+ exit(126);
+}
+
+static const char *pa_1arg(const char *const **argv) {
+ const char *arg= *(*argv)++;
+ if (!arg) badusage("input type needs a value");
+ return arg;
+}
+
+static long pa_int(const char *const **argv) {
+ const char *arg= pa_1arg(argv);
+ char *ep;
+ long l;
+
+ l= strtol(arg,&ep,0);
+ if (ep==arg || *ep) badusage("syntactically incorrect numeric input value");
+ return l;
+}
+static unsigned char pa_uc(const char *const **argv) {
+ long l= pa_int(argv);
+ if (l<-128 || l>255) badusage("input unsigned char out of range");
+ return (unsigned long)l;
+}
+
+static void parse_none(const char *const **argv) { }
+static void parse_int(const char *const **argv) {
+ long l= pa_int(argv);
+ if (l<INT_MIN || l>INT_MAX) badusage("input int out of range");
+ parm.i= l;
+}
+static void parse_uc(const char *const **argv) {
+ parm.uc= pa_uc(argv);
+}
+static void parse_ppdfs(const char *const **argv) {
+ parm.fs.mask= pa_uc(argv);
+ parm.fs.val= pa_uc(argv);
+}
+static void parse_get(const char *const **argv) { }
+static void parse_mode(const char *const **argv) {
+ const char *arg= pa_1arg(argv);
+ const struct numvalinfo *mi;
+ FIND(mi, modeinfos, "mode name");
+ parm.i= mi->num;
+}
+
+static void print_none(void) { }
+static void print_int(void) { printf("%d\n",parm.i); }
+static void print_uc(void) { printf("0x%02x\n",parm.uc); }
+static void print_hex(void) {
+ const unsigned char *p;
+ for (p= (void*)&parm;
+ p < (const unsigned char*)(&parm + 1);
+ p++)
+ printf("0x%02x",*p);
+ putchar('\n');
+}
+static void print_mode(void) {
+ const struct numvalinfo *mi;
+ for (mi= modeinfos; mi->name && mi->num != parm.i; mi++);
+ if (mi->name) printf("%s\n",mi->name);
+ else printf("unknown mode 0x%x\n",parm.i);
+}
+static void print_dump(void) {
+ const struct typeinfo *ti;
+ for (ti= typeinfos; ti->name; ti++) {
+ if (!ti->print || ti->print==print_dump || ti->print==print_none) continue;
+ printf("%s\t", ti->name);
+ ti->print();
+ }
+}
+
+static const struct typeinfo typeinfos[] = {
+#define T(x) { #x, parse_##x, print_##x },
+#define TI(x) { #x, parse_##x, 0 },
+#define TO(x) { #x, 0, print_##x },
+ T(none)
+ T(int)
+ T(uc)
+ T(mode)
+ TI(ppdfs)
+ TI(get)
+ TO(hex)
+ TO(dump)
+ { 0 }
+};
+
+#define FINDT(v, d, n) do { \
+ FIND((v), typeinfos, "type for " d); \
+ if (!(v)->n) badusage("unsupported type for " d); \
+ }while(0)
+
+int main(int argc, const char *const *argv) {
+ const struct numvalinfo *ioi;
+ const struct typeinfo *iti, *oti;
+ const char *arg;
+ int r;
+
+ if (!*argv++) badusage("need argv[0]");
+ if (!(arg= *argv++)) badusage("need ioctl name");
+ if (arg[0] == '-') badusage("no options supported");
+ FIND(ioi, ioctlinfos, "ioctl name");
+
+ memset(&parm,0,sizeof(parm));
+ if ((arg= *argv)) {
+ argv++;
+ FINDT(iti, "input to ioctl", parse);
+ iti->parse(&argv);
+ }
+ if ((arg= *argv)) {
+ argv++;
+ FINDT(oti, "type for output from ioctl", print);
+ } else {
+ oti= 0;
+ }
+ if (*argv) badusage("too many args");
+
+ r= ioctl(0, ioi->num, &parm);
+ if (r<0) { perror("parport-ctl: ioctl failed"); exit(-1); }
+ if (r>0) { fprintf(stderr,"parport-ctl: ioctl gave %d!\n",r); }
+
+ if (oti) {
+ oti->print();
+ if (ferror(stdout)) { perror("parport-ctl: write stdout"); exit(-1); }
+ }
+
+ return r>125 ? 125 : r;
+}