From owner-svn-src-all@FreeBSD.ORG Sat Jul 30 13:22:44 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 786EA106566B; Sat, 30 Jul 2011 13:22:44 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 661798FC0A; Sat, 30 Jul 2011 13:22:44 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p6UDMioF001446; Sat, 30 Jul 2011 13:22:44 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p6UDMicQ001442; Sat, 30 Jul 2011 13:22:44 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201107301322.p6UDMicQ001442@svn.freebsd.org> From: Alexander Motin Date: Sat, 30 Jul 2011 13:22:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r224511 - in head: lib/libusbhid usr.bin/usbhidaction usr.bin/usbhidctl X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 Jul 2011 13:22:44 -0000 Author: mav Date: Sat Jul 30 13:22:44 2011 New Revision: 224511 URL: http://svn.freebsd.org/changeset/base/224511 Log: MFprojects/hid: - Fix usbhidctl and usbhidaction to handle HID devices with multiple report ids, such as multimedia keyboards. - Add collection type and report id to the `usbhidctl -r` output. They are important for proper device understanding and debugging. - Fix usbhidaction tool to properly handle items having report_count more then 1. Approved by: re (kib) MFC after: 2 weeks Modified: head/lib/libusbhid/parse.c head/usr.bin/usbhidaction/usbhidaction.c head/usr.bin/usbhidctl/usbhid.c Modified: head/lib/libusbhid/parse.c ============================================================================== --- head/lib/libusbhid/parse.c Sat Jul 30 13:21:33 2011 (r224510) +++ head/lib/libusbhid/parse.c Sat Jul 30 13:22:44 2011 (r224511) @@ -322,6 +322,8 @@ hid_get_item(hid_data_t s, hid_item_t *h * one and one item: */ c->report_count = 1; + c->usage_minimum = 0; + c->usage_maximum = 0; } else { s->ncount = 1; } @@ -512,13 +514,14 @@ hid_report_size(report_desc_t r, enum hi uint32_t temp; uint32_t hpos; uint32_t lpos; + int report_id = 0; hpos = 0; lpos = 0xFFFFFFFF; memset(&h, 0, sizeof h); for (d = hid_start_parse(r, 1 << k, id); hid_get_item(d, &h); ) { - if (h.report_ID == id && h.kind == k) { + if ((h.report_ID == id || id < 0) && h.kind == k) { /* compute minimum */ if (lpos > h.pos) lpos = h.pos; @@ -527,6 +530,8 @@ hid_report_size(report_desc_t r, enum hi /* compute maximum */ if (hpos < temp) hpos = temp; + if (h.report_ID != 0) + report_id = 1; } } hid_end_parse(d); @@ -537,11 +542,8 @@ hid_report_size(report_desc_t r, enum hi else temp = hpos - lpos; - if (id) - temp += 8; - /* return length in bytes rounded up */ - return ((temp + 7) / 8); + return ((temp + 7) / 8 + report_id); } int Modified: head/usr.bin/usbhidaction/usbhidaction.c ============================================================================== --- head/usr.bin/usbhidaction/usbhidaction.c Sat Jul 30 13:21:33 2011 (r224510) +++ head/usr.bin/usbhidaction/usbhidaction.c Sat Jul 30 13:22:44 2011 (r224511) @@ -92,12 +92,12 @@ main(int argc, char **argv) char buf[100]; char devnamebuf[PATH_MAX]; struct command *cmd; - int reportid; + int reportid = -1; demon = 1; ignore = 0; dieearly = 0; - while ((ch = getopt(argc, argv, "c:def:ip:t:v")) != -1) { + while ((ch = getopt(argc, argv, "c:def:ip:r:t:v")) != -1) { switch(ch) { case 'c': conf = optarg; @@ -117,6 +117,9 @@ main(int argc, char **argv) case 'p': pidfile = optarg; break; + case 'r': + reportid = atoi(optarg); + break; case 't': table = optarg; break; @@ -146,14 +149,13 @@ main(int argc, char **argv) fd = open(dev, O_RDWR); if (fd < 0) err(1, "%s", dev); - reportid = hid_get_report_id(fd); repd = hid_get_report_desc(fd); if (repd == NULL) err(1, "hid_get_report_desc() failed"); commands = parse_conf(conf, repd, reportid, ignore); - sz = (size_t)hid_report_size(repd, hid_input, reportid); + sz = (size_t)hid_report_size(repd, hid_input, -1); if (verbose) printf("report size %zu\n", sz); @@ -198,7 +200,23 @@ main(int argc, char **argv) } #endif for (cmd = commands; cmd; cmd = cmd->next) { - val = hid_get_data(buf, &cmd->item); + if (cmd->item.report_ID != 0 && + buf[0] != cmd->item.report_ID) + continue; + if (cmd->item.flags & HIO_VARIABLE) + val = hid_get_data(buf, &cmd->item); + else { + uint32_t pos = cmd->item.pos; + for (i = 0; i < cmd->item.report_count; i++) { + val = hid_get_data(buf, &cmd->item); + if (val == cmd->value) + break; + cmd->item.pos += cmd->item.report_size; + } + cmd->item.pos = pos; + val = (i < cmd->item.report_count) ? + cmd->value : -1; + } if (cmd->value != val && cmd->anyvalue == 0) goto next; if ((cmd->debounce == 0) || Modified: head/usr.bin/usbhidctl/usbhid.c ============================================================================== --- head/usr.bin/usbhidctl/usbhid.c Sat Jul 30 13:21:33 2011 (r224510) +++ head/usr.bin/usbhidctl/usbhid.c Sat Jul 30 13:22:44 2011 (r224511) @@ -46,7 +46,6 @@ int verbose = 0; int all = 0; int noname = 0; int hexdump = 0; -static int reportid; char **names; int nnames; @@ -101,11 +100,12 @@ dumpitem(const char *label, struct hid_i { if ((h->flags & HIO_CONST) && !verbose) return; - printf("%s size=%d count=%d page=%s usage=%s%s", label, - h->report_size, h->report_count, + printf("%s rid=%d size=%d count=%d page=%s usage=%s%s%s", label, + h->report_ID, h->report_size, h->report_count, hid_usage_page(HID_PAGE(h->usage)), hid_usage_in_page(h->usage), - h->flags & HIO_CONST ? " Const" : ""); + h->flags & HIO_CONST ? " Const" : "", + h->flags & HIO_VARIABLE ? "" : " Array"); printf(", logical range %d..%d", h->logical_minimum, h->logical_maximum); if (h->physical_minimum != h->physical_maximum) @@ -116,6 +116,24 @@ dumpitem(const char *label, struct hid_i printf("\n"); } +static const char * +hid_collection_type(int32_t type) +{ + static char num[8]; + + switch (type) { + case 0: return ("Physical"); + case 1: return ("Application"); + case 2: return ("Logical"); + case 3: return ("Report"); + case 4: return ("Named_Array"); + case 5: return ("Usage_Switch"); + case 6: return ("Usage_Modifier"); + } + snprintf(num, sizeof(num), "0x%02x", type); + return (num); +} + void dumpitems(report_desc_t r) { @@ -123,10 +141,11 @@ dumpitems(report_desc_t r) struct hid_item h; int size; - for (d = hid_start_parse(r, ~0, reportid); hid_get_item(d, &h); ) { + for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) { switch (h.kind) { case hid_collection: - printf("Collection page=%s usage=%s\n", + printf("Collection type=%s page=%s usage=%s\n", + hid_collection_type(h.collection), hid_usage_page(HID_PAGE(h.usage)), hid_usage_in_page(h.usage)); break; @@ -145,13 +164,13 @@ dumpitems(report_desc_t r) } } hid_end_parse(d); - size = hid_report_size(r, hid_input, 0); + size = hid_report_size(r, hid_input, -1); printf("Total input size %d bytes\n", size); - size = hid_report_size(r, hid_output, 0); + size = hid_report_size(r, hid_output, -1); printf("Total output size %d bytes\n", size); - size = hid_report_size(r, hid_feature, 0); + size = hid_report_size(r, hid_feature, -1); printf("Total feature size %d bytes\n", size); } @@ -180,14 +199,17 @@ prdata(u_char *buf, struct hid_item *h) pos = h->pos; for (i = 0; i < h->report_count; i++) { data = hid_get_data(buf, h); + if (i > 0) + printf(" "); if (h->logical_minimum < 0) printf("%d", (int)data); else printf("%u", data); if (hexdump) printf(" [0x%x]", data); - pos += h->report_size; + h->pos += h->report_size; } + h->pos = pos; } void @@ -202,7 +224,7 @@ dumpdata(int f, report_desc_t rd, int lo char namebuf[10000], *namep; hids = 0; - for (d = hid_start_parse(rd, 1<next) { + if (n->report_ID != 0 && dbuf[0] != n->report_ID) + continue; namep = namebuf; namep += sprintf(namep, "%s:%s.", hid_usage_page(HID_PAGE(n->collection)), @@ -242,7 +266,7 @@ dumpdata(int f, report_desc_t rd, int lo if (all || gotname(namebuf)) { if (!noname) printf("%s=", namebuf); - prdata(dbuf + (reportid != 0), n); + prdata(dbuf, n); printf("\n"); } }