Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Sep 2007 16:09:21 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 126743 for review
Message-ID:  <200709231609.l8NG9Lx5095951@repoman.freebsd.org>

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

Change 126743 by hselasky@hselasky_laptop001 on 2007/09/23 16:09:11

	FYI; The comments follow the P4 diff from top to bottom.
	
	- the "usbd_devinfo_vp()" function has been removed. Now the
	  information that was once provided by this function is stored
	  in "udev->manufacturer" and "udev->product".
	
	- new internal function "usbd_finish_vp_info()". This function
	  will simply trim away spaces from "udev->manufacturer",
	  "udev->product" and make sure that these arrays have a sane
	  description string, if empty.
	
	- the "usbd_devinfo()" function now intelligently uses the
	  "bDeviceClass" value to decide if the class should be shown or not.
	
	- factored out ADD_BYTES() into USBD_ADD_BYTES()
	
	- new global function "usbd_pause_mtx()". Simply a wrapper for "msleep()".
	
	- "usbd_get_hdesc()" has been moved into "usb_hid.c" so that
	  HID parsing and other related functions are in the same file.
	
	- "usbd_find_idesc()", "usbd_find_edesc()"; Use correct type for
	  "iface_index" and "alt_index". There will never be more than "255"
	  alternate settings or interfaces, hence you will not be able to program
	  the USB device for more than 256 alternate settings according
	  to the USB specification.
	
	- "usbd_find_idesc()", "usbd_find_edesc()"; No functional changes.
	  Some refactorisation.
	
	- correct a misleading comment about the USB transaction translator.
	
	- add a "mtx_assert()" so that you more easily know what
	  mutexes must be locked before making a call.
	
	- "usbd_free_pipe_data()" now uses a mask to select which
	  interfaces are selected. Typical masks are "0" and "0-1".
	
	- "usbd_fill_iface_data"; Speed and wMaxPacketSize checks have
	  been moved into "usbd_transfer_setup_sub()".
	
	- "usbd_search_and_set_config()" was renamed back to "usbd_set_config_no()".
	
	- No need to loop on "usbreq_get_desc()", hence this function
	  will already loop internally, when specified by the "retries"
	  parameter.
	
	- passing a mutex to "usbd_do_request_flags()" and all
	  "usbreq_xxx()" functions is now mandatory.
	
	- "usbd_set_alt_interface_index()" is now part of
	  "usbd_subr.c", hence it will mess with the internal structures
	  and stuff, and not just do an USB request.
	
	- "usbd_probe_and_attach()"; get rid of passing USB port information.
	
	- specify valid USB speed combinations in the table
	  "usbd_hub_speed_combs[]", hence probably deciding validity
	  will become more complicated than a greater or less than
	  check.
	
	- "usbd_new_device()";
	
	   - search free device address from the beginning
	   - initialize new default mutex and sx lock.
	   - when a speed combination is not valid we reject instead
	     of reducing the speed.
	   - high-speed HUB address and port number is stored 
	     in "struct usbd_device".
	   - several size checks have been factored out.
	   - cache some common strings by default and pre-figure out
	     the laguage ID
	
	- "usbd_set_desc()"; stack reduction de-luxe
	
	- "usbd_get_page()" can only be used on pages that have a
	  length equal to "USBD_PAGE_SIZE" for sake of optimisation.
	
	- "usbd_uiomove()" new function.
	
	- "struct usbd_page_info" and assosiated functions using it
	  has been removed.
	
	- "usbd_std_transfer_setup()" has been replaced by
	  "usbd_transfer_setup_sub()".
	
	- all "usbd_get_max..." functions were removed. The
	  information is now stored in "struct usbd_xfer".

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#42 edit

Differences ...

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

@@ -102,42 +102,32 @@
 }
 
 static void
