1 /* $NetBSD: usscanner.c,v 1.39 2016/04/23 10:15:32 skrll 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.39 2016/04/23 10:15:32 skrll Exp $"); 51 52 #include "scsibus.h" 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/kernel.h> 56 #include <sys/lwp.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 struct usbd_device *sc_udev; 97 struct usbd_interface *sc_iface; 98 99 int sc_in_addr; 100 struct usbd_pipe *sc_in_pipe; 101 102 int sc_intr_addr; 103 struct usbd_pipe *sc_intr_pipe; 104 struct usbd_xfer *sc_intr_xfer; 105 u_char sc_status; 106 107 int sc_out_addr; 108 struct usbd_pipe *sc_out_pipe; 109 110 struct usbd_xfer *sc_cmd_xfer; 111 void *sc_cmd_buffer; 112 struct usbd_xfer *sc_datain_xfer; 113 void *sc_datain_buffer; 114 struct usbd_xfer *sc_dataout_xfer; 115 void *sc_dataout_buffer; 116 117 int sc_state; 118 #define UAS_IDLE 0 119 #define UAS_CMD 1 120 #define UAS_DATA 2 121 #define UAS_SENSECMD 3 122 #define UAS_SENSEDATA 4 123 #define UAS_STATUS 5 124 125 struct scsipi_xfer *sc_xs; 126 127 device_t sc_child; /* child device, for detach */ 128 129 struct scsipi_adapter sc_adapter; 130 struct scsipi_channel sc_channel; 131 132 int sc_refcnt; 133 char sc_dying; 134 }; 135 136 137 Static void usscanner_cleanup(struct usscanner_softc *); 138 Static void usscanner_scsipi_request(struct scsipi_channel *, 139 scsipi_adapter_req_t, void *); 140 Static void usscanner_scsipi_minphys(struct buf *); 141 Static void usscanner_done(struct usscanner_softc *); 142 Static void usscanner_sense(struct usscanner_softc *); 143 typedef void callback(struct usbd_xfer *, void *, usbd_status); 144 Static callback usscanner_intr_cb; 145 Static callback usscanner_cmd_cb; 146 Static callback usscanner_data_cb; 147 Static callback usscanner_sensecmd_cb; 148 Static callback usscanner_sensedata_cb; 149 150 int usscanner_match(device_t, cfdata_t, void *); 151 void usscanner_attach(device_t, device_t, void *); 152 void usscanner_childdet(device_t, device_t); 153 int usscanner_detach(device_t, int); 154 int usscanner_activate(device_t, enum devact); 155 extern struct cfdriver usscanner_cd; 156 CFATTACH_DECL2_NEW(usscanner, sizeof(struct usscanner_softc), 157 usscanner_match, usscanner_attach, usscanner_detach, usscanner_activate, 158 NULL, usscanner_childdet); 159 160 int 161 usscanner_match(device_t parent, cfdata_t match, void *aux) 162 { 163 struct usb_attach_arg *uaa = aux; 164 165 DPRINTFN(50,("usscanner_match\n")); 166 167 if (uaa->uaa_vendor == USB_VENDOR_HP && 168 uaa->uaa_product == USB_PRODUCT_HP_5300C) 169 return UMATCH_VENDOR_PRODUCT; 170 else 171 return UMATCH_NONE; 172 } 173 174 void 175 usscanner_attach(device_t parent, device_t self, void *aux) 176 { 177 struct usscanner_softc *sc = device_private(self); 178 struct usb_attach_arg *uaa = aux; 179 struct usbd_device * dev = uaa->uaa_device; 180 struct usbd_interface * iface; 181 char *devinfop; 182 usbd_status err; 183 usb_endpoint_descriptor_t *ed; 184 uint8_t epcount; 185 int i; 186 int error; 187 188 DPRINTFN(10,("usscanner_attach: sc=%p\n", sc)); 189 190 sc->sc_dev = self; 191 192 aprint_naive("\n"); 193 aprint_normal("\n"); 194 195 devinfop = usbd_devinfo_alloc(dev, 0); 196 aprint_normal_dev(self, "%s\n", devinfop); 197 usbd_devinfo_free(devinfop); 198 199 err = usbd_set_config_no(dev, USSCANNER_CONFIG_NO, 1); 200 if (err) { 201 aprint_error_dev(self, "failed to set configuration" 202 ", err=%s\n", usbd_errstr(err)); 203 return; 204 } 205 206 err = usbd_device2interface_handle(dev, USSCANNER_IFACE_IDX, &iface); 207 if (err) { 208 aprint_error_dev(self, "getting interface handle failed\n"); 209 return; 210 } 211 212 sc->sc_udev = dev; 213 sc->sc_iface = iface; 214 215 epcount = 0; 216 (void)usbd_endpoint_count(iface, &epcount); 217 218 sc->sc_in_addr = -1; 219 sc->sc_intr_addr = -1; 220 sc->sc_out_addr = -1; 221 for (i = 0; i < epcount; i++) { 222 ed = usbd_interface2endpoint_descriptor(iface, i); 223 if (ed == NULL) { 224 aprint_error_dev(self, "couldn't get ep %d\n", i); 225 return; 226 } 227 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 228 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 229 sc->sc_in_addr = ed->bEndpointAddress; 230 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 231 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 232 sc->sc_intr_addr = ed->bEndpointAddress; 233 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 234 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 235 sc->sc_out_addr = ed->bEndpointAddress; 236 } 237 } 238 if (sc->sc_in_addr == -1 || sc->sc_intr_addr == -1 || 239 sc->sc_out_addr == -1) { 240 aprint_error_dev(self, "missing endpoint\n"); 241 return; 242 } 243 244 err = usbd_open_pipe(sc->sc_iface, sc->sc_in_addr, 245 USBD_EXCLUSIVE_USE, &sc->sc_in_pipe); 246 if (err) { 247 aprint_error_dev(self, "open in pipe failed, err=%d\n", err); 248 return; 249 } 250 251 /* The interrupt endpoint must be opened as a normal pipe. */ 252 err = usbd_open_pipe(sc->sc_iface, sc->sc_intr_addr, 253 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe); 254 255 if (err) { 256 aprint_error_dev(self, "open intr pipe failed, err=%d\n", err); 257 usscanner_cleanup(sc); 258 return; 259 } 260 err = usbd_open_pipe(sc->sc_iface, sc->sc_out_addr, 261 USBD_EXCLUSIVE_USE, &sc->sc_out_pipe); 262 if (err) { 263 aprint_error_dev(self, "open out pipe failed, err=%d\n", err); 264 usscanner_cleanup(sc); 265 return; 266 } 267 268 /* XXX too big */ 269 error = usbd_create_xfer(sc->sc_out_pipe, USSCANNER_MAX_TRANSFER_SIZE, 270 0, 0, &sc->sc_cmd_xfer); 271 if (error) { 272 aprint_error_dev(self, "alloc cmd xfer failed, error=%d\n", 273 error); 274 usscanner_cleanup(sc); 275 return; 276 } 277 278 sc->sc_cmd_buffer = usbd_get_buffer(sc->sc_cmd_xfer); 279 280 error = usbd_create_xfer(sc->sc_intr_pipe, 1, USBD_SHORT_XFER_OK, 281 0, &sc->sc_intr_xfer); 282 if (error) { 283 aprint_error_dev(self, "alloc intr xfer failed, error=%d\n", 284 error); 285 usscanner_cleanup(sc); 286 return; 287 } 288 289 error = usbd_create_xfer(sc->sc_in_pipe, USSCANNER_MAX_TRANSFER_SIZE, 290 USBD_SHORT_XFER_OK, 0, &sc->sc_datain_xfer); 291 if (error) { 292 aprint_error_dev(self, "alloc data xfer failed, error=%d\n", 293 error); 294 usscanner_cleanup(sc); 295 return; 296 } 297 sc->sc_datain_buffer = usbd_get_buffer(sc->sc_datain_xfer); 298 299 error = usbd_create_xfer(sc->sc_out_pipe, USSCANNER_MAX_TRANSFER_SIZE, 300 USBD_SHORT_XFER_OK, 0, &sc->sc_dataout_xfer); 301 if (error) { 302 aprint_error_dev(self, "alloc data xfer failed, err=%d\n", err); 303 usscanner_cleanup(sc); 304 return; 305 } 306 sc->sc_dataout_buffer = usbd_get_buffer(sc->sc_dataout_xfer); 307 308 /* 309 * Fill in the adapter. 310 */ 311 sc->sc_adapter.adapt_request = usscanner_scsipi_request; 312 sc->sc_adapter.adapt_dev = sc->sc_dev; 313 sc->sc_adapter.adapt_nchannels = 1; 314 sc->sc_adapter.adapt_openings = 1; 315 sc->sc_adapter.adapt_max_periph = 1; 316 sc->sc_adapter.adapt_minphys = usscanner_scsipi_minphys; 317 318 #if NSCSIBUS > 0 319 /* 320 * fill in the scsipi_channel. 321 */ 322 sc->sc_channel.chan_adapter = &sc->sc_adapter; 323 sc->sc_channel.chan_bustype = &scsi_bustype; 324 sc->sc_channel.chan_channel = 0; 325 sc->sc_channel.chan_ntargets = USSCANNER_SCSIID_DEVICE + 1; 326 sc->sc_channel.chan_nluns = 1; 327 sc->sc_channel.chan_id = USSCANNER_SCSIID_HOST; 328 329 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 330 sc->sc_dev); 331 332 sc->sc_child = config_found(sc->sc_dev, &sc->sc_channel, scsiprint); 333 334 DPRINTFN(10, ("usscanner_attach: %p\n", sc->sc_udev)); 335 336 return; 337 338 #else 339 /* No SCSI bus, just ignore it */ 340 usscanner_cleanup(sc); 341 342 aprint_error_dev(self, 343 "no scsibus configured, see usscanner(4) for details\n"); 344 345 return; 346 347 #endif 348 } 349 350 void 351 usscanner_childdet(device_t self, device_t child) 352 { 353 struct usscanner_softc *sc = device_private(self); 354 355 KASSERT(sc->sc_child == NULL); 356 sc->sc_child = NULL; 357 } 358 359 int 360 usscanner_detach(device_t self, int flags) 361 { 362 struct usscanner_softc *sc = device_private(self); 363 int rv, s; 364 365 DPRINTF(("usscanner_detach: sc=%p flags=%d\n", sc, flags)); 366 367 sc->sc_dying = 1; 368 /* Abort all pipes. Causes processes waiting for transfer to wake. */ 369 if (sc->sc_in_pipe != NULL) 370 usbd_abort_pipe(sc->sc_in_pipe); 371 if (sc->sc_intr_pipe != NULL) 372 usbd_abort_pipe(sc->sc_intr_pipe); 373 if (sc->sc_out_pipe != NULL) 374 usbd_abort_pipe(sc->sc_out_pipe); 375 376 s = splusb(); 377 if (--sc->sc_refcnt >= 0) { 378 /* Wait for processes to go away. */ 379 usb_detach_waitold(sc->sc_dev); 380 } 381 splx(s); 382 383 if (sc->sc_child != NULL) 384 rv = config_detach(sc->sc_child, flags); 385 else 386 rv = 0; 387 388 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 389 sc->sc_dev); 390 391 return rv; 392 } 393 394 Static void 395 usscanner_cleanup(struct usscanner_softc *sc) 396 { 397 if (sc->sc_cmd_xfer != NULL) { 398 usbd_destroy_xfer(sc->sc_cmd_xfer); 399 sc->sc_cmd_xfer = NULL; 400 } 401 if (sc->sc_datain_xfer != NULL) { 402 usbd_destroy_xfer(sc->sc_datain_xfer); 403 sc->sc_datain_xfer = NULL; 404 } 405 if (sc->sc_dataout_xfer != NULL) { 406 usbd_destroy_xfer(sc->sc_dataout_xfer); 407 sc->sc_dataout_xfer = NULL; 408 } 409 if (sc->sc_in_pipe != NULL) { 410 usbd_close_pipe(sc->sc_in_pipe); 411 sc->sc_in_pipe = NULL; 412 } 413 if (sc->sc_intr_pipe != NULL) { 414 usbd_close_pipe(sc->sc_intr_pipe); 415 sc->sc_intr_pipe = NULL; 416 } 417 if (sc->sc_out_pipe != NULL) { 418 usbd_close_pipe(sc->sc_out_pipe); 419 sc->sc_out_pipe = NULL; 420 } 421 } 422 423 int 424 usscanner_activate(device_t self, enum devact act) 425 { 426 struct usscanner_softc *sc = device_private(self); 427 428 switch (act) { 429 case DVACT_DEACTIVATE: 430 sc->sc_dying = 1; 431 return 0; 432 default: 433 return EOPNOTSUPP; 434 } 435 } 436 437 Static void 438 usscanner_scsipi_minphys(struct buf *bp) 439 { 440 if (bp->b_bcount > USSCANNER_MAX_TRANSFER_SIZE) 441 bp->b_bcount = USSCANNER_MAX_TRANSFER_SIZE; 442 minphys(bp); 443 } 444 445 Static void 446 usscanner_sense(struct usscanner_softc *sc) 447 { 448 struct scsipi_xfer *xs = sc->sc_xs; 449 struct scsipi_periph *periph = xs->xs_periph; 450 struct scsi_request_sense sense_cmd; 451 usbd_status err; 452 453 /* fetch sense data */ 454 memset(&sense_cmd, 0, sizeof(sense_cmd)); 455 sense_cmd.opcode = SCSI_REQUEST_SENSE; 456 sense_cmd.byte2 = periph->periph_lun << SCSI_CMD_LUN_SHIFT; 457 sense_cmd.length = sizeof(xs->sense); 458 459 sc->sc_state = UAS_SENSECMD; 460 memcpy(sc->sc_cmd_buffer, &sense_cmd, sizeof(sense_cmd)); 461 462 usbd_setup_xfer(sc->sc_cmd_xfer, sc, sc->sc_cmd_buffer, 463 sizeof(sense_cmd), 0, USSCANNER_TIMEOUT, 464 usscanner_sensecmd_cb); 465 err = usbd_transfer(sc->sc_cmd_xfer); 466 if (err == USBD_IN_PROGRESS) 467 return; 468 469 xs->error = XS_DRIVER_STUFFUP; 470 usscanner_done(sc); 471 } 472 473 Static void 474 usscanner_intr_cb(struct usbd_xfer *xfer, void *priv, 475 usbd_status status) 476 { 477 struct usscanner_softc *sc = priv; 478 int s; 479 480 DPRINTFN(10, ("usscanner_data_cb status=%d\n", status)); 481 482 #ifdef USSCANNER_DEBUG 483 if (sc->sc_state != UAS_STATUS) { 484 printf("%s: !UAS_STATUS\n", device_xname(sc->sc_dev)); 485 } 486 if (sc->sc_status != 0) { 487 printf("%s: status byte=0x%02x\n", device_xname(sc->sc_dev), sc->sc_status); 488 } 489 #endif 490 /* XXX what should we do on non-0 status */ 491 492 sc->sc_state = UAS_IDLE; 493 494 s = splbio(); 495 KERNEL_LOCK(1, curlwp); 496 scsipi_done(sc->sc_xs); 497 KERNEL_UNLOCK_ONE(curlwp); 498 splx(s); 499 } 500 501 Static void 502 usscanner_data_cb(struct usbd_xfer *xfer, void *priv, 503 usbd_status status) 504 { 505 struct usscanner_softc *sc = priv; 506 struct scsipi_xfer *xs = sc->sc_xs; 507 uint32_t len; 508 509 DPRINTFN(10, ("usscanner_data_cb status=%d\n", status)); 510 511 #ifdef USSCANNER_DEBUG 512 if (sc->sc_state != UAS_DATA) { 513 printf("%s: !UAS_DATA\n", device_xname(sc->sc_dev)); 514 } 515 #endif 516 517 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); 518 519 xs->resid = xs->datalen - len; 520 521 switch (status) { 522 case USBD_NORMAL_COMPLETION: 523 xs->error = XS_NOERROR; 524 break; 525 case USBD_TIMEOUT: 526 xs->error = XS_TIMEOUT; 527 break; 528 case USBD_CANCELLED: 529 if (xs->error == XS_SENSE) { 530 usscanner_sense(sc); 531 return; 532 } 533 break; 534 default: 535 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */ 536 break; 537 } 538 usscanner_done(sc); 539 } 540 541 Static void 542 usscanner_sensedata_cb(struct usbd_xfer *xfer, void *priv, 543 usbd_status status) 544 { 545 struct usscanner_softc *sc = priv; 546 struct scsipi_xfer *xs = sc->sc_xs; 547 uint32_t len; 548 549 DPRINTFN(10, ("usscanner_sensedata_cb status=%d\n", status)); 550 551 #ifdef USSCANNER_DEBUG 552 if (sc->sc_state != UAS_SENSEDATA) { 553 printf("%s: !UAS_SENSEDATA\n", device_xname(sc->sc_dev)); 554 } 555 #endif 556 557 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); 558 559 switch (status) { 560 case USBD_NORMAL_COMPLETION: 561 memcpy(&xs->sense, sc->sc_datain_buffer, len); 562 if (len < sizeof(xs->sense)) 563 xs->error = XS_SHORTSENSE; 564 break; 565 case USBD_TIMEOUT: 566 xs->error = XS_TIMEOUT; 567 break; 568 case USBD_CANCELLED: 569 xs->error = XS_RESET; 570 break; 571 default: 572 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */ 573 break; 574 } 575 usscanner_done(sc); 576 } 577 578 Static void 579 usscanner_done(struct usscanner_softc *sc) 580 { 581 struct scsipi_xfer *xs = sc->sc_xs; 582 usbd_status err; 583 584 DPRINTFN(10,("usscanner_done: error=%d\n", sc->sc_xs->error)); 585 586 sc->sc_state = UAS_STATUS; 587 usbd_setup_xfer(sc->sc_intr_xfer, sc, &sc->sc_status, 1, 588 USBD_SHORT_XFER_OK, USSCANNER_TIMEOUT, usscanner_intr_cb); 589 err = usbd_transfer(sc->sc_intr_xfer); 590 if (err == USBD_IN_PROGRESS) 591 return; 592 xs->error = XS_DRIVER_STUFFUP; 593 } 594 595 Static void 596 usscanner_sensecmd_cb(struct usbd_xfer *xfer, void *priv, 597 usbd_status status) 598 { 599 struct usscanner_softc *sc = priv; 600 struct scsipi_xfer *xs = sc->sc_xs; 601 usbd_status err; 602 603 DPRINTFN(10, ("usscanner_sensecmd_cb status=%d\n", status)); 604 605 #ifdef USSCANNER_DEBUG 606 if (usscannerdebug > 15) 607 xs->xs_periph->periph_flags |= 1; /* XXX 1 */ 608 609 if (sc->sc_state != UAS_SENSECMD) { 610 aprint_error_dev(sc->sc_dev, "!UAS_SENSECMD\n"); 611 xs->error = XS_DRIVER_STUFFUP; 612 goto done; 613 } 614 #endif 615 616 switch (status) { 617 case USBD_NORMAL_COMPLETION: 618 break; 619 case USBD_TIMEOUT: 620 xs->error = XS_TIMEOUT; 621 goto done; 622 default: 623 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */ 624 goto done; 625 } 626 627 sc->sc_state = UAS_SENSEDATA; 628 usbd_setup_xfer(sc->sc_datain_xfer, sc, sc->sc_datain_buffer, 629 sizeof(xs->sense), USBD_SHORT_XFER_OK, 630 USSCANNER_TIMEOUT, usscanner_sensedata_cb); 631 err = usbd_transfer(sc->sc_datain_xfer); 632 if (err == USBD_IN_PROGRESS) 633 return; 634 xs->error = XS_DRIVER_STUFFUP; 635 done: 636 usscanner_done(sc); 637 } 638 639 Static void 640 usscanner_cmd_cb(struct usbd_xfer *xfer, void *priv, 641 usbd_status status) 642 { 643 struct usscanner_softc *sc = priv; 644 struct scsipi_xfer *xs = sc->sc_xs; 645 struct usbd_xfer *dxfer; 646 usbd_status err; 647 648 DPRINTFN(10, ("usscanner_cmd_cb status=%d\n", status)); 649 650 #ifdef USSCANNER_DEBUG 651 if (usscannerdebug > 15) 652 xs->xs_periph->periph_flags |= 1; /* XXX 1 */ 653 654 if (sc->sc_state != UAS_CMD) { 655 aprint_error_dev(sc->sc_dev, "!UAS_CMD\n"); 656 xs->error = XS_DRIVER_STUFFUP; 657 goto done; 658 } 659 #endif 660 661 switch (status) { 662 case USBD_NORMAL_COMPLETION: 663 break; 664 case USBD_TIMEOUT: 665 xs->error = XS_TIMEOUT; 666 goto done; 667 case USBD_CANCELLED: 668 goto done; 669 default: 670 xs->error = XS_DRIVER_STUFFUP; /* XXX ? */ 671 goto done; 672 } 673 674 if (xs->datalen == 0) { 675 DPRINTFN(4, ("usscanner_cmd_cb: no data phase\n")); 676 xs->error = XS_NOERROR; 677 goto done; 678 } 679 680 if (xs->xs_control & XS_CTL_DATA_IN) { 681 DPRINTFN(4, ("usscanner_cmd_cb: data in len=%d\n", 682 xs->datalen)); 683 dxfer = sc->sc_datain_xfer; 684 } else { 685 DPRINTFN(4, ("usscanner_cmd_cb: data out len=%d\n", 686 xs->datalen)); 687 dxfer = sc->sc_dataout_xfer; 688 } 689 sc->sc_state = UAS_DATA; 690 usbd_setup_xfer(dxfer, sc, xs->data, xs->datalen, 691 USBD_SHORT_XFER_OK, xs->timeout, usscanner_data_cb); 692 err = usbd_transfer(dxfer); 693 if (err == USBD_IN_PROGRESS) 694 return; 695 xs->error = XS_DRIVER_STUFFUP; 696 697 done: 698 usscanner_done(sc); 699 } 700 701 Static void 702 usscanner_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg) 703 { 704 struct scsipi_xfer *xs; 705 struct usscanner_softc *sc = 706 device_private(chan->chan_adapter->adapt_dev); 707 usbd_status err; 708 709 switch (req) { 710 case ADAPTER_REQ_RUN_XFER: 711 xs = arg; 712 713 DPRINTFN(8, ("%s: usscanner_scsipi_request: %d:%d " 714 "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n", 715 device_xname(sc->sc_dev), 716 xs->xs_periph->periph_target, xs->xs_periph->periph_lun, 717 xs, xs->cmd->opcode, xs->datalen, 718 xs->xs_periph->periph_quirks, 719 xs->xs_control & XS_CTL_POLL)); 720 721 if (sc->sc_dying) { 722 xs->error = XS_DRIVER_STUFFUP; 723 goto done; 724 } 725 726 #ifdef USSCANNER_DEBUG 727 if (xs->xs_periph->periph_target != USSCANNER_SCSIID_DEVICE) { 728 DPRINTF(("%s: wrong SCSI ID %d\n", 729 device_xname(sc->sc_dev), 730 xs->xs_periph->periph_target)); 731 xs->error = XS_DRIVER_STUFFUP; 732 goto done; 733 } 734 if (sc->sc_state != UAS_IDLE) { 735 printf("%s: !UAS_IDLE\n", device_xname(sc->sc_dev)); 736 xs->error = XS_DRIVER_STUFFUP; 737 goto done; 738 } 739 #endif 740 741 if (xs->datalen > USSCANNER_MAX_TRANSFER_SIZE) { 742 aprint_normal_dev(sc->sc_dev, 743 "usscanner_scsipi_request: large datalen, %d\n", 744 xs->datalen); 745 xs->error = XS_DRIVER_STUFFUP; 746 goto done; 747 } 748 749 DPRINTFN(4, ("%s: usscanner_scsipi_request: async cmdlen=%d" 750 " datalen=%d\n", device_xname(sc->sc_dev), xs->cmdlen, 751 xs->datalen)); 752 sc->sc_state = UAS_CMD; 753 sc->sc_xs = xs; 754 memcpy(sc->sc_cmd_buffer, xs->cmd, xs->cmdlen); 755 usbd_setup_xfer(sc->sc_cmd_xfer, sc, sc->sc_cmd_buffer, 756 xs->cmdlen, 0, USSCANNER_TIMEOUT, usscanner_cmd_cb); 757 err = usbd_transfer(sc->sc_cmd_xfer); 758 if (err != USBD_IN_PROGRESS) { 759 xs->error = XS_DRIVER_STUFFUP; 760 goto done; 761 } 762 763 return; 764 765 766 done: 767 sc->sc_state = UAS_IDLE; 768 KERNEL_LOCK(1, curlwp); 769 scsipi_done(xs); 770 KERNEL_UNLOCK_ONE(curlwp); 771 return; 772 773 case ADAPTER_REQ_GROW_RESOURCES: 774 /* XXX Not supported. */ 775 return; 776 case ADAPTER_REQ_SET_XFER_MODE: 777 /* XXX Not supported. */ 778 return; 779 } 780 781 } 782