00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "conf_usb_host.h"
00048 #include "USBHDriver.h"
00049 #include "USBH.h"
00050 #include "uhi_msc.h"
00051 #include <string.h>
00052
00053 #ifdef USB_HOST_HUB_SUPPORT
00054
00055 # error USB HUB support is not implemented on UHI MSC
00056 #endif
00057
00058 #ifndef UHI_MSC_NOTIFY_NEW_LUN_EXT
00059 # define UHI_MSC_NOTIFY_NEW_LUN_EXT
00060 #endif
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #define UHI_MSC_SCSI_TIMEOUT 20000
00072
00073
00074
00075
00076
00077
00078
00079 static volatile bool b_uhi_msc_free = true;
00080
00081
00082 typedef struct {
00083 USBH_device_t *dev;
00084 USBHS_Ep_t ep_in;
00085 USBHS_Ep_t ep_out;
00086 uint8_t iface_num;
00087 uint8_t nb_lun;
00088 uhi_msc_lun_t *lun;
00089 } uhi_msc_dev_t;
00090
00091
00092 static uhi_msc_dev_t uhi_msc_dev = {
00093 .dev = NULL,
00094 .lun = NULL,
00095 .nb_lun = 0,
00096 };
00097
00098
00099
00100 #ifdef USB_HOST_HUB_SUPPORT
00101 static uhi_msc_dev_t *uhi_msc_dev_sel;
00102 #else
00103 # define uhi_msc_dev_sel (&uhi_msc_dev)
00104 #endif
00105
00106
00107
00108
00109 static uhi_msc_lun_t *uhi_msc_lun_sel;
00110 #define uhi_msc_lun_num_sel uhi_msc_cbw.bCBWLUN
00111
00112
00113
00114
00115 static SBCReadCapacity10Data uhi_msc_capacity;
00116 static SBCInquiryData uhi_msc_inquiry;
00117 static SBCRequestSenseData uhi_msc_sense;
00118 static struct {
00119 SBCModeParameterHeader6 header;
00120 SBCInformationalExceptionsControl sense_data;
00121 } uhi_msc_sense6;
00122
00123
00124
00125 typedef void (*uhi_msc_scsi_sense_callback_t) (void);
00126
00127
00128
00129 static uhi_msc_scsi_callback_t uhi_msc_scsi_sub_callback;
00130 static uhi_msc_scsi_callback_t uhi_msc_scsi_callback;
00131 static uhi_msc_scsi_sense_callback_t uhi_msc_scsi_sense_callback;
00132
00133
00134
00135
00136
00137
00138
00139
00140 static MSCbw uhi_msc_cbw =
00141 {.dCBWSignature = MSD_CBW_SIGNATURE };
00142
00143
00144 static MSCsw uhi_msc_csw;
00145
00146
00147 static uint8_t *uhi_msc_data;
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 static void uhi_msc_enable_step1(void);
00160 static void uhi_msc_enable_step2(
00161 USBHS_Add_t add,
00162 USBH_XfrStatus_t status,
00163 uint16_t payload_trans);
00164 static void uhi_msc_enable_step3(void);
00165 static void uhi_msc_enable_step4(bool b_success);
00166 static void uhi_msc_enable_step5(bool b_success);
00167
00168
00169
00170
00171
00172
00173 static bool uhi_msc_select_lun(uint8_t lun);
00174 static void uhi_msc_scsi_inquiry(uhi_msc_scsi_callback_t callback);
00175 static void uhi_msc_scsi_inquiry_done(bool b_cbw_succes);
00176 static void uhi_msc_scsi_test_unit_ready_done(bool b_cbw_succes);
00177 static void uhi_msc_scsi_test_unit_ready_sense(void);
00178 static void uhi_msc_scsi_read_capacity(uhi_msc_scsi_callback_t callback);
00179 static void uhi_msc_scsi_read_capacity_done(bool b_cbw_succes);
00180 static void uhi_msc_scsi_read_capacity_sense(void);
00181 static void uhi_msc_scsi_mode_sense6(uhi_msc_scsi_callback_t callback);
00182 static void uhi_msc_scsi_mode_sense6_done(bool b_cbw_succes);
00183 static void uhi_msc_scsi_read_10_done(bool b_cbw_succes);
00184 static void uhi_msc_scsi_write_10_done(bool b_cbw_succes);
00185 static void uhi_msc_scsi_request_sense(uhi_msc_scsi_sense_callback_t callback);
00186 static void uhi_msc_scsi_request_sense_done(bool b_cbw_succes);
00187
00188
00189
00190
00191
00192
00193 static void uhi_msc_scsi(uhi_msc_scsi_callback_t callback, uint8_t *payload);
00194 static void uhi_msc_cbw_sent(
00195 USBHS_Add_t add,
00196 USBHS_Ep_t ep,
00197 USBH_XfrStatus_t status,
00198 uint32_t nb_transfered);
00199 static void uhi_msc_data_transfered(
00200 USBHS_Add_t add,
00201 USBHS_Ep_t ep,
00202 USBH_XfrStatus_t status,
00203 uint32_t nb_transfered);
00204 static void uhi_msc_csw_wait(void);
00205 static void uhi_msc_csw_received(
00206 USBHS_Add_t add,
00207 USBHS_Ep_t ep,
00208 USBH_XfrStatus_t status,
00209 uint32_t nb_transfered);
00210 static void uhi_msc_cbw_rst_stall(
00211 USBHS_Add_t add,
00212 USBH_XfrStatus_t status,
00213 uint16_t payload_trans);
00214 static void uhi_msc_data_csw_rst_stall(
00215 USBHS_Add_t add,
00216 USBH_XfrStatus_t status,
00217 uint16_t payload_trans);
00218 static void uhi_msc_transfer(USBHS_Ep_t endp,
00219 uint8_t* payload,
00220 uint16_t payload_size,
00221 uhd_callback_trans_t callback_end);
00222 static void uhi_msc_reset_endpoint(
00223 USBHS_Ep_t endp, uhd_callback_setup_end_t callback );
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 USBH_enum_status_t uhi_msc_install(USBH_device_t * dev)
00235 {
00236 bool b_iface_supported;
00237 uint16_t conf_desc_lgt;
00238 USBInterfaceDescriptor *ptr_iface;
00239
00240 if (uhi_msc_dev.dev != NULL) {
00241 return UHC_ENUM_SOFTWARE_LIMIT;
00242 }
00243 conf_desc_lgt = dev->conf_desc->wTotalLength;
00244 ptr_iface = (USBInterfaceDescriptor *) dev->conf_desc;
00245 b_iface_supported = false;
00246 while (conf_desc_lgt) {
00247 switch (ptr_iface->bDescriptorType) {
00248
00249 case USBGenericDescriptor_INTERFACE:
00250 if ((ptr_iface->bInterfaceClass == MSInterfaceDescriptor_CLASS)
00251 && (ptr_iface->bInterfaceSubClass == MSD_SUBCLASS_SCSI)
00252 && (ptr_iface->bInterfaceProtocol == MSD_PROTOCOL_BULK_ONLY) ) {
00253
00254 b_iface_supported = true;
00255 uhi_msc_dev_sel->iface_num = ptr_iface->bInterfaceNumber;
00256 uhi_msc_dev.ep_in = 0;
00257 uhi_msc_dev.ep_out = 0;
00258 } else {
00259
00260 b_iface_supported = false;
00261 }
00262 break;
00263
00264 case USBGenericDescriptor_ENDPOINT:
00265
00266 if (!b_iface_supported) {
00267 break;
00268 }
00269 USBEndpointDescriptor *ptr_ep = (USBEndpointDescriptor *) ptr_iface;
00270 if (ptr_ep->bmAttributes != USBEndpointDescriptor_BULK) {
00271
00272 break;
00273 }
00274 if (!USBH_HAL_ConfigurePipe(dev->address, ptr_ep)) {
00275 return UHC_ENUM_HARDWARE_LIMIT;
00276 }
00277 if (ptr_ep->bEndpointAddress & USB_EP_DIR_IN) {
00278 uhi_msc_dev.ep_in = ptr_ep->bEndpointAddress;
00279 } else {
00280 uhi_msc_dev.ep_out = ptr_ep->bEndpointAddress;
00281 }
00282 if (uhi_msc_dev.ep_out && uhi_msc_dev.ep_in) {
00283
00284 uhi_msc_dev.dev = dev;
00285 uhi_msc_dev.nb_lun = 0;
00286 return UHC_ENUM_SUCCESS;
00287 }
00288 break;
00289
00290 }
00291 assert(conf_desc_lgt >= ptr_iface->bLength);
00292 conf_desc_lgt -= ptr_iface->bLength;
00293 ptr_iface = (USBInterfaceDescriptor*)((uint8_t*)ptr_iface + ptr_iface->bLength);
00294 }
00295
00296 return UHC_ENUM_UNSUPPORTED;
00297 }
00298
00299 void uhi_msc_enable(USBH_device_t * dev)
00300 {
00301 if (uhi_msc_dev.dev != dev) {
00302 return;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312 #ifdef USB_HOST_HUB_SUPPORT
00313 uhi_msc_dev_sel = &uhi_msc_dev[];
00314 if (!b_uhi_msc_free) {
00315
00316 }
00317 #else
00318 assert(uhi_msc_dev.dev != NULL);
00319 #endif
00320 b_uhi_msc_free = false;
00321 uhi_msc_enable_step1();
00322 }
00323
00324 void uhi_msc_uninstall(USBH_device_t * dev)
00325 {
00326 if (uhi_msc_dev.dev != dev) {
00327 return;
00328 }
00329 uhi_msc_dev.dev = NULL;
00330 if (uhi_msc_dev_sel->lun != NULL) {
00331 free(uhi_msc_dev_sel->lun);
00332 }
00333 UHI_MSC_CHANGE(dev, false);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 static void uhi_msc_enable_step1(void)
00348 {
00349
00350
00351 uhi_msc_dev_sel->nb_lun = 0;
00352
00353
00354 USBGenericRequest req;
00355 req.bmRequestType = USB_REQ_RECIP_INTERFACE|USB_REQ_TYPE_CLASS|USB_REQ_DIR_IN;
00356 req.bRequest = MSD_GET_MAX_LUN;
00357 req.wValue = 0;
00358 req.wIndex = uhi_msc_dev_sel->iface_num;
00359 req.wLength = 1;
00360 USBH_HAL_SetupReq(uhi_msc_dev_sel->dev->address,
00361 &req,
00362 &(uhi_msc_dev_sel->nb_lun),
00363 1,
00364 NULL,
00365 uhi_msc_enable_step2);
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 static void uhi_msc_enable_step2(
00377 USBHS_Add_t add,
00378 USBH_XfrStatus_t status,
00379 uint16_t payload_trans)
00380 {
00381 UNUSED(add);
00382
00383 if (status == UHD_TRANS_NOERROR) {
00384 if (payload_trans) {
00385
00386 uhi_msc_dev_sel->nb_lun++;
00387 } else {
00388 uhi_msc_dev_sel->nb_lun = 1;
00389 }
00390 } else if (status == UHD_TRANS_STALL) {
00391 uhi_msc_dev_sel->nb_lun = 1;
00392 } else {
00393
00394 b_uhi_msc_free = true;
00395 return;
00396 }
00397
00398
00399 uhi_msc_dev_sel->lun = malloc(uhi_msc_dev_sel->nb_lun*sizeof(uhi_msc_lun_t));
00400 if (uhi_msc_dev_sel->lun == NULL) {
00401 assert(false);
00402 b_uhi_msc_free = true;
00403 return;
00404 }
00405
00406 uhi_msc_lun_num_sel = (uint8_t) - 1;
00407 uhi_msc_enable_step3();
00408 }
00409
00410
00411
00412
00413
00414
00415 static void uhi_msc_enable_step3(void)
00416 {
00417 if (!uhi_msc_select_lun(++uhi_msc_lun_num_sel)) {
00418
00419 b_uhi_msc_free = true;
00420 UHI_MSC_CHANGE(uhi_msc_dev.dev, true);
00421 return;
00422 }
00423 uhi_msc_lun_sel->status = LUN_NOT_PRESENT;
00424 uhi_msc_scsi_inquiry(uhi_msc_enable_step4);
00425 }
00426
00427
00428
00429
00430
00431
00432
00433 static void uhi_msc_enable_step4(bool b_success)
00434 {
00435 if (!b_success) {
00436 uhi_msc_enable_step3();
00437 return;
00438 }
00439 uhi_msc_scsi_read_capacity(uhi_msc_enable_step5);
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 static void uhi_msc_enable_step5(bool b_success)
00449 {
00450 UNUSED(b_success);
00451
00452 uhi_msc_enable_step3();
00453 }
00454
00455
00456
00457
00458
00459
00460
00461 bool uhi_msc_is_available(void)
00462 {
00463 return b_uhi_msc_free;
00464 }
00465
00466 uint8_t uhi_msc_get_lun(void)
00467 {
00468 if (uhi_msc_dev.dev == NULL) {
00469 return 0;
00470 }
00471 return uhi_msc_dev.nb_lun;
00472 }
00473
00474 uhi_msc_lun_t *uhi_msc_get_lun_desc(uint8_t lun)
00475 {
00476 if (lun >= uhi_msc_dev.nb_lun) {
00477 return NULL;
00478 }
00479 return &uhi_msc_dev.lun[lun];
00480 }
00481
00482 bool uhi_msc_scsi_test_unit_ready(uint8_t lun, uhi_msc_scsi_callback_t callback)
00483 {
00484 if (!uhi_msc_select_lun(lun)) {
00485 return false;
00486 }
00487 uhi_msc_scsi_callback = callback;
00488
00489
00490 uhi_msc_cbw.dCBWDataTransferLength = 0;
00491 uhi_msc_cbw.bmCBWFlags = MSD_CBW_DEVICE_TO_DEVICE;
00492 uhi_msc_cbw.bCBWCBLength = 6;
00493 memset(uhi_msc_cbw.pCommand, 0, sizeof(uhi_msc_cbw.pCommand));
00494 uhi_msc_cbw.pCommand[0] = SBC_TEST_UNIT_READY;
00495
00496 uhi_msc_scsi(uhi_msc_scsi_test_unit_ready_done, NULL);
00497 return true;
00498 }
00499
00500 bool uhi_msc_scsi_read_10(uint8_t lun, uint32_t addr, uint8_t *ram,
00501 uint8_t nb_sector, uhi_msc_scsi_callback_t callback )
00502 {
00503 uint32_t addrTmp = addr;
00504 uint32_t *pBlockLen = (uint32_t*)&uhi_msc_lun_sel->capacity.pLogicalBlockLength[0];
00505 if (!uhi_msc_select_lun(lun)) {
00506 return false;
00507 }
00508 uhi_msc_scsi_callback = callback;
00509
00510
00511 uhi_msc_cbw.dCBWDataTransferLength =
00512 (*pBlockLen) * nb_sector;
00513 uhi_msc_cbw.bmCBWFlags = MSD_CBW_DEVICE_TO_HOST;
00514 uhi_msc_cbw.bCBWCBLength = 10;
00515 memset(uhi_msc_cbw.pCommand, 0, sizeof(uhi_msc_cbw.pCommand));
00516
00517
00518
00519
00520 uhi_msc_cbw.pCommand[0] = SBC_READ_10;
00521
00522
00523
00524 addrTmp = CPU_TO_BE32(addr);
00525
00526 memcpy(&uhi_msc_cbw.pCommand[2], &addrTmp, sizeof(addr));
00527
00528
00529
00530
00531 uhi_msc_cbw.pCommand[8] = nb_sector;
00532
00533
00534 uhi_msc_scsi(uhi_msc_scsi_read_10_done, ram);
00535 return true;
00536 }
00537
00538 bool uhi_msc_scsi_write_10(uint8_t lun, uint32_t addr, const uint8_t *ram,
00539 uint8_t nb_sector, uhi_msc_scsi_callback_t callback )
00540 {
00541 uint32_t addrTmp = addr;
00542 uint32_t *pBlockLen = (uint32_t*)&uhi_msc_lun_sel->capacity.pLogicalBlockLength[0];
00543
00544 if (!uhi_msc_select_lun(lun)) {
00545 return false;
00546 }
00547 uhi_msc_scsi_callback = callback;
00548
00549
00550 uhi_msc_cbw.dCBWDataTransferLength =
00551 (*pBlockLen) * nb_sector ;
00552 uhi_msc_cbw.bmCBWFlags = MSD_CBW_DEVICE_TO_DEVICE;
00553 uhi_msc_cbw.bCBWCBLength = 10;
00554 memset(uhi_msc_cbw.pCommand, 0, sizeof(uhi_msc_cbw.pCommand));
00555
00556
00557 uhi_msc_cbw.pCommand[0] = SBC_WRITE_10;
00558
00559 addrTmp = CPU_TO_BE32(addr);
00560
00561
00562
00563 memcpy(&uhi_msc_cbw.pCommand[2], &addrTmp, sizeof(addr));
00564
00565
00566
00567
00568
00569 uhi_msc_cbw.pCommand[8] = nb_sector;
00570
00571
00572 uhi_msc_scsi(uhi_msc_scsi_write_10_done, (uint8_t *) ram);
00573 return true;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 static bool uhi_msc_select_lun(uint8_t lun)
00592 {
00593 if (lun >= uhi_msc_dev_sel->nb_lun) {
00594 return false;
00595 }
00596 uhi_msc_lun_num_sel = lun;
00597 uhi_msc_lun_sel = &uhi_msc_dev_sel->lun[lun];
00598 return true;
00599 }
00600
00601
00602
00603
00604
00605
00606 static void uhi_msc_scsi_inquiry(uhi_msc_scsi_callback_t callback)
00607 {
00608 uhi_msc_scsi_callback = callback;
00609
00610
00611 uhi_msc_cbw.dCBWDataTransferLength = sizeof( SBCInquiryData);
00612 uhi_msc_cbw.bmCBWFlags = MSD_CBW_DEVICE_TO_HOST;
00613 uhi_msc_cbw.bCBWCBLength = 6;
00614 memset(uhi_msc_cbw.pCommand, 0, sizeof(uhi_msc_cbw.pCommand));
00615 uhi_msc_cbw.pCommand[0] = SBC_INQUIRY;
00616 uhi_msc_cbw.pCommand[4] = sizeof(SBCInquiryData);
00617 uhi_msc_scsi(uhi_msc_scsi_inquiry_done, (uint8_t *) & uhi_msc_inquiry);
00618 }
00619
00620
00621
00622
00623
00624
00625 static void uhi_msc_scsi_inquiry_done(bool b_cbw_succes)
00626 {
00627 if ((!b_cbw_succes) || uhi_msc_csw.dCSWDataResidue) {
00628 uhi_msc_scsi_callback(false);
00629 return;
00630 }
00631
00632 uhi_msc_scsi_callback(true);
00633 }
00634
00635
00636
00637
00638
00639
00640
00641 static void uhi_msc_scsi_test_unit_ready_done(bool b_cbw_succes)
00642 {
00643 if (!b_cbw_succes) {
00644 uhi_msc_lun_sel->status = LUN_FAIL;
00645 uhi_msc_scsi_callback(false);
00646 return;
00647 }
00648
00649 if (uhi_msc_csw.bCSWStatus != MSD_CSW_COMMAND_PASSED) {
00650 uhi_msc_lun_sel->status = LUN_FAIL;
00651
00652
00653 uhi_msc_scsi_request_sense(uhi_msc_scsi_test_unit_ready_sense);
00654 return;
00655 }
00656 if (uhi_msc_lun_sel->status != LUN_GOOD) {
00657
00658 if (uhi_msc_lun_sel->status == LUN_BUSY) {
00659
00660 uhi_msc_lun_sel->status = LUN_GOOD;
00661 uhi_msc_scsi_read_capacity(uhi_msc_scsi_callback);
00662 return;
00663 }
00664
00665
00666
00667 uhi_msc_lun_sel->status = LUN_BUSY;
00668 }
00669 uhi_msc_scsi_callback(true);
00670 }
00671
00672
00673
00674
00675 static void uhi_msc_scsi_test_unit_ready_sense(void)
00676 {
00677 uint16_t sense_key = uhi_msc_sense.bSenseKey;
00678 uint16_t add_sense = (uint16_t)uhi_msc_sense.bAdditionalSenseCode<<8
00679 | uhi_msc_sense.bAdditionalSenseCodeQualifier;
00680
00681
00682 if ((uhi_msc_sense.bResponseCode
00683 & SBC_SENSE_RESPONSE_CODE_MASK) == SBC_SENSE_DATA_FIXED_CURRENT) {
00684
00685 if ((sense_key == SBC_SENSE_KEY_NOT_READY)
00686 && (add_sense==(SBC_ASC_MEDIUM_NOT_PRESENT <<8))) {
00687 uhi_msc_lun_sel->status = LUN_NOT_PRESENT;
00688 }
00689 if ((sense_key == SBC_SENSE_KEY_UNIT_ATTENTION)
00690 && (add_sense == (SBC_ASC_NOT_READY_TO_READY_CHANGE << 8))) {
00691 uhi_msc_lun_sel->status = LUN_BUSY;
00692 }
00693 }
00694 uhi_msc_scsi_callback(true);
00695 }
00696
00697
00698
00699
00700
00701
00702 static void uhi_msc_scsi_read_capacity(uhi_msc_scsi_callback_t callback)
00703 {
00704 uhi_msc_scsi_callback = callback;
00705
00706
00707 uhi_msc_cbw.dCBWDataTransferLength = sizeof(SBCReadCapacity10Data);
00708 uhi_msc_cbw.bmCBWFlags = MSD_CBW_DEVICE_TO_HOST;
00709 uhi_msc_cbw.bCBWCBLength = 10;
00710 memset(uhi_msc_cbw.pCommand, 0, sizeof(uhi_msc_cbw.pCommand));
00711 uhi_msc_cbw.pCommand[0] = SBC_READ_CAPACITY_10;
00712 uhi_msc_scsi(uhi_msc_scsi_read_capacity_done, (uint8_t*)&uhi_msc_capacity);
00713 }
00714
00715
00716
00717
00718
00719
00720
00721 static void uhi_msc_scsi_read_capacity_done(bool b_cbw_succes)
00722 {
00723 uint32_t *pBlockLen, *pBlockAddr;
00724 pBlockLen = (uint32_t *)&uhi_msc_lun_sel->capacity.pLogicalBlockLength[0];
00725 pBlockAddr = (uint32_t *)&uhi_msc_lun_sel->capacity.pLogicalBlockAddress[0];
00726 if ((!b_cbw_succes) || (uhi_msc_csw.bCSWStatus != MSD_CSW_COMMAND_PASSED)
00727 || uhi_msc_csw.dCSWDataResidue) {
00728
00729 uhi_msc_lun_sel->status = LUN_FAIL;
00730
00731
00732 uhi_msc_scsi_request_sense(uhi_msc_scsi_read_capacity_sense);
00733 return;
00734 }
00735
00736 *pBlockLen = be32_to_cpu(*( (uint32_t *)&uhi_msc_capacity.pLogicalBlockLength[0]));
00737 *pBlockAddr = be32_to_cpu(*( (uint32_t *)&uhi_msc_capacity.pLogicalBlockAddress[0]));
00738
00739
00740 uhi_msc_scsi_mode_sense6(uhi_msc_scsi_callback);
00741 }
00742
00743
00744
00745
00746 static void uhi_msc_scsi_read_capacity_sense(void)
00747 {
00748 uhi_msc_scsi_callback(false);
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758 static void uhi_msc_scsi_mode_sense6(uhi_msc_scsi_callback_t callback)
00759 {
00760 uhi_msc_scsi_callback = callback;
00761
00762
00763 uhi_msc_cbw.dCBWDataTransferLength = sizeof(uhi_msc_sense6);
00764 uhi_msc_cbw.bmCBWFlags = MSD_CBW_DEVICE_TO_HOST;
00765 uhi_msc_cbw.bCBWCBLength = 6;
00766 memset(uhi_msc_cbw.pCommand, 0, sizeof(uhi_msc_cbw.pCommand));
00767 uhi_msc_cbw.pCommand[0] = SBC_MODE_SENSE_6;
00768 uhi_msc_cbw.pCommand[2] = SBC_PAGE_INFORMATIONAL_EXCEPTIONS_CONTROL;
00769 uhi_msc_cbw.pCommand[4] = sizeof(uhi_msc_sense6);
00770 uhi_msc_scsi(uhi_msc_scsi_mode_sense6_done,
00771 (uint8_t *) & uhi_msc_sense6);
00772 }
00773
00774
00775
00776
00777
00778
00779 static void uhi_msc_scsi_mode_sense6_done(bool b_cbw_succes)
00780 {
00781 if ((!b_cbw_succes) || (uhi_msc_csw.bCSWStatus != MSD_CSW_COMMAND_PASSED)
00782 || (uhi_msc_csw.dCSWDataResidue < 4)) {
00783
00784
00785 uhi_msc_lun_sel->b_write_protected = false;
00786 uhi_msc_scsi_callback(true);
00787 return;
00788 }
00789
00790 uhi_msc_lun_sel->b_write_protected =
00791 (uhi_msc_sense6.header.isWP);
00792 uhi_msc_scsi_callback(true);
00793 }
00794
00795
00796
00797
00798
00799
00800 static void uhi_msc_scsi_read_10_done(bool b_cbw_succes)
00801 {
00802 if ((!b_cbw_succes) || (uhi_msc_csw.bCSWStatus != MSD_CSW_COMMAND_PASSED)
00803 || uhi_msc_csw.dCSWDataResidue) {
00804
00805 uhi_msc_lun_sel->status = LUN_FAIL;
00806 uhi_msc_scsi_callback(false);
00807 return;
00808 }
00809 uhi_msc_scsi_callback(true);
00810 }
00811
00812
00813
00814
00815
00816
00817 static void uhi_msc_scsi_write_10_done(bool b_cbw_succes)
00818 {
00819 if ((!b_cbw_succes) || (uhi_msc_csw.bCSWStatus != MSD_CSW_COMMAND_PASSED)
00820 || uhi_msc_csw.dCSWDataResidue) {
00821
00822 uhi_msc_lun_sel->status = LUN_FAIL;
00823 uhi_msc_scsi_callback(false);
00824 return;
00825 }
00826 uhi_msc_scsi_callback(true);
00827 }
00828
00829
00830
00831
00832
00833
00834
00835 static void uhi_msc_scsi_request_sense(uhi_msc_scsi_sense_callback_t callback)
00836 {
00837 uhi_msc_scsi_sense_callback = callback;
00838
00839
00840 uhi_msc_cbw.dCBWDataTransferLength = sizeof(SBCRequestSenseData);
00841 uhi_msc_cbw.bmCBWFlags = MSD_CBW_DEVICE_TO_HOST;
00842 uhi_msc_cbw.bCBWCBLength = 6;
00843 memset(uhi_msc_cbw.pCommand, 0, sizeof(uhi_msc_cbw.pCommand));
00844 uhi_msc_cbw.pCommand[0] = SBC_REQUEST_SENSE;
00845 uhi_msc_cbw.pCommand[4] = sizeof(SBCRequestSenseData);
00846
00847 uhi_msc_scsi(uhi_msc_scsi_request_sense_done, (uint8_t*)&uhi_msc_sense);
00848 }
00849
00850
00851
00852
00853
00854
00855 static void uhi_msc_scsi_request_sense_done(bool b_cbw_succes)
00856 {
00857 if ((!b_cbw_succes) || uhi_msc_csw.dCSWDataResidue) {
00858 uhi_msc_scsi_callback(false);
00859 return;
00860 }
00861
00862 uhi_msc_scsi_sense_callback();
00863 }
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 static void uhi_msc_scsi(uhi_msc_scsi_callback_t callback, uint8_t *payload)
00879 {
00880
00881 uhi_msc_scsi_sub_callback = callback;
00882 uhi_msc_data = payload;
00883
00884
00885 uhi_msc_cbw.dCBWTag++;
00886 uhi_msc_cbw.dCBWDataTransferLength =
00887 (uhi_msc_cbw.dCBWDataTransferLength);
00888
00889
00890
00891
00892
00893
00894
00895
00896 uhi_msc_transfer(uhi_msc_dev_sel->ep_out, (uint8_t *) &uhi_msc_cbw,
00897 sizeof(uhi_msc_cbw), uhi_msc_cbw_sent);
00898 }
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 static void uhi_msc_cbw_sent(
00909 USBHS_Add_t add,
00910 USBHS_Ep_t ep,
00911 USBH_XfrStatus_t status,
00912 uint32_t nb_transfered)
00913 {
00914 USBHS_Ep_t endp;
00915 UNUSED(add);
00916 UNUSED(ep);
00917 UNUSED(nb_transfered);
00918
00919
00920 if (status != UHD_TRANS_NOERROR) {
00921 if (status == UHD_TRANS_STALL) {
00922 uhi_msc_reset_endpoint(uhi_msc_dev_sel->ep_out,
00923 uhi_msc_cbw_rst_stall);
00924 return;
00925 }
00926 uhi_msc_scsi_sub_callback(false);
00927 return;
00928 }
00929 assert(nb_transfered == sizeof(uhi_msc_cbw));
00930 uhi_msc_cbw.dCBWDataTransferLength =
00931 (uhi_msc_cbw.dCBWDataTransferLength);
00932
00933
00934 if (!uhi_msc_cbw.dCBWDataTransferLength) {
00935
00936 uhi_msc_csw_wait();
00937 return;
00938 }
00939
00940 if (uhi_msc_cbw.bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) {
00941 endp = uhi_msc_dev_sel->ep_in;
00942 } else {
00943 endp = uhi_msc_dev_sel->ep_out;
00944 }
00945 uhi_msc_transfer(endp, uhi_msc_data, uhi_msc_cbw.dCBWDataTransferLength,
00946 uhi_msc_data_transfered);
00947 }
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 static void uhi_msc_data_transfered(
00958 USBHS_Add_t add,
00959 USBHS_Ep_t ep,
00960 USBH_XfrStatus_t status,
00961 uint32_t nb_transfered)
00962 {
00963 USBHS_Ep_t endp;
00964 UNUSED(add);
00965 UNUSED(ep);
00966 UNUSED(nb_transfered);
00967
00968 if (status != UHD_TRANS_NOERROR) {
00969 if (status == UHD_TRANS_STALL) {
00970 if (uhi_msc_cbw.bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) {
00971 endp = uhi_msc_dev_sel->ep_in;
00972 } else {
00973 endp = uhi_msc_dev_sel->ep_out;
00974 }
00975 uhi_msc_reset_endpoint(endp, uhi_msc_data_csw_rst_stall);
00976 return;
00977 }
00978 uhi_msc_scsi_sub_callback(false);
00979 return;
00980 }
00981
00982
00983
00984 uhi_msc_csw_wait();
00985 return;
00986 }
00987
00988
00989
00990
00991 static void uhi_msc_csw_wait(void)
00992 {
00993
00994 uhi_msc_transfer(uhi_msc_dev_sel->ep_in, (uint8_t *) & uhi_msc_csw,
00995 sizeof(uhi_msc_csw), uhi_msc_csw_received);
00996 }
00997
00998
00999
01000
01001
01002
01003
01004
01005 static void uhi_msc_csw_received(
01006 USBHS_Add_t add,
01007 USBHS_Ep_t ep,
01008 USBH_XfrStatus_t status,
01009 uint32_t nb_transfered)
01010 {
01011 UNUSED(add);
01012 UNUSED(ep);
01013 if (status != UHD_TRANS_NOERROR) {
01014 if (status == UHD_TRANS_STALL) {
01015 uhi_msc_reset_endpoint(uhi_msc_dev_sel->ep_in,
01016 uhi_msc_data_csw_rst_stall);
01017 return;
01018 }
01019 uhi_msc_scsi_sub_callback(false);
01020 return;
01021 }
01022 if ((nb_transfered != sizeof(uhi_msc_csw))
01023 || (uhi_msc_csw.dCSWTag != uhi_msc_cbw.dCBWTag)
01024 || (uhi_msc_csw.dCSWSignature != MSD_CSW_SIGNATURE)) {
01025
01026 uhi_msc_scsi_sub_callback(false);
01027 return;
01028 }
01029
01030
01031 uhi_msc_csw.dCSWDataResidue = uhi_msc_csw.dCSWDataResidue;
01032 uhi_msc_scsi_sub_callback(true);
01033 }
01034
01035
01036
01037
01038
01039
01040
01041
01042 static void uhi_msc_cbw_rst_stall(
01043 USBHS_Add_t add,
01044 USBH_XfrStatus_t status,
01045 uint16_t payload_trans)
01046 {
01047 UNUSED(add);
01048 UNUSED(status);
01049 UNUSED(payload_trans);
01050 uhi_msc_scsi_sub_callback(false);
01051 }
01052
01053
01054
01055
01056
01057
01058
01059
01060 static void uhi_msc_data_csw_rst_stall(
01061 USBHS_Add_t add,
01062 USBH_XfrStatus_t status,
01063 uint16_t payload_trans)
01064 {
01065 UNUSED(add);
01066 UNUSED(payload_trans);
01067 if (status != UHD_TRANS_NOERROR) {
01068 uhi_msc_scsi_sub_callback(false);
01069 return;
01070 }
01071
01072 uhi_msc_csw_wait();
01073 }
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 static void uhi_msc_transfer(USBHS_Ep_t endp,
01085 uint8_t* payload,
01086 uint16_t payload_size,
01087 uhd_callback_trans_t callback_end)
01088 {
01089 if (!USBH_HAL_RunEndpoint(uhi_msc_dev_sel->dev->address,
01090 endp, false, payload, payload_size,
01091 UHI_MSC_SCSI_TIMEOUT, callback_end)) {
01092 uhi_msc_scsi_sub_callback(false);
01093 }
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103 static void uhi_msc_reset_endpoint(
01104 USBHS_Ep_t endp, uhd_callback_setup_end_t callback )
01105 {
01106
01107 USBGenericRequest req;
01108 req.bmRequestType = USB_REQ_RECIP_ENDPOINT
01109 | USB_REQ_TYPE_STANDARD | USB_REQ_DIR_OUT;
01110 req.bRequest = USB_REQ_CLEAR_FEATURE;
01111 req.wValue = USB_EP_FEATURE_HALT;
01112 req.wIndex = endp;
01113 req.wLength = 0;
01114 if (!USBH_HAL_SetupReq(uhi_msc_dev_sel->dev->address,
01115 &req, NULL, 0, NULL, callback)) {
01116 callback(uhi_msc_dev_sel->dev->address,UHD_TRANS_DISCONNECT,0);
01117 }
01118 }
01119
01120
01121
01122