LCOV - code coverage report
Current view: top level - dev/usb - ulpt.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 299 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13