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