-usbd_devinfo_vp(struct usbd_device *udev, char *v, char *p, uint16_t v_len, 
-		uint16_t p_len, uint8_t usedev)
+usbd_finish_vp_info(struct usbd_device *udev)
 {
 	usb_device_descriptor_t *udd = &udev->ddesc;
-	char *vendor;
-	char *product;
+	uint8_t *vendor;
+	uint8_t *product;
 #ifdef USBVERBOSE
 	const struct usb_knowndev *kdp;
 #endif
 	uint16_t vendor_id;
 	uint16_t product_id;
-	usbd_status err;
 
-	v[0] = 0;
-	p[0] = 0;
+	usbd_trim_spaces(udev->manufacturer);
+	usbd_trim_spaces(udev->product);
 
-	if(udev == NULL) {
-		return;
+	if (udev->manufacturer[0]) {
+	    vendor = udev->manufacturer;
+	} else {
+	    vendor = NULL;
 	}
 
-	if (usedev)
-	{
-		err = usbreq_get_string_any
-		  (udev, udd->iManufacturer, v, v_len);
-
-		usbd_trim_spaces(v);
-
-		err = usbreq_get_string_any
-		  (udev, udd->iProduct, p, p_len);
-
-		usbd_trim_spaces(p);
+	if (udev->product[0]) {
+	    product = udev->product;
+	} else {
+	    product = NULL;
 	}
 
-	vendor = (*v) ? v : NULL;
-	product = (*p) ? p : NULL;
-
 	vendor_id = UGETW(udd->idVendor);
 	product_id = UGETW(udd->idProduct);
 
@@ -162,19 +152,23 @@
 	}
 #endif
 	if (vendor && *vendor) {
-	    if (v != vendor) {
-	        strlcpy(v, vendor, v_len);
+	    if (udev->manufacturer != vendor) {
+	        strlcpy(udev->manufacturer, vendor,
+			sizeof(udev->manufacturer));
 	    }
 	} else {
-	    snprintf(v, v_len, "vendor 0x%04x", vendor_id);
+	    snprintf(udev->manufacturer,
+		     sizeof(udev->manufacturer), "vendor 0x%04x", vendor_id);
 	}
 
 	if (product && *product) {
-	    if (p != product) {
-	        strlcpy(p, product, p_len);
+	    if (udev->product != product) {
+	        strlcpy(udev->product, product,
+			sizeof(udev->product));
 	    }
 	} else {
-	    snprintf(p, p_len, "product 0x%04x", product_id);
+	    snprintf(udev->product,
+		     sizeof(udev->product), "product 0x%04x", product_id);
 	}
 	return;
 }
@@ -188,24 +182,19 @@
 }
 
 void
-usbd_devinfo(struct usbd_device *udev, int showclass, 
-	     char *dst_ptr, u_int16_t dst_len)
+usbd_devinfo(struct usbd_device *udev, char *dst_ptr, uint16_t dst_len)
 {
 	usb_device_descriptor_t *udd = &udev->ddesc;
-	char vendor[USB_MAX_STRING_LEN];
-	char product[USB_MAX_STRING_LEN];
-	u_int16_t bcdDevice, bcdUSB;
-
-	usbd_devinfo_vp(udev, vendor, product, 
-			sizeof(vendor), sizeof(product), 1);
+	uint16_t bcdDevice;
+	uint16_t bcdUSB;
 
 	bcdUSB = UGETW(udd->bcdUSB);
 	bcdDevice = UGETW(udd->bcdDevice);
 
-	if(showclass)
+	if (udd->bDeviceClass != 0xFF)
 	{
 	    snprintf(dst_ptr, dst_len, "%s %s, class %d/%d, rev %x.%02x/"
-		     "%x.%02x, addr %d", vendor, product,
+		     "%x.%02x, addr %d", udev->manufacturer, udev->product,
 		     udd->bDeviceClass, udd->bDeviceSubClass,
 		     (bcdUSB >> 8), bcdUSB & 0xFF,
 		     (bcdDevice >> 8), bcdDevice & 0xFF,
@@ -214,7 +203,7 @@
 	else
 	{
 	    snprintf(dst_ptr, dst_len, "%s %s, rev %x.%02x/"
-		     "%x.%02x, addr %d", vendor, product,
+		     "%x.%02x, addr %d", udev->manufacturer, udev->product,
 		     (bcdUSB >> 8), bcdUSB & 0xFF,
 		     (bcdDevice >> 8), bcdDevice & 0xFF,
 		     udev->address);
@@ -254,7 +243,32 @@
 	usb_delay_ms(udev->bus, ms);
 }
 
-#define ADD_BYTES(ptr,len) ((void *)(((u_int8_t *)(ptr)) + (len)))
+/*------------------------------------------------------------------------*
+ *	 usbd_pause_mtx - factored out code
+ *
+ * NOTE: number of milliseconds per second is 1024 for sake of optimisation
+ *------------------------------------------------------------------------*/
+void
+usbd_pause_mtx(struct mtx *mtx, uint32_t ms)
+{
+	int error;
+
+	if (cold) {
+	    ms = (ms+1) * 1024;
+	    DELAY(ms);
+
+	} else {
+
+	    ms = USBD_MS_TO_TICKS(ms);
+
+	    if (ms == 0) {
+	        ms = 1;
+	    }
+
+	    error = mtx_sleep(&error, mtx, 0, "pause_mtx", ms);
+	}
+	return;
+}
 
 usb_descriptor_t *
 usbd_desc_foreach(usb_config_descriptor_t *cd, usb_descriptor_t *desc)
@@ -265,54 +279,30 @@
 	    return NULL;
 	}
 
-	end = ADD_BYTES(cd, UGETW(cd->wTotalLength));
+	end = USBD_ADD_BYTES(cd, UGETW(cd->wTotalLength));
 
 	if (desc == NULL) {
-	    desc = ADD_BYTES(cd, 0);
+	    desc = USBD_ADD_BYTES(cd, 0);
 	} else {
-	    desc = ADD_BYTES(desc, desc->bLength);
+	    desc = USBD_ADD_BYTES(desc, desc->bLength);
 	}
 	return (((((void *)desc) >= ((void *)cd)) &&
 		 (((void *)desc) < end) &&
-		 (ADD_BYTES(desc,desc->bLength) >= ((void *)cd)) &&
-		 (ADD_BYTES(desc,desc->bLength) <= end) &&
+		 (USBD_ADD_BYTES(desc,desc->bLength) >= ((void *)cd)) &&
+		 (USBD_ADD_BYTES(desc,desc->bLength) <= end) &&
 		 (desc->bLength >= sizeof(*desc))) ? desc : NULL);
 }
 
-usb_hid_descriptor_t *
-usbd_get_hdesc(usb_config_descriptor_t *cd, usb_interface_descriptor_t *id)
-{
-	usb_descriptor_t *desc = (void *)id;
-
-	if(desc == NULL) {
-	    return NULL;
-	}
-
-	while ((desc = usbd_desc_foreach(cd, desc)))
-	{
-		if ((desc->bDescriptorType == UDESC_HID) &&
-		    (desc->bLength >= USB_HID_DESCRIPTOR_SIZE(0)))
-		{
-			return (void *)desc;
-		}
-
-		if (desc->bDescriptorType == UDESC_INTERFACE)
-		{
-			break;
-		}
-	}
-	return NULL;
-}
-
 usb_interface_descriptor_t *
-usbd_find_idesc(usb_config_descriptor_t *cd, u_int16_t iface_index, 
-		u_int16_t alt_index)
+usbd_find_idesc(usb_config_descriptor_t *cd,
+		uint8_t iface_index, uint8_t alt_index)
 {
 	usb_descriptor_t *desc = NULL;
 	usb_interface_descriptor_t *id;
-	u_int16_t curidx = 0xFFFF;
-	u_int16_t lastidx = 0xFFFF;
-	u_int16_t curaidx = 0;
+	uint8_t curidx = 0;
+	uint8_t lastidx = 0;
+	uint8_t curaidx = 0;
+	uint8_t first = 1;
 
 	while ((desc = usbd_desc_foreach(cd, desc)))
 	{
@@ -321,16 +311,20 @@
 	    {
 	        id = (void *)desc;
 
-		if(id->bInterfaceNumber != lastidx)
-		{
+		if (first) {
+		    first = 0;
+		    lastidx = id->bInterfaceNumber;
+
+		} else if (id->bInterfaceNumber != lastidx) {
+
 		    lastidx = id->bInterfaceNumber;
 		    curidx++;
 		    curaidx = 0;
-		}
-		else
-		{
+
+		} else {
 		    curaidx++;
 		}
+
 		if((iface_index == curidx) && (alt_index == curaidx))
 		{
 		    return (id);
@@ -341,18 +335,18 @@
 }
 
 usb_endpoint_descriptor_t *
-usbd_find_edesc(usb_config_descriptor_t *cd, u_int16_t iface_index, 
-		u_int16_t alt_index, u_int16_t endptidx)
+usbd_find_edesc(usb_config_descriptor_t *cd,
+		uint8_t iface_index, uint8_t alt_index, uint8_t ep_index)
 {
 	usb_descriptor_t *desc = NULL;
 	usb_interface_descriptor_t *d;
-	u_int16_t curidx = 0;
+	uint8_t curidx = 0;
 
 	d = usbd_find_idesc(cd, iface_index, alt_index);
 	if (d == NULL)
 	    return NULL;
 
-	if (endptidx >= d->bNumEndpoints) /* quick exit */
+	if (ep_index >= d->bNumEndpoints) /* quick exit */
 	    return NULL;
 
 	desc = ((void *)d);
@@ -365,10 +359,14 @@
 
 	    if (desc->bDescriptorType == UDESC_ENDPOINT) {
 
-	        if (curidx == endptidx) {
-		    return ((desc->bLength >= USB_ENDPOINT_DESCRIPTOR_SIZE) ? 
-			    ((void *)desc) : NULL);
+	        if (curidx == ep_index) {
+		  if (desc->bLength < USB_ENDPOINT_DESCRIPTOR_SIZE) {
+		      /* endpoint index is invalid */
+		      break;
+		  }
+		  return ((void *)desc);
 		}
+
 		curidx++;
 	    }
 	}
@@ -386,8 +384,9 @@
  * matching the same criteria.
  *------------------------------------------------------------------------*/
 void *
-usbd_find_descriptor(struct usbd_device *udev, void *id, uint16_t iface_index,
-		     int16_t type, int16_t subtype)
+usbd_find_descriptor(struct usbd_device *udev, void *id, uint8_t iface_index,
+		     uint8_t type, uint8_t type_mask,
+		     uint8_t subtype, uint8_t subtype_mask)
 {
 	usb_descriptor_t *desc;
 	usb_config_descriptor_t *cd;
@@ -418,11 +417,8 @@
 			break;
 		}
 
-		if (((type == USBD_TYPE_ANY) ||
-		     (type == desc->bDescriptorType)) &&
-		    ((subtype == USBD_SUBTYPE_ANY) ||
-		     (subtype == desc->bDescriptorSubtype)))
-		{
+		if (((desc->bDescriptorType & type_mask) == type) &&
+		    ((desc->bDescriptorSubtype & subtype_mask) == subtype)) {
 			return desc;
 		}
 	}
@@ -494,7 +490,7 @@
  *
  * USB HUBs have a very simple Transaction Translator, that will
  * simply pipeline all the SPLIT transactions. That means that the
- * first one queued will be executed!
+ * transactions will be executed in the order they are queued!
  *
  */
 
@@ -524,6 +520,8 @@
 	struct usbd_bus *bus = udev->bus;
 	struct usbd_hub *hub;
 
+	mtx_assert(&(bus->mtx), MA_OWNED);
+
 	if (usbd_get_speed(udev) == USB_SPEED_HIGH) {
 	    if (slot >= USB_HS_MICRO_FRAMES_MAX) {
 	        slot = usbd_find_best_slot(bus->uframe_usage, 0, 
@@ -534,7 +532,15 @@
 	    if (usbd_get_speed(udev) == USB_SPEED_LOW) {
 	        len *= 8;
 	    }
-	    hub = udev->myhsport->parent->hub;
+
+	    /*
+	     * The Host Controller Driver should have
+	     * performed checks so that the lookup
+	     * below does not result in a NULL pointer
+	     * access.
+	     */
+
+	    hub = bus->devices[udev->hs_hub_addr]->hub;
 	    if (slot >= USB_HS_MICRO_FRAMES_MAX) {
 	        slot = usbd_find_best_slot(hub->uframe_usage, 
 					   USB_FS_ISOC_UFRAME_MAX, 6);
@@ -580,10 +586,9 @@
 
 	isoc_time = usbd_isoc_time_expand(udev->bus, isoc_time);
 
-	if (udev->myhsport &&
-	    udev->myhsport->parent->hub) {
+	hs_hub = udev->bus->devices[udev->hs_hub_addr]->hub;
 
-	    hs_hub = udev->myhsport->parent->hub;
+	if (hs_hub != NULL) {
 
 	    fss_a = hs_hub->fs_isoc_schedule + 
 	      (hs_hub->isoc_last_time % USB_ISOC_TIME_MAX);
@@ -646,20 +651,22 @@
 	return slot;
 }
 
-/* NOTE: pipes should not be in use when
- * ``usbd_free_pipe_data()'' is called
- */
+/*------------------------------------------------------------------------*
+ *	usbd_free_pipe_data
+ *
+ * NOTE: The interface pipes should not be in use when
+ * this function is called !
+ *------------------------------------------------------------------------*/
 static void
-usbd_free_pipe_data(struct usbd_device *udev, int iface_index)
+usbd_free_pipe_data(struct usbd_device *udev,
+		    uint8_t iface_index, uint8_t iface_mask)
 {
 	struct usbd_pipe *pipe = udev->pipes;
 	struct usbd_pipe *pipe_end = udev->pipes_end;
 
 	while (pipe != pipe_end)
 	{
-		if((iface_index == pipe->iface_index) ||
-		   (iface_index == -1))
-		{
+		if ((pipe->iface_index & iface_mask) == iface_index) {
 			/* free pipe */
 			pipe->edesc = NULL;
 		}
@@ -668,8 +675,12 @@
 	return;
 }
 
+/*------------------------------------------------------------------------*
+ *	usbd_fill_iface_data
+ *------------------------------------------------------------------------*/
 usbd_status
-usbd_fill_iface_data(struct usbd_device *udev, int iface_index, int alt_index)
+usbd_fill_iface_data(struct usbd_device *udev,
+		     uint8_t iface_index, uint8_t alt_index)
 {
 	struct usbd_interface *iface = usbd_get_iface(udev,iface_index);
 	struct usbd_pipe *pipe = udev->pipes;
@@ -704,7 +715,7 @@
 	pipe = &udev->pipes[0];
 
 	/* free old pipes if any */
-	usbd_free_pipe_data(udev, iface_index);
+	usbd_free_pipe_data(udev, iface_index, 0-1);
 
 	id = usbd_find_idesc(udev->cdesc, iface_index, alt_index);
 	if(id == NULL)
@@ -742,31 +753,6 @@
 	found:
 		ed = (void *)desc;
 
-		if(udev->speed == USB_SPEED_HIGH)
-		{
-			/* control and bulk endpoints have fixed max packet sizes */
-			switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
-			case UE_CONTROL:
-				USETW(ed->wMaxPacketSize, USB_2_MAX_CTRL_PACKET);
-				break;
-			case UE_BULK:
-				USETW(ed->wMaxPacketSize, USB_2_MAX_BULK_PACKET);
-				break;
-			}
-		}
-
-		if (usbd_get_max_frame_size(ed) == 0) {
-#ifdef USB_DEBUG
-			printf("%s: invalid wMaxPacketSize=0x%04x, addr=%d!\n",
-			       __FUNCTION__, UGETW(ed->wMaxPacketSize),
-			       udev->address);
-#endif
-			/* avoid division by zero 
-			 * (in EHCI/UHCI/OHCI drivers) 
-			 */
-			usbd_set_max_packet_size_count(ed, USB_MAX_IPACKET, 1);
-		}
-
 		/* find a free pipe */
 		while (pipe != pipe_end)
 		{
@@ -787,7 +773,7 @@
 	       __FUNCTION__, udev->address);
 
 	/* free old pipes if any */
-	usbd_free_pipe_data(udev, iface_index);
+	usbd_free_pipe_data(udev, iface_index, 0-1);
 	return (USBD_INVAL);
 }
 
@@ -800,7 +786,7 @@
 	/* mtx_assert() */
 
 	/* free all pipes, if any */
-	usbd_free_pipe_data(udev, -1);
+	usbd_free_pipe_data(udev, 0, 0);
 
 	/* free all interfaces, if any */
 	while (iface != iface_end)
@@ -819,7 +805,15 @@
 	return;
 }
 
-/* - USB config 0
+/*------------------------------------------------------------------------*
+ *	usbd_set_config_no
+ *
+ * This function will search all the configuration descriptors for a
+ * matching configuration number. It is recommended to use 
+ * the function "usbd_set_config_index()" when the configuration
+ * number does not matter.
+ *
+ * - USB config 0
  *   - USB interfaces
  *     - USB alternative interfaces
  *       - USB pipes
@@ -828,13 +822,13 @@
  *   - USB interfaces
  *     - USB alternative interfaces
  *       - USB pipes
- */
+ *------------------------------------------------------------------------*/
 usbd_status
-usbd_search_and_set_config(struct usbd_device *udev, int no, int msg)
+usbd_set_config_no(struct usbd_device *udev, uint8_t no, uint8_t msg)
 {
 	usb_config_descriptor_t cd;
 	usbd_status err;
-	int index;
+	uint8_t index;
 
 	if(no == USB_UNCONFIG_NO)
 	{
@@ -848,7 +842,7 @@
 	    index < udev->ddesc.bNumConfigurations;
 	    index++)
 	{
-		err = usbreq_get_config_desc(udev, index, &cd);
+		err = usbreq_get_config_desc(udev, &usb_global_lock, &cd, index);
 		if(err)
 		{
 			return (err);
@@ -862,13 +856,18 @@
 }
 
 usbd_status
-usbd_set_config_index(struct usbd_device *udev, int index, int msg)
+usbd_set_config_index(struct usbd_device *udev, uint8_t index, uint8_t msg)
 {
 	usb_status_t ds;
 	usb_hub_descriptor_t hd;
-	usb_config_descriptor_t cd, *cdp;
+	usb_config_descriptor_t cd;
+	usb_config_descriptor_t *cdp;
+	uint16_t len;
+	uint16_t power;
+	uint16_t max_power;
+	uint8_t nifc;
+	uint8_t selfpowered;
 	usbd_status err;
-	int nifc, len, selfpowered, power;
 
 	PRINTFN(5,("udev=%p index=%d\n", udev, index));
 
@@ -877,12 +876,12 @@
 		/* leave unallocated when
 		 * unconfiguring the device
 		 */
-		err = usbreq_set_config(udev, USB_UNCONFIG_NO);
+		err = usbreq_set_config(udev, &usb_global_lock, USB_UNCONFIG_NO);
 		goto error;
 	}
 
 	/* get the short descriptor */
-	err = usbreq_get_config_desc(udev, index, &cd);
+	err = usbreq_get_config_desc(udev, &usb_global_lock, &cd, index);
 	if(err)
 	{
 		goto error;
@@ -901,25 +900,13 @@
 
 	cdp = udev->cdesc;
 
-	/* Get the full descriptor. Try a few times for slow devices. */
-	for (nifc = 0; nifc < 3; nifc++) {
+	/* Get the full descriptor. Try 3 times for slow devices. */
 
-	    err = usbreq_get_desc(udev, UDESC_CONFIG, index, len, cdp, 3);
-
-	    if (!err) break;
-
-	    usbd_delay_ms(udev, 200);
-	}
-
+	err = usbreq_get_desc(udev, &usb_global_lock, cdp, len, len, 
+			      0, UDESC_CONFIG, index, 3);
 	if (err)
 		goto error;
-	if(cdp->bDescriptorType != UDESC_CONFIG)
-	{
-		PRINTF(("bad desc %d\n",
-			     cdp->bDescriptorType));
-		err = USBD_INVAL;
-		goto error;
-	}
+
 	if(cdp->bNumInterface > (sizeof(udev->ifaces)/sizeof(udev->ifaces[0])))
 	{
 		PRINTF(("too many interfaces: %d\n", cdp->bNumInterface));
@@ -939,7 +926,8 @@
 				 * It seems that the power status can be
 				 * determined by the hub characteristics.
 				 */
-				err = usbreq_get_hub_descriptor(udev, &hd);
+				err = usbreq_get_hub_descriptor
+				  (udev, &usb_global_lock, &hd);
 
 				if(!err &&
 				   (UGETW(hd.wHubCharacteristics) &
@@ -951,7 +939,9 @@
 					 UGETW(hd.wHubCharacteristics),
 					 usbd_errstr(err)));
 			} else {
-				err = usbreq_get_device_status(udev, &ds);
+				err = usbreq_get_device_status
+				  (udev, &usb_global_lock, &ds);
+
 				if(!err &&
 				   (UGETW(ds.wStatus) & UDS_SELF_POWERED))
 				{
@@ -971,18 +961,26 @@
 
 	/* Check if we have enough power. */
 	power = cdp->bMaxPower * 2;
-	if(power > udev->powersrc->power)
+
+	if (udev->parent_hub) {
+	  max_power = udev->parent_hub->hub->portpower;
+	} else {
+	  max_power = USB_MAX_POWER;
+	}
+
+	if(power > max_power)
 	{
-		PRINTF(("power exceeded %d %d\n", power, udev->powersrc->power));
+		PRINTF(("power exceeded %d %d\n", power, max_power));
+
 		/* XXX print nicer message */
 		if(msg)
 		{
 			device_printf(udev->bus->bdev,
-				      "device addr %d (config %d) exceeds power "
-				      "budget, %d mA > %d mA\n",
-				      udev->address,
-				      cdp->bConfigurationValue,
-				      power, udev->powersrc->power);
+				"device addr %d (config %d) exceeds power "
+				"budget, %d mA > %d mA\n",
+				udev->address,
+				cdp->bConfigurationValue,
+				power, max_power);
 		}
 		err = USBD_NO_POWER;
 		goto error;
@@ -993,7 +991,8 @@
 	udev->config = cdp->bConfigurationValue;
 
 	/* Set the actual configuration value. */
-	err = usbreq_set_config(udev, cdp->bConfigurationValue);
+	err = usbreq_set_config(udev, &usb_global_lock, 
+				cdp->bConfigurationValue);
 	if(err)
 	{
 		goto error;
@@ -1018,9 +1017,33 @@
 	return (err);
 }
 
+usbd_status
+usbd_set_alt_interface_index(struct usbd_device *udev,
+			     uint8_t iface_index, uint8_t alt_index)
+{
+	struct usbd_interface *iface = usbd_get_iface(udev, iface_index);
+	usbd_status err;
+
+	if (iface == NULL) {
+	    err = USBD_INVAL;
+	    goto done;
+	}
+
+	err = usbd_fill_iface_data(udev, iface_index, alt_index);
+	if(err) {
+	    goto done;
+	}
+
+	err = usbreq_set_alt_interface_no
+	  (udev, &usb_global_lock, iface_index, 
+	   iface->idesc->bAlternateSetting);
+
+ done:
+	return err;
+}
+
 int
-usbd_fill_deviceinfo(struct usbd_device *udev, struct usb_device_info *di,
-		     int usedev)
+usbd_fill_deviceinfo(struct usbd_device *udev, struct usb_device_info *di)
 {
 	struct usbd_port *p;
 	uint16_t s;
@@ -1034,11 +1057,16 @@
 
 	bzero(di, sizeof(di[0]));
 
+	mtx_lock(&usb_global_lock);
+
 	di->udi_bus = device_get_unit(udev->bus->bdev);
 	di->udi_addr = udev->address;
-	usbd_devinfo_vp(udev, di->udi_vendor, di->udi_product, 
-			sizeof(di->udi_vendor), sizeof(di->udi_product), usedev);
-	usbd_printBCD(di->udi_release, sizeof(di->udi_release), UGETW(udev->ddesc.bcdDevice));
+	strlcpy(di->udi_vendor, udev->manufacturer, 
+		sizeof(di->udi_vendor));
+	strlcpy(di->udi_product, udev->product,
+		sizeof(di->udi_product));
+	usbd_printBCD(di->udi_release, sizeof(di->udi_release),
+		      UGETW(udev->ddesc.bcdDevice));
 	di->udi_vendorNo = UGETW(udev->ddesc.idVendor);
 	di->udi_productNo = UGETW(udev->ddesc.idProduct);
 	di->udi_releaseNo = UGETW(udev->ddesc.bcdDevice);
@@ -1071,12 +1099,10 @@
 		    i++)
 		{
 			p = &udev->hub->ports[i];
-			if(p->device)
-			{
-				err = p->device->address;
-			}
-			else
-			{
+
+			if (p->device_addr != USB_START_ADDR) {
+				err = p->device_addr;
+			} else {
 				s = UGETW(p->status.wPortStatus);
 				if (s & UPS_PORT_ENABLED)
 				{
@@ -1099,6 +1125,7 @@
 		}
 		di->udi_nports = udev->hub->hubdesc.bNbrPorts;
 	}
+	mtx_unlock(&usb_global_lock);
 	return 0;
 }
 
@@ -1149,25 +1176,23 @@
 	return;
 }
 
-/* "usbd_probe_and_attach()" is called 
- * from "usbd_new_device()" and "uhub_explore()"
- */
+/*------------------------------------------------------------------------*
+ *	usbd_probe_and_attach
+ *
+ * This function is called from "uhub_explore_sub()"
+ *------------------------------------------------------------------------*/
 usbd_status
-usbd_probe_and_attach(device_t parent, int port, struct usbd_port *up)
+usbd_probe_and_attach(device_t parent, struct usbd_device *udev)
 {
 	struct usb_attach_arg uaa;
-	struct usbd_device *udev = up->device;
 	device_t bdev = NULL;
 	usbd_status err = 0;
 	u_int8_t config;
 	u_int8_t i;
 
-	up->last_refcount = usb_driver_added_refcount;
-
 	if(udev == NULL)
 	{
-		PRINTF(("%s: port %d has no device\n", 
-			device_get_nameunit(parent), port));
+		PRINTF(("udev == NULL\n"));
 		return (USBD_INVAL);
 	}
 
@@ -1178,7 +1203,7 @@
 	/* probe and attach */
 
 	uaa.device = udev;
-	uaa.port = port;
+	uaa.port = udev->port_no;
 	uaa.configno = -1;
 	uaa.vendor = UGETW(udev->ddesc.idVendor);
 	uaa.product = UGETW(udev->ddesc.idProduct);
@@ -1242,7 +1267,7 @@
 			    device_printf(parent,
 					  "port %d, set config at addr %d "
 					  "failed, error=%s\n",
-					  port, udev->address, 
+					  udev->port_no, udev->address, 
 					  usbd_errstr(err));
 			    goto done;
 			}
@@ -1321,7 +1346,7 @@
 		    device_printf(parent,
 				  "port %d, set config at addr %d "
 				  "failed, error=%s\n",
-				  port, udev->address, 
+				  udev->port_no, udev->address, 
 				  usbd_errstr(err));
 		    goto done;
 		}
@@ -1361,45 +1386,55 @@
 	return err;
 }
 
-/*
+static const uint8_t
+usbd_hub_speed_combs[USB_SPEED_MAX][USB_SPEED_MAX] = {
+  /* HUB */       /* subdevice */
+  [USB_SPEED_HIGH][USB_SPEED_HIGH] = 1,
+  [USB_SPEED_HIGH][USB_SPEED_FULL] = 1,
+  [USB_SPEED_HIGH][USB_SPEED_LOW] = 1,
+  [USB_SPEED_FULL][USB_SPEED_FULL] = 1,
+  [USB_SPEED_FULL][USB_SPEED_LOW] = 1,
+  [USB_SPEED_LOW][USB_SPEED_LOW] = 1,
+};
+
+/*------------------------------------------------------------------------*
+ *	usbd_new_device
+ *
  * Called when a new device has been put in the powered state,
  * but not yet in the addressed state.
  * Get initial descriptor, set the address, get full descriptor,
  * and attach a driver.
- */
+ *------------------------------------------------------------------------*/
 usbd_status
-usbd_new_device(device_t parent, struct usbd_bus *bus, int depth,
-		int speed, int port, struct usbd_port *up)
+usbd_new_device(device_t parent, struct usbd_bus *bus,
+		struct usbd_device *parent_hub, uint8_t depth,
+		uint8_t speed, uint8_t port_index, uint8_t port_no)
 {
 	struct usbd_device *adev;
 	struct usbd_device *udev;
 	struct usbd_device *hub;
 	usbd_status err = 0;
-	int addr;
-	int i;
+	uint8_t buf[4];
+	uint8_t addr;
 
 	PRINTF(("bus=%p port=%d depth=%d speed=%d\n",
-		 bus, port, depth, speed));
+		 bus, port_no, depth, speed));
+
+	/* find an unused and valid address */
 
-	/* find unused address */
-	addr = USB_MAX_DEVICES;
-#if (USB_MAX_DEVICES == 0)
-#error "(USB_MAX_DEVICES == 0)"
+#if (USB_MAX_DEVICES < USB_START_ADDR)
+#error "USB_MAX_DEVICES < USB_START_ADDR"
 #endif
-	while(addr--)
-	{
-		if(addr == 0)
-		{
-			/* address 0 is always unused */
-			device_printf(bus->bdev,
-				      "No free USB addresses, "
-				      "new device ignored.\n");
-			return (USBD_NO_ADDR);
-		}
-		if(bus->devices[addr] == 0)
-		{
-			break;
-		}
+	for (addr = USB_START_ADDR + 1; addr < USB_MAX_DEVICES; addr++) {
+	    if (bus->devices[addr] == NULL)  break;
+	}
+
+	if (addr == USB_MAX_DEVICES) {
+
+	    device_printf(bus->bdev,
+			  "No free USB addresses, "
+			  "new device ignored.\n");
+	    return USBD_NO_ADDR;
 	}
 
 	udev = malloc(sizeof(udev[0]), M_USB, M_WAITOK|M_ZERO);
@@ -1408,72 +1443,72 @@
 		return (USBD_NOMEM);
 	}
 
-	up->device = udev;
+	/* initialize our SX-lock */
+	sx_init(udev->default_sx, "USB device SX lock");
+
+	/* initialize our mutex */
+	mtx_init(udev->default_mtx, "USB device mutex", NULL, MTX_DEF);
+
+	/* make a relationship between port and device address */
+	if (parent_hub) {
+	    parent_hub->hub->ports[port_index].device_addr = addr;
+	}
 
 	/* set up default endpoint descriptor */
 	udev->default_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
 	udev->default_ep_desc.bDescriptorType = UDESC_ENDPOINT;
 	udev->default_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
 	udev->default_ep_desc.bmAttributes = UE_CONTROL;
-	USETW(udev->default_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
+	udev->default_ep_desc.wMaxPacketSize[0] = USB_MAX_IPACKET;
+	udev->default_ep_desc.wMaxPacketSize[1] = 0;
+	udev->ddesc.bMaxPacketSize = 0;
 	udev->default_ep_desc.bInterval = 0;
 
+	udev->parent_hub = parent_hub;
+	udev->port_index = port_index;
+	udev->port_no = port_no;
 	udev->bus = bus;
 	udev->quirks = &usbd_no_quirk;
 	udev->address = USB_START_ADDR;
-	udev->ddesc.bMaxPacketSize = 0;
 	udev->depth = depth;

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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