Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Dec 2007 15:56:09 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 131103 for review
Message-ID:  <200712171556.lBHFu9MD077133@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=131103

Change 131103 by hselasky@hselasky_laptop001 on 2007/12/17 15:55:39

	
	This change is device side related. Please see
	change 131102 for a detailed description.
	
	TODO: Add more comments.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_template.c#3 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_template.h#4 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#75 edit

Differences ...

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

@@ -70,8 +70,6 @@
 {
 	usb_endpoint_descriptor_t *ed;
 	const void **rd;
-	uint8_t *pEp;
-	uint8_t *pEpEnd;
 	uint16_t old_size;
 	uint16_t mps;
 	uint8_t ea = 0;			/* Endpoint Address */
@@ -104,57 +102,7 @@
 		/* escape for Zero Max Packet Size */
 		mps = 0;
 	}
-	if (ted->endpoint == 0) {
-		/* not initialized */
-		temp->err = USBD_NO_PIPE;
-		return;
-	} else if (ted->endpoint == UE_ADDR_ANY) {
-		if (temp->buf) {
-
-			/* search for a free endpoint */
-
-			pEp = temp->bEpToIface +
-			    ((ted->direction & (UE_DIR_IN |
-			    UE_DIR_OUT)) ? 1 : 0);
-			pEpEnd = pEp + USB_MAX_ENDPOINTS;
-			pEp += 2;	/* skip control endpoint */
-			while (1) {
-
-				if (pEp == pEpEnd) {
-					temp->err = USBD_NO_PIPE;
-					return;
-				}
-				if (*pEp == 0) {
-					/* found one */
-					*pEp = 1;	/* dummy value */
-					ea = (pEp - temp->bEpToIface) / 2;
-					break;
-				}
-				pEp += 2;
-			}
-
-		}
-	} else {
-		ea = (ted->endpoint & UE_ADDR);
-		pEp = temp->bEpToIface + (ea << 1) +
-		    ((ted->direction & (UE_DIR_IN |
-		    UE_DIR_OUT)) ? 1 : 0);
-
-		if (temp->buf) {
-			if (*pEp != temp->bInterfaceNumber) {
-				/*
-				 * An endpoint is being used in multiple USB
-				 * interfaces !
-				 */
-				temp->err = USBD_INVAL;
-				return;
-			}
-		} else {
-			*pEp = temp->bInterfaceNumber;
-		}
-	}
-
-	ea |= (ted->direction & (UE_DIR_IN | UE_DIR_OUT));
+	ea = (ted->direction & (UE_DIR_IN | UE_DIR_OUT));
 	et = (ted->bmAttributes & UE_XFERTYPE);
 
 	/*
@@ -320,9 +268,17 @@
     const struct usb_temp_device_desc *tdd)
 {
 	usb_device_descriptor_t *dd;
+	const void **pp;
 	const struct usb_temp_config_desc **tcd;
 	uint16_t old_size;
 
+	/* Store a pointer to our template device descriptor */
+	if (temp->buf) {
+		pp = USBD_ADD_BYTES(temp->buf, temp->size);
+		*pp = tdd;
+	}
+	temp->size += sizeof(void *);
+
 	/* Reserve memory */
 
 	old_size = temp->size;
@@ -374,7 +330,7 @@
 			break;
 		case USB_SPEED_VARIABLE:
 			USETW(dd->bcdUSB, 0x0250);
-			dd->bMaxPacketSize = 255;
+			dd->bMaxPacketSize = 255;	/* 512 bytes */
 			break;
 		default:
 			temp->err = USBD_INVAL;
@@ -384,15 +340,441 @@
 	return;
 }
 
-const void *
+static uint8_t
+usbd_hw_ep_match(const struct usbd_hw_ep_profile *pf,
+    uint8_t ep_type, uint8_t ep_dir_in)
+{
+	if (ep_type == UE_CONTROL) {
+		/* special */
+		return (pf->support_control);
+	}
+	if ((pf->support_in && ep_dir_in) ||
+	    (pf->support_out && !ep_dir_in)) {
+		if ((pf->support_interrupt && (ep_type == UE_INTERRUPT)) ||
+		    (pf->support_isochronous && (ep_type == UE_ISOCHRONOUS)) ||
+		    (pf->support_bulk && (ep_type == UE_BULK))) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+static uint8_t
+usbd_hw_ep_find_match(struct usbd_hw_ep_scratch *ues,
+    struct usbd_sw_ep_scratch *ep, uint8_t is_simplex)
+{
+	const struct usbd_hw_ep_profile *pf;
+	uint16_t distance;
+	uint16_t temp;
+	uint8_t n;
+	uint8_t best_n;
+	uint8_t dir_in;
+	uint8_t dir_out;
+
+	distance = 0xFFFF;
+	best_n = 0;
+
+	if (ep->needs_ep_type == UE_CONTROL) {
+		dir_in = 1;
+		dir_out = 1;
+	} else {
+		if (ep->needs_in) {
+			ep->needs_in = 0;
+			dir_in = 1;
+			dir_out = 0;
+		} else {
+			ep->needs_out = 0;
+			dir_in = 0;
+			dir_out = 1;
+		}
+	}
+
+	for (n = 1; n != (USB_MAX_ENDPOINTS / 2); n++) {
+
+		/* check if IN-endpoint is reserved */
+		if (dir_in) {
+			if (ues->bmInAlloc[n / 8] & (1 << (n % 8))) {
+				/* mismatch */
+				continue;
+			}
+		}
+		/* check if OUT-endpoint is reserved */
+		if (dir_out) {
+			if (ues->bmOutAlloc[n / 8] & (1 << (n % 8))) {
+				/* mismatch */
+				continue;
+			}
+		}
+		/* get HW endpoint profile */
+		pf = (ues->get_hw_ep_profile) (ues->udev, n);
+		if (pf == NULL) {
+			/* end of profiles */
+			break;
+		}
+		/* check simplex */
+		if (pf->is_simplex == is_simplex) {
+			/* mismatch */
+			continue;
+		}
+		/* check if HW endpoint matches */
+		if (!usbd_hw_ep_match(pf, ep->needs_ep_type, dir_in)) {
+			/* mismatch */
+			continue;
+		}
+		if (pf->max_frame_size >= ep->max_frame_size) {
+			temp = (pf->max_frame_size - ep->max_frame_size);
+			if (distance > temp) {
+				distance = temp;
+				best_n = n;
+				ep->pf = pf;
+			}
+		} else if ((ep->needs_ep_type == UE_BULK) ||
+		    (ep->needs_ep_type == UE_CONTROL)) {
+			/* frame size is not so important */
+			temp = (ep->max_frame_size - pf->max_frame_size);
+			if (distance > temp) {
+				distance = temp;
+				best_n = n;
+				ep->pf = pf;
+			}
+		}
+	}
+
+	/* see if we got a match */
+	if (best_n != 0) {
+		/* get the correct profile */
+		pf = ep->pf;
+
+		/* reserve IN-endpoint */
+		if (dir_in || pf->is_simplex) {
+			ues->bmInAlloc[best_n / 8] |=
+			    (1 << (best_n % 8));
+			ep->hw_endpoint_in = best_n | UE_DIR_IN;
+		}
+		/* reserve OUT-endpoint */
+		if (dir_out || pf->is_simplex) {
+			ues->bmOutAlloc[best_n / 8] |=
+			    (1 << (best_n % 8));
+			ep->hw_endpoint_out = best_n | UE_DIR_OUT;
+		}
+		/*
+		 * In case we choose an endpoint having a smaller Maximum
+		 * Frame Size than we wanted, we need to update the Maximum
+		 * Frame Size !
+		 */
+		if (ep->max_frame_size > pf->max_frame_size) {
+			ep->max_frame_size = pf->max_frame_size;
+		}
+		return (0);		/* got a match */
+	}
+	return (1);			/* failure */
+}
+
+static uint8_t
+usbd_hw_ep_get_needs(struct usbd_hw_ep_scratch *ues,
+    uint8_t ep_type, uint8_t is_complete)
+{
+	struct usbd_sw_ep_scratch *ep_iface;
+	struct usbd_sw_ep_scratch *ep_curr;
+	struct usbd_sw_ep_scratch *ep_max;
+	struct usbd_sw_ep_scratch *ep_end;
+	usb_descriptor_t *desc;
+	usb_interface_descriptor_t *id;
+	usb_endpoint_descriptor_t *ed;
+	uint16_t wMaxPacketSize;
+	uint16_t temp;
+	uint8_t allow_override;
+	uint8_t speed;
+
+	ep_iface = ues->ep_max;
+	ep_curr = ues->ep_max;
+	ep_end = ues->ep + USB_MAX_ENDPOINTS;
+	ep_max = ues->ep_max;
+	desc = NULL;
+	speed = ues->udev->speed;
+
+repeat:
+
+	while ((desc = usbd_desc_foreach(ues->cd, desc))) {
+
+		if ((desc->bDescriptorType == UDESC_INTERFACE) &&
+		    (desc->bLength >= sizeof(*id))) {
+
+			id = (void *)desc;
+
+			if (id->bAlternateSetting == 0) {
+				/* going forward */
+				ep_iface = ep_max;
+			} else {
+				/* reset */
+				ep_curr = ep_iface;
+			}
+		}
+		if ((desc->bDescriptorType == UDESC_ENDPOINT) &&
+		    (desc->bLength >= sizeof(*ed))) {
+
+			ed = (void *)desc;
+
+			goto handle_endpoint_desc;
+		}
+	}
+	ues->ep_max = ep_max;
+	return (0);
+
+handle_endpoint_desc:
+	temp = (ed->bmAttributes & UE_XFERTYPE);
+
+	if (temp == ep_type) {
+
+		if (ep_curr == ep_end) {
+			/* too many endpoints */
+			return (1);	/* failure */
+		}
+		wMaxPacketSize = UGETW(ed->wMaxPacketSize);
+		if ((wMaxPacketSize & 0xF800) &&
+		    (speed == USB_SPEED_HIGH)) {
+			/* handle frame multiplier */
+			temp = (wMaxPacketSize >> 11) & 3;
+			wMaxPacketSize &= 0x7FF;
+			if (temp == 2) {
+				wMaxPacketSize *= 2;
+			} else {
+				wMaxPacketSize *= 3;
+			}
+			allow_override = 0;
+		} else {
+			if ((ep_type == UE_BULK) ||
+			    (ep_type == UE_CONTROL)) {
+				allow_override = 1;
+			} else {
+				allow_override = 0;
+			}
+		}
+
+		if (is_complete) {
+
+			/*
+			 * We assume that
+			 * "ep_curr->max_frame_size"
+			 * is correct according to the
+			 * speed we are connected at !
+			 */
+			while (1) {
+
+				if (wMaxPacketSize <=
+				    ep_curr->max_frame_size) {
+					break;
+				}
+				if (wMaxPacketSize < 8) {
+					return (1);	/* failure */
+				}
+				if (!allow_override) {
+					return (1);	/* failure */
+				}
+				/*
+				 * We have a BULK or CONTROL
+				 * endpoint having a packet
+				 * size that the hardware
+				 * cannot handle ! Try to
+				 * work it around!
+				 */
+				wMaxPacketSize /= 2;
+				USETW(ed->wMaxPacketSize,
+				    wMaxPacketSize);
+			}
+
+			if (ed->bEndpointAddress & UE_DIR_IN) {
+				ed->bEndpointAddress =
+				    ep_curr->hw_endpoint_in;
+			} else {
+				ed->bEndpointAddress =
+				    ep_curr->hw_endpoint_out;
+			}
+
+		} else {
+
+			/* compute the maximum frame size */
+			if (ep_curr->max_frame_size < wMaxPacketSize) {
+				ep_curr->max_frame_size = wMaxPacketSize;
+			}
+			if (temp == UE_CONTROL) {
+				ep_curr->needs_in = 1;
+				ep_curr->needs_out = 1;
+			} else {
+				if (ed->bEndpointAddress & UE_DIR_IN) {
+					ep_curr->needs_in = 1;
+				} else {
+					ep_curr->needs_out = 1;
+				}
+			}
+			ep_curr->needs_ep_type = ep_type;
+		}
+
+		ep_curr++;
+		if (ep_max < ep_curr) {
+			ep_max = ep_curr;
+		}
+	}
+	goto repeat;
+}
+
+static usbd_status_t
+usbd_hw_ep_resolve(struct usbd_device *udev,
+    usb_descriptor_t *desc)
+{
+	struct usbd_hw_ep_scratch *ues;
+	struct usbd_sw_ep_scratch *ep;
+	struct usbd_hw_ep_profile *pf;
+	struct usbd_bus *bus;
+	usb_device_descriptor_t *dd;
+	uint16_t mps;
+
+	if (desc == NULL) {
+		return (USBD_INVAL);
+	}
+	/* get bus structure */
+	bus = udev->bus;
+
+	if (bus->methods->get_hw_ep_profile == NULL) {
+		return (USBD_INVAL);
+	}
+	if (desc->bDescriptorType == UDESC_DEVICE) {
+
+		if (desc->bLength < sizeof(*dd)) {
+			return (USBD_INVAL);
+		}
+		dd = (void *)desc;
+
+		/* get HW control endpoint 0 profile */
+		pf = (bus->methods->get_hw_ep_profile) (ues->udev, 0);
+		if (pf == NULL) {
+			return (USBD_INVAL);
+		}
+		if (!usbd_hw_ep_match(pf, UE_CONTROL, 0)) {
+			PRINTFN(-1, ("Endpoint 0 does not "
+			    "support control\n"));
+			return (USBD_INVAL);
+		}
+		mps = dd->bMaxPacketSize;
+
+		if (udev->speed == USB_SPEED_FULL) {
+			/*
+			 * We can optionally choose another packet size !
+			 */
+			while (1) {
+				/* check if "mps" is ok */
+				if (pf->max_frame_size >= mps) {
+					break;
+				}
+				/* reduce maximum packet size */
+				mps /= 2;
+
+				/* check if "mps" is too small */
+				if (mps < 8) {
+					return (USBD_INVAL);
+				}
+			}
+
+			dd->bMaxPacketSize = mps;
+
+		} else {
+			/* We only have one choice */
+			if (mps == 255) {
+				mps = 512;
+			}
+			/* Check if we support the specified wMaxPacketSize */
+			if (pf->max_frame_size < mps) {
+				return (USBD_INVAL);
+			}
+		}
+	}
+	if (desc->bDescriptorType != UDESC_CONFIG) {
+		return (USBD_INVAL);
+	}
+	if (desc->bLength < sizeof(*(ues->cd))) {
+		return (USBD_INVAL);
+	}
+	ues = udev->scratch[0].hw_ep_scratch;
+
+	bzero(ues, sizeof(*ues));
+
+	ues->ep_max = ues->ep;
+	ues->cd = (void *)desc;
+	ues->get_hw_ep_profile = bus->methods->get_hw_ep_profile;
+	ues->udev = udev;
+
+	/* Get all the endpoints we need */
+
+	if (usbd_hw_ep_get_needs(ues, UE_ISOCHRONOUS, 0) ||
+	    usbd_hw_ep_get_needs(ues, UE_INTERRUPT, 0) ||
+	    usbd_hw_ep_get_needs(ues, UE_CONTROL, 0) ||
+	    usbd_hw_ep_get_needs(ues, UE_BULK, 0)) {
+		return (USBD_INVAL);
+	}
+	for (ep = ues->ep; ep != ues->ep_max; ep++) {
+
+		while (ep->needs_in || ep->needs_out) {
+
+			/*
+		         * First try to use a simplex endpoint.
+		         * Then try to use a duplex endpoint.
+		         */
+			if (usbd_hw_ep_find_match(ues, ep, 1) &&
+			    usbd_hw_ep_find_match(ues, ep, 0)) {
+				return (USBD_INVAL);
+			}
+		}
+	}
+
+	ues->ep_max = ues->ep;
+
+	/* Update all endpoint addresses */
+
+	if (usbd_hw_ep_get_needs(ues, UE_ISOCHRONOUS, 1) ||
+	    usbd_hw_ep_get_needs(ues, UE_INTERRUPT, 1) ||
+	    usbd_hw_ep_get_needs(ues, UE_CONTROL, 1) ||
+	    usbd_hw_ep_get_needs(ues, UE_BULK, 1)) {
+		return (USBD_INVAL);
+	}
+	return (0);			/* success */
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_temp_get_tdd
+ *
+ * Returns:
+ *  NULL: No USB template device descriptor found.
+ *  Else: Pointer to the USB template device descriptor.
+ *------------------------------------------------------------------------*/
+static const struct usb_temp_device_desc *
+usbd_temp_get_tdd(struct usbd_device *udev)
+{
+	const void **pp;
+
+	pp = udev->usb_template_ptr;
+	if (pp == NULL) {
+		return (NULL);
+	}
+	return (*pp);
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_temp_get_device_desc
+ *
+ * Returns:
+ *  NULL: No USB device descriptor found.
+ *  Else: Pointer to USB device descriptor.
+ *------------------------------------------------------------------------*/
+static void *
 usbd_temp_get_device_desc(struct usbd_device *udev)
 {
-	const usb_device_descriptor_t *dd;
+	usb_device_descriptor_t *dd;
 
 	dd = udev->usb_template_ptr;
 	if (dd == NULL) {
 		return (NULL);
 	}
+	dd = USBD_ADD_BYTES(dd, sizeof(void *));
 	if (dd->bDescriptorType != UDESC_DEVICE) {
 		/* sanity check failed */
 		return (NULL);
@@ -400,11 +782,19 @@
 	return (dd);
 }
 
-const void *
-usbd_temp_get_config_desc(struct usbd_device *udev, uint8_t index)
+/*------------------------------------------------------------------------*
+ *	usbd_temp_get_config_desc
+ *
+ * Returns:
+ *  NULL: No USB config descriptor found.
+ *  Else: Pointer to USB config descriptor having index "index".
+ *------------------------------------------------------------------------*/
+static void *
+usbd_temp_get_config_desc(struct usbd_device *udev,
+    uint16_t *pLength, uint8_t index)
 {
-	const usb_device_descriptor_t *dd;
-	const usb_config_descriptor_t *cd;
+	usb_device_descriptor_t *dd;
+	usb_config_descriptor_t *cd;
 	uint16_t temp;
 
 	dd = usbd_temp_get_device_desc(udev);
@@ -425,14 +815,136 @@
 		temp = UGETW(cd->wTotalLength);
 		cd = USBD_ADD_BYTES(cd, temp);
 	}
+
+	if (pLength) {
+		*pLength = UGETW(cd->wTotalLength);
+	}
 	return (cd);
 }
 
 /*------------------------------------------------------------------------*
+ *	usbd_temp_get_string_desc
+ *
+ * Returns:
+ *  NULL: No string descriptor found.
+ *  Else: Pointer to a string descriptor.
+ *------------------------------------------------------------------------*/
+static const void *
+usbd_temp_get_string_desc(struct usbd_device *udev,
+    uint16_t lang_id, uint8_t string_index)
+{
+	const struct usb_temp_device_desc *tdd;
+
+	tdd = usbd_temp_get_tdd(udev);
+	if (tdd == NULL) {
+		return (NULL);
+	}
+	if (tdd->getStringDesc == NULL) {
+		return (NULL);
+	}
+	return ((tdd->getStringDesc) (lang_id, string_index));
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_temp_get_hub_desc
+ *
+ * Returns:
+ *  NULL: No USB HUB descriptor found.
+ *  Else: Pointer to a USB HUB descriptor.
+ *------------------------------------------------------------------------*/
+static const void *
+usbd_temp_get_hub_desc(struct usbd_device *udev)
+{
+	return (NULL);			/* needs to be implemented */
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_temp_get_desc
+ *
+ * This function is a demultiplexer for USB device requests.
+ *------------------------------------------------------------------------*/
+void
+usbd_temp_get_desc(struct usbd_device *udev, usb_device_request_t *req,
+    const void **pPtr, uint16_t *pLength)
+{
+	const uint8_t *buf;
+	uint16_t len;
+
+	buf = NULL;
+	len = 0;
+
+	switch (req->bmRequestType) {
+	case UT_READ_DEVICE:
+		switch (req->bRequest) {
+		case UR_GET_DESCRIPTOR:
+			goto tr_handle_get_descriptor;
+		default:
+			goto tr_stalled;
+		}
+		break;
+	case UT_READ_CLASS_DEVICE:
+		switch (req->bRequest) {
+		case UR_GET_DESCRIPTOR:
+			goto tr_handle_get_class_descriptor;
+		default:
+			goto tr_stalled;
+		}
+		break;
+	default:
+		goto tr_stalled;
+	}
+
+tr_handle_get_descriptor:
+	switch (req->wValue[1]) {
+	case UDESC_DEVICE:
+		if (req->wValue[0] & 0xff) {
+			goto tr_stalled;
+		}
+		buf = usbd_temp_get_device_desc(udev);
+		goto tr_valid;
+	case UDESC_CONFIG:
+		buf = usbd_temp_get_config_desc(udev,
+		    &len, req->wValue[0]);
+		goto tr_valid;
+	case UDESC_STRING:
+		buf = usbd_temp_get_string_desc(udev,
+		    UGETW(req->wIndex), req->wValue[0]);
+		goto tr_valid;
+	default:
+		goto tr_stalled;
+	}
+	goto tr_stalled;
+
+tr_handle_get_class_descriptor:
+	if (req->wValue[0] & 0xFF) {
+		goto tr_stalled;
+	}
+	buf = usbd_temp_get_hub_desc(udev);
+	goto tr_valid;
+
+tr_valid:
+	if (buf == NULL) {
+		goto tr_stalled;
+	}
+	if (len == 0) {
+		len = buf[0];
+	}
+	*pPtr = buf;
+	*pLength = len;
+	return;
+
+tr_stalled:
+	*pPtr = NULL;
+	*pLength = 0;
+	return;
+}
+
+/*------------------------------------------------------------------------*
  *	usbd_temp_setup
  *
- * This function generates USB descriptors according to
- * the given USB template device descriptor.
+ * This function generates USB descriptors according to the given USB
+ * template device descriptor. It will also try to figure out the best
+ * matching endpoint addresses using the hardware endpoint profiles.
  *
  * Returns:
  *    0: Success
@@ -443,15 +955,13 @@
     const struct usb_temp_device_desc *tdd)
 {
 	struct usbd_temp_setup *uts;
+	void *buf;
+	uint8_t n;
 
 	if (tdd == NULL) {
 		/* be NULL safe */
 		return (0);
 	}
-	if (tdd->pGetDescFn == NULL) {
-		/* not initialized properly */
-		return (USBD_INVAL);
-	}
 	uts = udev->scratch[0].temp_setup;
 
 	bzero(uts, sizeof(*uts));
@@ -480,14 +990,42 @@
 
 	usbd_make_device_desc(uts, tdd);
 
+	/*
+	 * Store a pointer to our descriptors:
+	 */
+	udev->usb_template_ptr = uts->buf;
+
 	if (uts->err) {
 		/* some error happened during second pass */
-		free(uts->buf, M_USB);
-		return (uts->err);
+		goto error;
+	}
+	/*
+	 * Resolve all endpoint addresses !
+	 */
+	buf = usbd_temp_get_device_desc(udev);
+	uts->err = usbd_hw_ep_resolve(udev, buf);
+	if (uts->err) {
+		PRINTFN(-1, ("Could not resolve endpoints for "
+		    "Device Descriptor\n"));
+		goto error;
+	}
+	for (n = 0;; n++) {
+
+		buf = usbd_temp_get_config_desc(udev, NULL, n);
+		uts->err = usbd_hw_ep_resolve(udev, buf);
+		if (uts->err) {
+			if (buf == NULL) {
+				break;
+			}
+			PRINTFN(-1, ("Could not resolve endpoints for "
+			    "Config Descriptor %u\n", n));
+			goto error;
+		}
 	}
-	udev->usb_template_ptr = uts->buf;
-	udev->usb_temp_get_desc = tdd->pGetDescFn;
+	return (uts->err);
 
+error:
+	usbd_temp_unsetup(udev);
 	return (uts->err);
 }
 
@@ -505,7 +1043,6 @@
 		free(udev->usb_template_ptr, M_USB);
 
 		udev->usb_template_ptr = NULL;
-		udev->usb_temp_get_desc = NULL;
 	}
 	return;
 }

==== //depot/projects/usb/src/sys/dev/usb/usb_template.h#4 (text+ko) ====

@@ -31,6 +31,8 @@
 #ifndef _USB_TEMPLATE_H_
 #define	_USB_TEMPLATE_H_
 
+typedef const void *(usbd_temp_get_string_desc_t)(uint16_t lang_id, uint8_t string_index);
+
 struct usb_temp_packet_size {
 	uint16_t mps[USB_SPEED_MAX];
 };
@@ -39,7 +41,6 @@
 	const void **ppRawDesc;
 	const struct usb_temp_packet_size *pPacketSize;
 	uint8_t	direction;		/* UE_DIR_IN or UE_DIR_OUT */
-	uint8_t	endpoint;		/* endpoint address */
 	uint8_t	bmAttributes;
 };
 
@@ -61,7 +62,7 @@
 };
 
 struct usb_temp_device_desc {
-	usbd_temp_get_desc_t *pGetDescFn;
+	usbd_temp_get_string_desc_t *getStringDesc;
 	const struct usb_temp_config_desc **ppConfigDesc;
 	uint16_t idVendor;
 	uint16_t idProduct;

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

@@ -3079,8 +3079,7 @@
 	goto tr_valid;
 
 tr_handle_get_descriptor:
-	(udev->usb_temp_get_desc) (
-	    udev, xfer->priv_mtx, &req, &ptr, &max_len);
+	usbd_temp_get_desc(udev, &req, &ptr, &max_len);
 	if (ptr == NULL) {
 		goto tr_stalled;
 	}
@@ -3362,17 +3361,7 @@
 	}
 	if (udev->flags.usb_mode == USB_MODE_DEVICE) {
 		PRINTFN(0, ("USB device mode\n"));
-		if ((req->bmRequestType == UT_READ_DEVICE) &&
-		    (req->bRequest == UR_GET_DESCRIPTOR)) {
-			(udev->usb_temp_get_desc) (
-			    udev, mtx, req, &desc, &temp);
-			if (desc == NULL) {
-				return (USBD_INVAL);
-			}
-		} else {
-			/* the rest we don't care about */
-			temp = 0;
-		}
+		usbd_temp_get_desc(udev, req, &desc, &temp);
 		if (length > temp) {
 			if (!(flags & USBD_SHORT_XFER_OK)) {
 				return (USBD_SHORT_XFER);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712171556.lBHFu9MD077133>