PERFORCE change 130539 for review

Hans Petter Selasky hselasky at FreeBSD.org
Sun Dec 9 03:09:47 PST 2007


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

Change 130539 by hselasky at hselasky_laptop001 on 2007/12/09 11:09:42

	
	This commit is part of USB device side support.
	
	o Slightly tweak the way we setup USB control transfers. This leads
	  to some changes and simplifications here and there. Here
	  is an overview on how USB control transfers should be setup:
	
	Example1: SETUP + STATUS
	 xfer->nframes = 1;
	 xfer->frlenghts[0] = 8;
	 usbd_start_hardware(xfer);
	
	Example2: SETUP + DATA + STATUS
	 xfer->nframes = 2;
	 xfer->frlenghts[0] = 8;
	 xfer->frlenghts[1] = 1;
	 usbd_start_hardware(xfer);
	
	Example3: SETUP + DATA + STATUS - split
	1st callback:
	 xfer->nframes = 1;
	 xfer->frlenghts[0] = 8;
	 usbd_start_hardware(xfer);
	
	2nd callback:
	 /* IMPORTANT: frbuffer[0] must still point at the setup packet! */
	 xfer->nframes = 2;
	 xfer->frlenghts[0] = 0;
	 xfer->frlenghts[1] = 1;
	 usbd_start_hardware(xfer);

Affected files ...

.. //depot/projects/usb/src/sys/dev/ata/ata-usb.c#28 edit
.. //depot/projects/usb/src/sys/dev/sound/usb/uaudio.c#27 edit
.. //depot/projects/usb/src/sys/dev/usb/README#26 edit
.. //depot/projects/usb/src/sys/dev/usb/ehci.c#59 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.c#48 edit
.. //depot/projects/usb/src/sys/dev/usb/ucycom.c#27 edit
.. //depot/projects/usb/src/sys/dev/usb/ufoma.c#34 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.c#49 edit
.. //depot/projects/usb/src/sys/dev/usb/uhid.c#26 edit
.. //depot/projects/usb/src/sys/dev/usb/ukbd.c#35 edit
.. //depot/projects/usb/src/sys/dev/usb/ulpt.c#35 edit
.. //depot/projects/usb/src/sys/dev/usb/umass.c#38 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_compat_linux.c#16 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#66 edit
.. //depot/projects/usb/src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c#21 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/ata/ata-usb.c#28 (text) ====

@@ -495,8 +495,7 @@
 		usbd_copy_in(xfer->frbuffers + 0, 0, &req, sizeof(req));
 
 		xfer->frlengths[0] = sizeof(req);
-		xfer->frlengths[1] = 0;
-
+		xfer->nframes = 1;
 		usbd_start_hardware(xfer);
 		return;
 

==== //depot/projects/usb/src/sys/dev/sound/usb/uaudio.c#27 (text+ko) ====

@@ -3038,6 +3038,7 @@
 
 					xfer->frlengths[0] = sizeof(req);
 					xfer->frlengths[1] = len;
+					xfer->nframes = xfer->frlengths[1] ? 2 : 1;
 					usbd_start_hardware(xfer);
 					return;
 				}

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

@@ -93,15 +93,42 @@
   }
 }
 
-NOTE: An USB control transfer has three parts. First the SETUP packet,
-then DATA packet(s) and then a STATUS packet. The SETUP packet is
+=== Notes for USB control transfers ===
+
+An USB control transfer has three parts. First the SETUP packet, then
+DATA packet(s) and then a STATUS packet. The SETUP packet is always
 pointed to by "xfer->frbuffers[0]" and the length is stored in
