svn commit: r245733 - in stable/9/sys/dev/usb: . input

Hans Petter Selasky hselasky at FreeBSD.org
Mon Jan 21 07:28:48 UTC 2013


Author: hselasky
Date: Mon Jan 21 07:28:46 2013
New Revision: 245733
URL: http://svnweb.freebsd.org/changeset/base/245733

Log:
  MFC r245248:
  Fix detection of Razer Copperhead as a USB mouse.
  Factor out USB mouse and keyboard detection logic.
  Reject USB keyboards which have mouse alike HID items
  in their HID descriptors.
  
  Submitted by:	Matthew W

Modified:
  stable/9/sys/dev/usb/input/ukbd.c
  stable/9/sys/dev/usb/input/ums.c
  stable/9/sys/dev/usb/usb_hid.c
  stable/9/sys/dev/usb/usbhid.h
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/usb/input/ukbd.c
==============================================================================
--- stable/9/sys/dev/usb/input/ukbd.c	Mon Jan 21 07:25:38 2013	(r245732)
+++ stable/9/sys/dev/usb/input/ukbd.c	Mon Jan 21 07:28:46 2013	(r245733)
@@ -995,13 +995,12 @@ ukbd_probe(device_t dev)
 	if (uaa->info.bInterfaceClass != UICLASS_HID)
 		return (ENXIO);
 
+	if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
+		return (ENXIO);
+
 	if ((uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) &&
-	    (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD)) {
-		if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
-			return (ENXIO);
-		else
-			return (BUS_PROBE_DEFAULT);
-	}
+	    (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD))
+		return (BUS_PROBE_DEFAULT);
 
 	error = usbd_req_get_hid_desc(uaa->device, NULL,
 	    &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex);
@@ -1009,23 +1008,20 @@ ukbd_probe(device_t dev)
 	if (error)
 		return (ENXIO);
 
