162642Sn_hibma/*	$NetBSD: usbhid.c,v 1.14 2000/07/03 02:51:37 matt Exp $	*/
262642Sn_hibma/*	$FreeBSD: stable/11/usr.bin/usbhidctl/usbhid.c 351845 2019-09-05 09:35:41Z hselasky $ */
362642Sn_hibma
4330449Seadler/*-
5330449Seadler * SPDX-License-Identifier: BSD-2-Clause-NetBSD
6330449Seadler *
762642Sn_hibma * Copyright (c) 1998 The NetBSD Foundation, Inc.
862642Sn_hibma * All rights reserved.
962642Sn_hibma *
1062642Sn_hibma * This code is derived from software contributed to The NetBSD Foundation
1162642Sn_hibma * by Lennart Augustsson (augustss@netbsd.org).
1262642Sn_hibma *
1362642Sn_hibma * Redistribution and use in source and binary forms, with or without
1462642Sn_hibma * modification, are permitted provided that the following conditions
1562642Sn_hibma * are met:
1662642Sn_hibma * 1. Redistributions of source code must retain the above copyright
1762642Sn_hibma *    notice, this list of conditions and the following disclaimer.
1862642Sn_hibma * 2. Redistributions in binary form must reproduce the above copyright
1962642Sn_hibma *    notice, this list of conditions and the following disclaimer in the
2062642Sn_hibma *    documentation and/or other materials provided with the distribution.
2162642Sn_hibma *
2262642Sn_hibma * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2362642Sn_hibma * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2462642Sn_hibma * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2562642Sn_hibma * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2662642Sn_hibma * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2762642Sn_hibma * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2862642Sn_hibma * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2962642Sn_hibma * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3062642Sn_hibma * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3162642Sn_hibma * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3262642Sn_hibma * POSSIBILITY OF SUCH DAMAGE.
3362642Sn_hibma */
3462642Sn_hibma
3562642Sn_hibma#include <stdio.h>
3662642Sn_hibma#include <stdlib.h>
3762642Sn_hibma#include <string.h>
3862642Sn_hibma#include <sys/types.h>
3962642Sn_hibma#include <fcntl.h>
4062642Sn_hibma#include <unistd.h>
4162642Sn_hibma#include <err.h>
4262642Sn_hibma#include <ctype.h>
4362642Sn_hibma#include <errno.h>
44113273Smdodd#include <usbhid.h>
45188945Sthompsa#include <dev/usb/usbhid.h>
4662642Sn_hibma
47227196Sedstatic struct variable {
48225839Smav	char *name;
49225839Smav	int instance;
50225839Smav	int val;
51225839Smav	struct hid_item h;
52225839Smav	struct variable *next;
53225839Smav} *vars;
54225839Smav
55227196Sedstatic int verbose = 0;
56227196Sedstatic int noname = 0;
57227196Sedstatic int hexdump = 0;
58227196Sedstatic int wflag = 0;
59227196Sedstatic int zflag = 0;
6062642Sn_hibma
61225839Smavstatic void usage(void);
62225839Smavstatic void dumpitem(const char *label, struct hid_item *h);
63225839Smavstatic void dumpitems(report_desc_t r);
64225839Smavstatic void prdata(u_char *buf, struct hid_item *h);
65225839Smavstatic void dumpdata(int f, report_desc_t r, int loop);
66225839Smavstatic void writedata(int f, report_desc_t r);
6762642Sn_hibma
68225839Smavstatic void
69225839Smavparceargs(report_desc_t r, int all, int nnames, char **names)
7062642Sn_hibma{
71225839Smav	struct hid_data *d;
72225839Smav	struct hid_item h;
73225839Smav	char colls[1000];
74225839Smav	char hname[1000], *tmp1, *tmp2;
75225839Smav	struct variable *var, **pnext;
76225839Smav	int i, instance, cp, t;
7762642Sn_hibma
78225839Smav	pnext = &vars;
79225839Smav	if (all) {
80225839Smav		if (wflag)
81225839Smav			errx(1, "Must not specify -w to read variables");
82225839Smav		cp = 0;
83225839Smav		for (d = hid_start_parse(r,
84225839Smav		    1<<hid_input | 1<<hid_output | 1<<hid_feature, -1);
85225839Smav		    hid_get_item(d, &h); ) {
86225839Smav			if (h.kind == hid_collection) {
87225839Smav				cp += sprintf(&colls[cp], "%s%s:%s",
88225839Smav				    cp != 0 ? "." : "",
89225839Smav				    hid_usage_page(HID_PAGE(h.usage)),
90225839Smav				    hid_usage_in_page(h.usage));
91225839Smav			} else if (h.kind == hid_endcollection) {
92225839Smav				tmp1 = strrchr(colls, '.');
93225839Smav				if (tmp1 != NULL) {
94225839Smav					cp -= strlen(tmp1);
95225839Smav					tmp1[0] = 0;
96225839Smav				} else {
97225839Smav					cp = 0;
98225839Smav					colls[0] = 0;
99225839Smav				}
100225839Smav			}
101225839Smav			if ((h.kind != hid_input && h.kind != hid_output &&
102225839Smav			    h.kind != hid_feature) || (h.flags & HIO_CONST))
103225839Smav				continue;
104225839Smav			var = malloc(sizeof(*var));
105225839Smav			memset(var, 0, sizeof(*var));
106225839Smav			asprintf(&var->name, "%s%s%s:%s",
107225839Smav			    colls, colls[0] != 0 ? "." : "",
108225839Smav			    hid_usage_page(HID_PAGE(h.usage)),
109225839Smav			    hid_usage_in_page(h.usage));
110225839Smav			var->h = h;
111225839Smav			*pnext = var;
112225839Smav			pnext = &var->next;
113225839Smav		}
114225839Smav		hid_end_parse(d);
115225839Smav		return;
116225839Smav	}
117225839Smav	for (i = 0; i < nnames; i++) {
118225839Smav		var = malloc(sizeof(*var));
119225839Smav		memset(var, 0, sizeof(*var));
120225839Smav		tmp1 = tmp2 = strdup(names[i]);
121225839Smav		strsep(&tmp2, "=");
122225839Smav		var->name = strsep(&tmp1, "#");
123225839Smav		if (tmp1 != NULL)
124225839Smav			var->instance = atoi(tmp1);
125225839Smav		if (tmp2 != NULL) {
126225839Smav			if (!wflag)
127225839Smav				errx(1, "Must specify -w to write variables");
128225839Smav			var->val = atoi(tmp2);
129225839Smav		} else
130225839Smav			if (wflag)
131225839Smav				errx(1, "Must not specify -w to read variables");
132225839Smav		*pnext = var;
133225839Smav		pnext = &var->next;
13462642Sn_hibma
135225839Smav		instance = 0;
136225839Smav		cp = 0;
137225839Smav		for (d = hid_start_parse(r,
138225839Smav		    1<<hid_input | 1<<hid_output | 1<<hid_feature, -1);
139225839Smav		    hid_get_item(d, &h); ) {
140225839Smav			if (h.kind == hid_collection) {
141225839Smav				cp += sprintf(&colls[cp], "%s%s:%s",
142225839Smav				    cp != 0 ? "." : "",
143225839Smav				    hid_usage_page(HID_PAGE(h.usage)),
144225839Smav				    hid_usage_in_page(h.usage));
145225839Smav			} else if (h.kind == hid_endcollection) {
146225839Smav				tmp1 = strrchr(colls, '.');
147225839Smav				if (tmp1 != NULL) {
148225839Smav					cp -= strlen(tmp1);
149225839Smav					tmp1[0] = 0;
150225839Smav				} else {
151225839Smav					cp = 0;
152225839Smav					colls[0] = 0;
153225839Smav				}
154225839Smav			}
155225839Smav			if ((h.kind != hid_input && h.kind != hid_output &&
156225839Smav			    h.kind != hid_feature) || (h.flags & HIO_CONST))
157225839Smav				continue;
158225839Smav			snprintf(hname, sizeof(hname), "%s%s%s:%s",
159225839Smav			    colls, colls[0] != 0 ? "." : "",
160225839Smav			    hid_usage_page(HID_PAGE(h.usage)),
161225839Smav			    hid_usage_in_page(h.usage));
162225839Smav			t = strlen(hname) - strlen(var->name);
163225839Smav			if (t > 0) {
164225839Smav				if (strcmp(hname + t, var->name) != 0)
165225839Smav					continue;
166225839Smav				if (hname[t - 1] != '.')
167225839Smav					continue;
168225839Smav			} else if (strcmp(hname, var->name) != 0)
169225839Smav				continue;
170225839Smav			if (var->instance != instance++)
171225839Smav				continue;
172225839Smav			var->h = h;
173225839Smav			break;
174225839Smav		}
175225839Smav		hid_end_parse(d);
176225839Smav		if (var->h.usage == 0)
177225839Smav			errx(1, "Unknown item '%s'", var->name);
178225839Smav	}
17962642Sn_hibma}
18062642Sn_hibma
181225839Smavstatic void
18262642Sn_hibmausage(void)
18362642Sn_hibma{
18462642Sn_hibma
185164531Sgrog	fprintf(stderr,
186164531Sgrog                "usage: %s -f device "
187235519Smav                "[-l] [-n] [-r] [-t tablefile] [-v] [-x] [-z] name ...\n",
188194789Sdelphij                getprogname());
189164531Sgrog	fprintf(stderr,
190164531Sgrog                "       %s -f device "
191235519Smav                "[-l] [-n] [-r] [-t tablefile] [-v] [-x] [-z] -a\n",
192194789Sdelphij                getprogname());
193225839Smav	fprintf(stderr,
194225839Smav                "       %s -f device "
195225839Smav                "[-t tablefile] [-v] [-z] -w name=value\n",
196225839Smav                getprogname());
19762642Sn_hibma	exit(1);
19862642Sn_hibma}
19962642Sn_hibma
200225839Smavstatic void
20187699Smarkmdumpitem(const char *label, struct hid_item *h)
20262642Sn_hibma{
20362642Sn_hibma	if ((h->flags & HIO_CONST) && !verbose)
20462642Sn_hibma		return;
205351845Shselasky	printf("%s rid=%d pos=%d size=%d count=%d page=%s usage=%s%s%s", label,
206351845Shselasky	       h->report_ID, h->pos, h->report_size, h->report_count,
207164531Sgrog	       hid_usage_page(HID_PAGE(h->usage)),
20862642Sn_hibma	       hid_usage_in_page(h->usage),
209224511Smav	       h->flags & HIO_CONST ? " Const" : "",
210224511Smav	       h->flags & HIO_VARIABLE ? "" : " Array");
21162642Sn_hibma	printf(", logical range %d..%d",
21262642Sn_hibma	       h->logical_minimum, h->logical_maximum);
21362642Sn_hibma	if (h->physical_minimum != h->physical_maximum)
21462642Sn_hibma		printf(", physical range %d..%d",
21562642Sn_hibma		       h->physical_minimum, h->physical_maximum);
21662642Sn_hibma	if (h->unit)
21762642Sn_hibma		printf(", unit=0x%02x exp=%d", h->unit, h->unit_exponent);
21862642Sn_hibma	printf("\n");
21962642Sn_hibma}
22062642Sn_hibma
221224511Smavstatic const char *
222224511Smavhid_collection_type(int32_t type)
223224511Smav{
224224511Smav	static char num[8];
225224511Smav
226224511Smav	switch (type) {
227224511Smav	case 0: return ("Physical");
228224511Smav	case 1: return ("Application");
229224511Smav	case 2: return ("Logical");
230224511Smav	case 3: return ("Report");
231224511Smav	case 4: return ("Named_Array");
232224511Smav	case 5: return ("Usage_Switch");
233224511Smav	case 6: return ("Usage_Modifier");
234224511Smav	}
235224511Smav	snprintf(num, sizeof(num), "0x%02x", type);
236224511Smav	return (num);
237224511Smav}
238224511Smav
239225839Smavstatic void
24062642Sn_hibmadumpitems(report_desc_t r)
24162642Sn_hibma{
24262642Sn_hibma	struct hid_data *d;
24362642Sn_hibma	struct hid_item h;
24467256Sn_hibma	int size;
24562642Sn_hibma
246224511Smav	for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) {
24762642Sn_hibma		switch (h.kind) {
24862642Sn_hibma		case hid_collection:
249224511Smav			printf("Collection type=%s page=%s usage=%s\n",
250224511Smav			       hid_collection_type(h.collection),
251164531Sgrog			       hid_usage_page(HID_PAGE(h.usage)),
25262642Sn_hibma			       hid_usage_in_page(h.usage));
25362642Sn_hibma			break;
25462642Sn_hibma		case hid_endcollection:
25562642Sn_hibma			printf("End collection\n");
25662642Sn_hibma			break;
25762642Sn_hibma		case hid_input:
25862642Sn_hibma			dumpitem("Input  ", &h);
25962642Sn_hibma			break;
26062642Sn_hibma		case hid_output:
26162642Sn_hibma			dumpitem("Output ", &h);
26262642Sn_hibma			break;
26362642Sn_hibma		case hid_feature:
26462642Sn_hibma			dumpitem("Feature", &h);
26562642Sn_hibma			break;
26662642Sn_hibma		}
26762642Sn_hibma	}
26862642Sn_hibma	hid_end_parse(d);
269224511Smav	size = hid_report_size(r, hid_input, -1);
27075606Sn_hibma	printf("Total   input size %d bytes\n", size);
27162642Sn_hibma
272224511Smav	size = hid_report_size(r, hid_output, -1);
27367256Sn_hibma	printf("Total  output size %d bytes\n", size);
27467256Sn_hibma
275224511Smav	size = hid_report_size(r, hid_feature, -1);
27667256Sn_hibma	printf("Total feature size %d bytes\n", size);
27762642Sn_hibma}
27862642Sn_hibma
279225839Smavstatic void
28062642Sn_hibmaprdata(u_char *buf, struct hid_item *h)
28162642Sn_hibma{
28262642Sn_hibma	u_int data;
28362642Sn_hibma	int i, pos;
28462642Sn_hibma
28562642Sn_hibma	pos = h->pos;
28662642Sn_hibma	for (i = 0; i < h->report_count; i++) {
28762642Sn_hibma		data = hid_get_data(buf, h);
288224511Smav		if (i > 0)
289224511Smav			printf(" ");
29062642Sn_hibma		if (h->logical_minimum < 0)
29162642Sn_hibma			printf("%d", (int)data);
29262642Sn_hibma		else
29362642Sn_hibma			printf("%u", data);
294164531Sgrog                if (hexdump)
295164531Sgrog			printf(" [0x%x]", data);
296224511Smav		h->pos += h->report_size;
29762642Sn_hibma	}
298224511Smav	h->pos = pos;
29962642Sn_hibma}
30062642Sn_hibma
301225839Smavstatic void
30262642Sn_hibmadumpdata(int f, report_desc_t rd, int loop)
30362642Sn_hibma{
304225839Smav	struct variable *var;
305225839Smav	int dlen, havedata, i, match, r, rid, use_rid;
30662642Sn_hibma	u_char *dbuf;
307225839Smav	enum hid_kind kind;
30862642Sn_hibma
309235519Smav	kind = zflag ? 3 : 0;
310225839Smav	rid = -1;
311225839Smav	use_rid = !!hid_get_report_id(f);
312225839Smav	do {
313225839Smav		if (kind < 3) {
314225839Smav			if (++rid >= 256) {
315225839Smav				rid = 0;
316225839Smav				kind++;
317225839Smav			}
318225839Smav			if (kind >= 3)
319225839Smav				rid = -1;
320225839Smav			for (var = vars; var; var = var->next) {
321225839Smav				if (rid == var->h.report_ID &&
322225839Smav				    kind == var->h.kind)
323225839Smav					break;
324225839Smav			}
325225839Smav			if (var == NULL)
326225839Smav				continue;
327225839Smav		}
328225839Smav		dlen = hid_report_size(rd, kind < 3 ? kind : hid_input, rid);
329225839Smav		if (dlen <= 0)
33062642Sn_hibma			continue;
331225839Smav		dbuf = malloc(dlen);
332225839Smav		memset(dbuf, 0, dlen);
333225839Smav		if (kind < 3) {
334225839Smav			dbuf[0] = rid;
335225839Smav			r = hid_get_report(f, kind, dbuf, dlen);
336225839Smav			if (r < 0)
337225839Smav				warn("hid_get_report(rid %d)", rid);
338225839Smav			havedata = !r && (rid == 0 || dbuf[0] == rid);
339225839Smav			if (rid != 0)
340225839Smav				dbuf[0] = rid;
341225839Smav		} else {
342225839Smav			r = read(f, dbuf, dlen);
343225839Smav			if (r < 1)
344225839Smav				err(1, "read error");
345225839Smav			havedata = 1;
34662642Sn_hibma		}
347225839Smav		if (verbose) {
348225839Smav			printf("Got %s report %d (%d bytes):",
349225839Smav			    kind == hid_output ? "output" :
350225839Smav			    kind == hid_feature ? "feature" : "input",
351225839Smav			    use_rid ? dbuf[0] : 0, dlen);
352225839Smav			if (havedata) {
353225839Smav				for (i = 0; i < dlen; i++)
354225839Smav					printf(" %02x", dbuf[i]);
355225839Smav			}
356225839Smav			printf("\n");
35762642Sn_hibma		}
358225839Smav		match = 0;
359225839Smav		for (var = vars; var; var = var->next) {
360225839Smav			if ((kind < 3 ? kind : hid_input) != var->h.kind)
361224511Smav				continue;
362225839Smav			if (var->h.report_ID != 0 &&
363225839Smav			    dbuf[0] != var->h.report_ID)
364225839Smav				continue;
365225839Smav			match = 1;
366225839Smav			if (!noname)
367225839Smav				printf("%s=", var->name);
368225839Smav			if (havedata)
369225839Smav				prdata(dbuf, &var->h);
370225839Smav			printf("\n");
371225839Smav		}
372225839Smav		if (match)
373225839Smav			printf("\n");
374225839Smav		free(dbuf);
375225839Smav	} while (loop || kind < 3);
376225839Smav}
377225839Smav
378225839Smavstatic void
379225839Smavwritedata(int f, report_desc_t rd)
380225839Smav{
381225839Smav	struct variable *var;
382225839Smav	int dlen, i, r, rid;
383225839Smav	u_char *dbuf;
384225839Smav	enum hid_kind kind;
385225839Smav
386225839Smav	kind = 0;
387225839Smav	rid = 0;
388225839Smav	for (kind = 0; kind < 3; kind ++) {
389225839Smav	    for (rid = 0; rid < 256; rid ++) {
390225839Smav		for (var = vars; var; var = var->next) {
391225839Smav			if (rid == var->h.report_ID && kind == var->h.kind)
392225839Smav				break;
393225839Smav		}
394225839Smav		if (var == NULL)
395225839Smav			continue;
396225839Smav		dlen = hid_report_size(rd, kind, rid);
397225839Smav		if (dlen <= 0)
398225839Smav			continue;
399225839Smav		dbuf = malloc(dlen);
400225839Smav		memset(dbuf, 0, dlen);
401225839Smav		dbuf[0] = rid;
402225839Smav		if (!zflag && hid_get_report(f, kind, dbuf, dlen) == 0) {
403225839Smav			if (verbose) {
404225839Smav				printf("Got %s report %d (%d bytes):",
405225839Smav				    kind == hid_input ? "input" :
406225839Smav				    kind == hid_output ? "output" : "feature",
407225839Smav				    rid, dlen);
408225839Smav				for (i = 0; i < dlen; i++)
409225839Smav					printf(" %02x", dbuf[i]);
41062642Sn_hibma				printf("\n");
41162642Sn_hibma			}
412225839Smav		} else if (!zflag) {
413225839Smav			warn("hid_get_report(rid %d)", rid);
414225839Smav			if (verbose) {
415225839Smav				printf("Can't get %s report %d (%d bytes). "
416225839Smav				    "Will be initialized with zeros.\n",
417225839Smav				    kind == hid_input ? "input" :
418225839Smav				    kind == hid_output ? "output" : "feature",
419225839Smav				    rid, dlen);
420225839Smav			}
42162642Sn_hibma		}
422225839Smav		for (var = vars; var; var = var->next) {
423225839Smav			if (rid != var->h.report_ID || kind != var->h.kind)
424225839Smav				continue;
425225839Smav			hid_set_data(dbuf, &var->h, var->val);
426225839Smav		}
427225839Smav		if (verbose) {
428225839Smav			printf("Setting %s report %d (%d bytes):",
429225839Smav			    kind == hid_output ? "output" :
430225839Smav			    kind == hid_feature ? "feature" : "input",
431225839Smav			    rid, dlen);
432225839Smav			for (i = 0; i < dlen; i++)
433225839Smav				printf(" %02x", dbuf[i]);
43462642Sn_hibma			printf("\n");
435225839Smav		}
436225839Smav		r = hid_set_report(f, kind, dbuf, dlen);
437225839Smav		if (r != 0)
438225839Smav			warn("hid_set_report(rid %d)", rid);
439225839Smav		free(dbuf);
440225839Smav	    }
441225839Smav	}
44262642Sn_hibma}
44362642Sn_hibma
44462642Sn_hibmaint
44562642Sn_hibmamain(int argc, char **argv)
44662642Sn_hibma{
447225839Smav	report_desc_t r;
448225839Smav	char *table = 0;
449225839Smav	char devnam[100], *dev = NULL;
45062642Sn_hibma	int f;
451225839Smav	int all = 0;
45262642Sn_hibma	int ch;
45362642Sn_hibma	int repdump = 0;
45462642Sn_hibma	int loop = 0;
45562642Sn_hibma
456225839Smav	while ((ch = getopt(argc, argv, "af:lnrt:vwxz")) != -1) {
45762642Sn_hibma		switch(ch) {
45862642Sn_hibma		case 'a':
45962642Sn_hibma			all++;
46062642Sn_hibma			break;
46162642Sn_hibma		case 'f':
46262642Sn_hibma			dev = optarg;
46362642Sn_hibma			break;
46462642Sn_hibma		case 'l':
46562642Sn_hibma			loop ^= 1;
46662642Sn_hibma			break;
46762642Sn_hibma		case 'n':
46862642Sn_hibma			noname++;
46962642Sn_hibma			break;
47062642Sn_hibma		case 'r':
47162642Sn_hibma			repdump++;
47262642Sn_hibma			break;
47362642Sn_hibma		case 't':
47462642Sn_hibma			table = optarg;
47562642Sn_hibma			break;
47662642Sn_hibma		case 'v':
47762642Sn_hibma			verbose++;
47862642Sn_hibma			break;
479225839Smav		case 'w':
480225839Smav			wflag = 1;
481225839Smav			break;
482164531Sgrog		case 'x':
483164544Sgrog			hexdump = 1;
484164531Sgrog			break;
485225839Smav		case 'z':
486225839Smav			zflag = 1;
487225839Smav			break;
48862642Sn_hibma		case '?':
48962642Sn_hibma		default:
49062642Sn_hibma			usage();
49162642Sn_hibma		}
49262642Sn_hibma	}
49362642Sn_hibma	argc -= optind;
49462642Sn_hibma	argv += optind;
495225839Smav	if (dev == NULL)
49662642Sn_hibma		usage();
49762642Sn_hibma
498225839Smav	if (argc == 0 && !all && !repdump)
49962642Sn_hibma		usage();
50062642Sn_hibma
50162642Sn_hibma	if (dev[0] != '/') {
50262642Sn_hibma		if (isdigit(dev[0]))
50387699Smarkm			snprintf(devnam, sizeof(devnam), "/dev/uhid%s", dev);
50462642Sn_hibma		else
50587699Smarkm			snprintf(devnam, sizeof(devnam), "/dev/%s", dev);
50687699Smarkm		dev = devnam;
50762642Sn_hibma	}
50862642Sn_hibma
50962642Sn_hibma	hid_init(table);
51062642Sn_hibma
51162642Sn_hibma	f = open(dev, O_RDWR);
51262642Sn_hibma	if (f < 0)
51362642Sn_hibma		err(1, "%s", dev);
51462642Sn_hibma
51562642Sn_hibma	r = hid_get_report_desc(f);
516164531Sgrog	if (r == 0)
51762642Sn_hibma		errx(1, "USB_GET_REPORT_DESC");
518164531Sgrog
51962642Sn_hibma	if (repdump) {
52062642Sn_hibma		printf("Report descriptor:\n");
52162642Sn_hibma		dumpitems(r);
52262642Sn_hibma	}
523225839Smav	if (argc != 0 || all) {
524225839Smav		parceargs(r, all, argc, argv);
525225839Smav		if (wflag)
526225839Smav			writedata(f, r);
527225839Smav		else
528225839Smav			dumpdata(f, r, loop);
529225839Smav	}
53062642Sn_hibma
53162642Sn_hibma	hid_dispose_report_desc(r);
53262642Sn_hibma	exit(0);
53362642Sn_hibma}
534