1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2011-12-12 Yi Qiu first version 9 */ 10 11 #include <rtthread.h> 12 #include <drivers/usb_host.h> 13 #include "mass.h" 14 15 #ifdef RT_USBH_MSTORAGE 16 17 extern rt_err_t rt_udisk_run(struct uhintf* intf); 18 extern rt_err_t rt_udisk_stop(struct uhintf* intf); 19 20 static struct uclass_driver storage_driver; 21 22 /** 23 * This function will do USBREQ_GET_MAX_LUN request for the usb interface instance. 24 * 25 * @param intf the interface instance. 26 * @param max_lun the buffer to save max_lun. 27 * 28 * @return the error code, RT_EOK on successfully. 29 */ 30 static rt_err_t _pipe_check(struct uhintf* intf, upipe_t pipe) 31 { 32 struct uinstance* device; 33 rt_err_t ret; 34 ustor_t stor; 35 int size = 0; 36 struct ustorage_csw csw; 37 38 if(intf == RT_NULL || pipe == RT_NULL) 39 { 40 rt_kprintf("the interface is not available\n"); 41 return -RT_EIO; 42 } 43 44 /* get usb device instance from the interface instance */ 45 device = intf->device; 46 47 /* get storage instance from the interface instance */ 48 stor = (ustor_t)intf->user_data; 49 50 /* check pipe status */ 51 if(pipe->status == UPIPE_STATUS_OK) return RT_EOK; 52 53 if(pipe->status == UPIPE_STATUS_ERROR) 54 { 55 rt_kprintf("pipe status error\n"); 56 return -RT_EIO; 57 } 58 if(pipe->status == UPIPE_STATUS_STALL) 59 { 60 /* clear the pipe stall status */ 61 ret = rt_usbh_clear_feature(device, pipe->ep.bEndpointAddress, 62 USB_FEATURE_ENDPOINT_HALT); 63 if(ret != RT_EOK) return ret; 64 } 65 66 67 rt_thread_delay(50); 68 69 rt_kprintf("pipes1 0x%x, 0x%x\n", stor->pipe_in, stor->pipe_out); 70 71 stor->pipe_in->status = UPIPE_STATUS_OK; 72 73 RT_DEBUG_LOG(RT_DEBUG_USB, ("clean storage in pipe stall\n")); 74 75 /* it should receive csw after clear the stall feature */ 76 size = rt_usb_hcd_pipe_xfer(stor->pipe_in->inst->hcd, 77 stor->pipe_in, &csw, SIZEOF_CSW, 100); 78 if(size != SIZEOF_CSW) 79 { 80 rt_kprintf("receive the csw after stall failed\n"); 81 return -RT_EIO; 82 } 83 84 return -RT_ERROR; 85 } 86 87 /** 88 * This function will do USBREQ_GET_MAX_LUN request for the usb interface instance. 89 * 90 * @param intf the interface instance. 91 * @param max_lun the buffer to save max_lun. 92 * 93 * @return the error code, RT_EOK on successfully. 94 */ 95 static rt_err_t rt_usb_bulk_only_xfer(struct uhintf* intf, 96 ustorage_cbw_t cmd, rt_uint8_t* buffer, int timeout) 97 { 98 rt_size_t size; 99 rt_err_t ret; 100 upipe_t pipe; 101 struct ustorage_csw csw; 102 ustor_t stor; 103 104 RT_ASSERT(cmd != RT_NULL); 105 106 if(intf == RT_NULL) 107 { 108 rt_kprintf("the interface is not available\n"); 109 return -RT_EIO; 110 } 111 112 /* get storage instance from the interface instance */ 113 stor = (ustor_t)intf->user_data; 114 115 do 116 { 117 /* send the cbw */ 118 size = rt_usb_hcd_pipe_xfer(stor->pipe_out->inst->hcd, stor->pipe_out, 119 cmd, SIZEOF_CBW, timeout); 120 if(size != SIZEOF_CBW) 121 { 122 rt_kprintf("CBW size error\n"); 123 return -RT_EIO; 124 } 125 if(cmd->xfer_len != 0) 126 { 127 pipe = (cmd->dflags == CBWFLAGS_DIR_IN) ? stor->pipe_in : 128 stor->pipe_out; 129 size = rt_usb_hcd_pipe_xfer(pipe->inst->hcd, pipe, (void*)buffer, 130 cmd->xfer_len, timeout); 131 if(size != cmd->xfer_len) 132 { 133 rt_kprintf("request size %d, transfer size %d\n", 134 cmd->xfer_len, size); 135 break; 136 } 137 } 138 139 /* receive the csw */ 140 size = rt_usb_hcd_pipe_xfer(stor->pipe_in->inst->hcd, stor->pipe_in, 141 &csw, SIZEOF_CSW, timeout); 142 if(size != SIZEOF_CSW) 143 { 144 rt_kprintf("csw size error\n"); 145 return -RT_EIO; 146 } 147 }while(0); 148 149 /* check in pipes status */ 150 ret = _pipe_check(intf, stor->pipe_in); 151 if(ret != RT_EOK) 152 { 153 rt_kprintf("in pipe error\n"); 154 return ret; 155 } 156 157 /* check out pipes status */ 158 ret = _pipe_check(intf, stor->pipe_out); 159 if(ret != RT_EOK) 160 { 161 rt_kprintf("out pipe error\n"); 162 return ret; 163 } 164 165 /* check csw status */ 166 if(csw.signature != CSW_SIGNATURE || csw.tag != CBW_TAG_VALUE) 167 { 168 rt_kprintf("csw signature error\n"); 169 return -RT_EIO; 170 } 171 172 if(csw.status != 0) 173 { 174 //rt_kprintf("csw status error:%d\n",csw.status); 175 return -RT_ERROR; 176 } 177 178 return RT_EOK; 179 } 180 181 /** 182 * This function will do USBREQ_GET_MAX_LUN request for the usb interface instance. 183 * 184 * @param intf the interface instance. 185 * @param max_lun the buffer to save max_lun. 186 * 187 * @return the error code, RT_EOK on successfully. 188 */ 189 rt_err_t rt_usbh_storage_get_max_lun(struct uhintf* intf, rt_uint8_t* max_lun) 190 { 191 struct uinstance* device; 192 struct urequest setup; 193 int timeout = USB_TIMEOUT_BASIC; 194 195 if(intf == RT_NULL) 196 { 197 rt_kprintf("the interface is not available\n"); 198 return -RT_EIO; 199 } 200 201 /* parameter check */ 202 RT_ASSERT(intf->device != RT_NULL); 203 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_get_max_lun\n")); 204 205 /* get usb device instance from the interface instance */ 206 device = intf->device; 207 208 /* construct the request */ 209 setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | 210 USB_REQ_TYPE_INTERFACE; 211 setup.bRequest = USBREQ_GET_MAX_LUN; 212 setup.wValue = intf->intf_desc->bInterfaceNumber; 213 setup.wIndex = 0; 214 setup.wLength = 1; 215 216 /* do control transfer request */ 217 if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) != 8) 218 { 219 return -RT_EIO; 220 } 221 if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, max_lun, 1, timeout) != 1) 222 { 223 return -RT_EIO; 224 } 225 if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_out, RT_NULL, 0, timeout) != 0) 226 { 227 return -RT_EIO; 228 } 229 return RT_EOK; 230 } 231 232 /** 233 * This function will do USBREQ_MASS_STORAGE_RESET request for the usb interface instance. 234 * 235 * @param intf the interface instance. 236 * 237 * @return the error code, RT_EOK on successfully. 238 */ 239 rt_err_t rt_usbh_storage_reset(struct uhintf* intf) 240 { 241 struct urequest setup; 242 struct uinstance* device; 243 int timeout = USB_TIMEOUT_BASIC; 244 245 /* parameter check */ 246 if(intf == RT_NULL) 247 { 248 rt_kprintf("the interface is not available\n"); 249 return -RT_EIO; 250 } 251 252 RT_ASSERT(intf->device != RT_NULL); 253 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_reset\n")); 254 255 /* get usb device instance from the interface instance */ 256 device = intf->device; 257 258 /* construct the request */ 259 setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS | 260 USB_REQ_TYPE_INTERFACE; 261 setup.bRequest = USBREQ_MASS_STORAGE_RESET; 262 setup.wIndex = intf->intf_desc->bInterfaceNumber; 263 setup.wLength = 0; 264 setup.wValue = 0; 265 266 if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) != 8) 267 { 268 return -RT_EIO; 269 } 270 if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, RT_NULL, 0, timeout) != 0) 271 { 272 return -RT_EIO; 273 } 274 return RT_EOK; 275 } 276 277 /** 278 * This function will execute SCSI_READ_10 command to read data from the usb device. 279 * 280 * @param intf the interface instance. 281 * @param buffer the data buffer to save read data 282 * @param sector the start sector address to read. 283 * @param sector the sector count to read. 284 * 285 * @return the error code, RT_EOK on successfully. 286 */ 287 rt_err_t rt_usbh_storage_read10(struct uhintf* intf, rt_uint8_t *buffer, 288 rt_uint32_t sector, rt_size_t count, int timeout) 289 { 290 struct ustorage_cbw cmd; 291 292 /* parameter check */ 293 if(intf == RT_NULL) 294 { 295 rt_kprintf("interface is not available\n"); 296 return -RT_EIO; 297 } 298 299 RT_ASSERT(intf->device != RT_NULL); 300 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_read10\n")); 301 302 /* construct the command block wrapper */ 303 rt_memset(&cmd, 0, sizeof(struct ustorage_cbw)); 304 cmd.signature = CBW_SIGNATURE; 305 cmd.tag = CBW_TAG_VALUE; 306 cmd.xfer_len = SECTOR_SIZE * count; 307 cmd.dflags = CBWFLAGS_DIR_IN; 308 cmd.lun = 0; 309 cmd.cb_len = 10; 310 cmd.cb[0] = SCSI_READ_10; 311 cmd.cb[1] = 0; 312 cmd.cb[2] = (rt_uint8_t)(sector >> 24); 313 cmd.cb[3] = (rt_uint8_t)(sector >> 16); 314 cmd.cb[4] = (rt_uint8_t)(sector >> 8); 315 cmd.cb[5] = (rt_uint8_t)sector; 316 cmd.cb[6] = 0; 317 cmd.cb[7] = (count & 0xff00) >> 8; 318 cmd.cb[8] = (rt_uint8_t) count & 0xff; 319 320 return rt_usb_bulk_only_xfer(intf, &cmd, buffer, timeout); 321 } 322 323 /** 324 * This function will execute SCSI_WRITE_10 command to write data to the usb device. 325 * 326 * @param intf the interface instance. 327 * @param buffer the data buffer to save write data 328 * @param sector the start sector address to write. 329 * @param sector the sector count to write. 330 * 331 * @return the error code, RT_EOK on successfully. 332 */ 333 rt_err_t rt_usbh_storage_write10(struct uhintf* intf, rt_uint8_t *buffer, 334 rt_uint32_t sector, rt_size_t count, int timeout) 335 { 336 struct ustorage_cbw cmd; 337 338 /* parameter check */ 339 if(intf == RT_NULL) 340 { 341 rt_kprintf("the interface is not available\n"); 342 return -RT_EIO; 343 } 344 345 RT_ASSERT(intf->device != RT_NULL); 346 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_write10\n")); 347 348 /* construct the command block wrapper */ 349 rt_memset(&cmd, 0, sizeof(struct ustorage_cbw)); 350 cmd.signature = CBW_SIGNATURE; 351 cmd.tag = CBW_TAG_VALUE; 352 cmd.xfer_len = SECTOR_SIZE * count; 353 cmd.dflags = CBWFLAGS_DIR_OUT; 354 cmd.lun = 0; 355 cmd.cb_len = 10; 356 cmd.cb[0] = SCSI_WRITE_10; 357 cmd.cb[1] = 0; 358 cmd.cb[2] = (rt_uint8_t)(sector >> 24); 359 cmd.cb[3] = (rt_uint8_t)(sector >> 16); 360 cmd.cb[4] = (rt_uint8_t)(sector >> 8); 361 cmd.cb[5] = (rt_uint8_t)sector; 362 cmd.cb[6] = 0; 363 cmd.cb[7] = (count & 0xff00) >> 8; 364 cmd.cb[8] = (rt_uint8_t) count & 0xff; 365 366 return rt_usb_bulk_only_xfer(intf, &cmd, buffer, timeout); 367 } 368 369 /** 370 * This function will execute SCSI_REQUEST_SENSE command to get sense data. 371 * 372 * @param intf the interface instance. 373 * @param buffer the data buffer to save sense data 374 * 375 * @return the error code, RT_EOK on successfully. 376 */ 377 rt_err_t rt_usbh_storage_request_sense(struct uhintf* intf, rt_uint8_t* buffer) 378 { 379 struct ustorage_cbw cmd; 380 int timeout = USB_TIMEOUT_LONG; 381 382 /* parameter check */ 383 if(intf == RT_NULL) 384 { 385 rt_kprintf("the interface is not available\n"); 386 return -RT_EIO; 387 } 388 389 RT_ASSERT(intf->device != RT_NULL); 390 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_request_sense\n")); 391 392 /* construct the command block wrapper */ 393 rt_memset(&cmd, 0, sizeof(struct ustorage_cbw)); 394 cmd.signature = CBW_SIGNATURE; 395 cmd.tag = CBW_TAG_VALUE; 396 cmd.xfer_len = 18; 397 cmd.dflags = CBWFLAGS_DIR_IN; 398 cmd.lun = 0; 399 cmd.cb_len = 6; 400 cmd.cb[0] = SCSI_REQUEST_SENSE; 401 cmd.cb[4] = 18; 402 403 return rt_usb_bulk_only_xfer(intf, &cmd, buffer, timeout); 404 } 405 406 /** 407 * This function will execute SCSI_TEST_UNIT_READY command to get unit ready status. 408 * 409 * @param intf the interface instance. 410 * 411 * @return the error code, RT_EOK on successfully. 412 */ 413 rt_err_t rt_usbh_storage_test_unit_ready(struct uhintf* intf) 414 { 415 struct ustorage_cbw cmd; 416 int timeout = USB_TIMEOUT_LONG; 417 418 /* parameter check */ 419 if(intf == RT_NULL) 420 { 421 rt_kprintf("the interface is not available\n"); 422 return -RT_EIO; 423 } 424 425 RT_ASSERT(intf->device != RT_NULL); 426 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_test_unit_ready\n")); 427 428 /* construct the command block wrapper */ 429 rt_memset(&cmd, 0, sizeof(struct ustorage_cbw)); 430 cmd.signature = CBW_SIGNATURE; 431 cmd.tag = CBW_TAG_VALUE; 432 cmd.xfer_len = 0; 433 cmd.dflags = CBWFLAGS_DIR_OUT; 434 cmd.lun = 0; 435 cmd.cb_len = 12; 436 cmd.cb[0] = SCSI_TEST_UNIT_READY; 437 438 return rt_usb_bulk_only_xfer(intf, &cmd, RT_NULL, timeout); 439 } 440 441 /** 442 * This function will execute SCSI_INQUIRY_CMD command to get inquiry data. 443 * 444 * @param intf the interface instance. 445 * @param buffer the data buffer to save inquiry data 446 * 447 * @return the error code, RT_EOK on successfully. 448 */ 449 rt_err_t rt_usbh_storage_inquiry(struct uhintf* intf, rt_uint8_t* buffer) 450 { 451 struct ustorage_cbw cmd; 452 int timeout = USB_TIMEOUT_LONG; 453 454 /* parameter check */ 455 if(intf == RT_NULL) 456 { 457 rt_kprintf("the interface is not available\n"); 458 return -RT_EIO; 459 } 460 461 RT_ASSERT(intf->device != RT_NULL); 462 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_inquiry\n")); 463 464 /* construct the command block wrapper */ 465 rt_memset(&cmd, 0, sizeof(struct ustorage_cbw)); 466 cmd.signature = CBW_SIGNATURE; 467 cmd.tag = CBW_TAG_VALUE; 468 cmd.xfer_len = 36; 469 cmd.dflags = CBWFLAGS_DIR_IN; 470 cmd.lun = 0; 471 cmd.cb_len = 6;//12 472 cmd.cb[0] = SCSI_INQUIRY_CMD; 473 cmd.cb[4] = 36; 474 475 return rt_usb_bulk_only_xfer(intf, &cmd, buffer, timeout); 476 } 477 478 /** 479 * This function will execute SCSI_READ_CAPACITY command to get capacity data. 480 * 481 * @param intf the interface instance. 482 * @param buffer the data buffer to save capacity data 483 * 484 * @return the error code, RT_EOK on successfully. 485 */ 486 rt_err_t rt_usbh_storage_get_capacity(struct uhintf* intf, rt_uint8_t* buffer) 487 { 488 struct ustorage_cbw cmd; 489 int timeout = USB_TIMEOUT_LONG; 490 491 /* parameter check */ 492 if(intf == RT_NULL) 493 { 494 rt_kprintf("the interface is not available\n"); 495 return -RT_EIO; 496 } 497 498 RT_ASSERT(intf->device != RT_NULL); 499 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_get_capacity\n")); 500 501 /* construct the command block wrapper */ 502 rt_memset(&cmd, 0, sizeof(struct ustorage_cbw)); 503 cmd.signature = CBW_SIGNATURE; 504 cmd.tag = CBW_TAG_VALUE; 505 cmd.xfer_len = 8; 506 cmd.dflags = CBWFLAGS_DIR_IN; 507 cmd.lun = 0; 508 cmd.cb_len = 12; 509 cmd.cb[0] = SCSI_READ_CAPACITY; 510 511 return rt_usb_bulk_only_xfer(intf, &cmd, buffer, timeout); 512 } 513 514 /** 515 * This function will run mass storage class driver when usb device is detected 516 * and identified as a mass storage class device, it will continue to do the enumulate 517 * process. 518 * 519 * @param arg the argument. 520 * 521 * @return the error code, RT_EOK on successfully. 522 */ 523 static rt_err_t rt_usbh_storage_enable(void* arg) 524 { 525 int i = 0; 526 rt_err_t ret; 527 ustor_t stor; 528 struct uhintf* intf = (struct uhintf*)arg; 529 530 /* parameter check */ 531 if(intf == RT_NULL) 532 { 533 rt_kprintf("the interface is not available\n"); 534 return -RT_EIO; 535 } 536 537 RT_DEBUG_LOG(RT_DEBUG_USB, ("subclass %d, protocal %d\n", 538 intf->intf_desc->bInterfaceSubClass, 539 intf->intf_desc->bInterfaceProtocol)); 540 541 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_run\n")); 542 543 /* only support SCSI subclass and bulk only protocal */ 544 545 stor = rt_malloc(sizeof(struct ustor)); 546 RT_ASSERT(stor != RT_NULL); 547 548 /* initilize the data structure */ 549 rt_memset(stor, 0, sizeof(struct ustor)); 550 intf->user_data = (void*)stor; 551 552 for(i=0; i<intf->intf_desc->bNumEndpoints; i++) 553 { 554 uep_desc_t ep_desc; 555 556 /* get endpoint descriptor from interface descriptor */ 557 rt_usbh_get_endpoint_descriptor(intf->intf_desc, i, &ep_desc); 558 if(ep_desc == RT_NULL) 559 { 560 rt_kprintf("rt_usb_get_endpoint_descriptor error\n"); 561 return -RT_ERROR; 562 } 563 564 /* the endpoint type of mass storage class should be BULK */ 565 if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK) 566 continue; 567 568 /* allocate pipes according to the endpoint type */ 569 if(ep_desc->bEndpointAddress & USB_DIR_IN) 570 { 571 /* alloc an in pipe for the storage instance */ 572 stor->pipe_in = rt_usb_instance_find_pipe(intf->device,ep_desc->bEndpointAddress); 573 } 574 else 575 { 576 /* alloc an output pipe for the storage instance */ 577 stor->pipe_out = rt_usb_instance_find_pipe(intf->device,ep_desc->bEndpointAddress); 578 } 579 } 580 581 /* check pipes infomation */ 582 if(stor->pipe_in == RT_NULL || stor->pipe_out == RT_NULL) 583 { 584 rt_kprintf("pipe error, unsupported device\n"); 585 return -RT_ERROR; 586 } 587 588 /* should implement as callback */ 589 ret = rt_udisk_run(intf); 590 if(ret != RT_EOK) return ret; 591 592 return RT_EOK; 593 } 594 595 /** 596 * This function will be invoked when usb device plug out is detected and it would clean 597 * and release all mass storage class related resources. 598 * 599 * @param arg the argument. 600 * 601 * @return the error code, RT_EOK on successfully. 602 */ 603 static rt_err_t rt_usbh_storage_disable(void* arg) 604 { 605 ustor_t stor; 606 struct uhintf* intf = (struct uhintf*)arg; 607 608 /* parameter check */ 609 RT_ASSERT(intf != RT_NULL); 610 RT_ASSERT(intf->user_data != RT_NULL); 611 RT_ASSERT(intf->device != RT_NULL); 612 613 RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_stop\n")); 614 615 /* get storage instance from interface instance */ 616 stor = (ustor_t)intf->user_data; 617 618 rt_udisk_stop(intf); 619 620 621 /* free storage instance */ 622 if(stor != RT_NULL) rt_free(stor); 623 return RT_EOK; 624 } 625 626 /** 627 * This function will register mass storage class driver to the usb class driver manager. 628 * and it should be invoked in the usb system initialization. 629 * 630 * @return the error code, RT_EOK on successfully. 631 */ 632 ucd_t rt_usbh_class_driver_storage(void) 633 { 634 storage_driver.class_code = USB_CLASS_MASS_STORAGE; 635 636 storage_driver.enable = rt_usbh_storage_enable; 637 storage_driver.disable = rt_usbh_storage_disable; 638 639 return &storage_driver; 640 } 641 642 #endif 643 644