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