109d308a8SNick Hibma /* $NetBSD: usbhid.c,v 1.14 2000/07/03 02:51:37 matt Exp $ */ 209d308a8SNick Hibma /* $FreeBSD$ */ 309d308a8SNick Hibma 409d308a8SNick Hibma /* 509d308a8SNick Hibma * Copyright (c) 1998 The NetBSD Foundation, Inc. 609d308a8SNick Hibma * All rights reserved. 709d308a8SNick Hibma * 809d308a8SNick Hibma * This code is derived from software contributed to The NetBSD Foundation 909d308a8SNick Hibma * by Lennart Augustsson (augustss@netbsd.org). 1009d308a8SNick Hibma * 1109d308a8SNick Hibma * Redistribution and use in source and binary forms, with or without 1209d308a8SNick Hibma * modification, are permitted provided that the following conditions 1309d308a8SNick Hibma * are met: 1409d308a8SNick Hibma * 1. Redistributions of source code must retain the above copyright 1509d308a8SNick Hibma * notice, this list of conditions and the following disclaimer. 1609d308a8SNick Hibma * 2. Redistributions in binary form must reproduce the above copyright 1709d308a8SNick Hibma * notice, this list of conditions and the following disclaimer in the 1809d308a8SNick Hibma * documentation and/or other materials provided with the distribution. 1909d308a8SNick Hibma * 2009d308a8SNick Hibma * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2109d308a8SNick Hibma * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2209d308a8SNick Hibma * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2309d308a8SNick Hibma * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2409d308a8SNick Hibma * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2509d308a8SNick Hibma * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2609d308a8SNick Hibma * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2709d308a8SNick Hibma * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2809d308a8SNick Hibma * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2909d308a8SNick Hibma * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3009d308a8SNick Hibma * POSSIBILITY OF SUCH DAMAGE. 3109d308a8SNick Hibma */ 3209d308a8SNick Hibma 3309d308a8SNick Hibma #include <stdio.h> 3409d308a8SNick Hibma #include <stdlib.h> 3509d308a8SNick Hibma #include <string.h> 3609d308a8SNick Hibma #include <sys/types.h> 3709d308a8SNick Hibma #include <fcntl.h> 3809d308a8SNick Hibma #include <unistd.h> 3909d308a8SNick Hibma #include <err.h> 4009d308a8SNick Hibma #include <ctype.h> 4109d308a8SNick Hibma #include <errno.h> 42cf0e07e5SMatthew N. Dodd #include <usbhid.h> 43bf41796cSAndrew Thompson #include <dev/usb/usbhid.h> 4409d308a8SNick Hibma 457778ab7eSAlexander Motin struct variable { 467778ab7eSAlexander Motin char *name; 477778ab7eSAlexander Motin int instance; 487778ab7eSAlexander Motin int val; 497778ab7eSAlexander Motin struct hid_item h; 507778ab7eSAlexander Motin struct variable *next; 517778ab7eSAlexander Motin } *vars; 527778ab7eSAlexander Motin 5309d308a8SNick Hibma int verbose = 0; 5409d308a8SNick Hibma int noname = 0; 559a2a66f1SGreg Lehey int hexdump = 0; 567778ab7eSAlexander Motin int wflag = 0; 577778ab7eSAlexander Motin int zflag = 0; 5809d308a8SNick Hibma 597778ab7eSAlexander Motin static void usage(void); 607778ab7eSAlexander Motin static void dumpitem(const char *label, struct hid_item *h); 617778ab7eSAlexander Motin static void dumpitems(report_desc_t r); 627778ab7eSAlexander Motin static void prdata(u_char *buf, struct hid_item *h); 637778ab7eSAlexander Motin static void dumpdata(int f, report_desc_t r, int loop); 647778ab7eSAlexander Motin static void writedata(int f, report_desc_t r); 6509d308a8SNick Hibma 667778ab7eSAlexander Motin static void 677778ab7eSAlexander Motin parceargs(report_desc_t r, int all, int nnames, char **names) 6809d308a8SNick Hibma { 697778ab7eSAlexander Motin struct hid_data *d; 707778ab7eSAlexander Motin struct hid_item h; 717778ab7eSAlexander Motin char colls[1000]; 727778ab7eSAlexander Motin char hname[1000], *tmp1, *tmp2; 737778ab7eSAlexander Motin struct variable *var, **pnext; 747778ab7eSAlexander Motin int i, instance, cp, t; 7509d308a8SNick Hibma 767778ab7eSAlexander Motin pnext = &vars; 777778ab7eSAlexander Motin if (all) { 787778ab7eSAlexander Motin if (wflag) 797778ab7eSAlexander Motin errx(1, "Must not specify -w to read variables"); 807778ab7eSAlexander Motin cp = 0; 817778ab7eSAlexander Motin for (d = hid_start_parse(r, 827778ab7eSAlexander Motin 1<<hid_input | 1<<hid_output | 1<<hid_feature, -1); 837778ab7eSAlexander Motin hid_get_item(d, &h); ) { 847778ab7eSAlexander Motin if (h.kind == hid_collection) { 857778ab7eSAlexander Motin cp += sprintf(&colls[cp], "%s%s:%s", 867778ab7eSAlexander Motin cp != 0 ? "." : "", 877778ab7eSAlexander Motin hid_usage_page(HID_PAGE(h.usage)), 887778ab7eSAlexander Motin hid_usage_in_page(h.usage)); 897778ab7eSAlexander Motin } else if (h.kind == hid_endcollection) { 907778ab7eSAlexander Motin tmp1 = strrchr(colls, '.'); 917778ab7eSAlexander Motin if (tmp1 != NULL) { 927778ab7eSAlexander Motin cp -= strlen(tmp1); 937778ab7eSAlexander Motin tmp1[0] = 0; 947778ab7eSAlexander Motin } else { 957778ab7eSAlexander Motin cp = 0; 967778ab7eSAlexander Motin colls[0] = 0; 977778ab7eSAlexander Motin } 987778ab7eSAlexander Motin } 997778ab7eSAlexander Motin if ((h.kind != hid_input && h.kind != hid_output && 1007778ab7eSAlexander Motin h.kind != hid_feature) || (h.flags & HIO_CONST)) 1017778ab7eSAlexander Motin continue; 1027778ab7eSAlexander Motin var = malloc(sizeof(*var)); 1037778ab7eSAlexander Motin memset(var, 0, sizeof(*var)); 1047778ab7eSAlexander Motin asprintf(&var->name, "%s%s%s:%s", 1057778ab7eSAlexander Motin colls, colls[0] != 0 ? "." : "", 1067778ab7eSAlexander Motin hid_usage_page(HID_PAGE(h.usage)), 1077778ab7eSAlexander Motin hid_usage_in_page(h.usage)); 1087778ab7eSAlexander Motin var->h = h; 1097778ab7eSAlexander Motin *pnext = var; 1107778ab7eSAlexander Motin pnext = &var->next; 1117778ab7eSAlexander Motin } 1127778ab7eSAlexander Motin hid_end_parse(d); 1137778ab7eSAlexander Motin return; 1147778ab7eSAlexander Motin } 1157778ab7eSAlexander Motin for (i = 0; i < nnames; i++) { 1167778ab7eSAlexander Motin var = malloc(sizeof(*var)); 1177778ab7eSAlexander Motin memset(var, 0, sizeof(*var)); 1187778ab7eSAlexander Motin tmp1 = tmp2 = strdup(names[i]); 1197778ab7eSAlexander Motin strsep(&tmp2, "="); 1207778ab7eSAlexander Motin var->name = strsep(&tmp1, "#"); 1217778ab7eSAlexander Motin if (tmp1 != NULL) 1227778ab7eSAlexander Motin var->instance = atoi(tmp1); 1237778ab7eSAlexander Motin if (tmp2 != NULL) { 1247778ab7eSAlexander Motin if (!wflag) 1257778ab7eSAlexander Motin errx(1, "Must specify -w to write variables"); 1267778ab7eSAlexander Motin var->val = atoi(tmp2); 1277778ab7eSAlexander Motin } else 1287778ab7eSAlexander Motin if (wflag) 1297778ab7eSAlexander Motin errx(1, "Must not specify -w to read variables"); 1307778ab7eSAlexander Motin *pnext = var; 1317778ab7eSAlexander Motin pnext = &var->next; 1327778ab7eSAlexander Motin 1337778ab7eSAlexander Motin instance = 0; 1347778ab7eSAlexander Motin cp = 0; 1357778ab7eSAlexander Motin for (d = hid_start_parse(r, 1367778ab7eSAlexander Motin 1<<hid_input | 1<<hid_output | 1<<hid_feature, -1); 1377778ab7eSAlexander Motin hid_get_item(d, &h); ) { 1387778ab7eSAlexander Motin if (h.kind == hid_collection) { 1397778ab7eSAlexander Motin cp += sprintf(&colls[cp], "%s%s:%s", 1407778ab7eSAlexander Motin cp != 0 ? "." : "", 1417778ab7eSAlexander Motin hid_usage_page(HID_PAGE(h.usage)), 1427778ab7eSAlexander Motin hid_usage_in_page(h.usage)); 1437778ab7eSAlexander Motin } else if (h.kind == hid_endcollection) { 1447778ab7eSAlexander Motin tmp1 = strrchr(colls, '.'); 1457778ab7eSAlexander Motin if (tmp1 != NULL) { 1467778ab7eSAlexander Motin cp -= strlen(tmp1); 1477778ab7eSAlexander Motin tmp1[0] = 0; 1487778ab7eSAlexander Motin } else { 1497778ab7eSAlexander Motin cp = 0; 1507778ab7eSAlexander Motin colls[0] = 0; 1517778ab7eSAlexander Motin } 1527778ab7eSAlexander Motin } 1537778ab7eSAlexander Motin if ((h.kind != hid_input && h.kind != hid_output && 1547778ab7eSAlexander Motin h.kind != hid_feature) || (h.flags & HIO_CONST)) 1557778ab7eSAlexander Motin continue; 1567778ab7eSAlexander Motin snprintf(hname, sizeof(hname), "%s%s%s:%s", 1577778ab7eSAlexander Motin colls, colls[0] != 0 ? "." : "", 1587778ab7eSAlexander Motin hid_usage_page(HID_PAGE(h.usage)), 1597778ab7eSAlexander Motin hid_usage_in_page(h.usage)); 1607778ab7eSAlexander Motin t = strlen(hname) - strlen(var->name); 1617778ab7eSAlexander Motin if (t > 0) { 1627778ab7eSAlexander Motin if (strcmp(hname + t, var->name) != 0) 1637778ab7eSAlexander Motin continue; 1647778ab7eSAlexander Motin if (hname[t - 1] != '.') 1657778ab7eSAlexander Motin continue; 1667778ab7eSAlexander Motin } else if (strcmp(hname, var->name) != 0) 1677778ab7eSAlexander Motin continue; 1687778ab7eSAlexander Motin if (var->instance != instance++) 1697778ab7eSAlexander Motin continue; 1707778ab7eSAlexander Motin var->h = h; 1717778ab7eSAlexander Motin break; 1727778ab7eSAlexander Motin } 1737778ab7eSAlexander Motin hid_end_parse(d); 1747778ab7eSAlexander Motin if (var->h.usage == 0) 1757778ab7eSAlexander Motin errx(1, "Unknown item '%s'", var->name); 1767778ab7eSAlexander Motin } 17709d308a8SNick Hibma } 17809d308a8SNick Hibma 1797778ab7eSAlexander Motin static void 18009d308a8SNick Hibma usage(void) 18109d308a8SNick Hibma { 18209d308a8SNick Hibma 1839a2a66f1SGreg Lehey fprintf(stderr, 1849a2a66f1SGreg Lehey "usage: %s -f device " 185eb29cfddSGreg Lehey "[-l] [-n] [-r] [-t tablefile] [-v] [-x] name ...\n", 1861946089bSXin LI getprogname()); 1879a2a66f1SGreg Lehey fprintf(stderr, 1889a2a66f1SGreg Lehey " %s -f device " 189eb29cfddSGreg Lehey "[-l] [-n] [-r] [-t tablefile] [-v] [-x] -a\n", 1901946089bSXin LI getprogname()); 1917778ab7eSAlexander Motin fprintf(stderr, 1927778ab7eSAlexander Motin " %s -f device " 1937778ab7eSAlexander Motin "[-t tablefile] [-v] [-z] -w name=value\n", 1947778ab7eSAlexander Motin getprogname()); 19509d308a8SNick Hibma exit(1); 19609d308a8SNick Hibma } 19709d308a8SNick Hibma 1987778ab7eSAlexander Motin static void 1991a27f4f2SMark Murray dumpitem(const char *label, struct hid_item *h) 20009d308a8SNick Hibma { 20109d308a8SNick Hibma if ((h->flags & HIO_CONST) && !verbose) 20209d308a8SNick Hibma return; 2031bee2ec7SAlexander Motin printf("%s rid=%d size=%d count=%d page=%s usage=%s%s%s", label, 2041bee2ec7SAlexander Motin h->report_ID, h->report_size, h->report_count, 20509d308a8SNick Hibma hid_usage_page(HID_PAGE(h->usage)), 20609d308a8SNick Hibma hid_usage_in_page(h->usage), 2071bee2ec7SAlexander Motin h->flags & HIO_CONST ? " Const" : "", 2081bee2ec7SAlexander Motin h->flags & HIO_VARIABLE ? "" : " Array"); 20909d308a8SNick Hibma printf(", logical range %d..%d", 21009d308a8SNick Hibma h->logical_minimum, h->logical_maximum); 21109d308a8SNick Hibma if (h->physical_minimum != h->physical_maximum) 21209d308a8SNick Hibma printf(", physical range %d..%d", 21309d308a8SNick Hibma h->physical_minimum, h->physical_maximum); 21409d308a8SNick Hibma if (h->unit) 21509d308a8SNick Hibma printf(", unit=0x%02x exp=%d", h->unit, h->unit_exponent); 21609d308a8SNick Hibma printf("\n"); 21709d308a8SNick Hibma } 21809d308a8SNick Hibma 2191bee2ec7SAlexander Motin static const char * 2201bee2ec7SAlexander Motin hid_collection_type(int32_t type) 2211bee2ec7SAlexander Motin { 2221bee2ec7SAlexander Motin static char num[8]; 2231bee2ec7SAlexander Motin 2241bee2ec7SAlexander Motin switch (type) { 2251bee2ec7SAlexander Motin case 0: return ("Physical"); 2261bee2ec7SAlexander Motin case 1: return ("Application"); 2271bee2ec7SAlexander Motin case 2: return ("Logical"); 2281bee2ec7SAlexander Motin case 3: return ("Report"); 2291bee2ec7SAlexander Motin case 4: return ("Named_Array"); 2301bee2ec7SAlexander Motin case 5: return ("Usage_Switch"); 2311bee2ec7SAlexander Motin case 6: return ("Usage_Modifier"); 2321bee2ec7SAlexander Motin } 2331bee2ec7SAlexander Motin snprintf(num, sizeof(num), "0x%02x", type); 2341bee2ec7SAlexander Motin return (num); 2351bee2ec7SAlexander Motin } 2361bee2ec7SAlexander Motin 2377778ab7eSAlexander Motin static void 23809d308a8SNick Hibma dumpitems(report_desc_t r) 23909d308a8SNick Hibma { 24009d308a8SNick Hibma struct hid_data *d; 24109d308a8SNick Hibma struct hid_item h; 2421d10fe50SNick Hibma int size; 24309d308a8SNick Hibma 2441bee2ec7SAlexander Motin for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) { 24509d308a8SNick Hibma switch (h.kind) { 24609d308a8SNick Hibma case hid_collection: 2471bee2ec7SAlexander Motin printf("Collection type=%s page=%s usage=%s\n", 2481bee2ec7SAlexander Motin hid_collection_type(h.collection), 24909d308a8SNick Hibma hid_usage_page(HID_PAGE(h.usage)), 25009d308a8SNick Hibma hid_usage_in_page(h.usage)); 25109d308a8SNick Hibma break; 25209d308a8SNick Hibma case hid_endcollection: 25309d308a8SNick Hibma printf("End collection\n"); 25409d308a8SNick Hibma break; 25509d308a8SNick Hibma case hid_input: 25609d308a8SNick Hibma dumpitem("Input ", &h); 25709d308a8SNick Hibma break; 25809d308a8SNick Hibma case hid_output: 25909d308a8SNick Hibma dumpitem("Output ", &h); 26009d308a8SNick Hibma break; 26109d308a8SNick Hibma case hid_feature: 26209d308a8SNick Hibma dumpitem("Feature", &h); 26309d308a8SNick Hibma break; 26409d308a8SNick Hibma } 26509d308a8SNick Hibma } 26609d308a8SNick Hibma hid_end_parse(d); 2671bee2ec7SAlexander Motin size = hid_report_size(r, hid_input, -1); 2681a2cdef4SNick Hibma printf("Total input size %d bytes\n", size); 26909d308a8SNick Hibma 2701bee2ec7SAlexander Motin size = hid_report_size(r, hid_output, -1); 2711d10fe50SNick Hibma printf("Total output size %d bytes\n", size); 27209d308a8SNick Hibma 2731bee2ec7SAlexander Motin size = hid_report_size(r, hid_feature, -1); 2741d10fe50SNick Hibma printf("Total feature size %d bytes\n", size); 27509d308a8SNick Hibma } 27609d308a8SNick Hibma 2777778ab7eSAlexander Motin static void 27809d308a8SNick Hibma prdata(u_char *buf, struct hid_item *h) 27909d308a8SNick Hibma { 28009d308a8SNick Hibma u_int data; 28109d308a8SNick Hibma int i, pos; 28209d308a8SNick Hibma 28309d308a8SNick Hibma pos = h->pos; 28409d308a8SNick Hibma for (i = 0; i < h->report_count; i++) { 28509d308a8SNick Hibma data = hid_get_data(buf, h); 2861bee2ec7SAlexander Motin if (i > 0) 2871bee2ec7SAlexander Motin printf(" "); 28809d308a8SNick Hibma if (h->logical_minimum < 0) 28909d308a8SNick Hibma printf("%d", (int)data); 29009d308a8SNick Hibma else 29109d308a8SNick Hibma printf("%u", data); 2929a2a66f1SGreg Lehey if (hexdump) 2939a2a66f1SGreg Lehey printf(" [0x%x]", data); 2941bee2ec7SAlexander Motin h->pos += h->report_size; 29509d308a8SNick Hibma } 2961bee2ec7SAlexander Motin h->pos = pos; 29709d308a8SNick Hibma } 29809d308a8SNick Hibma 2997778ab7eSAlexander Motin static void 30009d308a8SNick Hibma dumpdata(int f, report_desc_t rd, int loop) 30109d308a8SNick Hibma { 3027778ab7eSAlexander Motin struct variable *var; 3037778ab7eSAlexander Motin int dlen, havedata, i, match, r, rid, use_rid; 30409d308a8SNick Hibma u_char *dbuf; 3057778ab7eSAlexander Motin enum hid_kind kind; 30609d308a8SNick Hibma 3077778ab7eSAlexander Motin kind = 0; 3087778ab7eSAlexander Motin rid = -1; 3097778ab7eSAlexander Motin use_rid = !!hid_get_report_id(f); 31009d308a8SNick Hibma do { 3117778ab7eSAlexander Motin if (kind < 3) { 3127778ab7eSAlexander Motin if (++rid >= 256) { 3137778ab7eSAlexander Motin rid = 0; 3147778ab7eSAlexander Motin kind++; 31509d308a8SNick Hibma } 3167778ab7eSAlexander Motin if (kind >= 3) 3177778ab7eSAlexander Motin rid = -1; 3187778ab7eSAlexander Motin for (var = vars; var; var = var->next) { 3197778ab7eSAlexander Motin if (rid == var->h.report_ID && 3207778ab7eSAlexander Motin kind == var->h.kind) 3217778ab7eSAlexander Motin break; 3227778ab7eSAlexander Motin } 3237778ab7eSAlexander Motin if (var == NULL) 3241bee2ec7SAlexander Motin continue; 3257778ab7eSAlexander Motin } 3267778ab7eSAlexander Motin dlen = hid_report_size(rd, kind < 3 ? kind : hid_input, rid); 3277778ab7eSAlexander Motin if (dlen <= 0) 3287778ab7eSAlexander Motin continue; 3297778ab7eSAlexander Motin dbuf = malloc(dlen); 3307778ab7eSAlexander Motin memset(dbuf, 0, dlen); 3317778ab7eSAlexander Motin if (kind < 3) { 3327778ab7eSAlexander Motin dbuf[0] = rid; 3337778ab7eSAlexander Motin r = hid_get_report(f, kind, dbuf, dlen); 3347778ab7eSAlexander Motin if (r < 0) 3357778ab7eSAlexander Motin warn("hid_get_report(rid %d)", rid); 3367778ab7eSAlexander Motin havedata = !r && (rid == 0 || dbuf[0] == rid); 3377778ab7eSAlexander Motin if (rid != 0) 3387778ab7eSAlexander Motin dbuf[0] = rid; 3397778ab7eSAlexander Motin } else { 3407778ab7eSAlexander Motin r = read(f, dbuf, dlen); 3417778ab7eSAlexander Motin if (r < 1) 3427778ab7eSAlexander Motin err(1, "read error"); 3437778ab7eSAlexander Motin havedata = 1; 3447778ab7eSAlexander Motin } 3457778ab7eSAlexander Motin if (verbose) { 3467778ab7eSAlexander Motin printf("Got %s report %d (%d bytes):", 3477778ab7eSAlexander Motin kind == hid_output ? "output" : 3487778ab7eSAlexander Motin kind == hid_feature ? "feature" : "input", 3497778ab7eSAlexander Motin use_rid ? dbuf[0] : 0, dlen); 3507778ab7eSAlexander Motin if (havedata) { 3517778ab7eSAlexander Motin for (i = 0; i < dlen; i++) 3527778ab7eSAlexander Motin printf(" %02x", dbuf[i]); 3537778ab7eSAlexander Motin } 3547778ab7eSAlexander Motin printf("\n"); 3557778ab7eSAlexander Motin } 3567778ab7eSAlexander Motin match = 0; 3577778ab7eSAlexander Motin for (var = vars; var; var = var->next) { 3587778ab7eSAlexander Motin if ((kind < 3 ? kind : hid_input) != var->h.kind) 3597778ab7eSAlexander Motin continue; 3607778ab7eSAlexander Motin if (var->h.report_ID != 0 && 3617778ab7eSAlexander Motin dbuf[0] != var->h.report_ID) 3627778ab7eSAlexander Motin continue; 3637778ab7eSAlexander Motin match = 1; 36409d308a8SNick Hibma if (!noname) 3657778ab7eSAlexander Motin printf("%s=", var->name); 3667778ab7eSAlexander Motin if (havedata) 3677778ab7eSAlexander Motin prdata(dbuf, &var->h); 36809d308a8SNick Hibma printf("\n"); 36909d308a8SNick Hibma } 3707778ab7eSAlexander Motin if (match) 37109d308a8SNick Hibma printf("\n"); 37209d308a8SNick Hibma free(dbuf); 3737778ab7eSAlexander Motin } while (loop || kind < 3); 3747778ab7eSAlexander Motin } 3757778ab7eSAlexander Motin 3767778ab7eSAlexander Motin static void 3777778ab7eSAlexander Motin writedata(int f, report_desc_t rd) 3787778ab7eSAlexander Motin { 3797778ab7eSAlexander Motin struct variable *var; 3807778ab7eSAlexander Motin int dlen, i, r, rid; 3817778ab7eSAlexander Motin u_char *dbuf; 3827778ab7eSAlexander Motin enum hid_kind kind; 3837778ab7eSAlexander Motin 3847778ab7eSAlexander Motin kind = 0; 3857778ab7eSAlexander Motin rid = 0; 3867778ab7eSAlexander Motin for (kind = 0; kind < 3; kind ++) { 3877778ab7eSAlexander Motin for (rid = 0; rid < 256; rid ++) { 3887778ab7eSAlexander Motin for (var = vars; var; var = var->next) { 3897778ab7eSAlexander Motin if (rid == var->h.report_ID && kind == var->h.kind) 3907778ab7eSAlexander Motin break; 3917778ab7eSAlexander Motin } 3927778ab7eSAlexander Motin if (var == NULL) 3937778ab7eSAlexander Motin continue; 3947778ab7eSAlexander Motin dlen = hid_report_size(rd, kind, rid); 3957778ab7eSAlexander Motin if (dlen <= 0) 3967778ab7eSAlexander Motin continue; 3977778ab7eSAlexander Motin dbuf = malloc(dlen); 3987778ab7eSAlexander Motin memset(dbuf, 0, dlen); 3997778ab7eSAlexander Motin dbuf[0] = rid; 4007778ab7eSAlexander Motin if (!zflag && hid_get_report(f, kind, dbuf, dlen) == 0) { 4017778ab7eSAlexander Motin if (verbose) { 4027778ab7eSAlexander Motin printf("Got %s report %d (%d bytes):", 4037778ab7eSAlexander Motin kind == hid_input ? "input" : 4047778ab7eSAlexander Motin kind == hid_output ? "output" : "feature", 4057778ab7eSAlexander Motin rid, dlen); 4067778ab7eSAlexander Motin for (i = 0; i < dlen; i++) 4077778ab7eSAlexander Motin printf(" %02x", dbuf[i]); 4087778ab7eSAlexander Motin printf("\n"); 4097778ab7eSAlexander Motin } 4107778ab7eSAlexander Motin } else if (!zflag) { 4117778ab7eSAlexander Motin warn("hid_get_report(rid %d)", rid); 4127778ab7eSAlexander Motin if (verbose) { 4137778ab7eSAlexander Motin printf("Can't get %s report %d (%d bytes). " 4147778ab7eSAlexander Motin "Will be initialized with zeros.\n", 4157778ab7eSAlexander Motin kind == hid_input ? "input" : 4167778ab7eSAlexander Motin kind == hid_output ? "output" : "feature", 4177778ab7eSAlexander Motin rid, dlen); 4187778ab7eSAlexander Motin } 4197778ab7eSAlexander Motin } 4207778ab7eSAlexander Motin for (var = vars; var; var = var->next) { 4217778ab7eSAlexander Motin if (rid != var->h.report_ID || kind != var->h.kind) 4227778ab7eSAlexander Motin continue; 4237778ab7eSAlexander Motin hid_set_data(dbuf, &var->h, var->val); 4247778ab7eSAlexander Motin } 4257778ab7eSAlexander Motin if (verbose) { 4267778ab7eSAlexander Motin printf("Setting %s report %d (%d bytes):", 4277778ab7eSAlexander Motin kind == hid_output ? "output" : 4287778ab7eSAlexander Motin kind == hid_feature ? "feature" : "input", 4297778ab7eSAlexander Motin rid, dlen); 4307778ab7eSAlexander Motin for (i = 0; i < dlen; i++) 4317778ab7eSAlexander Motin printf(" %02x", dbuf[i]); 4327778ab7eSAlexander Motin printf("\n"); 4337778ab7eSAlexander Motin } 4347778ab7eSAlexander Motin r = hid_set_report(f, kind, dbuf, dlen); 4357778ab7eSAlexander Motin if (r != 0) 4367778ab7eSAlexander Motin warn("hid_set_report(rid %d)", rid); 4377778ab7eSAlexander Motin free(dbuf); 4387778ab7eSAlexander Motin } 4397778ab7eSAlexander Motin } 44009d308a8SNick Hibma } 44109d308a8SNick Hibma 44209d308a8SNick Hibma int 44309d308a8SNick Hibma main(int argc, char **argv) 44409d308a8SNick Hibma { 44509d308a8SNick Hibma report_desc_t r; 4467778ab7eSAlexander Motin char *table = 0; 4477778ab7eSAlexander Motin char devnam[100], *dev = NULL; 4487778ab7eSAlexander Motin int f; 4497778ab7eSAlexander Motin int all = 0; 45009d308a8SNick Hibma int ch; 45109d308a8SNick Hibma int repdump = 0; 45209d308a8SNick Hibma int loop = 0; 45309d308a8SNick Hibma 4547778ab7eSAlexander Motin while ((ch = getopt(argc, argv, "af:lnrt:vwxz")) != -1) { 45509d308a8SNick Hibma switch(ch) { 45609d308a8SNick Hibma case 'a': 45709d308a8SNick Hibma all++; 45809d308a8SNick Hibma break; 45909d308a8SNick Hibma case 'f': 46009d308a8SNick Hibma dev = optarg; 46109d308a8SNick Hibma break; 46209d308a8SNick Hibma case 'l': 46309d308a8SNick Hibma loop ^= 1; 46409d308a8SNick Hibma break; 46509d308a8SNick Hibma case 'n': 46609d308a8SNick Hibma noname++; 46709d308a8SNick Hibma break; 46809d308a8SNick Hibma case 'r': 46909d308a8SNick Hibma repdump++; 47009d308a8SNick Hibma break; 47109d308a8SNick Hibma case 't': 47209d308a8SNick Hibma table = optarg; 47309d308a8SNick Hibma break; 47409d308a8SNick Hibma case 'v': 47509d308a8SNick Hibma verbose++; 47609d308a8SNick Hibma break; 4777778ab7eSAlexander Motin case 'w': 4787778ab7eSAlexander Motin wflag = 1; 4797778ab7eSAlexander Motin break; 4809a2a66f1SGreg Lehey case 'x': 481eb29cfddSGreg Lehey hexdump = 1; 4829a2a66f1SGreg Lehey break; 4837778ab7eSAlexander Motin case 'z': 4847778ab7eSAlexander Motin zflag = 1; 4857778ab7eSAlexander Motin break; 48609d308a8SNick Hibma case '?': 48709d308a8SNick Hibma default: 48809d308a8SNick Hibma usage(); 48909d308a8SNick Hibma } 49009d308a8SNick Hibma } 49109d308a8SNick Hibma argc -= optind; 49209d308a8SNick Hibma argv += optind; 4937778ab7eSAlexander Motin if (dev == NULL) 49409d308a8SNick Hibma usage(); 49509d308a8SNick Hibma 4967778ab7eSAlexander Motin if (argc == 0 && !all && !repdump) 49709d308a8SNick Hibma usage(); 49809d308a8SNick Hibma 49909d308a8SNick Hibma if (dev[0] != '/') { 50009d308a8SNick Hibma if (isdigit(dev[0])) 5011a27f4f2SMark Murray snprintf(devnam, sizeof(devnam), "/dev/uhid%s", dev); 50209d308a8SNick Hibma else 5031a27f4f2SMark Murray snprintf(devnam, sizeof(devnam), "/dev/%s", dev); 5041a27f4f2SMark Murray dev = devnam; 50509d308a8SNick Hibma } 50609d308a8SNick Hibma 50709d308a8SNick Hibma hid_init(table); 50809d308a8SNick Hibma 50909d308a8SNick Hibma f = open(dev, O_RDWR); 51009d308a8SNick Hibma if (f < 0) 51109d308a8SNick Hibma err(1, "%s", dev); 51209d308a8SNick Hibma 51309d308a8SNick Hibma r = hid_get_report_desc(f); 51409d308a8SNick Hibma if (r == 0) 51509d308a8SNick Hibma errx(1, "USB_GET_REPORT_DESC"); 51609d308a8SNick Hibma 51709d308a8SNick Hibma if (repdump) { 51809d308a8SNick Hibma printf("Report descriptor:\n"); 51909d308a8SNick Hibma dumpitems(r); 52009d308a8SNick Hibma } 5217778ab7eSAlexander Motin if (argc != 0 || all) { 5227778ab7eSAlexander Motin parceargs(r, all, argc, argv); 5237778ab7eSAlexander Motin if (wflag) 5247778ab7eSAlexander Motin writedata(f, r); 5257778ab7eSAlexander Motin else 52609d308a8SNick Hibma dumpdata(f, r, loop); 5277778ab7eSAlexander Motin } 52809d308a8SNick Hibma 52909d308a8SNick Hibma hid_dispose_report_desc(r); 53009d308a8SNick Hibma exit(0); 53109d308a8SNick Hibma } 532