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