From owner-svn-src-all@FreeBSD.ORG Tue May 18 10:32:20 2010 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 7F1201065673; Tue, 18 May 2010 10:32:20 +0000 (UTC) (envelope-from kaiw@FreeBSD.org) Received: from svn.freebsd.org (unknown [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6CC088FC0C; Tue, 18 May 2010 10:32:20 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o4IAWKHt019979; Tue, 18 May 2010 10:32:20 GMT (envelope-from kaiw@svn.freebsd.org) Received: (from kaiw@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o4IAWK50019971; Tue, 18 May 2010 10:32:20 GMT (envelope-from kaiw@svn.freebsd.org) Message-Id: <201005181032.o4IAWK50019971@svn.freebsd.org> From: Kai Wang Date: Tue, 18 May 2010 10:32:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r208262 - in stable/8: lib/libusbhid usr.sbin/bluetooth/bthidd 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: Tue, 18 May 2010 10:32:20 -0000 Author: kaiw Date: Tue May 18 10:32:20 2010 New Revision: 208262 URL: http://svn.freebsd.org/changeset/base/208262 Log: MFC r205728 Merge improvements from kernel HID parser to the userland usbhid(3) parser. This merge does not change any API and should not break any native or thirdparty applications. Changes include: * Merge multiple report ID support and other improvements from kernel HID parser. * Ignore rid argument in hid_start_parser, parse all the report items since we now support multiple report ID. * Skip report ID byte in hid_get_data() and set report ID byte in hid_set_data(), if report ID is non-zero. * Reimplement hid_get_report_id: instead get report id from uhid device (which is always 0), try parsing the report descriptor and return the first report ID encountered. MFC r207812 hid_get_data() now expects that the hid data passed in always contains the report ID byte. Thus we should not skip the the report ID byte in hid_interrupt(). Also, if HUP_KEYBOARD usage is an array, do not try to modify the 'data' pointer, instead, increase the hid_item_t field 'pos' by 'report_size' before calling hid_get_data() during each iteration. Modified: stable/8/lib/libusbhid/data.c stable/8/lib/libusbhid/descr.c stable/8/lib/libusbhid/parse.c stable/8/lib/libusbhid/usage.c stable/8/lib/libusbhid/usbhid.h stable/8/lib/libusbhid/usbvar.h stable/8/usr.sbin/bluetooth/bthidd/hid.c Directory Properties: stable/8/lib/libusbhid/ (props changed) stable/8/usr.sbin/bluetooth/ (props changed) Modified: stable/8/lib/libusbhid/data.c ============================================================================== --- stable/8/lib/libusbhid/data.c Tue May 18 10:24:23 2010 (r208261) +++ stable/8/lib/libusbhid/data.c Tue May 18 10:32:20 2010 (r208262) @@ -29,6 +29,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include "usbhid.h" @@ -36,18 +37,27 @@ __FBSDID("$FreeBSD$"); int32_t hid_get_data(const void *p, const hid_item_t *h) { - const unsigned char *buf; - unsigned int hpos; - unsigned int hsize; - int data; + const uint8_t *buf; + uint32_t hpos; + uint32_t hsize; + uint32_t data; int i, end, offs; buf = p; + + /* Skip report ID byte. */ + if (h->report_ID > 0) + buf++; + hpos = h->pos; /* bit position of data */ hsize = h->report_size; /* bit length of data */ + /* Range check and limit */ if (hsize == 0) return (0); + if (hsize > 32) + hsize = 32; + offs = hpos / 8; end = (hpos + hsize) / 8 - offs; data = 0; @@ -70,15 +80,20 @@ hid_get_data(const void *p, const hid_it void hid_set_data(void *p, const hid_item_t *h, int32_t data) { - unsigned char *buf; - unsigned int hpos; - unsigned int hsize; + uint8_t *buf; + uint32_t hpos; + uint32_t hsize; uint32_t mask; int i; int end; int offs; buf = p; + + /* Set report ID byte. */ + if (h->report_ID > 0) + *buf++ = h->report_ID & 0xff; + hpos = h->pos; /* bit position of data */ hsize = h->report_size; /* bit length of data */ @@ -97,5 +112,5 @@ hid_set_data(void *p, const hid_item_t * for (i = 0; i <= end; i++) buf[offs + i] = (buf[offs + i] & (mask >> (i*8))) | - ((data >> (i*8)) & 0xff); + ((data >> (i*8)) & 0xff); } Modified: stable/8/lib/libusbhid/descr.c ============================================================================== --- stable/8/lib/libusbhid/descr.c Tue May 18 10:24:23 2010 (r208261) +++ stable/8/lib/libusbhid/descr.c Tue May 18 10:32:20 2010 (r208262) @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); #include #include #include - #include #include "usbhid.h" @@ -59,9 +58,30 @@ hid_set_immed(int fd, int enable) int hid_get_report_id(int fd) { + report_desc_t rep; + hid_data_t d; + hid_item_t h; + int kindset; int temp = -1; int ret; + if ((rep = hid_get_report_desc(fd)) == NULL) + goto use_ioctl; + kindset = 1 << hid_input | 1 << hid_output | 1 << hid_feature; + for (d = hid_start_parse(rep, kindset, 0); hid_get_item(d, &h); ) { + /* Return the first report ID we met. */ + if (h.report_ID != 0) { + temp = h.report_ID; + break; + } + } + hid_end_parse(d); + hid_dispose_report_desc(rep); + + if (temp > 0) + return (temp); + +use_ioctl: ret = ioctl(fd, USB_GET_REPORT_ID, &temp); #ifdef HID_COMPAT7 if (ret < 0) Modified: stable/8/lib/libusbhid/parse.c ============================================================================== --- stable/8/lib/libusbhid/parse.c Tue May 18 10:24:23 2010 (r208261) +++ stable/8/lib/libusbhid/parse.c Tue May 18 10:32:20 2010 (r208262) @@ -40,42 +40,43 @@ __FBSDID("$FreeBSD$"); #include "usbhid.h" #include "usbvar.h" -#define MAXUSAGE 100 -struct hid_data { - u_char *start; - u_char *end; - u_char *p; - hid_item_t cur; - unsigned int usages[MAXUSAGE]; - int nusage; - int minset; - int logminsize; - int multi; - int multimax; - int kindset; - int reportid; - - /* - * The start of collection item has no report ID set, so save - * it until we know the ID. - */ - hid_item_t savedcoll; - u_char hassavedcoll; - /* - * Absolute data position (bits) for input/output/feature. - * Assumes that hid_input, hid_output and hid_feature have - * values 0, 1 and 2. - */ - unsigned int kindpos[3]; +#define MAXUSAGE 100 +#define MAXPUSH 4 +#define MAXID 64 + +struct hid_pos_data { + int32_t rid; + uint32_t pos; }; -static int min(int x, int y) { return x < y ? x : y; } - -static int hid_get_item_raw(hid_data_t s, hid_item_t *h); +struct hid_data { + const uint8_t *start; + const uint8_t *end; + const uint8_t *p; + struct hid_item cur[MAXPUSH]; + struct hid_pos_data last_pos[MAXID]; + int32_t usages_min[MAXUSAGE]; + int32_t usages_max[MAXUSAGE]; + int32_t usage_last; /* last seen usage */ + uint32_t loc_size; /* last seen size */ + uint32_t loc_count; /* last seen count */ + uint8_t kindset; /* we have 5 kinds so 8 bits are enough */ + uint8_t pushlevel; /* current pushlevel */ + uint8_t ncount; /* end usage item count */ + uint8_t icount; /* current usage item count */ + uint8_t nusage; /* end "usages_min/max" index */ + uint8_t iusage; /* current "usages_min/max" index */ + uint8_t ousage; /* current "usages_min/max" offset */ + uint8_t susage; /* usage set flags */ +}; +/*------------------------------------------------------------------------* + * hid_clear_local + *------------------------------------------------------------------------*/ static void hid_clear_local(hid_item_t *c) { + c->usage = 0; c->usage_minimum = 0; c->usage_maximum = 0; @@ -88,8 +89,61 @@ hid_clear_local(hid_item_t *c) c->set_delimiter = 0; } +static void +hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) +{ + uint8_t i; + + /* check for same report ID - optimise */ + + if (c->report_ID == next_rID) + return; + + /* save current position for current rID */ + + if (c->report_ID == 0) { + i = 0; + } else { + for (i = 1; i != MAXID; i++) { + if (s->last_pos[i].rid == c->report_ID) + break; + if (s->last_pos[i].rid == 0) + break; + } + } + if (i != MAXID) { + s->last_pos[i].rid = c->report_ID; + s->last_pos[i].pos = c->pos; + } + + /* store next report ID */ + + c->report_ID = next_rID; + + /* lookup last position for next rID */ + + if (next_rID == 0) { + i = 0; + } else { + for (i = 1; i != MAXID; i++) { + if (s->last_pos[i].rid == next_rID) + break; + if (s->last_pos[i].rid == 0) + break; + } + } + if (i != MAXID) { + s->last_pos[i].rid = next_rID; + c->pos = s->last_pos[i].pos; + } else + c->pos = 0; /* Out of RID entries. */ +} + +/*------------------------------------------------------------------------* + * hid_start_parse + *------------------------------------------------------------------------*/ hid_data_t -hid_start_parse(report_desc_t d, int kindset, int id) +hid_start_parse(report_desc_t d, int kindset, int id __unused) { struct hid_data *s; @@ -98,213 +152,207 @@ hid_start_parse(report_desc_t d, int kin s->start = s->p = d->data; s->end = d->data + d->size; s->kindset = kindset; - s->reportid = id; - s->hassavedcoll = 0; return (s); } +/*------------------------------------------------------------------------* + * hid_end_parse + *------------------------------------------------------------------------*/ void hid_end_parse(hid_data_t s) { - while (s->cur.next) { - hid_item_t *hi = s->cur.next->next; - free(s->cur.next); - s->cur.next = hi; - } + + if (s == NULL) + return; + free(s); } -int -hid_get_item(hid_data_t s, hid_item_t *h) +/*------------------------------------------------------------------------* + * get byte from HID descriptor + *------------------------------------------------------------------------*/ +static uint8_t +hid_get_byte(struct hid_data *s, const uint16_t wSize) { - int r; + const uint8_t *ptr; + uint8_t retval; - for (;;) { - r = hid_get_item_raw(s, h); - if (r <= 0) - break; - if (h->report_ID == s->reportid || s->reportid == -1) - break; - } - return (r); -} + ptr = s->p; + + /* check if end is reached */ + if (ptr == s->end) + return (0); -#define REPORT_SAVED_COLL \ - do { \ - if (s->hassavedcoll) { \ - *h = s->savedcoll; \ - h->report_ID = c->report_ID; \ - s->hassavedcoll = 0; \ - return (1); \ - } \ - } while(/*LINTED*/ 0) + /* read out a byte */ + retval = *ptr; -static int -hid_get_item_raw(hid_data_t s, hid_item_t *h) + /* check if data pointer can be advanced by "wSize" bytes */ + if ((s->end - ptr) < wSize) + ptr = s->end; + else + ptr += wSize; + + /* update pointer */ + s->p = ptr; + + return (retval); +} + +/*------------------------------------------------------------------------* + * hid_get_item + *------------------------------------------------------------------------*/ +int +hid_get_item(hid_data_t s, hid_item_t *h) { hid_item_t *c; - unsigned int bTag = 0, bType = 0, bSize; - unsigned char *data; - int dval; - unsigned char *p; - hid_item_t *hi; - hid_item_t nc; - int i; - hid_kind_t retkind; + unsigned int bTag, bType, bSize; + uint32_t oldpos; + int32_t mask; + int32_t dval; - c = &s->cur; + if (s == NULL) + return (0); + + c = &s->cur[s->pushlevel]; top: - if (s->multimax) { - REPORT_SAVED_COLL; - if (c->logical_minimum >= c->logical_maximum) { - if (s->logminsize == 1) - c->logical_minimum =(int8_t)c->logical_minimum; - else if (s->logminsize == 2) - c->logical_minimum =(int16_t)c->logical_minimum; + /* check if there is an array of items */ + if (s->icount < s->ncount) { + /* get current usage */ + if (s->iusage < s->nusage) { + dval = s->usages_min[s->iusage] + s->ousage; + c->usage = dval; + s->usage_last = dval; + if (dval == s->usages_max[s->iusage]) { + s->iusage ++; + s->ousage = 0; + } else { + s->ousage ++; + } + } else { + /* Using last usage */ + dval = s->usage_last; } - if (s->multi < s->multimax) { - c->usage = s->usages[min(s->multi, s->nusage-1)]; - s->multi++; + s->icount ++; + /* + * Only copy HID item, increment position and return + * if correct kindset! + */ + if (s->kindset & (1 << c->kind)) { *h = *c; - /* - * 'multimax' is only non-zero if the current - * item kind is input/output/feature - */ - h->pos = s->kindpos[c->kind]; - s->kindpos[c->kind] += c->report_size; - h->next = 0; + c->pos += c->report_size * c->report_count; return (1); - } else { - c->report_count = s->multimax; - s->multimax = 0; - s->nusage = 0; - hid_clear_local(c); } } - for (;;) { - p = s->p; - if (p >= s->end) - return (0); - bSize = *p++; + /* reset state variables */ + s->icount = 0; + s->ncount = 0; + s->iusage = 0; + s->nusage = 0; + s->susage = 0; + s->ousage = 0; + hid_clear_local(c); + + /* get next item */ + while (s->p != s->end) { + + bSize = hid_get_byte(s, 1); if (bSize == 0xfe) { /* long item */ - bSize = *p++; - bSize |= *p++ << 8; - bTag = *p++; - data = p; - p += bSize; + bSize = hid_get_byte(s, 1); + bSize |= hid_get_byte(s, 1) << 8; + bTag = hid_get_byte(s, 1); + bType = 0xff; /* XXX what should it be */ } else { /* short item */ bTag = bSize >> 4; bType = (bSize >> 2) & 3; bSize &= 3; - if (bSize == 3) bSize = 4; - data = p; - p += bSize; + if (bSize == 3) + bSize = 4; } - s->p = p; - /* - * The spec is unclear if the data is signed or unsigned. - */ + switch(bSize) { case 0: dval = 0; + mask = 0; break; case 1: - dval = *data++; + dval = (int8_t)hid_get_byte(s, 1); + mask = 0xFF; break; case 2: - dval = *data++; - dval |= *data++ << 8; + dval = hid_get_byte(s, 1); + dval |= hid_get_byte(s, 1) << 8; + dval = (int16_t)dval; + mask = 0xFFFF; break; case 4: - dval = *data++; - dval |= *data++ << 8; - dval |= *data++ << 16; - dval |= *data++ << 24; + dval = hid_get_byte(s, 1); + dval |= hid_get_byte(s, 1) << 8; + dval |= hid_get_byte(s, 1) << 16; + dval |= hid_get_byte(s, 1) << 24; + mask = 0xFFFFFFFF; break; default: - return (-1); + dval = hid_get_byte(s, bSize); + continue; } switch (bType) { - case 0: /* Main */ + case 0: /* Main */ switch (bTag) { - case 8: /* Input */ - retkind = hid_input; - ret: - if (!(s->kindset & (1 << retkind))) { - /* Drop the items of this kind */ - s->nusage = 0; - continue; - } - c->kind = retkind; + case 8: /* Input */ + c->kind = hid_input; c->flags = dval; + ret: + c->report_count = s->loc_count; + c->report_size = s->loc_size; + if (c->flags & HIO_VARIABLE) { - s->multimax = c->report_count; - s->multi = 0; + /* range check usage count */ + if (c->report_count > 255) { + s->ncount = 255; + } else + s->ncount = c->report_count; + + /* + * The "top" loop will return + * one and one item: + */ c->report_count = 1; - if (s->minset) { - for (i = c->usage_minimum; - i <= c->usage_maximum; - i++) { - s->usages[s->nusage] = i; - if (s->nusage < MAXUSAGE-1) - s->nusage++; - } - c->usage_minimum = 0; - c->usage_maximum = 0; - s->minset = 0; - } - goto top; } 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->ncount = 1; } - case 9: /* Output */ - retkind = hid_output; + goto top; + + case 9: /* Output */ + c->kind = hid_output; + c->flags = dval; goto ret; case 10: /* Collection */ c->kind = hid_collection; c->collection = dval; c->collevel++; - nc = *c; - hid_clear_local(c); - /*c->report_ID = NO_REPORT_ID;*/ - s->nusage = 0; - if (s->hassavedcoll) { - *h = s->savedcoll; - h->report_ID = nc.report_ID; - s->savedcoll = nc; - return (1); - } else { - s->hassavedcoll = 1; - s->savedcoll = nc; - } - break; + c->usage = s->usage_last; + *h = *c; + return (1); case 11: /* Feature */ - retkind = hid_feature; + c->kind = hid_feature; + c->flags = dval; goto ret; case 12: /* End collection */ - REPORT_SAVED_COLL; c->kind = hid_endcollection; + if (c->collevel == 0) { + /* Invalid end collection. */ + return (0); + } c->collevel--; *h = *c; - /*hid_clear_local(c);*/ - s->nusage = 0; return (1); default: - return (-2); + break; } break; @@ -315,13 +363,12 @@ hid_get_item_raw(hid_data_t s, hid_item_ break; case 1: c->logical_minimum = dval; - s->logminsize = bSize; break; case 2: c->logical_maximum = dval; break; case 3: - c->physical_maximum = dval; + c->physical_minimum = dval; break; case 4: c->physical_maximum = dval; @@ -333,45 +380,97 @@ hid_get_item_raw(hid_data_t s, hid_item_ c->unit = dval; break; case 7: - c->report_size = dval; + /* mask because value is unsigned */ + s->loc_size = dval & mask; break; case 8: - c->report_ID = dval; - s->kindpos[hid_input] = - s->kindpos[hid_output] = - s->kindpos[hid_feature] = 0; + hid_switch_rid(s, c, dval); break; case 9: - c->report_count = dval; + /* mask because value is unsigned */ + s->loc_count = dval & mask; break; - case 10: /* Push */ - hi = malloc(sizeof *hi); - *hi = s->cur; - c->next = hi; - break; - case 11: /* Pop */ - hi = c->next; - s->cur = *hi; - free(hi); + case 10: /* Push */ + s->pushlevel ++; + if (s->pushlevel < MAXPUSH) { + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->report_size = s->loc_size; + c->report_count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; + } + break; + case 11: /* Pop */ + s->pushlevel --; + if (s->pushlevel < MAXPUSH) { + /* preserve position */ + oldpos = c->pos; + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->report_size; + s->loc_count = c->report_count; + /* set default item location */ + c->pos = oldpos; + c->report_size = 0; + c->report_count = 0; + } break; default: - return (-3); + break; } break; case 2: /* Local */ switch (bTag) { case 0: - c->usage = c->_usage_page | dval; - if (s->nusage < MAXUSAGE) - s->usages[s->nusage++] = c->usage; + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + + /* set last usage, in case of a collection */ + s->usage_last = dval; + + if (s->nusage < MAXUSAGE) { + s->usages_min[s->nusage] = dval; + s->usages_max[s->nusage] = dval; + s->nusage ++; + } /* else XXX */ + + /* clear any pending usage sets */ + s->susage = 0; break; case 1: - s->minset = 1; - c->usage_minimum = c->_usage_page | dval; - break; + s->susage |= 1; + + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + c->usage_minimum = dval; + + goto check_set; case 2: - c->usage_maximum = c->_usage_page | dval; + s->susage |= 2; + + if (bSize != 4) + dval = (dval & mask) | c->_usage_page; + c->usage_maximum = dval; + + check_set: + if (s->susage != 3) + break; + + /* sanity check */ + if ((s->nusage < MAXUSAGE) && + (c->usage_minimum <= c->usage_maximum)) { + /* add usage range */ + s->usages_min[s->nusage] = + c->usage_minimum; + s->usages_max[s->nusage] = + c->usage_maximum; + s->nusage ++; + } + /* else XXX */ + + s->susage = 0; break; case 3: c->designator_index = dval; @@ -395,40 +494,63 @@ hid_get_item_raw(hid_data_t s, hid_item_ c->set_delimiter = dval; break; default: - return (-4); + break; } break; default: - return (-5); + break; } } + return (0); } int hid_report_size(report_desc_t r, enum hid_kind k, int id) { struct hid_data *d; - hid_item_t h; - int size; + struct hid_item h; + uint32_t temp; + uint32_t hpos; + uint32_t lpos; + + hpos = 0; + lpos = 0xFFFFFFFF; memset(&h, 0, sizeof h); - size = 0; - for (d = hid_start_parse(r, 1<kindpos[k]; + /* compute minimum */ + if (lpos > h.pos) + lpos = h.pos; + /* compute end position */ + temp = h.pos + (h.report_size * h.report_count); + /* compute maximum */ + if (hpos < temp) + hpos = temp; } } hid_end_parse(d); - return ((size + 7) / 8); + + /* safety check - can happen in case of currupt descriptors */ + if (lpos > hpos) + temp = 0; + else + temp = hpos - lpos; + + if (id) + temp += 8; + + /* return length in bytes rounded up */ + return ((temp + 7) / 8); } int hid_locate(report_desc_t desc, unsigned int u, enum hid_kind k, hid_item_t *h, int id) { - hid_data_t d; + struct hid_data *d; - for (d = hid_start_parse(desc, 1<kind == k && !(h->flags & HIO_CONST) && h->usage == u) { hid_end_parse(d); return (1); Modified: stable/8/lib/libusbhid/usage.c ============================================================================== --- stable/8/lib/libusbhid/usage.c Tue May 18 10:24:23 2010 (r208261) +++ stable/8/lib/libusbhid/usage.c Tue May 18 10:32:20 2010 (r208262) @@ -29,6 +29,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include Modified: stable/8/lib/libusbhid/usbhid.h ============================================================================== --- stable/8/lib/libusbhid/usbhid.h Tue May 18 10:24:23 2010 (r208261) +++ stable/8/lib/libusbhid/usbhid.h Tue May 18 10:32:20 2010 (r208262) @@ -29,7 +29,7 @@ * */ -#include +#include #include typedef struct report_desc *report_desc_t; @@ -37,45 +37,41 @@ typedef struct report_desc *report_desc_ typedef struct hid_data *hid_data_t; typedef enum hid_kind { - hid_input = 0, - hid_output = 1, - hid_feature = 2, - hid_collection, - hid_endcollection + hid_input, hid_output, hid_feature, hid_collection, hid_endcollection } hid_kind_t; typedef struct hid_item { /* Global */ - unsigned int _usage_page; - int logical_minimum; - int logical_maximum; - int physical_minimum; - int physical_maximum; - int unit_exponent; - int unit; - int report_size; - int report_ID; + uint32_t _usage_page; + int32_t logical_minimum; + int32_t logical_maximum; + int32_t physical_minimum; + int32_t physical_maximum; + int32_t unit_exponent; + int32_t unit; + int32_t report_size; + int32_t report_ID; #define NO_REPORT_ID 0 - int report_count; + int32_t report_count; /* Local */ - unsigned int usage; - int usage_minimum; - int usage_maximum; - int designator_index; - int designator_minimum; - int designator_maximum; - int string_index; - int string_minimum; - int string_maximum; - int set_delimiter; + uint32_t usage; + int32_t usage_minimum; + int32_t usage_maximum; + int32_t designator_index; + int32_t designator_minimum; + int32_t designator_maximum; + int32_t string_index; + int32_t string_minimum; + int32_t string_maximum; + int32_t set_delimiter; /* Misc */ - int collection; - int collevel; + int32_t collection; + int collevel; enum hid_kind kind; - unsigned int flags; - /* Absolute data position (bits) */ - unsigned int pos; - /* */ + uint32_t flags; + /* Location */ + uint32_t pos; + /* unused */ struct hid_item *next; } hid_item_t; @@ -96,7 +92,8 @@ hid_data_t hid_start_parse(report_desc_t void hid_end_parse(hid_data_t s); int hid_get_item(hid_data_t s, hid_item_t *h); int hid_report_size(report_desc_t d, enum hid_kind k, int id); -int hid_locate(report_desc_t d, unsigned int usage, enum hid_kind k, hid_item_t *h, int id); +int hid_locate(report_desc_t d, unsigned int usage, enum hid_kind k, + hid_item_t *h, int id); /* Conversion to/from usage names, usage.c: */ const char *hid_usage_page(int i); Modified: stable/8/lib/libusbhid/usbvar.h ============================================================================== --- stable/8/lib/libusbhid/usbvar.h Tue May 18 10:24:23 2010 (r208261) +++ stable/8/lib/libusbhid/usbvar.h Tue May 18 10:32:20 2010 (r208262) @@ -30,8 +30,8 @@ */ struct report_desc { - unsigned int size; - unsigned char data[1]; + uint32_t size; + uint8_t data[1]; }; /* internal backwards compatibility functions */ Modified: stable/8/usr.sbin/bluetooth/bthidd/hid.c ============================================================================== --- stable/8/usr.sbin/bluetooth/bthidd/hid.c Tue May 18 10:24:23 2010 (r208261) +++ stable/8/usr.sbin/bluetooth/bthidd/hid.c Tue May 18 10:32:20 2010 (r208262) @@ -130,7 +130,7 @@ hid_interrupt(bthid_session_p s, uint8_t hid_item_t h; int32_t report_id, usage, page, val, mouse_x, mouse_y, mouse_z, mouse_butt, - mevents, kevents; + mevents, kevents, i; assert(s != NULL); assert(s->srv != NULL); @@ -150,8 +150,8 @@ hid_interrupt(bthid_session_p s, uint8_t } report_id = data[1]; - data += 2; - len -= 2; + data ++; + len --; hid_device = get_hid_device(&s->bdaddr); assert(hid_device != NULL); @@ -202,17 +202,11 @@ hid_interrupt(bthid_session_p s, uint8_t if (val && val < kbd_maxkey()) bit_set(s->keys1, val); - data ++; - len --; - - len = min(len, h.report_size); - while (len > 0) { + for (i = 1; i < h.report_count; i++) { + h.pos += h.report_size; val = hid_get_data(data, &h); if (val && val < kbd_maxkey()) bit_set(s->keys1, val); - - data ++; - len --; } } break;