svn commit: r195967 - head/sys/dev/usb

Alfred Perlstein alfred at FreeBSD.org
Thu Jul 30 00:17:09 UTC 2009


Author: alfred
Date: Thu Jul 30 00:17:08 2009
New Revision: 195967
URL: http://svn.freebsd.org/changeset/base/195967

Log:
  USB CORE - Improve HID parsing
  
  See PR description for more info. Patch is
  implemented differently than suggested, but
  having the same result.
  
  PR:     usb/137188
  
  Submitted by:	hps
  Approved by:	re

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

Modified: head/sys/dev/usb/usb_hid.c
==============================================================================
--- head/sys/dev/usb/usb_hid.c	Thu Jul 30 00:16:50 2009	(r195966)
+++ head/sys/dev/usb/usb_hid.c	Thu Jul 30 00:17:08 2009	(r195967)
@@ -78,11 +78,19 @@ static uint8_t hid_get_byte(struct hid_d
 
 #define	MAXUSAGE 64
 #define	MAXPUSH 4
+#define	MAXID 16
+
+struct hid_pos_data {
+	int32_t rid;
+	uint32_t pos;
+};
+
 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 */
@@ -119,6 +127,58 @@ hid_clear_local(struct hid_item *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->loc.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->loc.pos = s->last_pos[i].pos;
+	} else {
+		DPRINTF("Out of RID entries, position is set to zero!\n");
+		c->loc.pos = 0;
+	}
+}
+
 /*------------------------------------------------------------------------*
  *	hid_start_parse
  *------------------------------------------------------------------------*/
@@ -373,9 +433,7 @@ hid_get_item(struct hid_data *s, struct 
 				s->loc_size = dval & mask;
 				break;
 			case 8:
-				c->report_ID = dval;
-				/* new report - reset position */
-				c->loc.pos = 0;
+				hid_switch_rid(s, c, dval);
 				break;
 			case 9:
 				/* mask because value is unsigned */


More information about the svn-src-all mailing list