-"xfer->frlengths[0]". Zero-length entries in the "xfer->frlengths[]" array
-will be ignored. Typically the DATA packet(s) are pointed to by
-"xfer->frbuffers[1]" and the length is stored in "xfer->frlengths[1]".
-The STATUS packet is automatically executed unless "xfer->flags.manual_status"
-is set. If "xfer->flags.manual_status" is set the STATUS packet will 
-be executed if the length of last USB frame is zero.
+"xfer->frlengths[0]" also if there should not be sent any SETUP
+packet! If an USB control transfer has no DATA stage, then
+"xfer->nframes" should be set to 1. Else the default value is
+"xfer->nframes" equal to 2.
+
+Example1: SETUP + STATUS
+ xfer->nframes = 1;
+ xfer->frlenghts[0] = 8;
+ usbd_start_hardware(xfer);
+
+Example2: SETUP + DATA + STATUS
+ xfer->nframes = 2;
+ xfer->frlenghts[0] = 8;
+ xfer->frlenghts[1] = 1;
+ usbd_start_hardware(xfer);
+
+Example3: SETUP + DATA + STATUS - split
+1st callback:
+ xfer->nframes = 1;
+ xfer->frlenghts[0] = 8;
+ usbd_start_hardware(xfer);
+
+2nd callback:
+ /* IMPORTANT: frbuffer[0] must still point at the setup packet! */
+ xfer->nframes = 2;
+ xfer->frlenghts[0] = 0;
+ xfer->frlenghts[1] = 1;
+ usbd_start_hardware(xfer);
+
+
+=== General USB transfer notes ===
 
  1) Something that one should be aware of is that all USB callbacks support 
 recursation. That means one can start/stop whatever transfer from the callback 
@@ -319,11 +346,12 @@
 	This flag can not be changed during operation.
 
   manual_status
-	Setting this flag causes that the STATUS stage of a control
-	transfer needs to be sent separately like a zero-length USB
-	frame. This flag has currently no effect on non-control
-	transfers. This flag is mostly useful for the USB device side.
-	This flag can be changed during operation.
+	Setting this flag prevents an USB STATUS stage to be appended
+	to the end of the USB control transfer. If no control data is
+	transferred this flag must be cleared. Else an error will be
+	returned to the USB callback. 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

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

@@ -1240,10 +1240,12 @@
 
 	xfer->td_transfer_cache = xfer->td_transfer_first;
 
