Date: Wed, 20 Sep 2006 14:34:08 GMT From: Rene Ladan <r.c.ladan@gmail.com> To: FreeBSD-gnats-submit@FreeBSD.org Cc: Mark Linimon <linimon@FreeBSD.org> Subject: usb/103418: [usb] [patch] usbhidctl: add ability to write output and feature items Message-ID: <200609201434.k8KEY8ZV046478@freefall.freebsd.org> Resent-Message-ID: <200609201440.k8KEeQds047408@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 103418 >Category: usb >Synopsis: [usb] [patch] usbhidctl: add ability to write output and feature items >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-usb >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Wed Sep 20 14:40:25 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Rene Ladan >Release: FreeBSD 6.2-PRERELEASE i386 >Organization: >Environment: System: FreeBSD dyn172.win.tue.nl 6.2-PRERELEASE FreeBSD 6.2-PRERELEASE #5: Tue Sep 19 21:13:50 CEST 2006 root@s000655.campus.tue.nl:/usr/obj/usr/src6/sys/RENE i386 >Description: The usbhidctl(1) utility can read input items, but not set output nor feature items. This patch, loosely based on OpenBSD's usbhidctl, adds write support to usbhidctl(1) so that it can set output and feature items. Note: I am unable to test this patch as I do not have any usb hid with a known output report descriptor. It is therefore advisable that a committer with good hid knowledge or a device with a known output report descriptor reviews this patch before committing it. But at least it compiles :) >How-To-Repeat: >Fix: --- /usr/src/usr.bin/usbhidctl/usbhid.c Mon May 26 06:58:26 2003 +++ usbhid.c Tue Sep 19 23:59:07 2006 @@ -1,7 +1,7 @@ /* $NetBSD: usbhid.c,v 1.14 2000/07/03 02:51:37 matt Exp $ */ /* $FreeBSD: src/usr.bin/usbhidctl/usbhid.c,v 1.9 2003/05/26 04:58:26 mdodd Exp $ */ -/* +/*- * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * @@ -51,6 +51,8 @@ #include <dev/usb/usb.h> #include <dev/usb/usbhid.h> +#define DELIM_SET '=' + int verbose = 0; int all = 0; int noname = 0; @@ -66,6 +68,8 @@ void rev(struct hid_item **p); void prdata(u_char *buf, struct hid_item *h); void dumpdata(int f, report_desc_t r, int loop); +void wrdata(u_char *buf, struct hid_item *h, char const *name); +void setdata(int f, report_desc_t r); int gotname(char *n); int @@ -96,6 +100,7 @@ fprintf(stderr, "usage: %s -f device [-l] [-n] [-r] [-t tablefile] [-v] name ...\n", __progname); fprintf(stderr, " %s -f device [-l] [-n] [-r] [-t tablefile] [-v] -a\n", __progname); + fprintf(stderr, " %s -f device [-t tablefile] -w name=value ...\n", __progname); exit(1); } @@ -254,6 +259,57 @@ free(dbuf); } +void +wrdata(u_char *buf, struct hid_item *h, char const *name) +{ + u_int dataval; + char const *valuesep; + valuesep = strchr(name, DELIM_SET); + if (valuesep) { + /* Set up variable */ + dataval = (u_int)strtol(valuesep + 1, NULL, 10); + hid_set_data(buf, h, dataval); + } +} + +void +setdata(int f, report_desc_t rd) +{ + struct hid_data *d; + struct hid_item h, *hids, *n; + int dlen; + u_char *dbuf; + u_int32_t colls[100]; + int sp = 0; + int i; + + for (d = hid_start_parse(rd, 1<<hid_output | 1<<hid_feature, reportid); + hid_get_item(d, &h); ) { + if (h.kind == hid_collection) + colls[++sp] = h.usage; + else if (h.kind == hid_endcollection) + --sp; + if ((h.kind != hid_output && h.kind != hid_feature) || + (h.flags & HIO_CONST)) + continue; + h.next = hids; + h.collection = colls[sp]; + hids = malloc(sizeof *hids); + *hids = h; + } + hid_end_parse(d); + rev(&hids); + dlen = hid_report_size(rd, 0, hid_output | hid_feature); + dbuf = calloc(1, dlen); + + for (n = hids; n; n = n->next) { + for (i = 0; i < nnames; i++) + wrdata(dbuf + (reportid != 0), n, names[i]); + } + write(f, dbuf, dlen); + free(dbuf); +} + int main(int argc, char **argv) { @@ -263,9 +319,10 @@ int ch; int repdump = 0; int loop = 0; + int wflag = 0; char *table = 0; - while ((ch = getopt(argc, argv, "af:lnrt:v")) != -1) { + while ((ch = getopt(argc, argv, "af:lnrt:vw")) != -1) { switch(ch) { case 'a': all++; @@ -288,6 +345,9 @@ case 'v': verbose++; break; + case 'w': + wflag = 1; + break; case '?': default: usage(); @@ -295,7 +355,11 @@ } argc -= optind; argv += optind; - if (dev == 0) + if (dev == 0 || (loop && (wflag || repdump))) + /* + * No device specified, or attempting to loop and set + * or dump report at the same time + */ usage(); names = argv; nnames = argc; @@ -325,7 +389,11 @@ printf("Report descriptor:\n"); dumpitems(r); } - if (nnames != 0 || all) + + if (wflag) + setdata(f, r); + + if ((nnames != 0 && !wflag) || all) dumpdata(f, r, loop); hid_dispose_report_desc(r); >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609201434.k8KEY8ZV046478>