-	/*
-	 * NOTE: we currently don't support USB mouse and USB keyboard
-	 * on the same USB endpoint.
-	 */
-	if (hid_is_collection(d_ptr, d_len,
-	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) {
-		/* most likely a mouse */
-		error = ENXIO;
-	} else if (hid_is_collection(d_ptr, d_len,
-	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) {
-		if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
+	if (hid_is_keyboard(d_ptr, d_len)) {
+		if (hid_is_mouse(d_ptr, d_len)) {
+			/*
+			 * NOTE: We currently don't support USB mouse
+			 * and USB keyboard on the same USB endpoint.
+			 * Let "ums" driver win.
+			 */
 			error = ENXIO;
-		else
+		} else {
 			error = BUS_PROBE_DEFAULT;
-	} else
+		}
+	} else {
 		error = ENXIO;
-
+	}
 	free(d_ptr, M_TEMP);
 	return (error);
 }

Modified: stable/9/sys/dev/usb/input/ums.c
==============================================================================
--- stable/9/sys/dev/usb/input/ums.c	Mon Jan 21 07:25:38 2013	(r245732)
+++ stable/9/sys/dev/usb/input/ums.c	Mon Jan 21 07:28:46 2013	(r245733)
@@ -368,9 +368,7 @@ ums_probe(device_t dev)
 {
 	struct usb_attach_arg *uaa = device_get_ivars(dev);
 	void *d_ptr;
-	struct hid_data *hd;
-	struct hid_item hi;
-	int error, mdepth, found;
+	int error;
 	uint16_t d_len;
 
 	DPRINTFN(11, "\n");
@@ -394,44 +392,13 @@ ums_probe(device_t dev)
 	if (error)
 		return (ENXIO);
 
-	hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
-	if (hd == NULL)
-		return (0);
-	mdepth = 0;
-	found = 0;
-	while (hid_get_item(hd, &hi)) {
-		switch (hi.kind) {
-		case hid_collection:
-			if (mdepth != 0)
-				mdepth++;
-			else if (hi.collection == 1 &&
-			     hi.usage ==
-			      HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
-				mdepth++;
-			break;
-		case hid_endcollection:
-			if (mdepth != 0)
-				mdepth--;
-			break;
-		case hid_input:
-			if (mdepth == 0)
-				break;
-			if (hi.usage ==
-			     HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
-			    (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
-				found++;
-			if (hi.usage ==
-			     HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
-			    (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
-				found++;
-			break;
-		default:
-			break;
-		}
-	}
-	hid_end_parse(hd);
+	if (hid_is_mouse(d_ptr, d_len))
+		error = BUS_PROBE_DEFAULT;
+	else
+		error = ENXIO;
+
 	free(d_ptr, M_TEMP);
-	return (found ? BUS_PROBE_DEFAULT : ENXIO);
+	return (error);
 }
 
 static void

Modified: stable/9/sys/dev/usb/usb_hid.c
==============================================================================
--- stable/9/sys/dev/usb/usb_hid.c	Mon Jan 21 07:25:38 2013	(r245732)
+++ stable/9/sys/dev/usb/usb_hid.c	Mon Jan 21 07:28:46 2013	(r245733)
@@ -845,3 +845,79 @@ usbd_req_get_hid_desc(struct usb_device 
 	}
 	return (USB_ERR_NORMAL_COMPLETION);
 }
+
+/*------------------------------------------------------------------------*
+ *	hid_is_mouse
+ *
+ * This function will decide if a USB descriptor belongs to a USB mouse.
+ *
+ * Return values:
+ * Zero: Not a USB mouse.
+ * Else: Is a USB mouse.
+ *------------------------------------------------------------------------*/
+int
+hid_is_mouse(const void *d_ptr, uint16_t d_len)
+{
+	struct hid_data *hd;
+	struct hid_item hi;
+	int mdepth;
+	int found;
+
+	hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
+	if (hd == NULL)
+		return (0);
+
+	mdepth = 0;
+	found = 0;
+
+	while (hid_get_item(hd, &hi)) {
+		switch (hi.kind) {
+		case hid_collection:
+			if (mdepth != 0)
+				mdepth++;
+			else if (hi.collection == 1 &&
+			     hi.usage ==
+			      HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
+				mdepth++;
+			break;
+		case hid_endcollection:
+			if (mdepth != 0)
+				mdepth--;
+			break;
+		case hid_input:
+			if (mdepth == 0)
+				break;
+			if (hi.usage ==
+			     HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
+			    (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+				found++;
+			if (hi.usage ==
+			     HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
+			    (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+				found++;
+			break;
+		default:
+			break;
+		}
+	}
+	hid_end_parse(hd);
+	return (found);
+}
+
+/*------------------------------------------------------------------------*
+ *	hid_is_keyboard
+ *
+ * This function will decide if a USB descriptor belongs to a USB keyboard.
+ *
+ * Return values:
+ * Zero: Not a USB keyboard.
+ * Else: Is a USB keyboard.
+ *------------------------------------------------------------------------*/
+int
+hid_is_keyboard(const void *d_ptr, uint16_t d_len)
+{
+	if (hid_is_collection(d_ptr, d_len,
+	    HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
+		return (1);
+	return (0);
+}

Modified: stable/9/sys/dev/usb/usbhid.h
==============================================================================
--- stable/9/sys/dev/usb/usbhid.h	Mon Jan 21 07:25:38 2013	(r245732)
+++ stable/9/sys/dev/usb/usbhid.h	Mon Jan 21 07:28:46 2013	(r245733)
@@ -242,5 +242,7 @@ struct usb_hid_descriptor *hid_get_descr
 usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
 	    void **descp, uint16_t *sizep, struct malloc_type *mem,
 	    uint8_t iface_index);
+int	hid_is_mouse(const void *d_ptr, uint16_t d_len);
+int	hid_is_keyboard(const void *d_ptr, uint16_t d_len);
 #endif					/* _KERNEL */
 #endif					/* _USB_HID_H_ */


More information about the svn-src-all mailing list