-	if (xfer->flags_int.control_xfr &&
-	    xfer->flags_int.control_hdr) {
+	if (xfer->flags_int.control_xfr) {
+
+	  if (xfer->flags_int.control_hdr) {
 
 		err = ehci_non_isoc_done_sub(xfer);
+	  }
 
 		xfer->aframes = 1;
 
@@ -1253,11 +1255,7 @@
 	}
 	while (xfer->aframes != xfer->nframes) {
 
-		if ((!xfer->flags_int.control_xfr) ||
-		    (xfer->frlengths[xfer->aframes] > 0)) {
-
 			err = ehci_non_isoc_done_sub(xfer);
-		}
 		xfer->aframes++;
 
 		if (xfer->td_transfer_cache == NULL) {
@@ -1826,12 +1824,11 @@
 		/* max 3 retries */
 		temp.qtd_status |= htole32(EHCI_QTD_SET_CERR(3));
 	}
-	x = 0;
 
 	/* check if we should prepend a setup message */
 
-	if (xfer->flags_int.control_xfr &&
-	    xfer->flags_int.control_hdr) {
+	if (xfer->flags_int.control_xfr) {
+	  if (xfer->flags_int.control_hdr) {
 
 		temp.qtd_status &= htole32(EHCI_QTD_SET_CERR(3));
 		temp.qtd_status |= htole32
@@ -1844,9 +1841,13 @@
 		temp.shortpkt = temp.len ? 1 : 0;
 
 		ehci_setup_standard_chain_sub(&temp);
+	  }
 
 		x = 1;
+	} else {
+		x = 0;
 	}
+
 	while (x != xfer->nframes) {
 
 		/* DATA0 / DATA1 message */
@@ -1870,10 +1871,6 @@
 
 			temp.shortpkt = 0;
 
-			if (xfer->flags_int.control_xfr) {
-				/* we ignore zero length frames */
-				continue;
-			}
 		} else {
 
 			/* regular data transfer */

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

@@ -951,10 +951,12 @@
 
 	xfer->td_transfer_cache = xfer->td_transfer_first;
 
-	if (xfer->flags_int.control_xfr &&
-	    xfer->flags_int.control_hdr) {
+	if (xfer->flags_int.control_xfr) {
+
+	  if (xfer->flags_int.control_hdr) {
 
 		err = ohci_non_isoc_done_sub(xfer);
+	  }
 
 		xfer->aframes = 1;
 
@@ -964,11 +966,7 @@
 	}
 	while (xfer->aframes != xfer->nframes) {
 
-		if ((!xfer->flags_int.control_xfr) ||
-		    (xfer->frlengths[xfer->aframes] > 0)) {
-
 			err = ohci_non_isoc_done_sub(xfer);
-		}
 		xfer->aframes++;
 
 		if (xfer->td_transfer_cache == NULL) {
@@ -1532,12 +1530,10 @@
 
 	methods = xfer->pipe->methods;
 
-	x = 0;
-
 	/* check if we should prepend a setup message */
 
-	if (xfer->flags_int.control_xfr &&
-	    xfer->flags_int.control_hdr) {
+	if (xfer->flags_int.control_xfr) {
+	  if (xfer->flags_int.control_hdr) {
 
 		temp.td_flags = htole32(OHCI_TD_SETUP | OHCI_TD_NOCC |
 		    OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
@@ -1548,13 +1544,16 @@
 
 		ohci_setup_standard_chain_sub(&temp);
 
-		x = 1;
-
 		/*
 		 * XXX assume that the setup message is
 		 * contained within one USB packet:
 		 */
 		xfer->pipe->toggle_next = 1;
+	  }
+
+		x = 1;
+	} else {
+		x = 0;
 	}
 	temp.td_flags = htole32(OHCI_TD_NOCC | OHCI_TD_NOINTR);
 
@@ -1592,10 +1591,6 @@
 
 			temp.shortpkt = 0;
 
-			if (xfer->flags_int.control_xfr) {
-				/* we ignore zero length frames */
-				continue;
-			}
 		} else {
 
 			/* regular data transfer */

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

@@ -436,7 +436,7 @@
 
 			xfer->frlengths[0] = sizeof(req);
 			xfer->frlengths[1] = sc->sc_olen;
-
+			xfer->nframes = xfer->frlengths[1] ? 2 : 1;
 			usbd_start_hardware(xfer);
 		}
 		return;

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

@@ -600,7 +600,7 @@
 
 			xfer->frlengths[0] = sizeof(req);
 			xfer->frlengths[1] = UFOMA_CMD_BUF_SIZE;
-
+			xfer->nframes = 2;
 			usbd_start_hardware(xfer);
 		}
 		return;
@@ -644,6 +644,7 @@
 
 			xfer->frlengths[0] = sizeof(req);
 			xfer->frlengths[1] = 1;
+			xfer->nframes = 2;
 
 			usbd_start_hardware(xfer);
 		}

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

@@ -1245,10 +1245,11 @@
 
 	xfer->td_transfer_cache = xfer->td_transfer_first;
 
-	if (xfer->flags_int.control_xfr &&
-	    xfer->flags_int.control_hdr) {
+	if (xfer->flags_int.control_xfr) {
+	  if (xfer->flags_int.control_hdr) {
 
 		err = uhci_non_isoc_done_sub(xfer);
+	  }
 
 		xfer->aframes = 1;
 
@@ -1258,11 +1259,7 @@
 	}
 	while (xfer->aframes != xfer->nframes) {
 
-		if ((!xfer->flags_int.control_xfr) ||
-		    (xfer->frlengths[xfer->aframes] > 0)) {
-
 			err = uhci_non_isoc_done_sub(xfer);
-		}
 		xfer->aframes++;
 
 		if (xfer->td_transfer_cache == NULL) {
@@ -1821,12 +1818,12 @@
 		/* DATA1 is next */
 		temp.td_token |= htole32(UHCI_TD_SET_DT(1));
 	}
-	x = 0;
 
 	/* check if we should prepend a setup message */
 
-	if (xfer->flags_int.control_xfr &&
-	    xfer->flags_int.control_hdr) {
+	if (xfer->flags_int.control_xfr) {
+
+	  if (xfer->flags_int.control_hdr) {
 
 		temp.td_token &= htole32(UHCI_TD_SET_DEVADDR(0x7F) |
 		    UHCI_TD_SET_ENDPT(0xF));
@@ -1838,9 +1835,13 @@
 		temp.shortpkt = temp.len ? 1 : 0;
 
 		uhci_setup_standard_chain_sub(&temp);
+	  }
 
 		x = 1;
+	} else {
+		x = 0;
 	}
+
 	while (x != xfer->nframes) {
 
 		/* DATA0 / DATA1 message */
@@ -1868,10 +1869,6 @@
 
 			temp.shortpkt = 0;
 
-			if (xfer->flags_int.control_xfr) {
-				/* we ignore zero length frames */
-				continue;
-			}
 		} else {
 
 			/* regular data transfer */

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

@@ -237,7 +237,7 @@
 
 			xfer->frlengths[0] = sizeof(req);
 			xfer->frlengths[1] = size;
-
+			xfer->nframes = xfer->frlengths[1] ? 2 : 1;
 			usbd_start_hardware(xfer);
 		}
 		return;
@@ -274,7 +274,7 @@
 
 			xfer->frlengths[0] = sizeof(req);
 			xfer->frlengths[1] = sc->sc_isize;
-
+			xfer->nframes = xfer->frlengths[1] ? 2 : 1;
 			usbd_start_hardware(xfer);
 		}
 		return;

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

@@ -544,6 +544,7 @@
 
 			xfer->frlengths[0] = sizeof(req);
 			xfer->frlengths[1] = sizeof(buf);
+			xfer->nframes = 2;
 			usbd_start_hardware(xfer);
 		}
 		return;

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

@@ -268,6 +268,7 @@
 
 		xfer->frlengths[0] = sizeof(req);
 		xfer->frlengths[1] = 1;
+		xfer->nframes = 2;
 		usbd_start_hardware(xfer);
 
 		return;
@@ -306,9 +307,8 @@
 		usbd_copy_in(xfer->frbuffers + 0, 0, &req, sizeof(req));
 
 		xfer->frlengths[0] = sizeof(req);
-		xfer->frlengths[1] = 0;
+		xfer->nframes = 1;
 		usbd_start_hardware(xfer);
-
 		return;
 
 	default:			/* Error */

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

@@ -1760,7 +1760,7 @@
 		usbd_copy_in(xfer->frbuffers + 0, 0, &req, sizeof(req));
 
 		xfer->frlengths[0] = sizeof(req);
-		xfer->frlengths[1] = 0;
+		xfer->nframes = 1;
 		usbd_start_hardware(xfer);
 		return;
 
@@ -2264,7 +2264,7 @@
 
 		xfer->frlengths[0] = sizeof(req);
 		xfer->frlengths[1] = sizeof(buf);
-
+		xfer->nframes = 2;
 		usbd_start_hardware(xfer);
 		return;
 
@@ -2379,6 +2379,7 @@
 
 			xfer->frlengths[0] = sizeof(req);
 			xfer->frlengths[1] = sc->sc_transfer.cmd_len;
+			xfer->nframes = xfer->frlengths[1] ? 2 : 1;
 
 			DIF(UDMASS_CBI,
 			    umass_cbi_dump_cmd(sc,

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

@@ -1565,7 +1565,15 @@
 			    urb->bsd_data_ptr, max_bulk);
 		}
 		xfer->frlengths[data_frame] = max_bulk;
-		xfer->nframes = data_frame + 1;
+		if (xfer->flags_int.control_xfr) {
+		  if (max_bulk > 0) {
+		    xfer->nframes = 2;
+		  } else {
+		    xfer->nframes = 1;
+		  }
+		} else {
+		  xfer->nframes = 1;
+		}
 		usbd_start_hardware(xfer);
 		return;
 

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

@@ -431,9 +431,13 @@
 			parm->err = USBD_INVAL;
 			goto done;
 		}
-		n_frlengths = xfer->nframes;
-		n_frbuffers = 1;
-
+		if (xfer->nframes == 0) {
+			/*
+			 * this is not a valid value
+			 */
+			parm->err = USBD_ZERO_NFRAMES;
+			goto done;
+		}
 	} else {
 
 		/*
@@ -458,25 +462,8 @@
 				}
 			}
 		}
-		if (type == UE_CONTROL) {
-			xfer->flags_int.control_xfr = 1;
-			if (xfer->nframes == 0) {
-				xfer->nframes = 2;
-			}
-		} else {
-			if (xfer->nframes == 0) {
-				xfer->nframes = 1;
-			}
-		}
-
-		n_frlengths = xfer->nframes;
-		n_frbuffers = xfer->nframes;
 	}
 
-	if (xfer->nframes == 0) {
-		parm->err = USBD_ZERO_NFRAMES;
-		goto done;
-	}
 	/*
 	 * NOTE: we do not allow "max_packet_size" or "max_frame_size"
 	 * to be equal to zero when setting up USB transfers, hence
@@ -548,6 +535,36 @@
 	}
 	xfer->max_data_length = parm->bufsize;
 
+	/* Setup "n_frlengths" and "n_frbuffers" */
+
+	if (type == UE_ISOCHRONOUS) {
+		n_frlengths = xfer->nframes;
+		n_frbuffers = 1;
+	} else {
+
+		if (type == UE_CONTROL) {
+			xfer->flags_int.control_xfr = 1;
+			if (xfer->nframes == 0) {
+				if (parm->bufsize <= REQ_SIZE) {
+					/*
+					 * there will never be any data
+					 * stage
+					 */
+					xfer->nframes = 1;
+				} else {
+					xfer->nframes = 2;
+				}
+			}
+		} else {
+			if (xfer->nframes == 0) {
+				xfer->nframes = 1;
+			}
+		}
+
+		n_frlengths = xfer->nframes;
+		n_frbuffers = xfer->nframes;
+	}
+
 	/*
 	 * check if we have room for the
 	 * USB device request structure:
@@ -1235,6 +1252,31 @@
 }
 
 /*------------------------------------------------------------------------*
+ *	usbd_control_transfer_init
+ *------------------------------------------------------------------------*/
+static void
+usbd_control_transfer_init(struct usbd_xfer *xfer)
+{
+	usb_device_request_t req;
+
+	/* copy out the USB request header */
+
+	usbd_copy_out(xfer->frbuffers + 0, 0, &req, sizeof(req));
+
+	/* setup remainder */
+
+	xfer->flags_int.control_rem = UGETW(req.wLength);
+
+	/* copy direction to endpoint variable */
+
+	xfer->endpoint &= ~(UE_DIR_IN | UE_DIR_OUT);
+	xfer->endpoint |=
+	    (req.bmRequestType & UT_READ) ? UE_DIR_IN : UE_DIR_OUT;
+
+	return;
+}
+
+/*------------------------------------------------------------------------*
  *	usbd_start_hardware_sub
  *
  * To support split control transfers we need a special wrapper which
@@ -1243,7 +1285,6 @@
 static uint8_t
 usbd_start_hardware_sub(struct usbd_xfer *xfer)
 {
-	usb_device_request_t req;
 	uint32_t len;
 
 	/*
@@ -1252,42 +1293,61 @@
          */
 	if (xfer->flags_int.control_act) {
 
-		/* clear send header flag */
+		if (xfer->flags_int.control_hdr) {
+
+			/* clear send header flag */
 
-		xfer->flags_int.control_hdr = 0;
+			xfer->flags_int.control_hdr = 0;
 
+			/* setup control transfer */
+			if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
+				usbd_control_transfer_init(xfer);
+			}
+		}
 		/* get data length */
 
 		len = xfer->sumlen;
 
 	} else {
 
-		/* set send header flag */
-
-		xfer->flags_int.control_hdr = 1;
-
 		/* the size of the SETUP structure is hardcoded ! */
 
-		if (xfer->frlengths[0] != sizeof(req)) {
+		if (xfer->frlengths[0] != sizeof(usb_device_request_t)) {
 			goto error;
 		}
-		/* copy out the USB request header */
+		/* check USB mode */
+		if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
 
-		usbd_copy_out(xfer->frbuffers + 0, 0, &req, sizeof(req));
+			/* check number of frames */
+			if (xfer->nframes != 1) {
+				/*
+			         * We need to receive the setup
+			         * message first so that we know the
+			         * data direction!
+			         */
+				PRINTFN(0, ("Misconfigured transfer\n"));
+				goto error;
+			}
+			/*
+			 * Set a dummy "control_rem" value.  This
+			 * variable will be overwritten later by a
+			 * call to "usbd_control_transfer_init()" !
+			 */
+			xfer->flags_int.control_rem = 0xFFFF;
+		} else {
 
-		/* setup remainder */
+			/* setup "endpoint" and "control_rem" */
 
-		xfer->flags_int.control_rem = UGETW(req.wLength);
+			usbd_control_transfer_init(xfer);
+		}
 
-		/* copy direction to endpoint variable */
+		/* set transfer-header flag */
 
-		xfer->endpoint &= ~(UE_DIR_IN | UE_DIR_OUT);
-		xfer->endpoint |=
-		    (req.bmRequestType & UT_READ) ? UE_DIR_IN : UE_DIR_OUT;
+		xfer->flags_int.control_hdr = 1;
 
 		/* get data length */
 
-		len = (xfer->sumlen - sizeof(req));
+		len = (xfer->sumlen - sizeof(usb_device_request_t));
 	}
 
 	/* check if there is a length mismatch */
@@ -1299,26 +1359,24 @@
 
 	/* the status part is executed when "control_act" is 0 */
 
-	if (xfer->flags_int.control_rem > 0) {
-		/*
-		 * Moving no data is not allowed
-		 * in this case:
-		 */
-		if (xfer->sumlen == 0) {
-			goto error;
-		}
+	if ((xfer->flags_int.control_rem > 0) ||
+	    (xfer->flags.manual_status)) {
+		/* don't execute the STATUS stage yet */
 		xfer->flags_int.control_act = 1;
 
-	} else if (xfer->flags.manual_status &&
-	    xfer->frlengths[xfer->nframes - 1]) {
+		/* sanity check */
+		if ((!xfer->flags_int.control_hdr) &&
+		    (xfer->nframes == 1)) {
+			/*
+		         * This is not a valid operation!
+		         */
 
-		/*
-		 * A zero length frame last signals
-		 * a manual status stage
-		 */
-		xfer->flags_int.control_act = 1;
-
+			PRINTFN(-1, ("Invalid parameter "
+			    "combination\n"));
+			goto error;
+		}
 	} else {
+		/* time to execute the STATUS stage */
 		xfer->flags_int.control_act = 0;
 	}
 	return (0);
@@ -1965,21 +2023,23 @@
 			/* set correct USB state for callback */
 			if (!xfer->flags_int.transferring) {
 				xfer->usb_state = USBD_ST_SETUP;
-			} else {
-				xfer->flags_int.transferring = 0;
-				if (xfer->error) {
-					xfer->usb_state = USBD_ST_ERROR;
-				} else {
-					xfer->usb_state = USBD_ST_TRANSFERRED;
+				goto callback;
+			}
+			xfer->flags_int.transferring = 0;
 
-					/* sync any DMA memory */
-					if (xfer->flags_int.bdma_enable &&
-					    (!xfer->flags_int.bdma_no_post_sync)) {
-						usbd_bdma_post_sync(xfer);
-					}
-				}
+			if (xfer->error) {
+				xfer->usb_state = USBD_ST_ERROR;
+				goto callback;
 			}
+			/* set transferred state */
+			xfer->usb_state = USBD_ST_TRANSFERRED;
 
+			/* sync DMA memory, if any */
+			if (xfer->flags_int.bdma_enable &&
+			    (!xfer->flags_int.bdma_no_post_sync)) {
+				usbd_bdma_post_sync(xfer);
+			}
+	callback:
 			/* call processing routine */
 			(xfer->callback) (xfer);
 
@@ -2289,6 +2349,9 @@
 		uc[0].bufsize = 1024;	/* bytes */
 		uc[0].flags.proxy_buffer = 1;
 		uc[0].flags.short_xfer_ok = 1;
+		if (udev->usb_mode == USB_MODE_DEVICE) {
+			uc[0].flags.manual_status = 1;
+		}
 		uc[0].cb[USB_MODE_HOST] = &usbd_do_request_callback;
 		uc[0].cb[USB_MODE_DEVICE] = &usbd_serve_request_callback;
 
@@ -2423,10 +2486,12 @@
 			if (!(req->bmRequestType & UT_READ)) {
 				usbd_copy_in(xfer->frbuffers + 1, 0, data, temp);
 			}
+			xfer->nframes = 2;
 		} else {
 			if (xfer->frlengths[0] == 0) {
 				break;
 			}
+			xfer->nframes = 1;
 		}
 
 		usbd_transfer_start(xfer);

==== //depot/projects/usb/src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c#21 (text+ko) ====

@@ -723,6 +723,7 @@
 
 		xfer->frlengths[0] = sizeof(req);
 		xfer->frlengths[1] = m->m_pkthdr.len;
+		xfer->nframes = xfer->frlengths[1] ? 2 : 1;
 
 		NG_FREE_M(m);
 


More information about the p4-projects mailing list