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