Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Oct 2003 10:47:36 +0100
From:      Gernot Hueber <hueber@riic.at>
To:        freebsd-hackers@freebsd.org
Subject:   Patch Review: ulpt read patch
Message-ID:  <20031027094736.GW36100@hanni.riic.uni-linz.ac.at>

next in thread | raw e-mail | index | archive | help
Hi,

I have written a patch for ulpt.c which allows reading the
lpt device. This operation is required to get status information of
some printers (eg. Epson Stylus) when connected via usb.

Please can you review this patch (it applies to 5.1 P6)

Thanks,

Gernot

*** 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


-- 
Dipl.-Ing. Gernot Hueber
Institut f. Integrierte Schaltungen
Altenbergerstr. 69
4040 Linz

Tel: +43 732 2468-7120, Fax: -7126
E-mail: hueber@riic.at
WWW: www.riic.at



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031027094736.GW36100>