1 /* $FreeBSD$ */ 2 /*- 3 * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* 28 * The following file contains code that will detect USB autoinstall 29 * disks. 30 * 31 * TODO: Potentially we could add code to automatically detect USB 32 * mass storage quirks for not supported SCSI commands! 33 */ 34 35 #include <sys/stdint.h> 36 #include <sys/param.h> 37 #include <sys/queue.h> 38 #include <sys/types.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/bus.h> 42 #include <sys/module.h> 43 #include <sys/lock.h> 44 #include <sys/mutex.h> 45 #include <sys/condvar.h> 46 #include <sys/sysctl.h> 47 #include <sys/unistd.h> 48 #include <sys/callout.h> 49 #include <sys/malloc.h> 50 #include <sys/priv.h> 51 52 #include <bus/u4b/usb.h> 53 #include <bus/u4b/usbdi.h> 54 #include <bus/u4b/usbdi_util.h> 55 56 #define USB_DEBUG_VAR usb_debug 57 58 #include <bus/u4b/usb_busdma.h> 59 #include <bus/u4b/usb_process.h> 60 #include <bus/u4b/usb_transfer.h> 61 #include <bus/u4b/usb_msctest.h> 62 #include <bus/u4b/usb_debug.h> 63 #include <bus/u4b/usb_device.h> 64 #include <bus/u4b/usb_request.h> 65 #include <bus/u4b/usb_util.h> 66 #include <bus/u4b/quirk/usb_quirk.h> 67 68 enum { 69 ST_COMMAND, 70 ST_DATA_RD, 71 ST_DATA_RD_CS, 72 ST_DATA_WR, 73 ST_DATA_WR_CS, 74 ST_STATUS, 75 ST_MAX, 76 }; 77 78 enum { 79 DIR_IN, 80 DIR_OUT, 81 DIR_NONE, 82 }; 83 84 #define SCSI_MAX_LEN MAX(0x100, BULK_SIZE) 85 #define SCSI_INQ_LEN 0x24 86 #define SCSI_SENSE_LEN 0xFF 87 88 static uint8_t scsi_test_unit_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 89 static uint8_t scsi_inquiry[] = { 0x12, 0x00, 0x00, 0x00, SCSI_INQ_LEN, 0x00 }; 90 static uint8_t scsi_rezero_init[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; 91 static uint8_t scsi_start_stop_unit[] = { 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00 }; 92 static uint8_t scsi_ztestor_eject[] = { 0x85, 0x01, 0x01, 0x01, 0x18, 0x01, 93 0x01, 0x01, 0x01, 0x01, 0x00, 0x00 }; 94 static uint8_t scsi_cmotech_eject[] = { 0xff, 0x52, 0x44, 0x45, 0x56, 0x43, 95 0x48, 0x47 }; 96 static uint8_t scsi_huawei_eject[] = { 0x11, 0x06, 0x00, 0x00, 0x00, 0x00, 97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 0x00, 0x00, 0x00, 0x00 }; 99 static uint8_t scsi_tct_eject[] = { 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 }; 100 static uint8_t scsi_sync_cache[] = { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 101 0x00, 0x00, 0x00, 0x00 }; 102 static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00, 103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 104 static uint8_t scsi_read_capacity[] = { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 105 0x00, 0x00, 0x00, 0x00 }; 106 107 #define BULK_SIZE 64 /* dummy */ 108 #define ERR_CSW_FAILED -1 109 110 /* Command Block Wrapper */ 111 struct bbb_cbw { 112 uDWord dCBWSignature; 113 #define CBWSIGNATURE 0x43425355 114 uDWord dCBWTag; 115 uDWord dCBWDataTransferLength; 116 uByte bCBWFlags; 117 #define CBWFLAGS_OUT 0x00 118 #define CBWFLAGS_IN 0x80 119 uByte bCBWLUN; 120 uByte bCDBLength; 121 #define CBWCDBLENGTH 16 122 uByte CBWCDB[CBWCDBLENGTH]; 123 } __packed; 124 125 /* Command Status Wrapper */ 126 struct bbb_csw { 127 uDWord dCSWSignature; 128 #define CSWSIGNATURE 0x53425355 129 uDWord dCSWTag; 130 uDWord dCSWDataResidue; 131 uByte bCSWStatus; 132 #define CSWSTATUS_GOOD 0x0 133 #define CSWSTATUS_FAILED 0x1 134 #define CSWSTATUS_PHASE 0x2 135 } __packed; 136 137 struct bbb_transfer { 138 struct lock lock; 139 struct cv cv; 140 struct bbb_cbw *cbw; 141 struct bbb_csw *csw; 142 143 struct usb_xfer *xfer[ST_MAX]; 144 145 uint8_t *data_ptr; 146 147 usb_size_t data_len; /* bytes */ 148 usb_size_t data_rem; /* bytes */ 149 usb_timeout_t data_timeout; /* ms */ 150 usb_frlength_t actlen; /* bytes */ 151 usb_frlength_t buffer_size; /* bytes */ 152 153 uint8_t cmd_len; /* bytes */ 154 uint8_t dir; 155 uint8_t lun; 156 uint8_t state; 157 uint8_t status_try; 158 int error; 159 160 uint8_t *buffer; 161 }; 162 163 static usb_callback_t bbb_command_callback; 164 static usb_callback_t bbb_data_read_callback; 165 static usb_callback_t bbb_data_rd_cs_callback; 166 static usb_callback_t bbb_data_write_callback; 167 static usb_callback_t bbb_data_wr_cs_callback; 168 static usb_callback_t bbb_status_callback; 169 170 static void bbb_done(struct bbb_transfer *, int); 171 static void bbb_transfer_start(struct bbb_transfer *, uint8_t); 172 static void bbb_data_clear_stall_callback(struct usb_xfer *, uint8_t, 173 uint8_t); 174 static int bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t, 175 void *, size_t, void *, size_t, usb_timeout_t); 176 static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t); 177 static void bbb_detach(struct bbb_transfer *); 178 179 static const struct usb_config bbb_config[ST_MAX] = { 180 181 [ST_COMMAND] = { 182 .type = UE_BULK, 183 .endpoint = UE_ADDR_ANY, 184 .direction = UE_DIR_OUT, 185 .bufsize = sizeof(struct bbb_cbw), 186 .callback = &bbb_command_callback, 187 .timeout = 4 * USB_MS_HZ, /* 4 seconds */ 188 }, 189 190 [ST_DATA_RD] = { 191 .type = UE_BULK, 192 .endpoint = UE_ADDR_ANY, 193 .direction = UE_DIR_IN, 194 .bufsize = SCSI_MAX_LEN, 195 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,}, 196 .callback = &bbb_data_read_callback, 197 .timeout = 4 * USB_MS_HZ, /* 4 seconds */ 198 }, 199 200 [ST_DATA_RD_CS] = { 201 .type = UE_CONTROL, 202 .endpoint = 0x00, /* Control pipe */ 203 .direction = UE_DIR_ANY, 204 .bufsize = sizeof(struct usb_device_request), 205 .callback = &bbb_data_rd_cs_callback, 206 .timeout = 1 * USB_MS_HZ, /* 1 second */ 207 }, 208 209 [ST_DATA_WR] = { 210 .type = UE_BULK, 211 .endpoint = UE_ADDR_ANY, 212 .direction = UE_DIR_OUT, 213 .bufsize = SCSI_MAX_LEN, 214 .flags = {.ext_buffer = 1,.proxy_buffer = 1,}, 215 .callback = &bbb_data_write_callback, 216 .timeout = 4 * USB_MS_HZ, /* 4 seconds */ 217 }, 218 219 [ST_DATA_WR_CS] = { 220 .type = UE_CONTROL, 221 .endpoint = 0x00, /* Control pipe */ 222 .direction = UE_DIR_ANY, 223 .bufsize = sizeof(struct usb_device_request), 224 .callback = &bbb_data_wr_cs_callback, 225 .timeout = 1 * USB_MS_HZ, /* 1 second */ 226 }, 227 228 [ST_STATUS] = { 229 .type = UE_BULK, 230 .endpoint = UE_ADDR_ANY, 231 .direction = UE_DIR_IN, 232 .bufsize = sizeof(struct bbb_csw), 233 .flags = {.short_xfer_ok = 1,}, 234 .callback = &bbb_status_callback, 235 .timeout = 1 * USB_MS_HZ, /* 1 second */ 236 }, 237 }; 238 239 static void 240 bbb_done(struct bbb_transfer *sc, int error) 241 { 242 sc->error = error; 243 sc->state = ST_COMMAND; 244 sc->status_try = 1; 245 cv_signal(&sc->cv); 246 } 247 248 static void 249 bbb_transfer_start(struct bbb_transfer *sc, uint8_t xfer_index) 250 { 251 sc->state = xfer_index; 252 usbd_transfer_start(sc->xfer[xfer_index]); 253 } 254 255 static void 256 bbb_data_clear_stall_callback(struct usb_xfer *xfer, 257 uint8_t next_xfer, uint8_t stall_xfer) 258 { 259 struct bbb_transfer *sc = usbd_xfer_softc(xfer); 260 261 if (usbd_clear_stall_callback(xfer, sc->xfer[stall_xfer])) { 262 switch (USB_GET_STATE(xfer)) { 263 case USB_ST_SETUP: 264 case USB_ST_TRANSFERRED: 265 bbb_transfer_start(sc, next_xfer); 266 break; 267 default: 268 bbb_done(sc, USB_ERR_STALLED); 269 break; 270 } 271 } 272 } 273 274 static void 275 bbb_command_callback(struct usb_xfer *xfer, usb_error_t error) 276 { 277 struct bbb_transfer *sc = usbd_xfer_softc(xfer); 278 uint32_t tag; 279 280 switch (USB_GET_STATE(xfer)) { 281 case USB_ST_TRANSFERRED: 282 bbb_transfer_start 283 (sc, ((sc->dir == DIR_IN) ? ST_DATA_RD : 284 (sc->dir == DIR_OUT) ? ST_DATA_WR : 285 ST_STATUS)); 286 break; 287 288 case USB_ST_SETUP: 289 sc->status_try = 0; 290 tag = UGETDW(sc->cbw->dCBWTag) + 1; 291 USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE); 292 USETDW(sc->cbw->dCBWTag, tag); 293 USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len); 294 sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT); 295 sc->cbw->bCBWLUN = sc->lun; 296 sc->cbw->bCDBLength = sc->cmd_len; 297 if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) { 298 sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB); 299 DPRINTFN(0, "Truncating long command\n"); 300 } 301 usbd_xfer_set_frame_len(xfer, 0, 302 sizeof(struct bbb_cbw)); 303 usbd_transfer_submit(xfer); 304 break; 305 306 default: /* Error */ 307 bbb_done(sc, error); 308 break; 309 } 310 } 311 312 static void 313 bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error) 314 { 315 struct bbb_transfer *sc = usbd_xfer_softc(xfer); 316 usb_frlength_t max_bulk = usbd_xfer_max_len(xfer); 317 int actlen, sumlen; 318 319 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 320 321 switch (USB_GET_STATE(xfer)) { 322 case USB_ST_TRANSFERRED: 323 sc->data_rem -= actlen; 324 sc->data_ptr += actlen; 325 sc->actlen += actlen; 326 327 if (actlen < sumlen) { 328 /* short transfer */ 329 sc->data_rem = 0; 330 } 331 case USB_ST_SETUP: 332 DPRINTF("max_bulk=%d, data_rem=%d\n", 333 max_bulk, sc->data_rem); 334 335 if (sc->data_rem == 0) { 336 bbb_transfer_start(sc, ST_STATUS); 337 break; 338 } 339 if (max_bulk > sc->data_rem) { 340 max_bulk = sc->data_rem; 341 } 342 usbd_xfer_set_timeout(xfer, sc->data_timeout); 343 usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk); 344 usbd_transfer_submit(xfer); 345 break; 346 347 default: /* Error */ 348 if (error == USB_ERR_CANCELLED) { 349 bbb_done(sc, error); 350 } else { 351 bbb_transfer_start(sc, ST_DATA_RD_CS); 352 } 353 break; 354 } 355 } 356 357 static void 358 bbb_data_rd_cs_callback(struct usb_xfer *xfer, usb_error_t error) 359 { 360 bbb_data_clear_stall_callback(xfer, ST_STATUS, 361 ST_DATA_RD); 362 } 363 364 static void 365 bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error) 366 { 367 struct bbb_transfer *sc = usbd_xfer_softc(xfer); 368 usb_frlength_t max_bulk = usbd_xfer_max_len(xfer); 369 int actlen, sumlen; 370 371 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 372 373 switch (USB_GET_STATE(xfer)) { 374 case USB_ST_TRANSFERRED: 375 sc->data_rem -= actlen; 376 sc->data_ptr += actlen; 377 sc->actlen += actlen; 378 379 if (actlen < sumlen) { 380 /* short transfer */ 381 sc->data_rem = 0; 382 } 383 case USB_ST_SETUP: 384 DPRINTF("max_bulk=%d, data_rem=%d\n", 385 max_bulk, sc->data_rem); 386 387 if (sc->data_rem == 0) { 388 bbb_transfer_start(sc, ST_STATUS); 389 break; 390 } 391 if (max_bulk > sc->data_rem) { 392 max_bulk = sc->data_rem; 393 } 394 usbd_xfer_set_timeout(xfer, sc->data_timeout); 395 usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk); 396 usbd_transfer_submit(xfer); 397 break; 398 399 default: /* Error */ 400 if (error == USB_ERR_CANCELLED) { 401 bbb_done(sc, error); 402 } else { 403 bbb_transfer_start(sc, ST_DATA_WR_CS); 404 } 405 break; 406 } 407 } 408 409 static void 410 bbb_data_wr_cs_callback(struct usb_xfer *xfer, usb_error_t error) 411 { 412 bbb_data_clear_stall_callback(xfer, ST_STATUS, 413 ST_DATA_WR); 414 } 415 416 static void 417 bbb_status_callback(struct usb_xfer *xfer, usb_error_t error) 418 { 419 struct bbb_transfer *sc = usbd_xfer_softc(xfer); 420 int actlen; 421 int sumlen; 422 423 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 424 425 switch (USB_GET_STATE(xfer)) { 426 case USB_ST_TRANSFERRED: 427 428 /* very simple status check */ 429 430 if (actlen < (int)sizeof(struct bbb_csw)) { 431 bbb_done(sc, USB_ERR_SHORT_XFER); 432 } else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) { 433 bbb_done(sc, 0); /* success */ 434 } else { 435 bbb_done(sc, ERR_CSW_FAILED); /* error */ 436 } 437 break; 438 439 case USB_ST_SETUP: 440 usbd_xfer_set_frame_len(xfer, 0, 441 sizeof(struct bbb_csw)); 442 usbd_transfer_submit(xfer); 443 break; 444 445 default: 446 DPRINTF("Failed to read CSW: %s, try %d\n", 447 usbd_errstr(error), sc->status_try); 448 449 if (error == USB_ERR_CANCELLED || sc->status_try) { 450 bbb_done(sc, error); 451 } else { 452 sc->status_try = 1; 453 bbb_transfer_start(sc, ST_DATA_RD_CS); 454 } 455 break; 456 } 457 } 458 459 /*------------------------------------------------------------------------* 460 * bbb_command_start - execute a SCSI command synchronously 461 * 462 * Return values 463 * 0: Success 464 * Else: Failure 465 *------------------------------------------------------------------------*/ 466 static int 467 bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun, 468 void *data_ptr, size_t data_len, void *cmd_ptr, size_t cmd_len, 469 usb_timeout_t data_timeout) 470 { 471 sc->lun = lun; 472 sc->dir = data_len ? dir : DIR_NONE; 473 sc->data_ptr = data_ptr; 474 sc->data_len = data_len; 475 sc->data_rem = data_len; 476 sc->data_timeout = (data_timeout + USB_MS_HZ); 477 sc->actlen = 0; 478 sc->cmd_len = cmd_len; 479 memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB)); 480 memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len); 481 DPRINTFN(1, "SCSI cmd_len = %d, cmd %s\n", (int)cmd_len, (char *)sc->cbw->CBWCDB); 482 483 lockmgr(&sc->lock, LK_EXCLUSIVE); 484 usbd_transfer_start(sc->xfer[sc->state]); 485 486 while (usbd_transfer_pending(sc->xfer[sc->state])) { 487 cv_wait(&sc->cv, &sc->lock); 488 } 489 lockmgr(&sc->lock, LK_RELEASE); 490 return (sc->error); 491 } 492 493 static struct bbb_transfer * 494 bbb_attach(struct usb_device *udev, uint8_t iface_index) 495 { 496 struct usb_interface *iface; 497 struct usb_interface_descriptor *id; 498 struct bbb_transfer *sc; 499 usb_error_t err; 500 uint8_t do_unlock; 501 502 /* Prevent re-enumeration */ 503 do_unlock = usbd_enum_lock(udev); 504 505 /* 506 * Make sure any driver which is hooked up to this interface, 507 * like umass is gone: 508 */ 509 usb_detach_device(udev, iface_index, 0); 510 511 if (do_unlock) 512 usbd_enum_unlock(udev); 513 514 iface = usbd_get_iface(udev, iface_index); 515 if (iface == NULL) 516 return (NULL); 517 518 id = iface->idesc; 519 if (id == NULL || id->bInterfaceClass != UICLASS_MASS) 520 return (NULL); 521 522 switch (id->bInterfaceSubClass) { 523 case UISUBCLASS_SCSI: 524 case UISUBCLASS_UFI: 525 case UISUBCLASS_SFF8020I: 526 case UISUBCLASS_SFF8070I: 527 break; 528 default: 529 return (NULL); 530 } 531 532 switch (id->bInterfaceProtocol) { 533 case UIPROTO_MASS_BBB_OLD: 534 case UIPROTO_MASS_BBB: 535 break; 536 default: 537 return (NULL); 538 } 539 540 sc = kmalloc(sizeof(*sc), M_USB, M_WAITOK | M_ZERO); 541 lockinit(&sc->lock, "USB autoinstall", 0, 0); 542 cv_init(&sc->cv, "WBBB"); 543 544 err = usbd_transfer_setup(udev, &iface_index, sc->xfer, bbb_config, 545 ST_MAX, sc, &sc->lock); 546 if (err) { 547 bbb_detach(sc); 548 return (NULL); 549 } 550 /* store pointer to DMA buffers */ 551 sc->buffer = usbd_xfer_get_frame_buffer( 552 sc->xfer[ST_DATA_RD], 0); 553 sc->buffer_size = 554 usbd_xfer_max_len(sc->xfer[ST_DATA_RD]); 555 sc->cbw = usbd_xfer_get_frame_buffer( 556 sc->xfer[ST_COMMAND], 0); 557 sc->csw = usbd_xfer_get_frame_buffer( 558 sc->xfer[ST_STATUS], 0); 559 560 return (sc); 561 } 562 563 static void 564 bbb_detach(struct bbb_transfer *sc) 565 { 566 usbd_transfer_unsetup(sc->xfer, ST_MAX); 567 lockuninit(&sc->lock); 568 cv_destroy(&sc->cv); 569 kfree(sc, M_USB); 570 } 571 572 /*------------------------------------------------------------------------* 573 * usb_iface_is_cdrom 574 * 575 * Return values: 576 * 1: This interface is an auto install disk (CD-ROM) 577 * 0: Not an auto install disk. 578 *------------------------------------------------------------------------*/ 579 int 580 usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index) 581 { 582 struct bbb_transfer *sc; 583 uint8_t timeout; 584 uint8_t is_cdrom; 585 uint8_t sid_type; 586 int err; 587 588 sc = bbb_attach(udev, iface_index); 589 if (sc == NULL) 590 return (0); 591 592 is_cdrom = 0; 593 timeout = 4; /* tries */ 594 while (--timeout) { 595 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 596 SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry), 597 USB_MS_HZ); 598 599 if (err == 0 && sc->actlen > 0) { 600 sid_type = sc->buffer[0] & 0x1F; 601 if (sid_type == 0x05) 602 is_cdrom = 1; 603 break; 604 } else if (err != ERR_CSW_FAILED) 605 break; /* non retryable error */ 606 usb_pause_mtx(NULL, hz); 607 } 608 bbb_detach(sc); 609 return (is_cdrom); 610 } 611 612 static uint8_t 613 usb_msc_get_max_lun(struct usb_device *udev, uint8_t iface_index) 614 { 615 struct usb_device_request req; 616 usb_error_t err; 617 uint8_t buf = 0; 618 619 620 /* The Get Max Lun command is a class-specific request. */ 621 req.bmRequestType = UT_READ_CLASS_INTERFACE; 622 req.bRequest = 0xFE; /* GET_MAX_LUN */ 623 USETW(req.wValue, 0); 624 req.wIndex[0] = iface_index; 625 req.wIndex[1] = 0; 626 USETW(req.wLength, 1); 627 628 err = usbd_do_request(udev, NULL, &req, &buf); 629 if (err) 630 buf = 0; 631 632 return (buf); 633 } 634 635 usb_error_t 636 usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) 637 { 638 struct bbb_transfer *sc; 639 uint8_t timeout; 640 uint8_t is_no_direct; 641 uint8_t sid_type; 642 int err; 643 644 sc = bbb_attach(udev, iface_index); 645 if (sc == NULL) 646 return (0); 647 648 /* 649 * Some devices need a delay after that the configuration 650 * value is set to function properly: 651 */ 652 usb_pause_mtx(NULL, hz); 653 654 if (usb_msc_get_max_lun(udev, iface_index) == 0) { 655 DPRINTF("Device has only got one LUN.\n"); 656 usbd_add_dynamic_quirk(udev, UQ_MSC_NO_GETMAXLUN); 657 } 658 659 is_no_direct = 1; 660 for (timeout = 4; timeout != 0; timeout--) { 661 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 662 SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry), 663 USB_MS_HZ); 664 665 if (err == 0 && sc->actlen > 0) { 666 sid_type = sc->buffer[0] & 0x1F; 667 if (sid_type == 0x00) 668 is_no_direct = 0; 669 break; 670 } else if (err != ERR_CSW_FAILED) { 671 DPRINTF("Device is not responding " 672 "properly to SCSI INQUIRY command.\n"); 673 goto error; /* non retryable error */ 674 } 675 usb_pause_mtx(NULL, hz); 676 } 677 678 if (is_no_direct) { 679 DPRINTF("Device is not direct access.\n"); 680 goto done; 681 } 682 683 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, 684 &scsi_test_unit_ready, sizeof(scsi_test_unit_ready), 685 USB_MS_HZ); 686 687 if (err != 0) { 688 689 if (err != ERR_CSW_FAILED) 690 goto error; 691 } 692 timeout = 1; 693 694 retry_sync_cache: 695 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, 696 &scsi_sync_cache, sizeof(scsi_sync_cache), 697 USB_MS_HZ); 698 699 if (err != 0) { 700 701 if (err != ERR_CSW_FAILED) 702 goto error; 703 704 DPRINTF("Device doesn't handle synchronize cache\n"); 705 706 usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); 707 708 } else { 709 710 /* 711 * Certain Kingston memory sticks fail the first 712 * read capacity after a synchronize cache command 713 * has been issued. Disable the synchronize cache 714 * command for such devices. 715 */ 716 717 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8, 718 &scsi_read_capacity, sizeof(scsi_read_capacity), 719 USB_MS_HZ); 720 721 if (err != 0) { 722 if (err != ERR_CSW_FAILED) 723 goto error; 724 725 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8, 726 &scsi_read_capacity, sizeof(scsi_read_capacity), 727 USB_MS_HZ); 728 729 if (err == 0) { 730 if (timeout--) 731 goto retry_sync_cache; 732 733 DPRINTF("Device most likely doesn't " 734 "handle synchronize cache\n"); 735 736 usbd_add_dynamic_quirk(udev, 737 UQ_MSC_NO_SYNC_CACHE); 738 } else { 739 if (err != ERR_CSW_FAILED) 740 goto error; 741 } 742 } 743 } 744 745 /* clear sense status of any failed commands on the device */ 746 747 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 748 SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry), 749 USB_MS_HZ); 750 751 DPRINTF("Inquiry = %d\n", err); 752 753 if (err != 0) { 754 755 if (err != ERR_CSW_FAILED) 756 goto error; 757 } 758 759 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 760 SCSI_SENSE_LEN, &scsi_request_sense, 761 sizeof(scsi_request_sense), USB_MS_HZ); 762 763 DPRINTF("Request sense = %d\n", err); 764 765 if (err != 0) { 766 767 if (err != ERR_CSW_FAILED) 768 goto error; 769 } 770 771 done: 772 bbb_detach(sc); 773 return (0); 774 775 error: 776 bbb_detach(sc); 777 778 DPRINTF("Device did not respond, enabling all quirks\n"); 779 780 usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); 781 usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY); 782 783 /* Need to re-enumerate the device */ 784 usbd_req_re_enumerate(udev, NULL); 785 786 return (USB_ERR_STALLED); 787 } 788 789 usb_error_t 790 usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method) 791 { 792 struct bbb_transfer *sc; 793 usb_error_t err; 794 795 sc = bbb_attach(udev, iface_index); 796 if (sc == NULL) 797 return (USB_ERR_INVAL); 798 799 switch (method) { 800 case MSC_EJECT_STOPUNIT: 801 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, 802 &scsi_test_unit_ready, sizeof(scsi_test_unit_ready), 803 USB_MS_HZ); 804 DPRINTF("Test unit ready status: %s\n", usbd_errstr(err)); 805 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, 806 &scsi_start_stop_unit, sizeof(scsi_start_stop_unit), 807 USB_MS_HZ); 808 break; 809 case MSC_EJECT_REZERO: 810 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, 811 &scsi_rezero_init, sizeof(scsi_rezero_init), 812 USB_MS_HZ); 813 break; 814 case MSC_EJECT_ZTESTOR: 815 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, 816 &scsi_ztestor_eject, sizeof(scsi_ztestor_eject), 817 USB_MS_HZ); 818 break; 819 case MSC_EJECT_CMOTECH: 820 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, 821 &scsi_cmotech_eject, sizeof(scsi_cmotech_eject), 822 USB_MS_HZ); 823 break; 824 case MSC_EJECT_HUAWEI: 825 err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, 826 &scsi_huawei_eject, sizeof(scsi_huawei_eject), 827 USB_MS_HZ); 828 break; 829 case MSC_EJECT_TCT: 830 /* 831 * TCTMobile needs DIR_IN flag. To get it, we 832 * supply a dummy data with the command. 833 */ 834 err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 835 sc->buffer_size, &scsi_tct_eject, 836 sizeof(scsi_tct_eject), USB_MS_HZ); 837 break; 838 default: 839 DPRINTF("Unknown eject method (%d)\n", method); 840 err = 0; 841 break; 842 } 843 DPRINTF("Eject CD command status: %s\n", usbd_errstr(err)); 844 845 bbb_detach(sc); 846 return (0); 847 } 848