kern/59169: ulpt is missing read operation
Gernot Hueber
hueber at riic.at
Tue Nov 11 00:20:17 PST 2003
>Number: 59169
>Category: kern
>Synopsis: ulpt is missing read operation
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Nov 11 00:20:11 PST 2003
>Closed-Date:
>Last-Modified:
>Originator: Gernot Hueber
>Release: FreeBSD 5.1-RELEASE-p6 i386
>Organization:
>Environment:
System: FreeBSD midori.riic.uni-linz.ac.at 5.1-RELEASE-p6 FreeBSD 5.1-RELEASE-p6 #5: Wed Oct 22 20:34:05 CEST 2003 root at midori.riic.uni-linz.ac.at:/usr/src/sys/i386/compile/MIDORI i386
>Description:
The ulpt driver is missing the read operation, which is required for
some tools to report the status of the printer (eg. the ink level of
ink jet printers).
>How-To-Repeat:
Try esputil (included with gimpprint) for Epson printers
>Fix:
Apply patch below.
--- ulpt.diff begins here ---
*** ulpt.c.orig Wed Oct 22 10:59:53 2003
--- ulpt.c Fri Oct 24 21:40:57 2003
***************
*** 71,76 ****
--- 71,77 ----
#define LPTPRI (PZERO+8)
#define ULPT_BSIZE 16384
+ #define ULPT_IN_BUFFERLEN 1024
#ifdef USB_DEBUG
#define DPRINTF(x) if (ulptdebug) logprintf x
***************
*** 105,112 ****
int sc_in;
usbd_pipe_handle sc_in_pipe; /* bulk in pipe */
! usbd_xfer_handle sc_in_xfer1;
! usbd_xfer_handle sc_in_xfer2;
u_char sc_junk[64]; /* somewhere to dump input */
u_char sc_state;
--- 106,114 ----
int sc_in;
usbd_pipe_handle sc_in_pipe; /* bulk in pipe */
! usbd_xfer_handle sc_in_xfer;
! void *sc_in_buffer;
! int sc_in_bufferlen;
u_char sc_junk[64]; /* somewhere to dump input */
u_char sc_state;
***************
*** 141,146 ****
--- 143,149 ----
#elif defined(__FreeBSD__)
Static d_open_t ulptopen;
Static d_close_t ulptclose;
+ Static d_read_t ulptread;
Static d_write_t ulptwrite;
Static d_ioctl_t ulptioctl;
***************
*** 149,154 ****
--- 152,158 ----
Static struct cdevsw ulpt_cdevsw = {
.d_open = ulptopen,
.d_close = ulptclose,
+ .d_read = ulptread,
.d_write = ulptwrite,
.d_ioctl = ulptioctl,
.d_name = "ulpt",
***************
*** 162,167 ****
--- 166,172 ----
void ulpt_disco(void *);
int ulpt_do_write(struct ulpt_softc *, struct uio *uio, int);
+ int ulpt_do_read(struct ulpt_softc *, struct uio *uio, int);
int ulpt_status(struct ulpt_softc *);
void ulpt_reset(struct ulpt_softc *);
int ulpt_statusmsg(u_char, struct ulpt_softc *);
***************
*** 344,349 ****
--- 349,356 ----
UID_ROOT, GID_OPERATOR, 0644, "unlpt%d", device_get_unit(self));
#endif
+
+
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
USBDEV(sc->sc_dev));
***************
*** 473,497 ****
}
}
- static void
- ulpt_input(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
- {
- struct ulpt_softc *sc = priv;
- u_int32_t count;
-
- /* Don't loop on errors or 0-length input. */
- usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
- if (status != USBD_NORMAL_COMPLETION || count == 0)
- return;
-
- DPRINTFN(2,("ulpt_input: got some data\n"));
- /* Do it again. */
- if (xfer == sc->sc_in_xfer1)
- usbd_transfer(sc->sc_in_xfer2);
- else
- usbd_transfer(sc->sc_in_xfer1);
- }
-
int ulptusein = 1;
/*
--- 480,485 ----
***************
*** 517,522 ****
--- 505,513 ----
sc->sc_flags = flags;
DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags));
+ sc->sc_in_buffer = malloc(ULPT_IN_BUFFERLEN, M_USBDEV, M_WAITOK);
+ sc->sc_in_bufferlen = ULPT_IN_BUFFERLEN;
+
#if defined(USB_DEBUG) && defined(__FreeBSD__)
/* Ignoring these flags might not be a good idea */
if ((flags & ~ULPT_NOPRIME) != 0)
***************
*** 569,600 ****
sc->sc_state = 0;
goto done;
}
! sc->sc_in_xfer1 = usbd_alloc_xfer(sc->sc_udev);
! sc->sc_in_xfer2 = usbd_alloc_xfer(sc->sc_udev);
! if (sc->sc_in_xfer1 == NULL || sc->sc_in_xfer2 == NULL) {
! error = ENOMEM;
! if (sc->sc_in_xfer1 != NULL) {
! usbd_free_xfer(sc->sc_in_xfer1);
! sc->sc_in_xfer1 = NULL;
! }
! if (sc->sc_in_xfer2 != NULL) {
! usbd_free_xfer(sc->sc_in_xfer2);
! sc->sc_in_xfer2 = NULL;
! }
! usbd_close_pipe(sc->sc_out_pipe);
! sc->sc_out_pipe = NULL;
! usbd_close_pipe(sc->sc_in_pipe);
! sc->sc_in_pipe = NULL;
! sc->sc_state = 0;
! goto done;
! }
! usbd_setup_xfer(sc->sc_in_xfer1, sc->sc_in_pipe, sc,
! sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK,
! USBD_NO_TIMEOUT, ulpt_input);
! usbd_setup_xfer(sc->sc_in_xfer2, sc->sc_in_pipe, sc,
! sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK,
! USBD_NO_TIMEOUT, ulpt_input);
! usbd_transfer(sc->sc_in_xfer1); /* ignore failed start */
}
sc->sc_state = ULPT_OPEN;
--- 560,571 ----
sc->sc_state = 0;
goto done;
}
!
! sc->sc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
! if (sc->sc_in_xfer == NULL) {
! error=ENOMEM;
! goto done;
! }
}
sc->sc_state = ULPT_OPEN;
***************
*** 645,664 ****
usbd_abort_pipe(sc->sc_in_pipe);
usbd_close_pipe(sc->sc_in_pipe);
sc->sc_in_pipe = NULL;
- if (sc->sc_in_xfer1 != NULL) {
- usbd_free_xfer(sc->sc_in_xfer1);
- sc->sc_in_xfer1 = NULL;
- }
- if (sc->sc_in_xfer2 != NULL) {
- usbd_free_xfer(sc->sc_in_xfer2);
- sc->sc_in_xfer2 = NULL;
- }
}
sc->sc_state = 0;
DPRINTF(("ulptclose: closed\n"));
return (0);
}
int
--- 616,690 ----
usbd_abort_pipe(sc->sc_in_pipe);
usbd_close_pipe(sc->sc_in_pipe);
sc->sc_in_pipe = NULL;
}
+ if (sc->sc_in_xfer) {
+ usbd_free_xfer(sc->sc_in_xfer);
+ sc->sc_in_xfer = NULL;
+ }
+ if (sc->sc_in_buffer) {
+ free(sc->sc_in_buffer, M_USBDEV);
+ sc->sc_in_buffer = NULL;
+ }
sc->sc_state = 0;
DPRINTF(("ulptclose: closed\n"));
return (0);
+ }
+
+ int
+ ulpt_do_read(struct ulpt_softc *sc, struct uio *uio, int flag)
+ {
+ u_int32_t n, tn;
+ usbd_status err;
+ int error = 0;
+
+ DPRINTFN(5, ("%s: ulptread\n", USBDEVNAME(sc->sc_dev)));
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ while ((n = min(sc->sc_in_bufferlen, uio->uio_resid)) != 0) {
+ DPRINTFN(1, ("ulptread: start transfer %d bytes\n",n));
+ tn = n;
+
+ err = usbd_bulk_transfer(
+ sc->sc_in_xfer, sc->sc_in_pipe,
+ USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
+ sc->sc_in_buffer, &tn,
+ "uscnrb");
+ if (err) {
+ if (err == USBD_INTERRUPTED)
+ error = EINTR;
+ else if (err == USBD_TIMEOUT)
+ error = ETIMEDOUT;
+ else
+ error = EIO;
+ break;
+ }
+ DPRINTFN(1, ("ulptread: got %d bytes\n", tn));
+ error = uiomove(sc->sc_in_buffer, tn, uio);
+ if (error || tn < n)
+ break;
+ }
+
+ return (error);
+ }
+
+ int
+ ulptread(dev_t dev, struct uio *uio, int flag)
+ {
+ struct ulpt_softc *sc;
+ int error;
+
+ USB_GET_SC(ulpt, ULPTUNIT(dev), sc);
+
+ sc->sc_refcnt++;
+ error = ulpt_do_read(sc, uio, flag);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+
+ return (error);
}
int
--- ulpt.diff ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list