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