Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Dec 2007 19:09:27 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 130358 for review
Message-ID:  <200712061909.lB6J9R9D026983@repoman.freebsd.org>

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

Change 130358 by hselasky@hselasky_laptop001 on 2007/12/06 19:09:06

	
	Some steps closer to full USB device side support.
	
	o Internal flag "is_dci" was renamed "usb_mode".
	o Reworked "usbd_get_pipe()" to support new flag: "no_pipe_ok".
	o Updated documentation.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/README#24 edit
.. //depot/projects/usb/src/sys/dev/usb/usb.h#21 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#66 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#62 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/README#24 (text+ko) ====

@@ -135,21 +135,20 @@
  *                     n_setup, priv_sc, priv_mtx)
  *------------------------------------------------------------------------*/
 
-- "udev" is a pointer to "struct usbd_device"
+- "udev" is a pointer to "struct usbd_device".
 
-- "iface_index" is the interface index number
+- "iface_index" is the interface index number.
 
 - "pxfer" is a pointer to an array of USB transfer pointers that are
-  initialized to NULL, and then pointed to the allocated DMA-able USB
-  transfers
+  initialized to NULL, and then pointed to allocated USB transfers.
 
-- "setup_start" is a pointer to an array of USB config structures
+- "setup_start" is a pointer to an array of USB config structures.
 
 - "n_setup" is a number telling the USB system how many USB transfers
-  should be setup
+  should be setup.
 
 - "priv_sc" is the private softc pointer, which will be used to
-  initialize "xfer->priv_sc"
+  initialize "xfer->priv_sc".
 
 - "priv_mtx" is the private mutex protecting the transfer structure and
   the softc. This pointer is used to initialize "xfer->priv_mtx".
@@ -206,9 +205,14 @@
   0xFF, "-1" or "UE_ADDR_ANY" will select the first matching endpoint.
   This field is mandatory.
 
-- The "direction" field selects the USB endpoint direction. A value of 0xFF,
-  "-1" or "UE_DIR_ANY" will select the first matching endpoint. Else valid
-  values are: "UE_DIR_IN" and "UE_DIR_OUT". This field is mandatory.
+- The "direction" field selects the USB endpoint direction. A value of
+  "UE_DIR_ANY" will select the first matching endpoint. Else valid
+  values are: "UE_DIR_IN" and "UE_DIR_OUT". "UE_DIR_IN" and
+  "UE_DIR_OUT" can be binary ORed by "UE_DIR_SID" which means that the
+  direction will be swapped in case of USB_MODE_DEVICE. Note that
+  "UE_DIR_IN" refers to the data transfer direction of the "IN" tokens
+  and "UE_DIR_OUT" refers to the data transfer direction of the "OUT"
+  tokens. This field is mandatory.
 
 - The "interval" field selects the interrupt interval. The value of this 
   field is given in milliseconds and is independent of device speed. Depending
@@ -310,8 +314,8 @@
 	during operation.
 
   ext_buffer
-	Setting this flag will cause that no DMA data buffer will be
-	allocated. Instead the USB client can use its own DMA buffer.
+	Setting this flag will cause that no data buffer will be
+	allocated. Instead the USB client must supply a data buffer.
 	This flag can not be changed during operation.
 
   manual_status
@@ -321,6 +325,10 @@
 	transfers. This flag is mostly useful for the USB device side.
 	This flag can be changed during operation.
 
+  no_pipe_ok
+	Setting this flag causes the USBD_NO_PIPE error to be
+	ignored. This flag can not be changed during operation.
+
 - The "bufsize" field sets the total buffer size in bytes. If
   this field is zero, "wMaxPacketSize" will be used, multiplied by the
   "frames" field if the transfer type is ISOCHRONOUS. This is useful for

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

@@ -253,6 +253,8 @@
 #define	UE_SET_DIR(a,d)	((a) | (((d)&1) << 7))
 #define	UE_DIR_IN	0x80
 #define	UE_DIR_OUT	0x00
+#define	UE_DIR_SID	0x40		/* Swap If Device - for internal use
+					 * only! */
 #define	UE_DIR_ANY	0xff		/* for internal use only! */
 #define	UE_ADDR		0x0f
 #define	UE_ADDR_ANY	0xff		/* for internal use only! */

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

