Annotation of sys/dev/usb/usscanner.c, Revision 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