PERFORCE change 165771 for review

Hans Petter Selasky hselasky at FreeBSD.org
Tue Jul 7 18:35:53 UTC 2009


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

Change 165771 by hselasky at hselasky_laptop001 on 2009/07/07 18:35:28

	
	USB CORE:
	 - add support for automatic defragging of written device data.
	 - fix issue with CUPS and /dev/ulpt reported by Patrick Lamaiziere
	 - a new device node, /dev/urlptX, has been created to preserve the
	   old behaviour

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/serial/ulpt.c#16 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_dev.c#31 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_dev.h#16 edit
.. //depot/projects/usb/src/sys/dev/usb/usbdi.h#11 edit

Differences ...

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

@@ -110,6 +110,7 @@
 struct ulpt_softc {
 	struct usb_fifo_sc sc_fifo;
 	struct usb_fifo_sc sc_fifo_noreset;
+	struct usb_fifo_sc sc_fifo_raw;
 	struct mtx sc_mtx;
 	struct usb_callout sc_watchdog;
 
@@ -147,6 +148,7 @@
 static usb_fifo_ioctl_t ulpt_ioctl;
 static usb_fifo_open_t ulpt_open;
 static usb_fifo_open_t unlpt_open;
+static usb_fifo_open_t urlpt_open;
 
 static struct usb_fifo_methods ulpt_fifo_methods = {
 	.f_close = &ulpt_close,
@@ -170,6 +172,17 @@
 	.basename[0] = "unlpt",
 };
 
+static struct usb_fifo_methods urlpt_fifo_methods = {
+	.f_close = &ulpt_close,
+	.f_ioctl = &ulpt_ioctl,
+	.f_open = &urlpt_open,
+	.f_start_read = &ulpt_start_read,
+	.f_start_write = &ulpt_start_write,
+	.f_stop_read = &ulpt_stop_read,
+	.f_stop_write = &ulpt_stop_write,
+	.basename[0] = "urlpt",
+};
+
 static void
 ulpt_reset(struct ulpt_softc *sc)
 {
@@ -419,6 +432,27 @@
 }
 
 static int
+urlpt_open(struct usb_fifo *fifo, int fflags)
+{
+	struct ulpt_softc *sc = usb_fifo_softc(fifo);
+
+	/* we assume that open is a serial process */
+
+	if (sc->sc_fflags == 0) {
+
+		/* reset USB paralell port */
+
+		ulpt_reset(sc);
+	}
+	/* set raw write mode */
+
+	if (fflags & FWRITE) {
+		usb_fifo_set_write_defrag(fifo, 0);
+	}
+	return (unlpt_open(fifo, fflags));
+}
+
+static int
 ulpt_open(struct usb_fifo *fifo, int fflags)
 {
 	struct ulpt_softc *sc = usb_fifo_softc(fifo);
@@ -426,8 +460,16 @@
 	/* we assume that open is a serial process */
 
 	if (sc->sc_fflags == 0) {
+
+		/* reset USB paralell port */
+
 		ulpt_reset(sc);
 	}
+	/* set defrag write mode */
+
+	if (fflags & FWRITE) {
+		usb_fifo_set_write_defrag(fifo, 1);
+	}
 	return (unlpt_open(fifo, fflags));
 }
 
@@ -633,6 +675,13 @@
 	if (error) {
 		goto detach;
 	}
+	error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx,
+	    &urlpt_fifo_methods, &sc->sc_fifo_raw,
+	    unit, 0 - 1, uaa->info.bIfaceIndex,
+	    UID_ROOT, GID_OPERATOR, 0644);
+	if (error) {
+		goto detach;
+	}
 	/* start reading of status */
 
 	mtx_lock(&sc->sc_mtx);
@@ -654,6 +703,7 @@
 
 	usb_fifo_detach(&sc->sc_fifo);
 	usb_fifo_detach(&sc->sc_fifo_noreset);
+	usb_fifo_detach(&sc->sc_fifo_raw);
 
 	mtx_lock(&sc->sc_mtx);
 	usb_callout_stop(&sc->sc_watchdog);

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

@@ -740,6 +740,8 @@
 			break;
 		}
 	}
+	/* reset have fragment flag */
+	f->flag_have_fragment = 0;
 }
 
 /*------------------------------------------------------------------------*
@@ -783,6 +785,16 @@
 			/* set flushing flag */
 			f->flag_flushing = 1;
 
+			/* get the last packet in */
+			if (f->flag_have_fragment) {
+				struct usb_mbuf *m;
+				f->flag_have_fragment = 0;
+				USB_IF_DEQUEUE(&f->free_q, m);
+				if (m) {
+					USB_IF_ENQUEUE(&f->used_q, m);
+				}
+			}
+
 			/* start write transfer, if not already started */
 			(f->methods->f_start_write) (f);
 
@@ -1303,6 +1315,7 @@
 	struct usb_cdev_privdata* cpd;
 	struct usb_fifo *f;
 	struct usb_mbuf *m;
