[BACK]Return to usscanner.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/usscanner.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb