diff options
author | thompsa <thompsa@FreeBSD.org> | 2009-03-12 02:32:54 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2009-03-12 02:32:54 +0000 |
commit | 8de969f06675ded49971133b36c234d6f7c39491 (patch) | |
tree | de59af6b05528eb32783cad1cd662987ed18574b /sys/dev/usb | |
parent | 829d831d90f6fc75b25f689ef686673729feb302 (diff) | |
download | FreeBSD-src-8de969f06675ded49971133b36c234d6f7c39491.zip FreeBSD-src-8de969f06675ded49971133b36c234d6f7c39491.tar.gz |
MFp4 //depot/projects/usb 159004,159053,159091
More HID parsing fixes for usb mice.
- be less strict on the last HID item usage.
- preserve item size and count accross items
- improve default HID usage selection.
Tested by: ache
Submitted by: Hans Petter Selasky
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/usb_hid.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/sys/dev/usb/usb_hid.c b/sys/dev/usb/usb_hid.c index 3008184..5ac1930 100644 --- a/sys/dev/usb/usb_hid.c +++ b/sys/dev/usb/usb_hid.c @@ -68,7 +68,10 @@ struct hid_data { struct hid_item cur[MAXPUSH]; int32_t usages_min[MAXUSAGE]; int32_t usages_max[MAXUSAGE]; - int kindset; + 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 */ @@ -181,15 +184,21 @@ hid_get_item(struct hid_data *s, struct hid_item *h) top: /* check if there is an array of items */ - if ((s->icount != s->ncount) && - (s->iusage != s->nusage)) { - dval = s->usages_min[s->iusage] + s->ousage; - c->usage = dval; - if (dval == s->usages_max[s->iusage]) { - s->iusage ++; - s->ousage = 0; + 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 { - s->ousage ++; + DPRINTFN(1, "Using last usage\n"); + dval = s->usage_last; } s->icount ++; /* @@ -268,6 +277,9 @@ hid_get_item(struct hid_data *s, struct hid_item *h) c->kind = hid_input; c->flags = dval; ret: + c->loc.count = s->loc_count; + c->loc.size = s->loc_size; + if (c->flags & HIO_VARIABLE) { /* range check usage count */ if (c->loc.count > 255) { @@ -285,13 +297,9 @@ hid_get_item(struct hid_data *s, struct hid_item *h) } else { s->ncount = 1; } - /* make sure we have a usage */ - if (s->nusage == 0) { - /* use the undefined HID PAGE */ - s->usages_min[s->nusage] = 0x0000; - s->usages_max[s->nusage] = 0xFFFF; - s->nusage = s->ncount; - } + /* set default usage */ + /* use the undefined HID PAGE */ + s->usage_last = 0; goto top; case 9: /* Output */ @@ -346,7 +354,8 @@ hid_get_item(struct hid_data *s, struct hid_item *h) c->unit = dval; break; case 7: - c->loc.size = dval; + /* mask because value is unsigned */ + s->loc_size = dval & mask; break; case 8: c->report_ID = dval; @@ -354,12 +363,17 @@ hid_get_item(struct hid_data *s, struct hid_item *h) c->loc.pos = 0; break; case 9: - c->loc.count = dval; + /* mask because value is unsigned */ + s->loc_count = dval & mask; break; case 10: /* Push */ s->pushlevel ++; if (s->pushlevel < MAXPUSH) { s->cur[s->pushlevel] = *c; + /* store size and count */ + c->loc.size = s->loc_size; + c->loc.count = s->loc_count; + /* update current item pointer */ c = &s->cur[s->pushlevel]; } else { DPRINTFN(0, "Cannot push " @@ -372,7 +386,13 @@ hid_get_item(struct hid_data *s, struct hid_item *h) /* preserve position */ oldpos = c->loc.pos; c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->loc.size; + s->loc_count = c->loc.count; + /* set default item location */ c->loc.pos = oldpos; + c->loc.size = 0; + c->loc.count = 0; } else { DPRINTFN(0, "Cannot pop " "item @ %d!\n", s->pushlevel); |