PERFORCE change 166156 for review

Hans Petter Selasky hselasky at FreeBSD.org
Thu Jul 16 08:28:01 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=166156

Change 166156 by hselasky at hselasky_laptop001 on 2009/07/16 08:27:42

	
	USB core:
	 - improve handling of alternate settings in device side mode.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_device.c#43 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_handle_request.c#17 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_parse.c#7 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/usb_device.c#43 (text+ko) ====

@@ -833,18 +833,13 @@
 		err = USB_ERR_INVAL;
 		goto done;
 	}
-	if (udev->flags.usb_mode == USB_MODE_DEVICE) {
-		usb_detach_device(udev, iface_index,
-		    USB_UNCFG_FLAG_FREE_SUBDEV);
-	} else {
-		if (iface->alt_index == alt_index) {
-			/* 
-			 * Optimise away duplicate setting of
-			 * alternate setting in USB Host Mode!
-			 */
-			err = 0;
-			goto done;
-		}
+	if (iface->alt_index == alt_index) {
+		/* 
+		 * Optimise away duplicate setting of
+		 * alternate setting in USB Host Mode!
+		 */
+		err = 0;
+		goto done;
 	}
 #if USB_HAVE_UGEN
 	/*
@@ -858,6 +853,12 @@
 	if (err) {
 		goto done;
 	}
+	if (iface->alt_index != alt_index) {
+		/* the alternate setting does not exist */
+		err = USB_ERR_INVAL;
+		goto done;
+	}
+
 	err = usbd_req_set_alt_interface_no(udev, NULL, iface_index,
 	    iface->idesc->bAlternateSetting);
 
@@ -959,7 +960,6 @@
 {
 	struct usb_endpoint *ep;
 	struct usb_endpoint *ep_end;
-	usb_error_t err;
 
 	ep = udev->endpoints;
 	ep_end = udev->endpoints + udev->endpoints_max;
@@ -971,10 +971,7 @@
 			continue;
 		}
 		/* simulate a clear stall from the peer */
-		err = usbd_set_endpoint_stall(udev, ep, 0);
-		if (err) {
-			/* just ignore */
-		}
+		usbd_set_endpoint_stall(udev, ep, 0);
 	}
 	return (0);
 }

==== //depot/projects/usb/src/sys/dev/usb/usb_handle_request.c#17 (text+ko) ====

@@ -46,6 +46,7 @@
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
 #include "usb_if.h"
 
 #define	USB_DEBUG_VAR usb_debug
@@ -181,6 +182,30 @@
 	return (err);
 }
 
+static usb_error_t
+usb_check_alt_setting(struct usb_device *udev, 
+     struct usb_interface *iface, uint8_t alt_index)
+{
+	uint8_t do_unlock;
+	usb_error_t err = 0;
+
+	/* automatic locking */
+	if (sx_xlocked(udev->default_sx + 1)) {
+		do_unlock = 0;
+	} else {
+		do_unlock = 1;
+		sx_xlock(udev->default_sx + 1);
+	}
+
+	if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
+		err = USB_ERR_INVAL;
+
+	if (do_unlock) {
+		sx_unlock(udev->default_sx + 1);
+	}
+	return (err);
+}
+
 /*------------------------------------------------------------------------*
  *	usb_handle_iface_request
  *
@@ -285,42 +310,29 @@
 		switch (req.bRequest) {
 		case UR_SET_INTERFACE:
 			/*
-			 * Handle special case. If we have parent interface
-			 * we just reset the endpoints, because this is a
-			 * multi interface device and re-attaching only a
-			 * part of the device is not possible. Also if the
-			 * alternate setting is the same like before we just
-			 * reset the interface endoints.
+			 * We assume that the endpoints are the same
+			 * accross the alternate settings.
+			 *
+			 * Reset the endpoints, because re-attaching
+			 * only a part of the device is not possible.
 			 */
-			if ((iface_parent != NULL) ||
-			    (iface->alt_index == req.wValue[0])) {
-				error = usb_reset_iface_endpoints(udev,
-				    iface_index);
-				if (error) {
-					DPRINTF("alt setting failed %s\n",
-					    usbd_errstr(error));
-					goto tr_stalled;
-				}
-				break;
-			}
-			/* 
-			 * Doing the alternate setting will detach the
-			 * interface aswell:
-			 */
-			error = usbd_set_alt_interface_index(udev,
-			    iface_index, req.wValue[0]);
+			error = usb_check_alt_setting(udev,
+			    iface, req.wValue[0]);
 			if (error) {
-				DPRINTF("alt setting failed %s\n",
+				DPRINTF("alt setting does not exist %s\n",
 				    usbd_errstr(error));
 				goto tr_stalled;
 			}
-			error = usb_probe_and_attach(udev,
-			    iface_index);
+			error = usb_reset_iface_endpoints(udev, iface_index);
 			if (error) {
-				DPRINTF("alt setting probe failed\n");
+				DPRINTF("alt setting failed %s\n",
+				    usbd_errstr(error));
 				goto tr_stalled;
 			}
+			/* update the current alternate setting */
+			iface->alt_index = req.wValue[0];
 			break;
+
 		default:
 			goto tr_stalled;
 		}

==== //depot/projects/usb/src/sys/dev/usb/usb_parse.c#7 (text+ko) ====

@@ -222,11 +222,22 @@
     struct usb_interface_descriptor *id)
 {
 	struct usb_descriptor *desc;
-	uint8_t n = 0;
+	uint8_t n;
 	uint8_t ifaceno;
 
+	/* 
+	 * We always have at least one interface setting, due to the
+	 * fact that the usb_desc_foreach() call below will skip the
+	 * first interface descriptor.
+	 */
+	n = 1;
+
+	/* Get the interface number */
+
 	ifaceno = id->bInterfaceNumber;
 
+	/* Get the interface descriptor */
+
 	desc = (struct usb_descriptor *)id;
 
 	while ((desc = usb_desc_foreach(cd, desc))) {


More information about the p4-projects mailing list