Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Mar 2009 02:32:54 +0000 (UTC)
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r189718 - head/sys/dev/usb
Message-ID:  <200903120232.n2C2WsnM013936@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: thompsa
Date: Thu Mar 12 02:32:54 2009
New Revision: 189718
URL: http://svn.freebsd.org/changeset/base/189718

Log:
  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

Modified:
  head/sys/dev/usb/usb_hid.c

Modified: head/sys/dev/usb/usb_hid.c
==============================================================================
--- head/sys/dev/usb/usb_hid.c	Thu Mar 12 01:27:15 2009	(r189717)
+++ head/sys/dev/usb/usb_hid.c	Thu Mar 12 02:32:54 2009	(r189718)
@@ -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 
 
  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 
 				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 
 				} 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 
 				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 
 				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 
 					/* 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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903120232.n2C2WsnM013936>