-/**/
+/*
+ * usage:
+ * .../hidraw-ioctl </dev/hidrawN -a
+ * .../hidraw-ioctl </dev/hidrawN -[drnp]
+ * where -a means all, and the other letters are:
+ * -d descriptors (in hex)
+ * -D descriptors length (decimal), descriptors (in hex)
+ * -i HIDIOCGRAWINFO: bustype, vendor, product (all in hex)
+ * -n HIDIOCGRAWNAME
+ * -p HIDIOCGRAWPATHPHYS
+ * exit status:
+ * 0 all ok
+ * 2 at least one ioctl on the device failed
+ * other some other problem
+ */
#include <stdio.h>
#include <stdint.h>
#include "common.h"
+void die_vprintf_hook(const char *fmt, va_list al) { }
+void die_hook(void) { }
+const char *progname= "hidraw-ioctl";
+
+static void prerror(const char *what) {
+ printf("%s: %s\n", what, strerror(errno));
+}
+
+#define ERR(s) do{ prerror(s); e=1; goto next_opt; }while(0)
+
int main(int argc, char **argv) {
- int r, descsz;
-
- r= ioctl(0, HIDIOCGRDESCSIZE, &descsz);
- if (r) {
- perror("HIDIOCGRDESCSIZE");
- } else {
- printf("%d\n",descsz);
- struct {
- struct hidraw_report_descriptor d;
- unsigned char buf[descsz];
- } d;
- d.d.size = descsz;
- r= ioctl(0, HIDIOCGRDESC, &d);
- if (r) perror("HIDIOCGRDESC");
- else { dump(d.d.value, d.d.size); putchar('\n'); }
- }
+ static const char allopts[]= "Dinp";
+ int r, opt, e=0;
+ const char *opts;
- struct hidraw_devinfo di;
- r= ioctl(0, HIDIOCGRAWINFO, &di);
- if (r) perror("HIDIOCGRAWINFO");
- else {
- printf("%08"PRIx32" %04"PRIx16" %04"PRIx16"\n",
- di.bustype, di.vendor, di.product);
- }
+ if (!*argv || !(opts=*++argv) || *opts++!='-' || *++argv)
+ badusage("need exactly one argument, containing options");
+ if (!strcmp(opts,"a")) opts= allopts;
+
+ while ((opt= *opts++)) {
+ switch (opt) {
- unsigned char buf[PATH_MAX];
+ case 'd': case 'D':;
+ int descsz;
+ r= ioctl(0, HIDIOCGRDESCSIZE, &descsz);
+ if (r) ERR("HIDIOCGRDESCSIZE");
- r= ioctl(0, HIDIOCGRAWNAME(PATH_MAX), buf);
- if (r<0) perror("HIDIOCGRAWNAME");
- else printf("%d %.*s\n", r, r,buf);
+ if (opt=='D') printf("%d\n",descsz);
- r= ioctl(0, HIDIOCGRAWPHYS(PATH_MAX), buf);
- if (r<0) perror("HIDIOCGRAWPHYS");
- else printf("%d %.*s\n", r, r,buf);
+ {
+ struct {
+ struct hidraw_report_descriptor d;
+ unsigned char buf[descsz];
+ } d;
+ d.d.size = descsz;
+ r= ioctl(0, HIDIOCGRDESC, &d);
+ if (r) ERR("HIDIOCGRDESC");
+
+ dumphex(stdout, d.d.value, d.d.size);
+ }
+ putchar('\n');
+ break;
+
+ case 'i':;
+ struct hidraw_devinfo di;
+ r= ioctl(0, HIDIOCGRAWINFO, &di);
+ if (r) ERR("HIDIOCGRAWINFO");
+ printf("%08"PRIx32" %04"PRIx16" %04"PRIx16"\n",
+ di.bustype, di.vendor, di.product);
+ break;
+
+ case 'n':;
+ unsigned char buf[PATH_MAX];
+ r= ioctl(0, HIDIOCGRAWNAME(PATH_MAX), buf);
+ if (r<0) ERR("HIDIOCGRAWNAME");
+ printf("%d %.*s\n", r, r,buf);
+ break;
+
+ case 'p':
+ r= ioctl(0, HIDIOCGRAWPHYS(PATH_MAX), buf);
+ if (r<0) ERR("HIDIOCGRAWPHYS");
+ printf("%d %.*s\n", r, r,buf);
+ break;
+
+ default:
+ badusage("unknown option");
+ }
+
+ next_opt:;
+ if (ferror(stdout) || fflush(stdout))
+ diee("write/flush stdout");
+ }
- return 0;
+ return e;
}