+	uint8_t *pdata;
 	int fflags;
 	int resid;
 	int io_len;
@@ -1373,33 +1386,59 @@
 		}
 		tr_data = 1;
 
-		USB_MBUF_RESET(m);
-
-		io_len = MIN(m->cur_data_len, uio->uio_resid);
-
-		m->cur_data_len = io_len;
+		if (f->flag_have_fragment == 0) {
+			USB_MBUF_RESET(m);
+			io_len = m->cur_data_len;
+			pdata = m->cur_data_ptr;
+			if (io_len > uio->uio_resid)
+				io_len = uio->uio_resid;
+			m->cur_data_len = io_len;
+		} else {
+			io_len = m->max_data_len - m->cur_data_len;
+			pdata = m->cur_data_ptr + io_len;
+			if (io_len > uio->uio_resid)
+				io_len = uio->uio_resid;
+			m->cur_data_len += io_len;
+		}
 
 		DPRINTFN(2, "transfer %d bytes to %p\n",
-		    io_len, m->cur_data_ptr);
+		    io_len, pdata);
 
-		err = usb_fifo_uiomove(f,
-		    m->cur_data_ptr, io_len, uio);
+		err = usb_fifo_uiomove(f, pdata, io_len, uio);
 
 		if (err) {
+			f->flag_have_fragment = 0;
 			USB_IF_ENQUEUE(&f->free_q, m);
 			break;
 		}
-		if (f->methods->f_filter_write) {
+
+		/* check if the buffer is ready to be transmitted */
+
+		if ((f->flag_write_defrag == 0) ||
+		    (m->cur_data_len == m->max_data_len)) {
+			f->flag_have_fragment = 0;
+
 			/*
-			 * Sometimes it is convenient to process data at the
-			 * expense of a userland process instead of a kernel
-			 * process.
+			 * Check for write filter:
+			 *
+			 * Sometimes it is convenient to process data
+			 * at the expense of a userland process
+			 * instead of a kernel process.
 			 */
-			(f->methods->f_filter_write) (f, m);
+			if (f->methods->f_filter_write) {
+				(f->methods->f_filter_write) (f, m);
+			}
+
+			/* Put USB mbuf in the used queue */
+			USB_IF_ENQUEUE(&f->used_q, m);
+
+			/* Start writing data, if not already started */
+			(f->methods->f_start_write) (f);
+		} else {
+			/* Wait for more data or close */
+			f->flag_have_fragment = 1;
+			USB_IF_PREPEND(&f->free_q, m);
 		}
-		USB_IF_ENQUEUE(&f->used_q, m);
-
-		(f->methods->f_start_write) (f);
 
 	} while (uio->uio_resid > 0);
 done:
@@ -2220,6 +2259,18 @@
 	f->flag_short = onoff;
 }
 
+void
+usb_fifo_set_write_defrag(struct usb_fifo *f, uint8_t onoff)
+{
+	if (f == NULL)
+		return;
+
+	/* defrag written data */
+	f->flag_write_defrag = onoff;
+	/* reset defrag state */
+	f->flag_have_fragment = 0;
+}
+
 void *
 usb_fifo_softc(struct usb_fifo *f)
 {

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

@@ -130,6 +130,8 @@
 	uint8_t	flag_short;		/* set if short_ok or force_short
 					 * transfer flags should be set */
 	uint8_t	flag_stall;		/* set if clear stall should be run */
+	uint8_t	flag_write_defrag;	/* set to defrag written data */
+	uint8_t	flag_have_fragment;	/* set if defragging */
 	uint8_t	iface_index;		/* set to the interface we belong to */
 	uint8_t	fifo_index;		/* set to the FIFO index in "struct
 					 * usb_device" */
@@ -144,11 +146,9 @@
 int	usb_fifo_wait(struct usb_fifo *fifo);
 void	usb_fifo_signal(struct usb_fifo *fifo);
 uint8_t	usb_fifo_opened(struct usb_fifo *fifo);
-void	usb_fifo_free(struct usb_fifo *f);
 struct usb_symlink *usb_alloc_symlink(const char *target);
 void	usb_free_symlink(struct usb_symlink *ps);
 int	usb_read_symlink(uint8_t *user_ptr, uint32_t startentry,
 	    uint32_t user_len);
-void	usb_fifo_set_close_zlp(struct usb_fifo *, uint8_t);
 
 #endif					/* _USB_DEV_H_ */

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

@@ -531,5 +531,8 @@
 void	usb_fifo_wakeup(struct usb_fifo *f);
 void	usb_fifo_get_data_error(struct usb_fifo *fifo);
 void	*usb_fifo_softc(struct usb_fifo *fifo);
+void	usb_fifo_set_close_zlp(struct usb_fifo *, uint8_t);
+void	usb_fifo_set_write_defrag(struct usb_fifo *, uint8_t);
+void	usb_fifo_free(struct usb_fifo *f);
 #endif /* _KERNEL */
 #endif /* _USB_USBDI_H_ */


More information about the p4-projects mailing list