USB Host Shield 2.0
Loading...
Searching...
No Matches
masstorage.cpp
Go to the documentation of this file.
1/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2
3This program is free software; you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by
5the Free Software Foundation; either version 2 of the License, or
6(at your option) any later version.
7
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11GNU General Public License for more details.
12
13You should have received a copy of the GNU General Public License
14along with this program; if not, write to the Free Software
15Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
17Contact information
18-------------------
19
20Circuits At Home, LTD
21Web : http://www.circuitsathome.com
22e-mail : support@circuitsathome.com
23 */
24
25#include "masstorage.h"
26
30
32
33// Interface code
34
36
44 if(LUNOk[lun])
45 return CurrentCapacity[lun];
46 return 0LU;
47}
48
60
68 return LUNOk[lun];
69}
70
80
91 // promote buf_size to 32bits.
93 //SetCurLUN(cdb->LUN);
94 return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
95}
96
107 // promote buf_size to 32bits.
109 //SetCurLUN(cdb->LUN);
110 return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
111}
112
122 Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
123 Notify(PSTR("---------\r\n"), 0x80);
124
127}
128
138 Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
139 Notify(PSTR("-----------------\r\n"), 0x80);
140
142 if(bAddress) {
145 } else {
146 SetCurLUN(lun);
147 }
148 return rcode;
149}
150
162 if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
163 Notify(PSTR("\r\nRead LUN:\t"), 0x80);
165 Notify(PSTR("\r\nLBA:\t\t"), 0x90);
167 Notify(PSTR("\r\nblocks:\t\t"), 0x90);
169 Notify(PSTR("\r\nblock size:\t"), 0x90);
171 Notify(PSTR("\r\n---------\r\n"), 0x80);
173
174again:
176
177 if(er == MASS_ERR_STALL) {
178 MediaCTL(lun, 1);
179 delay(150);
180 if(!TestUnitReady(lun)) goto again;
181 }
182 return er;
183}
184
196 if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
198 Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
200 Notify(PSTR("\r\nLBA:\t\t"), 0x90);
202 Notify(PSTR("\r\nblocks:\t\t"), 0x90);
204 Notify(PSTR("\r\nblock size:\t"), 0x90);
206 Notify(PSTR("\r\n---------\r\n"), 0x80);
208
209again:
211
212 if(er == MASS_ERR_WRITE_STALL) {
213 MediaCTL(lun, 1);
214 delay(150);
215 if(!TestUnitReady(lun)) goto again;
216 }
217 return er;
218}
219
220// End of user functions, the remaining code below is driver internals.
221// Only developer serviceable parts below!
222
224
225// Main driver code
226
228
230pUsb(p),
231bAddress(0),
232bIface(0),
233bNumEP(1),
234qNextPollTime(0),
235bPollEnable(false),
236//dCBWTag(0),
237bLastUsbError(0) {
238 ClearAllEP();
239 dCBWTag = 0;
240 if(pUsb)
242}
243
259
261
263 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
265 UsbDevice *p = NULL;
267 USBTRACE("MS ConfigureDevice\r\n");
268 ClearAllEP();
269 AddressPool &addrPool = pUsb->GetAddressPool();
270
271
272 if(bAddress)
274
275 // <TECHNICAL>
276 // Get pointer to pseudo device with address 0 assigned
277 p = addrPool.GetUsbDevicePtr(0);
278 if(!p) {
280 }
281
282 if(!p->epinfo) {
283 USBTRACE("epinfo\r\n");
285 }
286
287 // Save old pointer to EP_RECORD of address 0
288 oldep_ptr = p->epinfo;
289
290 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
291 p->epinfo = epInfo;
292
293 p->lowspeed = lowspeed;
294 // Get device descriptor
296
297 // Restore p->epinfo
298 p->epinfo = oldep_ptr;
299
300 if(rcode) {
301 goto FailGetDevDescr;
302 }
303 // Allocate new address according to device class
304 bAddress = addrPool.AllocAddress(parent, false, port);
305
306 if(!bAddress)
308
309 // Extract Max Packet Size from the device descriptor
310 epInfo[0].maxPktSize = udd->bMaxPacketSize0;
311 // Steal and abuse from epInfo structure to save on memory.
312 epInfo[1].epAddr = udd->bNumConfigurations;
313 // </TECHNICAL>
315
317#ifdef DEBUG_USB_HOST
319#endif
321
322 Release();
323 return rcode;
324};
325
335 uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
336 epInfo[1].epAddr = 0;
337 USBTRACE("MS Init\r\n");
338
339 AddressPool &addrPool = pUsb->GetAddressPool();
340 UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
341
342 if(!p)
344
345 // Assign new address to the device
346 delay(2000);
347 rcode = pUsb->setAddr(0, 0, bAddress);
348
349 if(rcode) {
350 p->lowspeed = false;
351 addrPool.FreeAddress(bAddress);
352 bAddress = 0;
353 USBTRACE2("setAddr:", rcode);
354 return rcode;
355 }
356
357 USBTRACE2("Addr:", bAddress);
358
359 p->lowspeed = false;
360
361 p = addrPool.GetUsbDevicePtr(bAddress);
362
363 if(!p)
365
366 p->lowspeed = lowspeed;
367
368 // Assign epInfo to epinfo pointer
370
371 if(rcode)
373
374 USBTRACE2("NC:", num_of_conf);
375
376 for(uint8_t i = 0; i < num_of_conf; i++) {
383
385
386 if(rcode)
387 goto FailGetConfDescr;
388
389 if(bNumEP > 1)
390 break;
391 }
392
393 if(bNumEP < 3)
395
396 // Assign epInfo to epinfo pointer
398
399 USBTRACE2("Conf:", bConfNum);
400
401 // Set Configuration Value
403
404 if(rcode)
405 goto FailSetConfDescr;
406
407 //Linux does a 1sec delay after this.
408 delay(1000);
409
410 rcode = GetMaxLUN(&bMaxLUN);
411 if(rcode)
412 goto FailGetMaxLUN;
413
416
417 delay(1000); // Delay a bit for slow firmware.
418
419 for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
421 rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
422 if(rcode) {
423 ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
424 } else {
425#if 0
426 printf("LUN %i `", lun);
427 uint8_t *buf = response.VendorID;
428 for(int i = 0; i < 28; i++) printf("%c", buf[i]);
429 printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
430 printf("Device type %2.2X ", response.DeviceType);
431 printf("RMB %1.1X ", response.Removable);
432 printf("SSCS %1.1X ", response.SCCS);
433 uint8_t sv = response.Version;
434 printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
435 switch(sv) {
436 case 0:
437 printf("No specific");
438 break;
439 case 1:
440 printf("ANSI X3.131-1986 (ANSI 1)");
441 break;
442 case 2:
443 printf("ANSI X3.131-1994 (ANSI 2)");
444 break;
445 case 3:
446 printf("ANSI INCITS 301-1997 (SPC)");
447 break;
448 case 4:
449 printf("ANSI INCITS 351-2001 (SPC-2)");
450 break;
451 case 5:
452 printf("ANSI INCITS 408-2005 (SPC-4)");
453 break;
454 case 6:
455 printf("T10/1731-D (SPC-4)");
456 break;
457 default:
458 printf("unknown");
459 }
460 printf(" standards.\r\n");
461#endif
462 uint8_t tries = 0xf0;
463 while((rcode = TestUnitReady(lun))) {
464 if(rcode == 0x08) break; // break on no media, this is OK to do.
465 // try to lock media and spin up
466 if(tries < 14) {
467 LockMedia(lun, 1);
468 MediaCTL(lun, 1); // I actually have a USB stick that needs this!
469 } else delay(2 * (tries + 1));
470 tries++;
471 if(!tries) break;
472 }
473 if(!rcode) {
474 delay(1000);
475 LUNOk[lun] = CheckLUN(lun);
476 if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
477 }
478 }
479 }
480
481
482 CheckMedia();
483
484 rcode = OnInit();
485
486 if(rcode)
487 goto FailOnInit;
488
489#ifdef DEBUG_USB_HOST
490 USBTRACE("MS configured\r\n\r\n");
491#endif
492
493 bPollEnable = true;
494
495 //USBTRACE("Poll enabled\r\n");
496 return 0;
497
499#ifdef DEBUG_USB_HOST
501 goto Fail;
502#endif
503
505#ifdef DEBUG_USB_HOST
506 USBTRACE("OnInit:");
507 goto Fail;
508#endif
509
511#ifdef DEBUG_USB_HOST
512 USBTRACE("GetMaxLUN:");
513 goto Fail;
514#endif
515
516 //#ifdef DEBUG_USB_HOST
517 //FailInvalidSectorSize:
518 // USBTRACE("Sector Size is NOT VALID: ");
519 // goto Fail;
520 //#endif
521
523#ifdef DEBUG_USB_HOST
525 goto Fail;
526#endif
527
529#ifdef DEBUG_USB_HOST
531#endif
532
533#ifdef DEBUG_USB_HOST
534Fail:
536#endif
537 Release();
538 return rcode;
539}
540
551 ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
552 ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
553 ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
554
555 bConfNum = conf;
556
557 uint8_t index;
558
559#if 1
560 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) {
561 index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
562 // Fill in the endpoint info structure
563 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
564 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
565 epInfo[index].bmSndToggle = 0;
566 epInfo[index].bmRcvToggle = 0;
567
568 bNumEP++;
569
571
572 }
573#else
574 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80)
575 index = epInterruptInIndex;
576 else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK)
577 index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
578 else
579 return;
580
581 // Fill in the endpoint info structure
582 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
583 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
584 epInfo[index].bmSndToggle = 0;
585 epInfo[index].bmRcvToggle = 0;
586
587 bNumEP++;
588
590#endif
591}
592
599 ClearAllEP();
601 return 0;
602}
603
610bool BulkOnly::CheckLUN(uint8_t lun) {
613 for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
614
615 rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
616 if(rcode) {
617 //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
618 return false;
619 }
620 ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
621 for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
622 D_PrintHex<uint8_t > (capacity.data[i], 0x80);
623 Notify(PSTR("\r\n\r\n"), 0x80);
624 // Only 512/1024/2048/4096 are valid values!
625 uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
626 if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
627 return false;
628 }
629 // Store capacity information.
630 CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
631
632 CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
633 if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) {
634 // Buggy firmware will report 0xffffffff or 0 for no media
636 ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
637 return false;
638 }
639 delay(20);
640 Page3F(lun);
641 if(!TestUnitReady(lun)) return true;
642 return false;
643}
644
650void BulkOnly::CheckMedia() {
651 for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
652 if(TestUnitReady(lun)) {
653 LUNOk[lun] = false;
654 continue;
655 }
656 if(!LUNOk[lun])
657 LUNOk[lun] = CheckLUN(lun);
658 }
659#if 0
660 printf("}}}}}}}}}}}}}}}}STATUS ");
661 for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
662 if(LUNOk[lun])
663 printf("#");
664 else printf(".");
665 }
666 printf("\r\n");
667#endif
668 qNextPollTime = (uint32_t)millis() + 2000;
669}
670
677 //uint8_t rcode = 0;
678
679 if(!bPollEnable)
680 return 0;
681
682 if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) {
683 CheckMedia();
684 }
685 //rcode = 0;
686
687 return 0;
688}
689
691
692
693// SCSI code
694
695
697
704uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
706
707 if(ret == hrSTALL)
708 *plun = 0;
709
710 return 0;
711}
712
721uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
722 Notify(PSTR("\r\nInquiry\r\n"), 0x80);
723 Notify(PSTR("---------\r\n"), 0x80);
724
727
728 return rc;
729}
730
737uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
738 //SetCurLUN(lun);
739 if(!bAddress)
741
742 Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
743 Notify(PSTR("-----------------\r\n"), 0x80);
744
747
748}
749
762 Notify(PSTR("\r\rModeSense\r\n"), 0x80);
763 Notify(PSTR("------------\r\n"), 0x80);
764
765 CDB6_t cdb = CDB6_t(SCSI_CMD_MODE_SENSE_6, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0);
767}
768
777uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
778 Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
779 Notify(PSTR("---------------\r\n"), 0x80);
780
783}
784
793uint8_t BulkOnly::Page3F(uint8_t lun) {
794 uint8_t buf[192];
795 for(int i = 0; i < 192; i++) {
796 buf[i] = 0x00;
797 }
798 WriteOk[lun] = true;
799 uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
800 if(!rc) {
801 WriteOk[lun] = ((buf[2] & 0x80) == 0);
802 Notify(PSTR("Mode Sense: "), 0x80);
803 for(int i = 0; i < 4; i++) {
804 D_PrintHex<uint8_t > (buf[i], 0x80);
805 Notify(PSTR(" "), 0x80);
806 }
807 Notify(PSTR("\r\n"), 0x80);
808 }
809 return rc;
810}
811
820uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
821 Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
822 Notify(PSTR("----------------\r\n"), 0x80);
823
826 //SetCurLUN(lun);
827 return Transaction(&cbw, size, buf);
828}
829
830
832
833
834// USB code
835
836
838
845uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
846 if(index == 0)
847 return 0;
848
849 uint8_t ret = 0;
850
852 delay(6);
853
854 if(ret) {
855 ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
856 ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
857 return ret;
858 }
859 epInfo[index].bmSndToggle = 0;
860 epInfo[index].bmRcvToggle = 0;
861 return 0;
862}
863
868void BulkOnly::Reset() {
869 while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
870}
871
877uint8_t BulkOnly::ResetRecovery() {
878 Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
879 Notify(PSTR("-----------------\r\n"), 0x80);
880
881 delay(6);
882 Reset();
883 delay(6);
884 ClearEpHalt(epDataInIndex);
885 delay(6);
886 bLastUsbError = ClearEpHalt(epDataOutIndex);
887 delay(6);
888 return bLastUsbError;
889}
890
896void BulkOnly::ClearAllEP() {
897 for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
898 epInfo[i].epAddr = 0;
899 epInfo[i].maxPktSize = (i) ? 0 : 8;
900 epInfo[i].bmSndToggle = 0;
901 epInfo[i].bmRcvToggle = 0;
903 }
904
905 for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
906 LUNOk[i] = false;
907 WriteOk[i] = false;
908 CurrentCapacity[i] = 0lu;
909 CurrentSectorSize[i] = 0;
910 }
911
912 bIface = 0;
913 bNumEP = 1;
914 bAddress = 0;
915 qNextPollTime = 0;
916 bPollEnable = false;
917 bLastUsbError = 0;
918 bMaxLUN = 0;
919 bTheLUN = 0;
920}
921
929bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
930 if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
931 Notify(PSTR("CSW:Sig error\r\n"), 0x80);
932 return false;
933 }
934 if(pcsw->dCSWTag != pcbw->dCBWTag) {
935 Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
936 return false;
937 }
938 return true;
939}
940
948uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
949 uint8_t count = 3;
950
952 //if (error)
953 //ClearEpHalt(index);
954 while(error && count) {
955 if(error != hrSUCCESS) {
956 ErrorMessage<uint8_t > (PSTR("USB Error"), error);
957 ErrorMessage<uint8_t > (PSTR("Index"), index);
958 }
959 switch(error) {
960 // case hrWRONGPID:
961 case hrSUCCESS:
962 return MASS_ERR_SUCCESS;
963 case hrBUSY:
964 // SIE is busy, just hang out and try again.
965 return MASS_ERR_UNIT_BUSY;
966 case hrTIMEOUT:
968 case hrSTALL:
969 if(index == 0)
970 return MASS_ERR_STALL;
971 ClearEpHalt(index);
972 if(index != epDataInIndex)
974 return MASS_ERR_STALL;
975
976 case hrNAK:
977 if(index == 0)
978 return MASS_ERR_UNIT_BUSY;
979 return MASS_ERR_UNIT_BUSY;
980
981 case hrTOGERR:
982 // Handle a very super rare corner case, where toggles become de-synched.
983 // I have only ran into one device that has this firmware bug, and this is
984 // the only clean way to get back into sync with the buggy device firmware.
985 // --AJK
986 if(bAddress && bConfNum) {
988
989 if(error)
990 break;
991 }
992 return MASS_ERR_SUCCESS;
993 default:
994 ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
996 }
997 count--;
998 } // while
999
1001}
1002
1003#if MS_WANT_PARSER
1004
1005uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
1006 return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
1007}
1008#endif
1009
1019uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
1021 , uint8_t flags
1022#endif
1023 ) {
1024
1025#if MS_WANT_PARSER
1026 uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
1027 printf("Transfersize %i\r\n", bytes);
1028 delay(1000);
1029
1031#else
1033#endif
1034 bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
1035 uint8_t ret = 0;
1037 CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
1038 SetCurLUN(pcbw->bmCBWLUN);
1039 ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
1040
1042
1043 ret = HandleUsbError(usberr, epDataOutIndex);
1044 //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
1045 if(ret) {
1046 ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
1047 } else {
1048 if(bytes) {
1049 if(!write) {
1050#if MS_WANT_PARSER
1051 if(callback) {
1054 if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
1055 } else {
1056#endif
1058#if MS_WANT_PARSER
1059
1060 }
1061#endif
1062 ret = HandleUsbError(usberr, epDataInIndex);
1063 } else {
1065 ret = HandleUsbError(usberr, epDataOutIndex);
1066 }
1067 if(ret) {
1068 ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
1069 }
1070 }
1071 }
1072
1073 {
1074 bytes = sizeof (CommandStatusWrapper);
1075 int tries = 2;
1076 while(tries--) {
1078 if(!usberr) break;
1079 ClearEpHalt(epDataInIndex);
1080 if(tries) ResetRecovery();
1081 }
1082 if(!ret) {
1083 Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
1084 Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
1085 } else {
1086 // Throw away csw, IT IS NOT OF ANY USE.
1087 ResetRecovery();
1088 return ret;
1089 }
1090 ret = HandleUsbError(usberr, epDataInIndex);
1091 if(ret) {
1092 ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
1093 }
1094 if(usberr == hrSUCCESS) {
1095 if(IsValidCSW(&csw, pcbw)) {
1096 //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
1097 //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
1098 //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
1099 Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
1100 return csw.bCSWStatus;
1101 } else {
1102 // NOTE! Sometimes this is caused by the reported residue being wrong.
1103 // Get a different device. It isn't compliant, and should have never passed Q&A.
1104 // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
1105 // Other devices that exhibit this behavior exist in the wild too.
1106 // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk
1107 Notify(PSTR("Invalid CSW\r\n"), 0x80);
1108 ResetRecovery();
1109 //return MASS_ERR_SUCCESS;
1110 return MASS_ERR_INVALID_CSW;
1111 }
1112 }
1113 }
1114 return ret;
1115}
1116
1123uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
1124 if(lun > bMaxLUN)
1125 return MASS_ERR_INVALID_LUN;
1126 bTheLUN = lun;
1127 return MASS_ERR_SUCCESS;
1128};
1129
1136uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
1137 uint8_t ret = 0;
1138
1139 switch(status) {
1140 case 0: return MASS_ERR_SUCCESS;
1141
1142 case 2:
1143 ErrorMessage<uint8_t > (PSTR("Phase Error"), status);
1145 ResetRecovery();
1147
1148 case 1:
1149 ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
1152
1153 ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
1154
1155 if(ret) {
1157 }
1158 ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
1159 if(rsp.bResponseCode & 0x80) {
1160 Notify(PSTR("Information field: "), 0x80);
1161 for(int i = 0; i < 4; i++) {
1162 D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
1163 Notify(PSTR(" "), 0x80);
1164 }
1165 Notify(PSTR("\r\n"), 0x80);
1166 }
1167 ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
1168 ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
1169 ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
1170 // warning, this is not testing ASQ, only SK and ASC.
1171 switch(rsp.bmSenseKey) {
1173 switch(rsp.bAdditionalSenseCode) {
1176 default:
1178 }
1179 case SCSI_S_NOT_READY:
1180 switch(rsp.bAdditionalSenseCode) {
1182 return MASS_ERR_NO_MEDIA;
1183 default:
1185 }
1187 switch(rsp.bAdditionalSenseCode) {
1189 return MASS_ERR_BAD_LBA;
1190 default:
1192 }
1193 default:
1195 }
1196
1197 // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
1198 // case 0x05/0x14: we stalled out
1199 // case 0x15/0x16: we naked out.
1200 default:
1201 ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
1203 return status;
1204 } // switch
1205}
1206
1207
1209
1210
1211// Debugging code
1212
1213
1215
1221 Notify(PSTR("Endpoint descriptor:"), 0x80);
1222 Notify(PSTR("\r\nLength:\t\t"), 0x80);
1223 D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
1224 Notify(PSTR("\r\nType:\t\t"), 0x80);
1225 D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
1226 Notify(PSTR("\r\nAddress:\t"), 0x80);
1227 D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
1228 Notify(PSTR("\r\nAttributes:\t"), 0x80);
1229 D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
1230 Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
1231 D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
1232 Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
1233 D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
1234 Notify(PSTR("\r\n"), 0x80);
1235}
1236
1237
1239
1240
1241// misc/to kill/to-do
1242
1243
1245
1246/* We won't be needing this... */
1248#if MS_WANT_PARSER
1249 if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
1250 Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
1251 Notify(PSTR("---------\r\n"), 0x80);
1252
1254
1255 cbw.dCBWSignature = MASS_CBW_SIGNATURE;
1256 cbw.dCBWTag = ++dCBWTag;
1257 cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
1258 cbw.bmCBWFlags = MASS_CMD_DIR_IN,
1259 cbw.bmCBWLUN = lun;
1260 cbw.bmCBWCBLength = 10;
1261
1262 cbw.CBWCB[0] = SCSI_CMD_READ_10;
1263 cbw.CBWCB[8] = blocks;
1264 cbw.CBWCB[2] = ((addr >> 24) & 0xff);
1265 cbw.CBWCB[3] = ((addr >> 16) & 0xff);
1266 cbw.CBWCB[4] = ((addr >> 8) & 0xff);
1267 cbw.CBWCB[5] = (addr & 0xff);
1268
1269 return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
1270#else
1272#endif
1273}
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition UsbCore.h:103
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition UsbCore.h:108
#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET
Definition UsbCore.h:111
#define USB_ERROR_FailGetDevDescr
Definition UsbCore.h:112
#define USB_CLASS_MASS_STORAGE
Definition UsbCore.h:86
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition UsbCore.h:100
#define USB_ERROR_EPINFO_IS_NULL
Definition UsbCore.h:106
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition UsbCore.h:105
#define USB_NAK_DEFAULT
Definition address.h:35
virtual void FreeAddress(uint8_t addr)=0
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
static const uint8_t epInterruptInIndex
Definition masstorage.h:473
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
uint8_t bLastUsbError
Definition masstorage.h:487
bool bPollEnable
Definition masstorage.h:481
uint8_t bTheLUN
Definition masstorage.h:489
uint32_t qNextPollTime
Definition masstorage.h:480
uint8_t MediaCTL(uint8_t lun, uint8_t ctl)
virtual uint8_t OnInit()
Definition masstorage.h:499
uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf)
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf)
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
uint8_t Poll()
BulkOnly(USB *p)
uint32_t GetCapacity(uint8_t lun)
USB * pUsb
Definition masstorage.h:475
uint8_t bMaxLUN
Definition masstorage.h:488
uint8_t bNumEP
Definition masstorage.h:479
uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]
Definition masstorage.h:490
uint32_t dCBWTag
Definition masstorage.h:485
bool WriteProtected(uint8_t lun)
uint8_t Release()
static const uint8_t epDataOutIndex
Definition masstorage.h:472
uint8_t bAddress
Definition masstorage.h:476
static const uint8_t epDataInIndex
Definition masstorage.h:471
bool LUNOk[MASS_MAX_SUPPORTED_LUN]
Definition masstorage.h:492
uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]
Definition masstorage.h:491
bool LUNIsGood(uint8_t lun)
uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed)
uint8_t bConfNum
Definition masstorage.h:477
uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir)
uint8_t bIface
Definition masstorage.h:478
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)
uint16_t GetSectorSize(uint8_t lun)
uint8_t LockMedia(uint8_t lun, uint8_t lock)
EpInfo epInfo[MASS_MAX_ENDPOINTS]
Definition masstorage.h:483
uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir)
bool WriteOk[MASS_MAX_SUPPORTED_LUN]
Definition masstorage.h:493
Definition UsbCore.h:220
AddressPool & GetAddressPool()
Definition UsbCore.h:236
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition Usb.cpp:801
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition Usb.cpp:850
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition Usb.cpp:841
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition UsbCore.h:240
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition Usb.cpp:806
uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t *dataptr, USBReadParser *p)
Definition Usb.cpp:126
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition Usb.cpp:64
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval=0)
Definition Usb.cpp:209
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
Definition Usb.cpp:303
#define CP_MASK_COMPARE_PROTOCOL
#define CP_MASK_COMPARE_SUBCLASS
#define CP_MASK_COMPARE_CLASS
#define BMAKE32(__usc3__, __usc2__, __usc1__, __usc0__)
Definition macros.h:75
#define USBTRACE2(s, r)
Definition macros.h:84
#define USBTRACE(s)
Definition macros.h:82
#define MASS_CMD_DIR_IN
Definition masstorage.h:67
#define MASS_ERR_UNIT_NOT_READY
Definition masstorage.h:160
#define MASS_ERR_STALL
Definition masstorage.h:162
#define MASS_REQ_BOMSR
Definition masstorage.h:61
#define MASS_PROTO_BBB
Definition masstorage.h:53
#define SCSI_CMD_START_STOP_UNIT
Definition masstorage.h:85
#define MASS_ERR_WRITE_STALL
Definition masstorage.h:171
#define SCSI_CMD_READ_CAPACITY_10
Definition masstorage.h:89
#define MASS_ERR_GENERAL_SCSI_ERROR
Definition masstorage.h:176
#define SCSI_S_ILLEGAL_REQUEST
Definition masstorage.h:151
#define MASS_REQ_GET_MAX_LUN
Definition masstorage.h:60
#define MASS_CBW_SIGNATURE
Definition masstorage.h:63
#define MASS_ERR_SUCCESS
Definition masstorage.h:158
#define MASS_ERR_NOT_IMPLEMENTED
Definition masstorage.h:175
#define MS_WANT_PARSER
Definition masstorage.h:30
#define MASS_ERR_INVALID_LUN
Definition masstorage.h:170
CDB6 CDB6_t
Definition masstorage.h:227
#define MASS_ERR_BAD_LBA
Definition masstorage.h:166
#define MASS_TRANS_FLG_CALLBACK
Definition masstorage.h:180
#define SCSI_S_NOT_READY
Definition masstorage.h:149
#define MASS_ERR_GENERAL_USB_ERROR
Definition masstorage.h:177
#define MASS_ERR_MEDIA_CHANGED
Definition masstorage.h:167
#define MASS_ERR_DEVICE_DISCONNECTED
Definition masstorage.h:168
#define MASS_ERR_INVALID_CSW
Definition masstorage.h:164
#define bmREQ_MASSOUT
Definition masstorage.h:35
#define SCSI_ASC_MEDIA_CHANGED
Definition masstorage.h:154
#define SCSI_CMD_TEST_UNIT_READY
Definition masstorage.h:77
#define MASS_SUBCLASS_SCSI
Definition masstorage.h:45
#define MASS_MAX_ENDPOINTS
Definition masstorage.h:184
#define SCSI_CMD_MODE_SENSE_6
Definition masstorage.h:84
#define MASS_ERR_UNIT_BUSY
Definition masstorage.h:161
#define SCSI_ASC_MEDIUM_NOT_PRESENT
Definition masstorage.h:155
#define SCSI_CMD_INQUIRY
Definition masstorage.h:82
#define MASS_ERR_CMD_NOT_SUPPORTED
Definition masstorage.h:163
#define SCSI_CMD_PREVENT_REMOVAL
Definition masstorage.h:86
#define SCSI_ASC_LBA_OUT_OF_RANGE
Definition masstorage.h:153
#define MASS_ERR_WRITE_PROTECTED
Definition masstorage.h:174
#define SCSI_CMD_REQUEST_SENSE
Definition masstorage.h:78
#define SCSI_CMD_WRITE_10
Definition masstorage.h:91
#define SCSI_CMD_READ_10
Definition masstorage.h:90
#define MASS_CMD_DIR_OUT
Definition masstorage.h:66
#define SCSI_S_UNIT_ATTENTION
Definition masstorage.h:152
#define MASS_ERR_NO_MEDIA
Definition masstorage.h:165
#define MASS_CSW_SIGNATURE
Definition masstorage.h:64
CDB10 CDB10_t
Definition masstorage.h:261
#define bmREQ_MASSIN
Definition masstorage.h:36
#define hrTOGERR
Definition max3421e.h:220
#define hrSTALL
Definition max3421e.h:219
#define hrJERR
Definition max3421e.h:227
#define hrNAK
Definition max3421e.h:218
#define hrTIMEOUT
Definition max3421e.h:228
#define hrSUCCESS
Definition max3421e.h:214
#define hrBUSY
Definition max3421e.h:215
#define NotifyFailSetConfDescr(...)
Definition message.h:60
#define NotifyFail(...)
Definition message.h:62
#define Notify(...)
Definition message.h:51
#define NotifyFailGetConfDescr(...)
Definition message.h:56
#define NotifyFailSetDevTblEntry(...)
Definition message.h:55
#define NotifyFailGetDevDescr(...)
Definition message.h:54
#define MASS_MAX_SUPPORTED_LUN
Definition settings.h:79
uint8_t bmNakPower
Definition address.h:49
uint8_t bmRcvToggle
Definition address.h:48
uint8_t epAddr
Definition address.h:40
uint8_t maxPktSize
Definition address.h:41
uint8_t bmSndToggle
Definition address.h:47
#define USB_FEATURE_ENDPOINT_HALT
Definition usb_ch9.h:52
#define USB_SETUP_TYPE_STANDARD
Definition usb_ch9.h:60
#define USB_TRANSFER_TYPE_BULK
Definition usb_ch9.h:92
#define USB_SETUP_HOST_TO_DEVICE
Definition usb_ch9.h:58
#define USB_REQUEST_CLEAR_FEATURE
Definition usb_ch9.h:41
#define bmUSB_TRANSFER_TYPE
Definition usb_ch9.h:94
#define USB_SETUP_RECIPIENT_ENDPOINT
Definition usb_ch9.h:65
#define USB_TRANSFER_TYPE_INTERRUPT
Definition usb_ch9.h:93
#define PSTR(str)