root/dev/usb/ulpt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ulpt_match
  2. ulpt_attach
  3. ulpt_activate
  4. ulpt_detach
  5. ulpt_status
  6. ulpt_reset
  7. ulpt_input
  8. ulptopen
  9. ulpt_statusmsg
  10. ulptclose
  11. ulpt_do_write
  12. ulptwrite
  13. ulptioctl
  14. ieee1284_print_id

    1 /*      $OpenBSD: ulpt.c,v 1.32 2007/06/14 10:11:16 mbalmer Exp $ */
    2 /*      $NetBSD: ulpt.c,v 1.57 2003/01/05 10:19:42 scw Exp $    */
    3 /*      $FreeBSD: src/sys/dev/usb/ulpt.c,v 1.24 1999/11/17 22:33:44 n_hibma Exp $       */
    4 
    5 /*
    6  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to The NetBSD Foundation
   10  * by Lennart Augustsson (lennart@augustsson.net) at
   11  * Carlstedt Research & Technology.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. All advertising materials mentioning features or use of this software
   22  *    must display the following acknowledgement:
   23  *        This product includes software developed by the NetBSD
   24  *        Foundation, Inc. and its contributors.
   25  * 4. Neither the name of The NetBSD Foundation nor the names of its
   26  *    contributors may be used to endorse or promote products derived
   27  *    from this software without specific prior written permission.
   28  *
   29  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   30  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   31  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   32  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   33  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   36  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   37  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   39  * POSSIBILITY OF SUCH DAMAGE.
   40  */
   41 
   42 /*
   43  * Printer Class spec:
   44  *   http://www.usb.org/developers/devclass_docs/usbprint11.pdf
   45  */
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/proc.h>
   50 #include <sys/kernel.h>
   51 #include <sys/device.h>
   52 #include <sys/ioctl.h>
   53 #include <sys/uio.h>
   54 #include <sys/conf.h>
   55 #include <sys/vnode.h>
   56 #include <sys/syslog.h>
   57 
   58 #include <dev/usb/usb.h>
   59 #include <dev/usb/usbdi.h>
   60 #include <dev/usb/usbdi_util.h>
   61 #include <dev/usb/usbdevs.h>
   62 #include <dev/usb/usb_quirks.h>
   63 
   64 #define TIMEOUT         hz*16   /* wait up to 16 seconds for a ready */
   65 #define STEP            hz/4
   66 
   67 #define LPTPRI          (PZERO+8)
   68 #define ULPT_BSIZE      16384
   69 
   70 #ifdef ULPT_DEBUG
   71 #define DPRINTF(x)      do { if (ulptdebug) printf x; } while (0)
   72 #define DPRINTFN(n,x)   do { if (ulptdebug>(n)) printf x; } while (0)
   73 int     ulptdebug = 0;
   74 #else
   75 #define DPRINTF(x)
   76 #define DPRINTFN(n,x)
   77 #endif
   78 
   79 #define UR_GET_DEVICE_ID 0
   80 #define UR_GET_PORT_STATUS 1
   81 #define UR_SOFT_RESET 2
   82 
   83 #define LPS_NERR                0x08    /* printer no error */
   84 #define LPS_SELECT              0x10    /* printer selected */
   85 #define LPS_NOPAPER             0x20    /* printer out of paper */
   86 #define LPS_INVERT      (LPS_SELECT|LPS_NERR)
   87 #define LPS_MASK        (LPS_SELECT|LPS_NERR|LPS_NOPAPER)
   88 
   89 struct ulpt_softc {
   90         struct device sc_dev;
   91         usbd_device_handle sc_udev;     /* device */
   92         usbd_interface_handle sc_iface; /* interface */
   93         int sc_ifaceno;
   94 
   95         int sc_out;
   96         usbd_pipe_handle sc_out_pipe;   /* bulk out pipe */
   97 
   98         int sc_in;
   99         usbd_pipe_handle sc_in_pipe;    /* bulk in pipe */
  100         usbd_xfer_handle sc_in_xfer1;
  101         usbd_xfer_handle sc_in_xfer2;
  102         u_char sc_junk[64];     /* somewhere to dump input */
  103 
  104         u_char sc_state;
  105 #define ULPT_OPEN       0x01    /* device is open */
  106 #define ULPT_OBUSY      0x02    /* printer is busy doing output */
  107 #define ULPT_INIT       0x04    /* waiting to initialize for open */
  108         u_char sc_flags;
  109 #define ULPT_NOPRIME    0x40    /* don't prime on open */
  110         u_char sc_laststatus;
  111 
  112         int sc_refcnt;
  113         u_char sc_dying;
  114 };
  115 
  116 void ulpt_disco(void *);
  117 
  118 int ulpt_do_write(struct ulpt_softc *, struct uio *uio, int);
  119 int ulpt_status(struct ulpt_softc *);
  120 void ulpt_reset(struct ulpt_softc *);
  121 int ulpt_statusmsg(u_char, struct ulpt_softc *);
  122 
  123 #if 0
  124 void ieee1284_print_id(char *);
  125 #endif
  126 
  127 #define ULPTUNIT(s)     (minor(s) & 0x1f)
  128 #define ULPTFLAGS(s)    (minor(s) & 0xe0)
  129 
  130 
  131 int ulpt_match(struct device *, void *, void *); 
  132 void ulpt_attach(struct device *, struct device *, void *); 
  133 int ulpt_detach(struct device *, int); 
  134 int ulpt_activate(struct device *, enum devact); 
  135 
  136 struct cfdriver ulpt_cd = { 
  137         NULL, "ulpt", DV_DULL 
  138 }; 
  139 
  140 const struct cfattach ulpt_ca = { 
  141         sizeof(struct ulpt_softc), 
  142         ulpt_match, 
  143         ulpt_attach, 
  144         ulpt_detach, 
  145         ulpt_activate, 
  146 };
  147 
  148 int
  149 ulpt_match(struct device *parent, void *match, void *aux)
  150 {
  151         struct usb_attach_arg *uaa = aux;
  152         usb_interface_descriptor_t *id;
  153 
  154         DPRINTFN(10,("ulpt_match\n"));
  155         if (uaa->iface == NULL)
  156                 return (UMATCH_NONE);
  157         id = usbd_get_interface_descriptor(uaa->iface);
  158         if (id != NULL &&
  159             id->bInterfaceClass == UICLASS_PRINTER &&
  160             id->bInterfaceSubClass == UISUBCLASS_PRINTER &&
  161             ((id->bInterfaceProtocol == UIPROTO_PRINTER_UNI) ||
  162              (id->bInterfaceProtocol == UIPROTO_PRINTER_BI) ||
  163              (id->bInterfaceProtocol == UIPROTO_PRINTER_1284)))
  164                 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
  165         return (UMATCH_NONE);
  166 }
  167 
  168 void
  169 ulpt_attach(struct device *parent, struct device *self, void *aux)
  170 {
  171         struct ulpt_softc *sc = (struct ulpt_softc *)self;
  172         struct usb_attach_arg *uaa = aux;
  173         usbd_device_handle dev = uaa->device;
  174         usbd_interface_handle iface = uaa->iface;
  175         usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface);
  176         usb_interface_descriptor_t *id, *iend;
  177         usb_config_descriptor_t *cdesc;
  178         usbd_status err;
  179         char *devinfop;
  180         usb_endpoint_descriptor_t *ed;
  181         u_int8_t epcount;
  182         int i, altno;
  183 
  184         DPRINTFN(10,("ulpt_attach: sc=%p\n", sc));
  185 
  186         devinfop = usbd_devinfo_alloc(dev, 0);
  187         printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname,
  188                devinfop, ifcd->bInterfaceClass, ifcd->bInterfaceSubClass);
  189         usbd_devinfo_free(devinfop);
  190 
  191         /* XXX
  192          * Stepping through the alternate settings needs to be abstracted out.
  193          */
  194         cdesc = usbd_get_config_descriptor(dev);
  195         if (cdesc == NULL) {
  196                 printf("%s: failed to get configuration descriptor\n",
  197                        sc->sc_dev.dv_xname);
  198                 return;
  199         }
  200         iend = (usb_interface_descriptor_t *)
  201                    ((char *)cdesc + UGETW(cdesc->wTotalLength));
  202 #ifdef DIAGNOSTIC
  203         if (ifcd < (usb_interface_descriptor_t *)cdesc ||
  204             ifcd >= iend)
  205                 panic("ulpt: iface desc out of range");
  206 #endif
  207         /* Step through all the descriptors looking for bidir mode */
  208         for (id = ifcd, altno = 0;
  209              id < iend;
  210              id = (void *)((char *)id + id->bLength)) {
  211                 if (id->bDescriptorType == UDESC_INTERFACE &&
  212                     id->bInterfaceNumber == ifcd->bInterfaceNumber) {
  213                         if (id->bInterfaceClass == UICLASS_PRINTER &&
  214                             id->bInterfaceSubClass == UISUBCLASS_PRINTER &&
  215                             (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /*||
  216                              id->bInterfaceProtocol == UIPROTO_PRINTER_1284*/))
  217                                 goto found;
  218                         altno++;
  219                 }
  220         }
  221         id = ifcd;              /* not found, use original */
  222  found:
  223         if (id != ifcd) {
  224                 /* Found a new bidir setting */
  225                 DPRINTF(("ulpt_attach: set altno = %d\n", altno));
  226                 err = usbd_set_interface(iface, altno);
  227                 if (err) {
  228                         printf("%s: setting alternate interface failed\n",
  229                                sc->sc_dev.dv_xname);
  230                         sc->sc_dying = 1;
  231                         return;
  232                 }
  233         }
  234 
  235         epcount = 0;
  236         (void)usbd_endpoint_count(iface, &epcount);
  237 
  238         sc->sc_in = -1;
  239         sc->sc_out = -1;
  240         for (i = 0; i < epcount; i++) {
  241                 ed = usbd_interface2endpoint_descriptor(iface, i);
  242                 if (ed == NULL) {
  243                         printf("%s: couldn't get ep %d\n",
  244                             sc->sc_dev.dv_xname, i);
  245                         return;
  246                 }
  247                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  248                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  249                         sc->sc_in = ed->bEndpointAddress;
  250                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  251                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  252                         sc->sc_out = ed->bEndpointAddress;
  253                 }
  254         }
  255         if (sc->sc_out == -1) {
  256                 printf("%s: could not find bulk out endpoint\n",
  257                     sc->sc_dev.dv_xname);
  258                 sc->sc_dying = 1;
  259                 return;
  260         }
  261 
  262         if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) {
  263                 /* This device doesn't handle reading properly. */
  264                 sc->sc_in = -1;
  265         }
  266 
  267         printf("%s: using %s-directional mode\n", sc->sc_dev.dv_xname,
  268                sc->sc_in >= 0 ? "bi" : "uni");
  269 
  270         DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_out));
  271 
  272         sc->sc_iface = iface;
  273         sc->sc_ifaceno = id->bInterfaceNumber;
  274         sc->sc_udev = dev;
  275 
  276 #if 0
  277 /*
  278  * This code is disabled because for some mysterious reason it causes
  279  * printing not to work.  But only sometimes, and mostly with
  280  * UHCI and less often with OHCI.  *sigh*
  281  */
  282         {
  283         usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
  284         usb_device_request_t req;
  285         int len, alen;
  286 
  287         req.bmRequestType = UT_READ_CLASS_INTERFACE;
  288         req.bRequest = UR_GET_DEVICE_ID;
  289         USETW(req.wValue, cd->bConfigurationValue);
  290         USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting);
  291         USETW(req.wLength, DEVINFOSIZE - 1);
  292         err = usbd_do_request_flags(dev, &req, devinfop, USBD_SHORT_XFER_OK,
  293                   &alen, USBD_DEFAULT_TIMEOUT);
  294         if (err) {
  295                 printf("%s: cannot get device id\n", sc->sc_dev.dv_xname);
  296         } else if (alen <= 2) {
  297                 printf("%s: empty device id, no printer connected?\n",
  298                        sc->sc_dev.dv_xname);
  299         } else {
  300                 /* devinfop now contains an IEEE-1284 device ID */
  301                 len = ((devinfop[0] & 0xff) << 8) | (devinfop[1] & 0xff);
  302                 if (len > DEVINFOSIZE - 3)
  303                         len = DEVINFOSIZE - 3;
  304                 devinfo[len] = 0;
  305                 printf("%s: device id <", sc->sc_dev.dv_xname);
  306                 ieee1284_print_id(devinfop+2);
  307                 printf(">\n");
  308         }
  309         }
  310 #endif
  311         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  312                            &sc->sc_dev);
  313 }
  314 
  315 int
  316 ulpt_activate(struct device *self, enum devact act)
  317 {
  318         struct ulpt_softc *sc = (struct ulpt_softc *)self;
  319 
  320         switch (act) {
  321         case DVACT_ACTIVATE:
  322                 break;
  323 
  324         case DVACT_DEACTIVATE:
  325                 sc->sc_dying = 1;
  326                 break;
  327         }
  328         return (0);
  329 }
  330 
  331 int
  332 ulpt_detach(struct device *self, int flags)
  333 {
  334         struct ulpt_softc *sc = (struct ulpt_softc *)self;
  335         int s;
  336         int maj, mn;
  337 
  338         DPRINTF(("ulpt_detach: sc=%p\n", sc));
  339 
  340         sc->sc_dying = 1;
  341         if (sc->sc_out_pipe != NULL)
  342                 usbd_abort_pipe(sc->sc_out_pipe);
  343         if (sc->sc_in_pipe != NULL)
  344                 usbd_abort_pipe(sc->sc_in_pipe);
  345 
  346         s = splusb();
  347         if (--sc->sc_refcnt >= 0) {
  348                 /* There is noone to wake, aborting the pipe is enough */
  349                 /* Wait for processes to go away. */
  350                 usb_detach_wait(&sc->sc_dev);
  351         }
  352         splx(s);
  353 
  354         /* locate the major number */
  355         for (maj = 0; maj < nchrdev; maj++)
  356                 if (cdevsw[maj].d_open == ulptopen)
  357                         break;
  358 
  359         /* Nuke the vnodes for any open instances (calls close). */
  360         mn = self->dv_unit;
  361         vdevgone(maj, mn, mn, VCHR);
  362         vdevgone(maj, mn | ULPT_NOPRIME , mn | ULPT_NOPRIME, VCHR);
  363 
  364         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  365                            &sc->sc_dev);
  366 
  367         return (0);
  368 }
  369 
  370 int
  371 ulpt_status(struct ulpt_softc *sc)
  372 {
  373         usb_device_request_t req;
  374         usbd_status err;
  375         u_char status;
  376 
  377         req.bmRequestType = UT_READ_CLASS_INTERFACE;
  378         req.bRequest = UR_GET_PORT_STATUS;
  379         USETW(req.wValue, 0);
  380         USETW(req.wIndex, sc->sc_ifaceno);
  381         USETW(req.wLength, 1);
  382         err = usbd_do_request(sc->sc_udev, &req, &status);
  383         DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err));
  384         if (!err)
  385                 return (status);
  386         else
  387                 return (0);
  388 }
  389 
  390 void
  391 ulpt_reset(struct ulpt_softc *sc)
  392 {
  393         usb_device_request_t req;
  394 
  395         DPRINTFN(1, ("ulpt_reset\n"));
  396         req.bRequest = UR_SOFT_RESET;
  397         USETW(req.wValue, 0);
  398         USETW(req.wIndex, sc->sc_ifaceno);
  399         USETW(req.wLength, 0);
  400 
  401         /*
  402          * There was a mistake in the USB printer 1.0 spec that gave the
  403          * request type as UT_WRITE_CLASS_OTHER; it should have been
  404          * UT_WRITE_CLASS_INTERFACE.  Many printers use the old one,
  405          * so we try both.
  406          */
  407         req.bmRequestType = UT_WRITE_CLASS_OTHER;
  408         if (usbd_do_request(sc->sc_udev, &req, 0)) {    /* 1.0 */
  409                 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  410                 (void)usbd_do_request(sc->sc_udev, &req, 0); /* 1.1 */
  411         }
  412 }
  413 
  414 static void
  415 ulpt_input(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  416 {
  417         struct ulpt_softc *sc = priv;
  418 
  419         DPRINTFN(2,("ulpt_input: got some data\n"));
  420         /* Do it again. */
  421         if (xfer == sc->sc_in_xfer1)
  422                 usbd_transfer(sc->sc_in_xfer2);
  423         else
  424                 usbd_transfer(sc->sc_in_xfer1);
  425 }
  426 
  427 int ulptusein = 1;
  428 
  429 /*
  430  * Reset the printer, then wait until it's selected and not busy.
  431  */
  432 int
  433 ulptopen(dev_t dev, int flag, int mode, struct proc *p)
  434 {
  435         u_char flags = ULPTFLAGS(dev);
  436         struct ulpt_softc *sc;
  437         usbd_status err;
  438         int spin, error;
  439 
  440         if (ULPTUNIT(dev) >= ulpt_cd.cd_ndevs)
  441                 return (ENXIO);
  442         sc = ulpt_cd.cd_devs[ULPTUNIT(dev)];
  443         if (sc == NULL)
  444                 return (ENXIO);
  445 
  446         if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying)
  447                 return (ENXIO);
  448 
  449         if (sc->sc_state)
  450                 return (EBUSY);
  451 
  452         sc->sc_state = ULPT_INIT;
  453         sc->sc_flags = flags;
  454         DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags));
  455 
  456         error = 0;
  457         sc->sc_refcnt++;
  458 
  459         if ((flags & ULPT_NOPRIME) == 0)
  460                 ulpt_reset(sc);
  461 
  462         for (spin = 0; (ulpt_status(sc) & LPS_SELECT) == 0; spin += STEP) {
  463                 DPRINTF(("ulpt_open: waiting a while\n"));
  464                 if (spin >= TIMEOUT) {
  465                         error = EBUSY;
  466                         sc->sc_state = 0;
  467                         goto done;
  468                 }
  469 
  470                 /* wait 1/4 second, give up if we get a signal */
  471                 error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "ulptop", STEP);
  472                 if (error != EWOULDBLOCK) {
  473                         sc->sc_state = 0;
  474                         goto done;
  475                 }
  476 
  477                 if (sc->sc_dying) {
  478                         error = ENXIO;
  479                         sc->sc_state = 0;
  480                         goto done;
  481                 }
  482         }
  483 
  484         err = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe);
  485         if (err) {
  486                 sc->sc_state = 0;
  487                 error = EIO;
  488                 goto done;
  489         }
  490         if (ulptusein && sc->sc_in != -1) {
  491                 DPRINTF(("ulpt_open: open input pipe\n"));
  492                 err = usbd_open_pipe(sc->sc_iface, sc->sc_in,0,&sc->sc_in_pipe);
  493                 if (err) {
  494                         error = EIO;
  495                         usbd_close_pipe(sc->sc_out_pipe);
  496                         sc->sc_out_pipe = NULL;
  497                         sc->sc_state = 0;
  498                         goto done;
  499                 }
  500                 sc->sc_in_xfer1 = usbd_alloc_xfer(sc->sc_udev);
  501                 sc->sc_in_xfer2 = usbd_alloc_xfer(sc->sc_udev);
  502                 if (sc->sc_in_xfer1 == NULL || sc->sc_in_xfer2 == NULL) {
  503                         error = ENOMEM;
  504                         if (sc->sc_in_xfer1 != NULL) {
  505                                 usbd_free_xfer(sc->sc_in_xfer1);
  506                                 sc->sc_in_xfer1 = NULL;
  507                         }
  508                         if (sc->sc_in_xfer2 != NULL) {
  509                                 usbd_free_xfer(sc->sc_in_xfer2);
  510                                 sc->sc_in_xfer2 = NULL;
  511                         }
  512                         usbd_close_pipe(sc->sc_out_pipe);
  513                         sc->sc_out_pipe = NULL;
  514                         usbd_close_pipe(sc->sc_in_pipe);
  515                         sc->sc_in_pipe = NULL;
  516                         sc->sc_state = 0;
  517                         goto done;
  518                 }
  519                 usbd_setup_xfer(sc->sc_in_xfer1, sc->sc_in_pipe, sc,
  520                     sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK,
  521                     USBD_NO_TIMEOUT, ulpt_input);
  522                 usbd_setup_xfer(sc->sc_in_xfer2, sc->sc_in_pipe, sc,
  523                     sc->sc_junk, sizeof sc->sc_junk, USBD_SHORT_XFER_OK,
  524                     USBD_NO_TIMEOUT, ulpt_input);
  525                 usbd_transfer(sc->sc_in_xfer1); /* ignore failed start */
  526         }
  527 
  528         sc->sc_state = ULPT_OPEN;
  529 
  530  done:
  531         if (--sc->sc_refcnt < 0)
  532                 usb_detach_wakeup(&sc->sc_dev);
  533 
  534         DPRINTF(("ulptopen: done, error=%d\n", error));
  535         return (error);
  536 }
  537 
  538 int
  539 ulpt_statusmsg(u_char status, struct ulpt_softc *sc)
  540 {
  541         u_char new;
  542 
  543         status = (status ^ LPS_INVERT) & LPS_MASK;
  544         new = status & ~sc->sc_laststatus;
  545         sc->sc_laststatus = status;
  546 
  547         if (new & LPS_SELECT)
  548                 log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
  549         else if (new & LPS_NOPAPER)
  550                 log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
  551         else if (new & LPS_NERR)
  552                 log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
  553 
  554         return (status);
  555 }
  556 
  557 int
  558 ulptclose(dev_t dev, int flag, int mode, struct proc *p)
  559 {
  560         struct ulpt_softc *sc;
  561 
  562         sc = ulpt_cd.cd_devs[ULPTUNIT(dev)];
  563 
  564         if (sc->sc_state != ULPT_OPEN)
  565                 /* We are being forced to close before the open completed. */
  566                 return (0);
  567 
  568         if (sc->sc_out_pipe != NULL) {
  569                 usbd_close_pipe(sc->sc_out_pipe);
  570                 sc->sc_out_pipe = NULL;
  571         }
  572         if (sc->sc_in_pipe != NULL) {
  573                 usbd_abort_pipe(sc->sc_in_pipe);
  574                 usbd_close_pipe(sc->sc_in_pipe);
  575                 sc->sc_in_pipe = NULL;
  576                 if (sc->sc_in_xfer1 != NULL) {
  577                         usbd_free_xfer(sc->sc_in_xfer1);
  578                         sc->sc_in_xfer1 = NULL;
  579                 }
  580                 if (sc->sc_in_xfer2 != NULL) {
  581                         usbd_free_xfer(sc->sc_in_xfer2);
  582                         sc->sc_in_xfer2 = NULL;
  583                 }
  584         }
  585 
  586         sc->sc_state = 0;
  587 
  588         DPRINTF(("ulptclose: closed\n"));
  589         return (0);
  590 }
  591 
  592 int
  593 ulpt_do_write(struct ulpt_softc *sc, struct uio *uio, int flags)
  594 {
  595         u_int32_t n;
  596         int error = 0;
  597         void *bufp;
  598         usbd_xfer_handle xfer;
  599         usbd_status err;
  600 
  601         DPRINTF(("ulptwrite\n"));
  602         xfer = usbd_alloc_xfer(sc->sc_udev);
  603         if (xfer == NULL)
  604                 return (ENOMEM);
  605         bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE);
  606         if (bufp == NULL) {
  607                 usbd_free_xfer(xfer);
  608                 return (ENOMEM);
  609         }
  610         while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) {
  611                 ulpt_statusmsg(ulpt_status(sc), sc);
  612                 error = uiomove(bufp, n, uio);
  613                 if (error)
  614                         break;
  615                 DPRINTFN(1, ("ulptwrite: transfer %d bytes\n", n));
  616                 err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY,
  617                           USBD_NO_TIMEOUT, bufp, &n, "ulptwr");
  618                 if (err) {
  619                         DPRINTF(("ulptwrite: error=%d\n", err));
  620                         error = EIO;
  621                         break;
  622                 }
  623         }
  624         usbd_free_xfer(xfer);
  625 
  626         return (error);
  627 }
  628 
  629 int
  630 ulptwrite(dev_t dev, struct uio *uio, int flags)
  631 {
  632         struct ulpt_softc *sc;
  633         int error;
  634 
  635         sc = ulpt_cd.cd_devs[ULPTUNIT(dev)];
  636 
  637         if (sc->sc_dying)
  638                 return (EIO);
  639 
  640         sc->sc_refcnt++;
  641         error = ulpt_do_write(sc, uio, flags);
  642         if (--sc->sc_refcnt < 0)
  643                 usb_detach_wakeup(&sc->sc_dev);
  644         return (error);
  645 }
  646 
  647 int
  648 ulptioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  649 {
  650         int error = 0;
  651 
  652         switch (cmd) {
  653         default:
  654                 error = ENODEV;
  655         }
  656 
  657         return (error);
  658 }
  659 
  660 #if 0
  661 /* XXX This does not belong here. */
  662 /*
  663  * Print select parts of a IEEE 1284 device ID.
  664  */
  665 void
  666 ieee1284_print_id(char *str)
  667 {
  668         char *p, *q;
  669 
  670         for (p = str-1; p; p = strchr(p, ';')) {
  671                 p++;            /* skip ';' */
  672                 if (strncmp(p, "MFG:", 4) == 0 ||
  673                     strncmp(p, "MANUFACTURER:", 14) == 0 ||
  674                     strncmp(p, "MDL:", 4) == 0 ||
  675                     strncmp(p, "MODEL:", 6) == 0) {
  676                         q = strchr(p, ';');
  677                         if (q)
  678                                 printf("%.*s", (int)(q - p + 1), p);
  679                 }
  680         }
  681 }
  682 #endif

/* [<][>][^][v][top][bottom][index][help] */