From owner-freebsd-usb@FreeBSD.ORG Mon May 14 23:54:26 2007 Return-Path: X-Original-To: freebsd-usb@freebsd.org Delivered-To: freebsd-usb@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id D033916A400 for ; Mon, 14 May 2007 23:54:26 +0000 (UTC) (envelope-from sec@42.org) Received: from ice.42.org (ice.42.org [194.77.85.2]) by mx1.freebsd.org (Postfix) with ESMTP id 64C6E13C448 for ; Mon, 14 May 2007 23:54:26 +0000 (UTC) (envelope-from sec@42.org) Received: by ice.42.org (Postfix, from userid 1000) id 2779BC46C; Tue, 15 May 2007 01:34:38 +0200 (CEST) Date: Tue, 15 May 2007 01:34:38 +0200 From: Stefan `Sec` Zehl To: freebsd-bluetooth@freebsd.org, freebsd-usb@freebsd.org Message-ID: <20070514233438.GD24803@ice.42.org> X-Current-Backlog: 2710 messages Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.2i I-love-doing-this: really X-Modeline: vim:set ts=8 sw=4 smarttab tw=72 si noic notitle: Accept-Languages: de, en X-URL: http://sec.42.org/ Cc: Subject: libusbhid bug? X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 14 May 2007 23:54:26 -0000 Hi, I've been playing around with a Bluetooth HID device. Bluetooth uses the same HID format as USB, so libusbhid is used to parse these messages. While debugging, I've found what I think is a mistake in parsing "Array"-type input messages: In my HID descriptor, there is the following snippet: | 95 06 | Report Count(6) | 75 08 | Report Size(8) | 15 00 | Logical Minimum(0) | 26 a4 00| Logical Maximum(164) | 05 07 | Usage Page(Key Codes) | 19 00 | Usage Minimum(0x00) | 29 a4 | Usage Maximum(0xa4) | 81 00 | Input(Data,Array,Absolute) The current usbhid only parses one item of Report_Size (8bit). According to the spec it should parse Report_Count items: | An array provides an alternate means for | describing the data returned from a group of | buttons. Arrays are more efficient, if less flexible | than variable items. Rather than returning a single | bit for each button in the group, an array returns an | index in each field that corresponds to the pressed | button (like keyboard scan codes). An out-of range | value in and array field is considered no controls | asserted. Buttons or keys in an array that are | simultaneously pressed need to be reported in | multiple fields. Therefore, the number of fields in | an array input item (Report Count) dictates the | maximum number of simultaneous controls that | can be reported. A keyboard could report up to | three simultaneous keys using an array with three | 8-bit fields (Report Size = 8, Report Count = 3). I have created a patch which changes that behaviour, and attached it below. My sample code works fine with these changes, but as I don't have an USB Keyboard, it would be great if someone could check that this doesn't break anything. --- parse.c.org Wed Feb 11 22:09:13 2004 +++ parse.c Tue May 15 01:26:08 2007 @@ -54,6 +54,7 @@ int multimax; int kindset; int reportid; + int isarray; /* * The start of collection item has no report ID set, so save @@ -100,6 +101,7 @@ s->kindset = kindset; s->reportid = id; s->hassavedcoll = 0; + s->isarray = 0; return (s); } @@ -182,6 +184,16 @@ hid_clear_local(c); } } + if(s->isarray) { + REPORT_SAVED_COLL; + *h = *c; + h->next = 0; + h->pos = s->kindpos[c->kind]; + s->kindpos[c->kind] += c->report_size ; + if(--s->isarray ==0) + hid_clear_local(c); + return(1); + }; for (;;) { p = s->p; if (p >= s->end) @@ -262,14 +274,9 @@ } else { if (s->minset) c->usage = c->usage_minimum; - *h = *c; - h->next = 0; - h->pos = s->kindpos[c->kind]; - s->kindpos[c->kind] += - c->report_size * c->report_count; - hid_clear_local(c); s->minset = 0; - return (1); + s->isarray=c->report_count; + goto top; } case 9: /* Output */ retkind = hid_output; CU, Sec -- "The General who in a hundred battles is always victorious is not as great as the one who achieves his objectives without fighting." -- Sun Tzu