[PATCH] USB: usbtest updates

Updates to "usbtest" driver:

  * Improve some diagnostics.  One path that never generated diagnostics
    before should now generate two ... unless you hit a GCC bug that
    all my compilers seem to have, go figure.

  * Add suspend/resume support, so this behaves when the Linux host
    being used for testing suspends.

  * Don't test the "zero byte ep0 read" case unless real-world relevance
    for the testing is is irrelevant.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 3104f28..cda7249 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -461,7 +461,7 @@
 
 static unsigned realworld = 1;
 module_param (realworld, uint, 0);
-MODULE_PARM_DESC (realworld, "clear to demand stricter ch9 compliance");
+MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance");
 
 static int get_altsetting (struct usbtest_dev *dev)
 {
@@ -604,9 +604,8 @@
 				USB_DIR_IN | USB_RECIP_DEVICE,
 				0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);
 		if (retval != 1 || dev->buf [0] != expected) {
-			dev_dbg (&iface->dev,
-				"get config --> %d (%d)\n", retval,
-				expected);
+			dev_dbg (&iface->dev, "get config --> %d %d (1 %d)\n",
+				retval, dev->buf[0], expected);
 			return (retval < 0) ? retval : -EDOM;
 		}
 	}
@@ -1243,7 +1242,7 @@
 	char			*what = "?";
 	struct usb_device	*udev;
 	
-	if (length > 0xffff || vary >= length)
+	if (length < 1 || length > 0xffff || vary >= length)
 		return -EINVAL;
 
 	buf = kmalloc(length, SLAB_KERNEL);
@@ -1266,6 +1265,11 @@
 				0, 0, buf, len, USB_CTRL_SET_TIMEOUT);
 		if (retval != len) {
 			what = "write";
+			if (retval >= 0) {
+				INFO(dev, "ctrl_out, wlen %d (expected %d)\n",
+						retval, len);
+				retval = -EBADMSG;
+			}
 			break;
 		}
 
@@ -1275,6 +1279,11 @@
 				0, 0, buf, len, USB_CTRL_GET_TIMEOUT);
 		if (retval != len) {
 			what = "read";
+			if (retval >= 0) {
+				INFO(dev, "ctrl_out, rlen %d (expected %d)\n",
+						retval, len);
+				retval = -EBADMSG;
+			}
 			break;
 		}
 
@@ -1293,8 +1302,13 @@
 		}
 
 		len += vary;
+
+		/* [real world] the "zero bytes IN" case isn't really used.
+		 * hardware can easily trip up in this wierd case, since its
+		 * status stage is IN, not OUT like other ep0in transfers.
+		 */
 		if (len > length)
-			len = 0;
+			len = realworld ? 1 : 0;
 	}
 
 	if (retval < 0)
@@ -1519,6 +1533,11 @@
 	if (down_interruptible (&dev->sem))
 		return -ERESTARTSYS;
 
+	if (intf->dev.power.power_state != PMSG_ON) {
+		up (&dev->sem);
+		return -EHOSTUNREACH;
+	}
+
 	/* some devices, like ez-usb default devices, need a non-default
 	 * altsetting to have any active endpoints.  some tests change
 	 * altsettings; force a default so most tests don't need to check.
@@ -1762,8 +1781,10 @@
 	case 14:
 		if (!dev->info->ctrl_out)
 			break;
-		dev_dbg (&intf->dev, "TEST 14:  %d ep0out, 0..%d vary %d\n",
-				param->iterations, param->length, param->vary);
+		dev_dbg (&intf->dev, "TEST 14:  %d ep0out, %d..%d vary %d\n",
+				param->iterations,
+				realworld ? 1 : 0, param->length,
+				param->vary);
 		retval = ctrl_out (dev, param->iterations, 
 				param->length, param->vary);
 		break;
@@ -1927,6 +1948,27 @@
 	return 0;
 }
 
+static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)
+{
+	struct usbtest_dev	*dev = usb_get_intfdata (intf);
+
+	down (&dev->sem);
+	intf->dev.power.power_state = PMSG_SUSPEND;
+	up (&dev->sem);
+	return 0;
+}
+
+static int usbtest_resume (struct usb_interface *intf)
+{
+	struct usbtest_dev	*dev = usb_get_intfdata (intf);
+
+	down (&dev->sem);
+	intf->dev.power.power_state = PMSG_ON;
+	up (&dev->sem);
+	return 0;
+}
+
+
 static void usbtest_disconnect (struct usb_interface *intf)
 {
 	struct usbtest_dev	*dev = usb_get_intfdata (intf);
@@ -2115,6 +2157,8 @@
 	.probe =	usbtest_probe,
 	.ioctl =	usbtest_ioctl,
 	.disconnect =	usbtest_disconnect,
+	.suspend =	usbtest_suspend,
+	.resume =	usbtest_resume,
 };
 
 /*-------------------------------------------------------------------------*/