root/dev/usb/usscanner.c

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

DEFINITIONS

This source file includes following definitions.
  1. usscanner_match
  2. usscanner_attach
  3. usscanner_detach
  4. usscanner_cleanup
  5. usscanner_activate
  6. usscanner_scsipi_minphys
  7. usscanner_sense
  8. usscanner_intr_cb
  9. usscanner_data_cb
  10. usscanner_sensedata_cb
  11. usscanner_done
  12. usscanner_sensecmd_cb
  13. usscanner_cmd_cb
  14. usscanner_scsipi_cmd

    1 /*      $OpenBSD: usscanner.c,v 1.22 2007/06/14 10:11:16 mbalmer Exp $  */
    2 /*      $NetBSD: usscanner.c,v 1.6 2001/01/23 14:04:14 augustss Exp $   */
    3 
    4 /*
    5  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (lennart@augustsson.net) and LLoyd Parkes.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * This driver is partly based on information taken from the Linux driver
   42  * by John Fremlin, Oliver Neukum, and Jeremy Hall.
   43  */
   44 /*
   45  * Protocol:
   46  * Send raw SCSI command on the bulk-out pipe.
   47  * If output command then
   48  *     send further data on the bulk-out pipe
   49  * else if input command then
   50  *     read data on the bulk-in pipe
   51  * else
   52  *     don't do anything.
   53  * Read status byte on the interrupt pipe (which doesn't seem to be
   54  * an interrupt pipe at all).  This operation sometimes times out.
   55  */
   56 
   57 #include <sys/param.h>
   58 #include <sys/systm.h>
   59 #include <sys/kernel.h>
   60 #include <sys/malloc.h>
   61 #include <sys/device.h>
   62 #include <sys/conf.h>
   63 #include <sys/buf.h>
   64 
   65 #include <dev/usb/usb.h>
   66 #include <dev/usb/usbdi.h>
   67 #include <dev/usb/usbdi_util.h>
   68 
   69 #include <dev/usb/usbdevs.h>
   70 
   71 #include <scsi/scsi_all.h>
   72 #include <scsi/scsiconf.h>
   73 #include <machine/bus.h>
   74 
   75 #ifdef USSCANNER_DEBUG
   76 #define DPRINTF(x)      do { if (usscannerdebug) printf x; } while (0)
   77 #define DPRINTFN(n,x)   do { if (usscannerdebug>(n)) printf x; } while (0)
   78 int     usscannerdebug = 0;
   79 #else
   80 #define DPRINTF(x)
   81 #define DPRINTFN(n,x)
   82 #endif
   83 
   84 #define XS_CTL_DATA_IN          SCSI_DATA_IN
   85 #define XS_CTL_DATA_OUT         SCSI_DATA_OUT
   86 #define scsipi_adapter          scsi_adapter
   87 #define scsipi_cmd              scsi_cmd
   88 #define scsipi_device           scsi_device
   89 #define scsipi_done             scsi_done
   90 #define scsipi_link             scsi_link
   91 #define scsipi_minphys          scsi_minphys
   92 #define scsipi_sense            scsi_sense
   93 #define scsipi_xfer             scsi_xfer
   94 #define show_scsipi_xs          show_scsi_xs
   95 #define show_scsipi_cmd         show_scsi_cmd
   96 #define xs_control              flags
   97 #define xs_status               status
   98 #define XS_STS_DONE             ITSDONE
   99 #define XS_CTL_POLL             SCSI_POLL
  100 
  101 #define USSCANNER_CONFIG_NO             1
  102 #define USSCANNER_IFACE_IDX             0
  103 
  104 #define USSCANNER_SCSIID_HOST   0x00
  105 #define USSCANNER_SCSIID_DEVICE 0x01
  106 
  107 #define USSCANNER_MAX_TRANSFER_SIZE     MAXBSIZE
  108 
  109 #define USSCANNER_TIMEOUT 2000
  110 
  111 struct scsipi_device usscanner_dev =
  112 {
  113         NULL,                   /* Use default error handler */
  114         NULL,                   /* have a queue, served by this */
  115         NULL,                   /* have no async handler */
  116         NULL,                   /* Use default 'done' routine */
  117 };
  118 
  119 struct usscanner_softc {
  120         struct device           sc_dev;
  121         usbd_device_handle      sc_udev;
  122         usbd_interface_handle   sc_iface;
  123 
  124         int                     sc_in_addr;
  125         usbd_pipe_handle        sc_in_pipe;
  126 
  127         int                     sc_intr_addr;
  128         usbd_pipe_handle        sc_intr_pipe;
  129         usbd_xfer_handle        sc_intr_xfer;
  130         u_char                  sc_status;
  131 
  132         int                     sc_out_addr;
  133         usbd_pipe_handle        sc_out_pipe;
  134 
  135         usbd_xfer_handle        sc_cmd_xfer;
  136         void                    *sc_cmd_buffer;
  137         usbd_xfer_handle        sc_data_xfer;
  138         void                    *sc_data_buffer;
  139 
  140         int                     sc_state;
  141 #define UAS_IDLE        0
  142 #define UAS_CMD         1
  143 #define UAS_DATA        2
  144 #define UAS_SENSECMD    3
  145 #define UAS_SENSEDATA   4
  146 #define UAS_STATUS      5
  147 
  148         struct scsipi_xfer      *sc_xs;
  149 
  150         struct device           *sc_child;      /* child device, for detach */
  151 
  152         struct scsipi_link      sc_link;
  153         struct scsi_adapter     sc_atapi_adapter;
  154 #define sc_adapter sc_atapi_adapter
  155 
  156         int                     sc_refcnt;
  157         char                    sc_dying;
  158 };
  159 
  160 
  161 void usscanner_cleanup(struct usscanner_softc *sc);
  162 int usscanner_scsipi_cmd(struct scsipi_xfer *xs);
  163 void usscanner_scsipi_minphys(struct buf *bp);
  164 void usscanner_done(struct usscanner_softc *sc);
  165 void usscanner_sense(struct usscanner_softc *sc);
  166 typedef void callback(usbd_xfer_handle, usbd_private_handle, usbd_status);
  167 callback usscanner_intr_cb;
  168 callback usscanner_cmd_cb;
  169 callback usscanner_data_cb;
  170 callback usscanner_sensecmd_cb;
  171 callback usscanner_sensedata_cb;
  172 
  173 int usscanner_match(struct device *, void *, void *); 
  174 void usscanner_attach(struct device *, struct device *, void *); 
  175 int usscanner_detach(struct device *, int); 
  176 int usscanner_activate(struct device *, enum devact); 
  177 
  178 struct cfdriver usscanner_cd = { 
  179         NULL, "usscanner", DV_DULL 
  180 }; 
  181 
  182 const struct cfattach usscanner_ca = { 
  183         sizeof(struct usscanner_softc), 
  184         usscanner_match, 
  185         usscanner_attach, 
  186         usscanner_detach, 
  187         usscanner_activate, 
  188 };
  189 
  190 int
  191 usscanner_match(struct device *parent, void *match, void *aux)
  192 {
  193         struct usb_attach_arg   *uaa = aux;
  194 
  195         DPRINTFN(50,("usscanner_match\n"));
  196 
  197         if (uaa->iface != NULL)
  198                 return (UMATCH_NONE);
  199 
  200         if (uaa->vendor == USB_VENDOR_HP &&
  201             uaa->product == USB_PRODUCT_HP_5300C)
  202                 return (UMATCH_VENDOR_PRODUCT);
  203         else
  204                 return (UMATCH_NONE);
  205 }
  206 
  207 void
  208 usscanner_attach(struct device *parent, struct device *self, void *aux)
  209 {
  210         struct usscanner_softc  *sc = (struct usscanner_softc *)self;
  211         struct usb_attach_arg   *uaa = aux;
  212         struct scsibus_attach_args saa;
  213         usbd_device_handle      dev = uaa->device;
  214         usbd_interface_handle   iface;
  215         char                    *devinfop;
  216         usbd_status             err;
  217         usb_endpoint_descriptor_t *ed;
  218         u_int8_t                epcount;
  219         int                     i;
  220 
  221         DPRINTFN(10,("usscanner_attach: sc=%p\n", sc));
  222 
  223         devinfop = usbd_devinfo_alloc(dev, 0);
  224         printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
  225         usbd_devinfo_free(devinfop);
  226 
  227         err = usbd_set_config_no(dev, USSCANNER_CONFIG_NO, 1);
  228         if (err) {
  229                 printf("%s: setting config no failed\n",
  230                     sc->sc_dev.dv_xname);
  231                 return;
  232         }
  233 
  234         err = usbd_device2interface_handle(dev, USSCANNER_IFACE_IDX, &iface);
  235         if (err) {
  236                 printf("%s: getting interface handle failed\n",
  237                     sc->sc_dev.dv_xname);
  238                 return;
  239         }
  240 
  241         sc->sc_udev = dev;
  242         sc->sc_iface = iface;
  243 
  244         epcount = 0;
  245         (void)usbd_endpoint_count(iface, &epcount);
  246 
  247         sc->sc_in_addr = -1;
  248         sc->sc_intr_addr = -1;
  249         sc->sc_out_addr = -1;
  250         for (i = 0; i < epcount; i++) {
  251                 ed = usbd_interface2endpoint_descriptor(iface, i);
  252                 if (ed == NULL) {
  253                         printf("%s: couldn't get ep %d\n",
  254                             sc->sc_dev.dv_xname, i);
  255                         return;
  256                 }
  257                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  258                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  259                         sc->sc_in_addr = ed->bEndpointAddress;
  260                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  261                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
  262                         sc->sc_intr_addr = ed->bEndpointAddress;
  263                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  264                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  265                         sc->sc_out_addr = ed->bEndpointAddress;
  266                 }
  267         }
  268         if (sc->sc_in_addr == -1 || sc->sc_intr_addr == -1 ||
  269             sc->sc_out_addr == -1) {
  270                 printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
  271                 return;
  272         }
  273 
  274         err = usbd_open_pipe(sc->sc_iface, sc->sc_in_addr,
  275                              USBD_EXCLUSIVE_USE, &sc->sc_in_pipe);
  276         if (err) {
  277                 printf("%s: open in pipe failed, err=%d\n",
  278                        sc->sc_dev.dv_xname, err);
  279                 return;
  280         }
  281 
  282         /* The interrupt endpoint must be opened as a normal pipe. */
  283         err = usbd_open_pipe(sc->sc_iface, sc->sc_intr_addr,
  284                              USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
  285 
  286         if (err) {
  287                 printf("%s: open intr pipe failed, err=%d\n",
  288                        sc->sc_dev.dv_xname, err);
  289                 usscanner_cleanup(sc);
  290                 return;
  291         }
  292         err = usbd_open_pipe(sc->sc_iface, sc->sc_out_addr,
  293                              USBD_EXCLUSIVE_USE, &sc->sc_out_pipe);
  294         if (err) {
  295                 printf("%s: open out pipe failed, err=%d\n",
  296                        sc->sc_dev.dv_xname, err);
  297                 usscanner_cleanup(sc);
  298                 return;
  299         }
  300 
  301         sc->sc_cmd_xfer = usbd_alloc_xfer(uaa->device);
  302         if (sc->sc_cmd_xfer == NULL) {
  303                 printf("%s: alloc cmd xfer failed, err=%d\n",
  304                        sc->sc_dev.dv_xname, err);
  305                 usscanner_cleanup(sc);
  306                 return;
  307         }
  308 
  309         /* XXX too big */
  310         sc->sc_cmd_buffer = usbd_alloc_buffer(sc->sc_cmd_xfer,
  311                                              USSCANNER_MAX_TRANSFER_SIZE);
  312         if (sc->sc_cmd_buffer == NULL) {
  313                 printf("%s: alloc cmd buffer failed, err=%d\n",
  314                        sc->sc_dev.dv_xname, err);
  315                 usscanner_cleanup(sc);
  316                 return;
  317         }
  318 
  319         sc->sc_intr_xfer = usbd_alloc_xfer (uaa->device);
  320         if (sc->sc_intr_xfer == NULL) {
  321           printf("%s: alloc intr xfer failed, err=%d\n",
  322                  sc->sc_dev.dv_xname, err);
  323           usscanner_cleanup(sc);
  324           return; 
  325         }
  326 
  327         sc->sc_data_xfer = usbd_alloc_xfer(uaa->device);
  328         if (sc->sc_data_xfer == NULL) {
  329                 printf("%s: alloc data xfer failed, err=%d\n",
  330                        sc->sc_dev.dv_xname, err);
  331                 usscanner_cleanup(sc);
  332                 return;
  333         }
  334         sc->sc_data_buffer = usbd_alloc_buffer(sc->sc_data_xfer,
  335                                               USSCANNER_MAX_TRANSFER_SIZE);
  336         if (sc->sc_data_buffer == NULL) {
  337                 printf("%s: alloc data buffer failed, err=%d\n",
  338                        sc->sc_dev.dv_xname, err);
  339                 usscanner_cleanup(sc);
  340                 return;
  341         }
  342 
  343         /*
  344          * Fill in the adapter.
  345          */
  346         sc->sc_adapter.scsipi_cmd = usscanner_scsipi_cmd;
  347         sc->sc_adapter.scsipi_minphys = usscanner_scsipi_minphys;
  348 
  349         /*
  350          * fill in the prototype scsipi_link.
  351          */
  352         sc->sc_link.flags &= ~SDEV_ATAPI;
  353         sc->sc_link.adapter_buswidth = 2;
  354         sc->sc_link.adapter_target = USSCANNER_SCSIID_HOST;
  355 
  356         sc->sc_link.adapter_softc = sc;
  357         sc->sc_link.adapter = &sc->sc_adapter;
  358         sc->sc_link.device = &usscanner_dev;
  359         sc->sc_link.openings = 1;
  360 
  361         bzero(&saa, sizeof(saa));
  362         saa.saa_sc_link = &sc->sc_link;
  363 
  364         sc->sc_child = config_found(&sc->sc_dev, &saa, scsiprint);
  365 
  366         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  367                            &sc->sc_dev);
  368 
  369         DPRINTFN(10, ("usscanner_attach: %p\n", sc->sc_udev));
  370 }
  371 
  372 int
  373 usscanner_detach(struct device *self, int flags)
  374 {
  375         struct usscanner_softc *sc = (struct usscanner_softc *)self;
  376         int rv, s;
  377 
  378         DPRINTF(("usscanner_detach: sc=%p flags=%d\n", sc, flags));
  379 
  380         sc->sc_dying = 1;
  381         /* Abort all pipes.  Causes processes waiting for transfer to wake. */
  382         if (sc->sc_in_pipe != NULL)
  383                 usbd_abort_pipe(sc->sc_in_pipe);
  384         if (sc->sc_intr_pipe != NULL)
  385                 usbd_abort_pipe(sc->sc_intr_pipe);
  386         if (sc->sc_out_pipe != NULL)
  387                 usbd_abort_pipe(sc->sc_out_pipe);
  388 
  389         s = splusb();
  390         if (--sc->sc_refcnt >= 0) {
  391                 /* Wait for processes to go away. */
  392                 usb_detach_wait(&sc->sc_dev);
  393         }
  394         splx(s);
  395 
  396         if (sc->sc_child != NULL)
  397                 rv = config_detach(sc->sc_child, flags);
  398         else
  399                 rv = 0;
  400 
  401         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  402                            &sc->sc_dev);
  403 
  404         return (rv);
  405 }
  406 
  407 void
  408 usscanner_cleanup(struct usscanner_softc *sc)
  409 {
  410         if (sc->sc_in_pipe != NULL) {
  411                 usbd_close_pipe(sc->sc_in_pipe);
  412                 sc->sc_in_pipe = NULL;
  413         }
  414         if (sc->sc_intr_pipe != NULL) {
  415                 usbd_close_pipe(sc->sc_intr_pipe);
  416                 sc->sc_intr_pipe = NULL;
  417         }
  418         if (sc->sc_out_pipe != NULL) {
  419                 usbd_close_pipe(sc->sc_out_pipe);
  420                 sc->sc_out_pipe = NULL;
  421         }
  422         if (sc->sc_cmd_xfer != NULL) {
  423                 usbd_free_xfer(sc->sc_cmd_xfer);
  424                 sc->sc_cmd_xfer = NULL;
  425         }
  426         if (sc->sc_data_xfer != NULL) {
  427                 usbd_free_xfer(sc->sc_data_xfer);
  428                 sc->sc_data_xfer = NULL;
  429         }
  430 }
  431 
  432 int
  433 usscanner_activate(struct device *self, enum devact act)
  434 {
  435         struct usscanner_softc *sc = (struct usscanner_softc *)self;
  436 
  437         switch (act) {
  438         case DVACT_ACTIVATE:
  439                 break;
  440 
  441         case DVACT_DEACTIVATE:
  442                 sc->sc_dying = 1;
  443                 break;
  444         }
  445         return (0);
  446 }
  447 
  448 void
  449 usscanner_scsipi_minphys(struct buf *bp)
  450 {
  451         if (bp->b_bcount > USSCANNER_MAX_TRANSFER_SIZE)
  452                 bp->b_bcount = USSCANNER_MAX_TRANSFER_SIZE;
  453         minphys(bp);
  454 }
  455 
  456 void
  457 usscanner_sense(struct usscanner_softc *sc)
  458 {
  459         struct scsipi_xfer *xs = sc->sc_xs;
  460         struct scsipi_link *sc_link = xs->sc_link;
  461         struct scsipi_sense sense_cmd;
  462         usbd_status err;
  463 
  464         /* fetch sense data */
  465         memset(&sense_cmd, 0, sizeof(sense_cmd));
  466         sense_cmd.opcode = REQUEST_SENSE;
  467         sense_cmd.byte2 = sc_link->lun << SCSI_CMD_LUN_SHIFT;
  468         sense_cmd.length = sizeof xs->sense;
  469 
  470         sc->sc_state = UAS_SENSECMD;
  471         memcpy(sc->sc_cmd_buffer, &sense_cmd, sizeof sense_cmd);
  472         usbd_setup_xfer(sc->sc_cmd_xfer, sc->sc_out_pipe, sc, sc->sc_cmd_buffer,
  473             sizeof sense_cmd, USBD_NO_COPY, USSCANNER_TIMEOUT,
  474             usscanner_sensecmd_cb);
  475         err = usbd_transfer(sc->sc_cmd_xfer);
  476         if (err == USBD_IN_PROGRESS)
  477                 return;
  478 
  479         xs->error = XS_DRIVER_STUFFUP;
  480         usscanner_done(sc);
  481 }
  482 
  483 void
  484 usscanner_intr_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  485                  usbd_status status)
  486 {
  487         struct usscanner_softc *sc = priv;
  488         int s;
  489 
  490         DPRINTFN(10, ("usscanner_data_cb status=%d\n", status));
  491 
  492 #ifdef USSCANNER_DEBUG
  493         if (sc->sc_state != UAS_STATUS) {
  494                 printf("%s: !UAS_STATUS\n", sc->sc_dev.dv_xname);
  495         }
  496         if (sc->sc_status != 0) {
  497                 printf("%s: status byte=0x%02x\n", sc->sc_dev.dv_xname, sc->sc_status);
  498         }
  499 #endif
  500         /* XXX what should we do on non-0 status */
  501 
  502         sc->sc_state = UAS_IDLE;
  503 
  504         sc->sc_xs->xs_status |= XS_STS_DONE;
  505         s = splbio();
  506         scsipi_done(sc->sc_xs);
  507         splx(s);
  508 }
  509 
  510 void
  511 usscanner_data_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  512                  usbd_status status)
  513 {
  514         struct usscanner_softc *sc = priv;
  515         struct scsipi_xfer *xs = sc->sc_xs;
  516         u_int32_t len;
  517 
  518         DPRINTFN(10, ("usscanner_data_cb status=%d\n", status));
  519 
  520 #ifdef USSCANNER_DEBUG
  521         if (sc->sc_state != UAS_DATA) {
  522                 printf("%s: !UAS_DATA\n", sc->sc_dev.dv_xname);
  523         }
  524 #endif
  525 
  526         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
  527 
  528         xs->resid = xs->datalen - len;
  529 
  530         switch (status) {
  531         case USBD_NORMAL_COMPLETION:
  532                 if (xs->xs_control & XS_CTL_DATA_IN)
  533                         memcpy(xs->data, sc->sc_data_buffer, len);
  534                 xs->error = XS_NOERROR;
  535                 break;
  536         case USBD_TIMEOUT:
  537                 xs->error = XS_TIMEOUT;
  538                 break;
  539         case USBD_CANCELLED:
  540                 if (xs->error == XS_SENSE) {
  541                         usscanner_sense(sc);
  542                         return;
  543                 }
  544                 break;
  545         default:
  546                 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */
  547                 break;
  548         }
  549         usscanner_done(sc);
  550 }
  551 
  552 void
  553 usscanner_sensedata_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  554                        usbd_status status)
  555 {
  556         struct usscanner_softc *sc = priv;
  557         struct scsipi_xfer *xs = sc->sc_xs;
  558         u_int32_t len;
  559 
  560         DPRINTFN(10, ("usscanner_sensedata_cb status=%d\n", status));
  561 
  562 #ifdef USSCANNER_DEBUG
  563         if (sc->sc_state != UAS_SENSEDATA) {
  564                 printf("%s: !UAS_SENSEDATA\n", sc->sc_dev.dv_xname);
  565         }
  566 #endif
  567 
  568         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
  569 
  570         switch (status) {
  571         case USBD_NORMAL_COMPLETION:
  572                 memcpy(&xs->sense, sc->sc_data_buffer, len);
  573                 if (len < sizeof xs->sense)
  574                         xs->error = XS_SHORTSENSE;
  575                 break;
  576         case USBD_TIMEOUT:
  577                 xs->error = XS_TIMEOUT;
  578                 break;
  579         case USBD_CANCELLED:
  580                 xs->error = XS_RESET;
  581                 break;
  582         default:
  583                 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */
  584                 break;
  585         }
  586         usscanner_done(sc);
  587 }
  588 
  589 void
  590 usscanner_done(struct usscanner_softc *sc)
  591 {
  592         struct scsipi_xfer *xs = sc->sc_xs;
  593         usbd_status err;
  594 
  595         DPRINTFN(10,("usscanner_done: error=%d\n", sc->sc_xs->error));
  596 
  597         sc->sc_state = UAS_STATUS;
  598         usbd_setup_xfer(sc->sc_intr_xfer, sc->sc_intr_pipe, sc, &sc->sc_status,
  599             1, USBD_SHORT_XFER_OK | USBD_NO_COPY,
  600             USSCANNER_TIMEOUT, usscanner_intr_cb);
  601         err = usbd_transfer(sc->sc_intr_xfer);
  602         if (err == USBD_IN_PROGRESS)
  603                 return;
  604         xs->error = XS_DRIVER_STUFFUP;
  605 }
  606 
  607 void
  608 usscanner_sensecmd_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  609                       usbd_status status)
  610 {
  611         struct usscanner_softc *sc = priv;
  612         struct scsipi_xfer *xs = sc->sc_xs;
  613         usbd_status err;
  614 
  615         DPRINTFN(10, ("usscanner_sensecmd_cb status=%d\n", status));
  616 
  617 #ifdef USSCANNER_DEBUG
  618 #ifdef notyet
  619         if (usscannerdebug > 15)
  620                 xs->sc_link->flags |= DEBUGLEVEL;
  621 #endif
  622 
  623         if (sc->sc_state != UAS_SENSECMD) {
  624                 printf("%s: !UAS_SENSECMD\n", sc->sc_dev.dv_xname);
  625                 xs->error = XS_DRIVER_STUFFUP;
  626                 goto done;
  627         }
  628 #endif
  629 
  630         switch (status) {
  631         case USBD_NORMAL_COMPLETION:
  632                 break;
  633         case USBD_TIMEOUT:
  634                 xs->error = XS_TIMEOUT;
  635                 goto done;
  636         default:
  637                 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */
  638                 goto done;
  639         }
  640 
  641         sc->sc_state = UAS_SENSEDATA;
  642         usbd_setup_xfer(sc->sc_data_xfer, sc->sc_in_pipe, sc,
  643             sc->sc_data_buffer,
  644             sizeof xs->sense, USBD_SHORT_XFER_OK | USBD_NO_COPY,
  645             USSCANNER_TIMEOUT, usscanner_sensedata_cb);
  646         err = usbd_transfer(sc->sc_data_xfer);
  647         if (err == USBD_IN_PROGRESS)
  648                 return;
  649         xs->error = XS_DRIVER_STUFFUP;
  650  done:
  651         usscanner_done(sc);
  652 }
  653 
  654 void
  655 usscanner_cmd_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  656                  usbd_status status)
  657 {
  658         struct usscanner_softc *sc = priv;
  659         struct scsipi_xfer *xs = sc->sc_xs;
  660         usbd_pipe_handle pipe;
  661         usbd_status err;
  662 
  663         DPRINTFN(10, ("usscanner_cmd_cb status=%d\n", status));
  664 
  665 #ifdef USSCANNER_DEBUG
  666 #ifdef notyet
  667         if (usscannerdebug > 15)
  668                 xs->sc_link->flags |= DEBUGLEVEL;
  669 #endif
  670 
  671         if (sc->sc_state != UAS_CMD) {
  672                 printf("%s: !UAS_CMD\n", sc->sc_dev.dv_xname);
  673                 xs->error = XS_DRIVER_STUFFUP;
  674                 goto done;
  675         }
  676 #endif
  677 
  678         switch (status) {
  679         case USBD_NORMAL_COMPLETION:
  680                 break;
  681         case USBD_TIMEOUT:
  682                 xs->error = XS_TIMEOUT;
  683                 goto done;
  684         case USBD_CANCELLED:
  685                 goto done;
  686         default:
  687                 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */
  688                 goto done;
  689         }
  690 
  691         if (xs->datalen == 0) {
  692                 DPRINTFN(4, ("usscanner_cmd_cb: no data phase\n"));
  693                 xs->error = XS_NOERROR;
  694                 goto done;
  695         }
  696 
  697         if (xs->xs_control & XS_CTL_DATA_IN) {
  698                 DPRINTFN(4, ("usscanner_cmd_cb: data in len=%d\n",
  699                              xs->datalen));
  700                 pipe = sc->sc_in_pipe;
  701         } else {
  702                 DPRINTFN(4, ("usscanner_cmd_cb: data out len=%d\n",
  703                              xs->datalen));
  704                 memcpy(sc->sc_data_buffer, xs->data, xs->datalen);
  705                 pipe = sc->sc_out_pipe;
  706         }
  707         sc->sc_state = UAS_DATA;
  708         usbd_setup_xfer(sc->sc_data_xfer, pipe, sc, sc->sc_data_buffer,
  709             xs->datalen, USBD_SHORT_XFER_OK | USBD_NO_COPY,
  710             xs->timeout, usscanner_data_cb);
  711         err = usbd_transfer(sc->sc_data_xfer);
  712         if (err == USBD_IN_PROGRESS)
  713                 return;
  714         xs->error = XS_DRIVER_STUFFUP;
  715 
  716  done:
  717         usscanner_done(sc);
  718 }
  719 
  720 int
  721 usscanner_scsipi_cmd(struct scsipi_xfer *xs)
  722 {
  723         struct scsipi_link *sc_link = xs->sc_link;
  724         struct usscanner_softc *sc = sc_link->adapter_softc;
  725         usbd_status err;
  726 
  727 #ifdef notyet
  728         DPRINTFN(8, ("%s: usscanner_scsi_cmd: %d:%d "
  729             "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n",
  730             sc->sc_dev.dv_xname,
  731             sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun,
  732             xs, xs->cmd->opcode, xs->datalen,
  733             sc_link->quirks, xs->xs_control & XS_CTL_POLL));
  734 #endif
  735 
  736         if (sc->sc_dying) {
  737                 xs->error = XS_DRIVER_STUFFUP;
  738                 goto done;
  739         }
  740 
  741 #ifdef USSCANNER_DEBUG
  742 #ifdef notyet
  743         if (sc_link->scsipi_scsi.target != USSCANNER_SCSIID_DEVICE) {
  744                 DPRINTF(("%s: wrong SCSI ID %d\n", sc->sc_dev.dv_xname,
  745                     sc_link->scsipi_scsi.target));
  746                 xs->error = XS_DRIVER_STUFFUP;
  747                 goto done;
  748         }
  749 #endif
  750         if (sc->sc_state != UAS_IDLE) {
  751                 printf("%s: !UAS_IDLE\n", sc->sc_dev.dv_xname);
  752                 xs->error = XS_DRIVER_STUFFUP;
  753                 goto done;
  754         }
  755 #endif
  756 
  757         if (xs->datalen > USSCANNER_MAX_TRANSFER_SIZE) {
  758                 printf("umass_cmd: large datalen, %d\n", xs->datalen);
  759                 xs->error = XS_DRIVER_STUFFUP;
  760                 goto done;
  761         }
  762 
  763         DPRINTFN(4, ("usscanner_scsi_cmd: async cmdlen=%d datalen=%d\n",
  764                     xs->cmdlen, xs->datalen));
  765         sc->sc_state = UAS_CMD;
  766         sc->sc_xs = xs;
  767         memcpy(sc->sc_cmd_buffer, xs->cmd, xs->cmdlen);
  768         usbd_setup_xfer(sc->sc_cmd_xfer, sc->sc_out_pipe, sc, sc->sc_cmd_buffer,
  769             xs->cmdlen, USBD_NO_COPY, USSCANNER_TIMEOUT, usscanner_cmd_cb);
  770         err = usbd_transfer(sc->sc_cmd_xfer);
  771         if (err != USBD_IN_PROGRESS) {
  772                 xs->error = XS_DRIVER_STUFFUP;
  773                 goto done;
  774         }
  775 
  776         return (SUCCESSFULLY_QUEUED);
  777 
  778 
  779  done:
  780         sc->sc_state = UAS_IDLE;
  781         xs->xs_status |= XS_STS_DONE;
  782         scsipi_done(xs);
  783         if (xs->xs_control & XS_CTL_POLL)
  784                 return (COMPLETE);
  785         else
  786                 return (SUCCESSFULLY_QUEUED);
  787 }

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