1 /* $NetBSD: usbhid.c,v 1.14 2000/07/03 02:51:37 matt Exp $ */
2 /* $FreeBSD: head/usr.bin/usbhidctl/usbhid.c 235519 2012-05-16 20:30:20Z mav $ */
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (augustss@netbsd.org).
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/types.h>
43 #include <bus/u4b/usbhid.h>
45 static struct variable
{
50 struct variable
*next
;
53 static int verbose
= 0;
54 static int noname
= 0;
55 static int hexdump
= 0;
59 static void usage(void);
60 static void dumpitem(const char *label
, struct hid_item
*h
);
61 static void dumpitems(report_desc_t r
);
62 static void prdata(u_char
*buf
, struct hid_item
*h
);
63 static void dumpdata(int f
, report_desc_t r
, int loop
);
64 static void writedata(int f
, report_desc_t r
);
67 parceargs(report_desc_t r
, int all
, int nnames
, char **names
)
72 char hname
[1000], *tmp1
, *tmp2
;
73 struct variable
*var
, **pnext
;
74 int i
, instance
, cp
, t
;
79 errx(1, "Must not specify -w to read variables");
81 for (d
= hid_start_parse(r
,
82 1<<hid_input
| 1<<hid_output
| 1<<hid_feature
, -1);
83 hid_get_item(d
, &h
); ) {
84 if (h
.kind
== hid_collection
) {
85 cp
+= sprintf(&colls
[cp
], "%s%s:%s",
87 hid_usage_page(HID_PAGE(h
.usage
)),
88 hid_usage_in_page(h
.usage
));
89 } else if (h
.kind
== hid_endcollection
) {
90 tmp1
= strrchr(colls
, '.');
99 if ((h
.kind
!= hid_input
&& h
.kind
!= hid_output
&&
100 h
.kind
!= hid_feature
) || (h
.flags
& HIO_CONST
))
102 var
= malloc(sizeof(*var
));
103 memset(var
, 0, sizeof(*var
));
104 asprintf(&var
->name
, "%s%s%s:%s",
105 colls
, colls
[0] != 0 ? "." : "",
106 hid_usage_page(HID_PAGE(h
.usage
)),
107 hid_usage_in_page(h
.usage
));
115 for (i
= 0; i
< nnames
; i
++) {
116 var
= malloc(sizeof(*var
));
117 memset(var
, 0, sizeof(*var
));
118 tmp1
= tmp2
= strdup(names
[i
]);
120 var
->name
= strsep(&tmp1
, "#");
122 var
->instance
= atoi(tmp1
);
125 errx(1, "Must specify -w to write variables");
126 var
->val
= atoi(tmp2
);
129 errx(1, "Must not specify -w to read variables");
135 for (d
= hid_start_parse(r
,
136 1<<hid_input
| 1<<hid_output
| 1<<hid_feature
, -1);
137 hid_get_item(d
, &h
); ) {
138 if (h
.kind
== hid_collection
) {
139 cp
+= sprintf(&colls
[cp
], "%s%s:%s",
141 hid_usage_page(HID_PAGE(h
.usage
)),
142 hid_usage_in_page(h
.usage
));
143 } else if (h
.kind
== hid_endcollection
) {
144 tmp1
= strrchr(colls
, '.');
153 if ((h
.kind
!= hid_input
&& h
.kind
!= hid_output
&&
154 h
.kind
!= hid_feature
) || (h
.flags
& HIO_CONST
))
156 snprintf(hname
, sizeof(hname
), "%s%s%s:%s",
157 colls
, colls
[0] != 0 ? "." : "",
158 hid_usage_page(HID_PAGE(h
.usage
)),
159 hid_usage_in_page(h
.usage
));
160 t
= strlen(hname
) - strlen(var
->name
);
162 if (strcmp(hname
+ t
, var
->name
) != 0)
164 if (hname
[t
- 1] != '.')
166 } else if (strcmp(hname
, var
->name
) != 0)
168 if (var
->instance
!= instance
++)
174 if (var
->h
.usage
== 0)
175 errx(1, "Unknown item '%s'", var
->name
);
184 "usage: %s -f device "
185 "[-l] [-n] [-r] [-t tablefile] [-v] [-x] [-z] name ...\n",
189 "[-l] [-n] [-r] [-t tablefile] [-v] [-x] [-z] -a\n",
193 "[-t tablefile] [-v] [-z] -w name=value\n",
199 dumpitem(const char *label
, struct hid_item
*h
)
201 if ((h
->flags
& HIO_CONST
) && !verbose
)
203 printf("%s rid=%d size=%d count=%d page=%s usage=%s%s%s", label
,
204 h
->report_ID
, h
->report_size
, h
->report_count
,
205 hid_usage_page(HID_PAGE(h
->usage
)),
206 hid_usage_in_page(h
->usage
),
207 h
->flags
& HIO_CONST
? " Const" : "",
208 h
->flags
& HIO_VARIABLE
? "" : " Array");
209 printf(", logical range %d..%d",
210 h
->logical_minimum
, h
->logical_maximum
);
211 if (h
->physical_minimum
!= h
->physical_maximum
)
212 printf(", physical range %d..%d",
213 h
->physical_minimum
, h
->physical_maximum
);
215 printf(", unit=0x%02x exp=%d", h
->unit
, h
->unit_exponent
);
220 hid_collection_type(int32_t type
)
225 case 0: return ("Physical");
226 case 1: return ("Application");
227 case 2: return ("Logical");
228 case 3: return ("Report");
229 case 4: return ("Named_Array");
230 case 5: return ("Usage_Switch");
231 case 6: return ("Usage_Modifier");
233 snprintf(num
, sizeof(num
), "0x%02x", type
);
238 dumpitems(report_desc_t r
)
244 for (d
= hid_start_parse(r
, ~0, -1); hid_get_item(d
, &h
); ) {
247 printf("Collection type=%s page=%s usage=%s\n",
248 hid_collection_type(h
.collection
),
249 hid_usage_page(HID_PAGE(h
.usage
)),
250 hid_usage_in_page(h
.usage
));
252 case hid_endcollection
:
253 printf("End collection\n");
256 dumpitem("Input ", &h
);
259 dumpitem("Output ", &h
);
262 dumpitem("Feature", &h
);
267 size
= hid_report_size(r
, hid_input
, -1);
268 printf("Total input size %d bytes\n", size
);
270 size
= hid_report_size(r
, hid_output
, -1);
271 printf("Total output size %d bytes\n", size
);
273 size
= hid_report_size(r
, hid_feature
, -1);
274 printf("Total feature size %d bytes\n", size
);
278 prdata(u_char
*buf
, struct hid_item
*h
)
284 for (i
= 0; i
< h
->report_count
; i
++) {
285 data
= hid_get_data(buf
, h
);
288 if (h
->logical_minimum
< 0)
289 printf("%d", (int)data
);
293 printf(" [0x%x]", data
);
294 h
->pos
+= h
->report_size
;
300 dumpdata(int f
, report_desc_t rd
, int loop
)
302 struct variable
*var
;
303 int dlen
, havedata
, i
, match
, r
, rid
, use_rid
;
307 kind
= zflag
? 3 : 0;
309 use_rid
= !!hid_get_report_id(f
);
318 for (var
= vars
; var
; var
= var
->next
) {
319 if (rid
== var
->h
.report_ID
&&
326 dlen
= hid_report_size(rd
, kind
< 3 ? kind
: hid_input
, rid
);
330 memset(dbuf
, 0, dlen
);
333 r
= hid_get_report(f
, kind
, dbuf
, dlen
);
335 warn("hid_get_report(rid %d)", rid
);
336 havedata
= !r
&& (rid
== 0 || dbuf
[0] == rid
);
340 r
= read(f
, dbuf
, dlen
);
342 err(1, "read error");
346 printf("Got %s report %d (%d bytes):",
347 kind
== hid_output
? "output" :
348 kind
== hid_feature
? "feature" : "input",
349 use_rid
? dbuf
[0] : 0, dlen
);
351 for (i
= 0; i
< dlen
; i
++)
352 printf(" %02x", dbuf
[i
]);
357 for (var
= vars
; var
; var
= var
->next
) {
358 if ((kind
< 3 ? kind
: hid_input
) != var
->h
.kind
)
360 if (var
->h
.report_ID
!= 0 &&
361 dbuf
[0] != var
->h
.report_ID
)
365 printf("%s=", var
->name
);
367 prdata(dbuf
, &var
->h
);
373 } while (loop
|| kind
< 3);
377 writedata(int f
, report_desc_t rd
)
379 struct variable
*var
;
386 for (kind
= 0; kind
< 3; kind
++) {
387 for (rid
= 0; rid
< 256; rid
++) {
388 for (var
= vars
; var
; var
= var
->next
) {
389 if (rid
== var
->h
.report_ID
&& kind
== var
->h
.kind
)
394 dlen
= hid_report_size(rd
, kind
, rid
);
398 memset(dbuf
, 0, dlen
);
400 if (!zflag
&& hid_get_report(f
, kind
, dbuf
, dlen
) == 0) {
402 printf("Got %s report %d (%d bytes):",
403 kind
== hid_input
? "input" :
404 kind
== hid_output
? "output" : "feature",
406 for (i
= 0; i
< dlen
; i
++)
407 printf(" %02x", dbuf
[i
]);
411 warn("hid_get_report(rid %d)", rid
);
413 printf("Can't get %s report %d (%d bytes). "
414 "Will be initialized with zeros.\n",
415 kind
== hid_input
? "input" :
416 kind
== hid_output
? "output" : "feature",
420 for (var
= vars
; var
; var
= var
->next
) {
421 if (rid
!= var
->h
.report_ID
|| kind
!= var
->h
.kind
)
423 hid_set_data(dbuf
, &var
->h
, var
->val
);
426 printf("Setting %s report %d (%d bytes):",
427 kind
== hid_output
? "output" :
428 kind
== hid_feature
? "feature" : "input",
430 for (i
= 0; i
< dlen
; i
++)
431 printf(" %02x", dbuf
[i
]);
434 r
= hid_set_report(f
, kind
, dbuf
, dlen
);
436 warn("hid_set_report(rid %d)", rid
);
443 main(int argc
, char **argv
)
447 char devnam
[100], *dev
= NULL
;
454 while ((ch
= getopt(argc
, argv
, "af:lnrt:vwxz")) != -1) {
496 if (argc
== 0 && !all
&& !repdump
)
501 snprintf(devnam
, sizeof(devnam
), "/dev/uhid%s", dev
);
503 snprintf(devnam
, sizeof(devnam
), "/dev/%s", dev
);
509 f
= open(dev
, O_RDWR
);
513 r
= hid_get_report_desc(f
);
515 errx(1, "USB_GET_REPORT_DESC");
518 printf("Report descriptor:\n");
521 if (argc
!= 0 || all
) {
522 parceargs(r
, all
, argc
, argv
);
526 dumpdata(f
, r
, loop
);
529 hid_dispose_report_desc(r
);