PERFORCE change 145314 for review

Weongyo Jeong weongyo at FreeBSD.org
Wed Jul 16 10:41:23 UTC 2008


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

Change 145314 by weongyo at weongyo_ws on 2008/07/16 10:40:51

	When we're handling URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, we should
	set a actual value which is responsed by the USB device not the status
	value.  This was a critical bug.

Affected files ...

.. //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#9 edit

Differences ...

==== //depot/projects/ndisusb/sys/compat/ndis/subr_usbd.c#9 (text+ko) ====

@@ -79,6 +79,8 @@
 static int32_t		 usbd_func_vendorclass(irp *);
 static int32_t		 usbd_func_selconf(irp *);
 static int32_t		 usbd_func_getdesc(irp *);
+static usbd_status	 usbd_get_desc_ndis(usbd_device_handle, int, int, int,
+			    void *, int *);
 static union usbd_urb	*usbd_geturb(irp *);
 static usbd_status	 usbd_init_ndispipe(irp *, usb_endpoint_descriptor_t *);
 static usbd_xfer_handle	 usbd_init_ndisxfer(irp *, usb_endpoint_descriptor_t *,
@@ -354,70 +356,61 @@
 	irp			*ip;
 {
 	device_t dev = IRP_NDIS_DEV(ip);
-	int i;
+	int actlen, i;
 	struct usb_attach_arg *uaa = device_get_ivars(dev);
 	struct usbd_urb_control_descriptor_request *ctldesc;
-	uint32_t len;
 	union usbd_urb *urb;
-	usb_config_descriptor_t cd, *cdp;
 	usbd_status status;
 
 	urb = usbd_geturb(ip);
 	ctldesc = &urb->uu_ctldesc;
-	if (ctldesc->ucd_desctype == UDESC_CONFIG) {
-		/* Get the short config descriptor. */
-		status = usbd_get_config_desc(uaa->device, ctldesc->ucd_idx,
-		    &cd);
-		if (status != USBD_NORMAL_COMPLETION) {
-			ctldesc->ucd_trans_buflen = 0;
-			return usbd_usb2urb(status);
-		}
-		len = MIN(UGETW(cd.wTotalLength), ctldesc->ucd_trans_buflen);
-		/* Get the full descriptor.  Try a few times for slow devices. */
-		for (i = 0; i < 3; i++) {
-			status = usbd_get_desc(uaa->device,
-			    ctldesc->ucd_desctype, ctldesc->ucd_idx,
-			    len, ctldesc->ucd_trans_buf);
-			if (status == USBD_NORMAL_COMPLETION)
-				break;
-			usbd_delay_ms(uaa->device, 200);
-		}
-		if (status != USBD_NORMAL_COMPLETION) {
-			ctldesc->ucd_trans_buflen = 0;
-			return usbd_usb2urb(status);
-		}
-
-		cdp = (usb_config_descriptor_t *)ctldesc->ucd_trans_buf;
-		if (cdp->bDescriptorType != UDESC_CONFIG) {
-			device_printf(dev, "bad desc %d\n",
-			    cdp->bDescriptorType);
-			status = USBD_INVAL;
-		}
-	} else if (ctldesc->ucd_desctype == UDESC_STRING) {
+	if (ctldesc->ucd_desctype == UDESC_STRING) {
 		/* Try a few times for slow devices.  */
 		for (i = 0; i < 3; i++) {
-			status = usbd_get_string(uaa->device,
+			status = usbd_get_string_desc(uaa->device,
 			    (UDESC_STRING << 8) + ctldesc->ucd_idx,
-			    ctldesc->ucd_trans_buf, ctldesc->ucd_trans_buflen);
-			if (status != USBD_NORMAL_COMPLETION)
+			    ctldesc->ucd_langid, ctldesc->ucd_trans_buf,
+			    &actlen);
+			if (actlen > ctldesc->ucd_trans_buflen)
+				panic("small string buffer for UDESC_STRING");
+			if (status == USBD_NORMAL_COMPLETION)
 				break;
 			usbd_delay_ms(uaa->device, 200);
 		}
 	} else
-		status = usbd_get_desc(uaa->device, ctldesc->ucd_desctype,
+		status = usbd_get_desc_ndis(uaa->device, ctldesc->ucd_desctype,
 		    ctldesc->ucd_idx, ctldesc->ucd_trans_buflen,
-		    ctldesc->ucd_trans_buf);
+		    ctldesc->ucd_trans_buf, &actlen);
 
 	if (status != USBD_NORMAL_COMPLETION) {
 		ctldesc->ucd_trans_buflen = 0;
 		return usbd_usb2urb(status);
 	}
 
-	ctldesc->ucd_trans_buflen = status;
-	ip->irp_iostat.isb_info = status;
+	ctldesc->ucd_trans_buflen = actlen;
+	ip->irp_iostat.isb_info = actlen;
 	return (USBD_STATUS_SUCCESS);
 }
 
+/*
+ * FIXME: at USB1, not USB2, framework, there's no a interface to get `actlen'.
+ * However, we need it!!!
+ */
+static usbd_status
+usbd_get_desc_ndis(usbd_device_handle dev, int type, int index, int len,
+    void *desc, int *actlen)
+{
+	usb_device_request_t req;
+
+	req.bmRequestType = UT_READ_DEVICE;
+	req.bRequest = UR_GET_DESCRIPTOR;
+	USETW2(req.wValue, type, index);
+	USETW(req.wIndex, 0);
+	USETW(req.wLength, len);
+	return usbd_do_request_flags_pipe(dev, dev->default_pipe, &req, desc,
+	    0, actlen, USBD_DEFAULT_TIMEOUT);
+}
+
 static int32_t
 usbd_func_selconf(ip)
 	irp			*ip;


More information about the p4-projects mailing list