@@ -72,8 +72,8 @@
     N_USBD_STATUS);
 
 #define	USBD_GET_STATE(xfer) ((xfer)->usb_state)
-#define	USBD_GET_DATA_ISREAD(xfer) ((xfer)->flags_int.is_dci ?	\
-	((xfer->endpoint & UE_DIR_IN) ? 0 : 1) :		\
+#define	USBD_GET_DATA_ISREAD(xfer) (((xfer)->flags_int.usb_mode == \
+	USB_MODE_DEVICE) ? ((xfer->endpoint & UE_DIR_IN) ? 0 : 1) : \
 	((xfer->endpoint & UE_DIR_IN) ? 1 : 0))
 
 #undef LIST_PREV
@@ -114,6 +114,13 @@
 
 typedef void (usbd_std_root_transfer_func_t)(struct usbd_xfer *, struct usbd_std_root_transfer *);
 
+/* USB modes */
+
+enum {
+	USB_MODE_HOST = 0,		/* default */
+	USB_MODE_DEVICE = 1,
+};
+
 /* Standard root transfer function state argument values */
 
 enum {
@@ -336,6 +343,8 @@
 	uint8_t	hs_hub_addr;		/* high-speed HUB address */
 	uint8_t	hs_port_no;		/* high-speed HUB port number */
 	uint8_t	driver_added_refcount;
+	uint8_t	usb_mode:1;		/* USB mode (see USB_MODE_XXX) */
+	uint8_t	unused:7;
 
 	usb_endpoint_descriptor_t default_ep_desc;	/* for pipe 0 */
 	usb_device_descriptor_t ddesc;	/* device descriptor */
@@ -374,6 +383,8 @@
 	uint8_t	ext_buffer:1;		/* uses external DMA buffer */
 	uint8_t	manual_status:1;	/* non automatic status stage on
 					 * control transfers */
+	uint8_t	no_pipe_ok:1;		/* set if "USBD_NO_PIPE" error can be
+					 * ignored */
 };
 
 struct usbd_xfer_flags_int {
@@ -397,8 +408,7 @@
 					 * should not do the BUS-DMA post sync
 					 * operation */
 	uint8_t	isochronous_xfr:1;	/* set if isochronous transfer */
-	uint8_t	is_dci:1;		/* set if hardware is a device
-					 * controller interface */
+	uint8_t	usb_mode:1;		/* shadow copy of "udev->usb_mode" */
 };
 
 struct usbd_config {

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

@@ -162,14 +162,61 @@
 	struct usbd_pipe *pipe = udev->pipes;
 	struct usbd_pipe *pipe_end = udev->pipes_end;
 	uint8_t index = setup->index;
-	uint8_t ea;
-	uint8_t at;
+	uint8_t ea_mask;
+	uint8_t ea_val;
+	uint8_t type_mask;
+	uint8_t type_val;
 
 	PRINTFN(8, ("udev=%p iface_index=%d address=0x%x "
 	    "type=0x%x dir=0x%x index=%d\n",
 	    udev, iface_index, setup->endpoint,
 	    setup->type, setup->direction, setup->index));
 
+	/* setup expected endpoint direction mask and value */
+
+	if (setup->direction == UE_DIR_ANY) {
+		/* match any endpoint direction */
+		ea_mask = 0;
+		ea_val = 0;
+	} else {
+		/* match the given endpoint direction */
+		ea_mask = (UE_DIR_IN | UE_DIR_OUT);
+		ea_val = (setup->direction & (UE_DIR_IN | UE_DIR_OUT));
+
+		/* swap endpoint direction, if device */
+		if (setup->direction & UE_DIR_SID) {
+			if (udev->usb_mode == USB_MODE_DEVICE) {
+				ea_val ^= (UE_DIR_IN | UE_DIR_OUT);
+			}
+		}
+	}
+
+	/* setup expected endpoint address */
+
+	if (setup->endpoint == UE_ADDR_ANY) {
+		/* match any endpoint address */
+	} else {
+		/* match the given endpoint address */
+		ea_mask |= UE_ADDR;
+		ea_val |= (setup->endpoint & UE_ADDR);
+	}
+
+	/* setup expected endpoint type */
+
+	if (setup->type == UE_BULK_INTR) {
+		/* this will match BULK and INTERRUPT endpoints */
+		type_mask = 2;
+		type_val = 2;
+	} else if (setup->type == UE_TYPE_ANY) {
+		/* match any endpoint type */
+		type_mask = 0;
+		type_val = 0;
+	} else {
+		/* match the given endpoint type */
+		type_mask = UE_XFERTYPE;
+		type_val = (setup->type & UE_XFERTYPE);
+	}
+
 	/* NOTE: pipes are searched from the beginning */
 
 	for (; pipe != pipe_end; pipe++) {
@@ -178,17 +225,10 @@
 		    (pipe->iface_index != iface_index)) {
 			continue;
 		}
-		ea = pipe->edesc->bEndpointAddress;
-		at = pipe->edesc->bmAttributes;
+		/* do the masks and check the values */
 
-		if (((setup->direction == (ea & (UE_DIR_IN | UE_DIR_OUT))) ||
-		    (setup->direction == UE_DIR_ANY)) &&
-		    ((setup->endpoint == (ea & UE_ADDR)) ||
-		    (setup->endpoint == UE_ADDR_ANY)) &&
-		    ((setup->type == (at & UE_XFERTYPE)) ||
-		    (setup->type == UE_TYPE_ANY) ||
-		    ((setup->type == UE_BULK_INTR) && (at & 2)))) {
-
+		if (((pipe->edesc->bEndpointAddress & ea_mask) == ea_val) &&
+		    ((pipe->edesc->bmAttributes & type_mask) == type_val)) {
 			if (!index--) {
 				goto found;
 			}
@@ -200,9 +240,9 @@
 	 * address" and "any direction" returns the first pipe of the
 	 * interface. "iface_index" and "direction" is ignored:
 	 */
-	if ((setup->endpoint == 0) &&
-	    (setup->type == 0) &&
-	    (udev->default_pipe.edesc) &&
+	if ((udev->default_pipe.edesc) &&
+	    ((udev->default_pipe.edesc->bEndpointAddress & ea_mask) == ea_val) &&
+	    ((udev->default_pipe.edesc->bmAttributes & type_mask) == type_val) &&
 	    (!index)) {
 		pipe = &udev->default_pipe;
 		goto found;
@@ -320,6 +360,7 @@
 	xfer->endpoint = edesc->bEndpointAddress;
 	xfer->max_packet_size = UGETW(edesc->wMaxPacketSize);
 	xfer->max_packet_count = 1;
+	xfer->flags_int.usb_mode = parm->udev->usb_mode;	/* make a shadow copy */
 
 	parm->bufsize = setup->bufsize;
 
@@ -666,6 +707,7 @@
 	struct usbd_setup_params parm;
 	const struct usbd_config *setup_end = setup_start + n_setup;
 	const struct usbd_config *setup;
+	struct usbd_pipe *pipe;
 	struct usbd_memory_info *info;
 	struct usbd_xfer *xfer;
 	void *buf = NULL;
@@ -746,6 +788,15 @@
 		for (setup = setup_start, n = 0;
 		    setup != setup_end; setup++, n++) {
 
+			/* see if there is a matching endpoint */
+			pipe = usbd_get_pipe(udev, iface_index, setup);
+			if (!pipe) {
+				if (setup->flags.no_pipe_ok) {
+					continue;
+				}
+				parm.err = USBD_NO_PIPE;
+				goto done;
+			}
 			/* store current setup pointer */
 			parm.curr_setup = setup;
 
@@ -776,12 +827,8 @@
 
 			parm.size[0] += sizeof(xfer[0]);
 
-			xfer->pipe = usbd_get_pipe(udev, iface_index, setup);
+			xfer->pipe = pipe;
 
-			if (!xfer->pipe) {
-				parm.err = USBD_NO_PIPE;
-				goto done;
-			}
 			if (buf) {
 				xfer->pipe->refcount++;
 			}
@@ -1579,7 +1626,7 @@
 	if (xfer->flags_int.control_xfr &&
 	    xfer->flags_int.control_hdr) {
 		/* special case */
-		if (xfer->flags_int.is_dci) {
+		if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
 			xfer->frbuffers[0].isread = 0;
 		} else {
 			xfer->frbuffers[0].isread = 1;



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