USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
masstorage.cpp
Go to the documentation of this file.
1 #include "masstorage.h"
2 
3 const uint8_t BulkOnly::epDataInIndex = 1;
4 const uint8_t BulkOnly::epDataOutIndex = 2;
5 const uint8_t BulkOnly::epInterruptInIndex = 3;
6 
8 
9 // Interface code
10 
12 
19 uint32_t BulkOnly::GetCapacity(uint8_t lun) {
20  if (LUNOk[lun])
21  return CurrentCapacity[lun];
22  return 0LU;
23 }
24 
31 uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
32  if (LUNOk[lun])
33  return CurrentSectorSize[lun];
34  return 0U;
35 }
36 
43 bool BulkOnly::LUNIsGood(uint8_t lun) {
44  return LUNOk[lun];
45 }
46 
53 boolean BulkOnly::WriteProtected(uint8_t lun) {
54  return WriteOk[lun];
55 }
56 
57 
66 uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
67  Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
68  Notify(PSTR("---------\r\n"), 0x80);
69 
71  SetCurLUN(lun);
73  cbw.dCBWTag = ++dCBWTag;
74  cbw.dCBWDataTransferLength = 0;
76  cbw.bmCBWLUN = lun;
77  cbw.bmCBWCBLength = 6;
78 
79  for (uint8_t i = 0; i < 16; i++)
80  cbw.CBWCB[i] = 0;
81 
83  cbw.CBWCB[4] = lock;
84 
85  return (HandleSCSIError(Transaction(&cbw, 0, NULL, 0)));
86 
87 }
88 
97 uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
98  Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
99  Notify(PSTR("-----------------\r\n"), 0x80);
100  SetCurLUN(lun);
101  uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
102  if (bAddress) {
104 
106  cbw.dCBWTag = ++dCBWTag;
107  cbw.dCBWDataTransferLength = 0;
109  cbw.bmCBWLUN = lun;
110  cbw.bmCBWCBLength = 6;
111 
112  for (uint8_t i = 0; i < 16; i++)
113  cbw.CBWCB[i] = 0;
114 
116  cbw.CBWCB[1] = lun << 5;
117  cbw.CBWCB[4] = ctl & 0x03;
118 
119  rcode = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
120  }
121  return rcode;
122 }
123 
134 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
135  if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
136  Notify(PSTR("\r\nRead LUN:\t"), 0x80);
137  PrintHex<uint8_t > (lun, 0x90);
138  //printf("LUN=%i LBA=%8.8X BLOCKS=%i SIZE=%i\r\n", lun, addr, blocks, bsize);
139  Notify(PSTR("\r\nLBA:\t\t"), 0x90);
140  PrintHex<uint32_t > (addr, 0x90);
141  Notify(PSTR("\r\nblocks:\t\t"), 0x90);
142  PrintHex<uint8_t > (blocks, 0x90);
143  Notify(PSTR("\r\nblock size:\t"), 0x90);
144  PrintHex<uint16_t > (bsize, 0x90);
145  Notify(PSTR("\r\n---------\r\n"), 0x80);
147 
148 again:
150  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
152  cbw.bmCBWLUN = lun;
153  cbw.bmCBWCBLength = 10;
154 
155  for (uint8_t i = 0; i < 16; i++)
156  cbw.CBWCB[i] = 0;
157 
158  cbw.CBWCB[0] = SCSI_CMD_READ_10;
159  cbw.CBWCB[1] = lun << 5;
160  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
161  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
162  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
163  cbw.CBWCB[5] = (addr & 0xff);
164  cbw.CBWCB[8] = blocks;
165  cbw.dCBWTag = ++dCBWTag;
166  SetCurLUN(lun);
167  uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
168  if (er == MASS_ERR_STALL) {
169  MediaCTL(lun, 1);
170  delay(150);
171  if (!TestUnitReady(lun)) goto again;
172  }
173  return er;
174 }
175 
186 uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
187  if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
188  if (!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
189  Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
190  PrintHex<uint8_t > (lun, 0x90);
191  //printf("LUN=%i LBA=%8.8X BLOCKS=%i SIZE=%i\r\n", lun, addr, blocks, bsize);
192  Notify(PSTR("\r\nLBA:\t\t"), 0x90);
193  PrintHex<uint32_t > (addr, 0x90);
194  Notify(PSTR("\r\nblocks:\t\t"), 0x90);
195  PrintHex<uint8_t > (blocks, 0x90);
196  Notify(PSTR("\r\nblock size:\t"), 0x90);
197  PrintHex<uint16_t > (bsize, 0x90);
198  Notify(PSTR("\r\n---------\r\n"), 0x80);
199  //MediaCTL(lun, 0x01);
201 
202 again:
204  cbw.dCBWTag = ++dCBWTag;
205  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
207  cbw.bmCBWLUN = lun;
208  cbw.bmCBWCBLength = 10;
209 
210  for (uint8_t i = 0; i < 16; i++)
211  cbw.CBWCB[i] = 0;
212 
213  cbw.CBWCB[0] = SCSI_CMD_WRITE_10;
214  cbw.CBWCB[1] = lun << 5;
215  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
216  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
217  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
218  cbw.CBWCB[5] = (addr & 0xff);
219  cbw.CBWCB[8] = 1;
220 
221  SetCurLUN(lun);
222  uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0));
223  if (er == MASS_ERR_WRITE_STALL) {
224  MediaCTL(lun, 1);
225  delay(150);
226  if (!TestUnitReady(lun)) goto again;
227  }
228  return er;
229 }
230 
231 // End of user functions, the remaining code below is driver internals.
232 // Only developer serviceable parts below!
233 
235 
236 // Main driver code
237 
239 
240 
242 pUsb(p),
243 bAddress(0),
244 bIface(0),
245 bNumEP(1),
246 qNextPollTime(0),
247 bPollEnable(false),
248 dCBWTag(0),
249 bLastUsbError(0) {
250  ClearAllEP();
251  dCBWTag = 0;
252  if (pUsb)
253  pUsb->RegisterDeviceClass(this);
254 }
255 
270 uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
271 
272  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
273 
274  uint8_t buf[constBufSize];
275  uint8_t rcode;
276  UsbDevice *p = NULL;
277  EpInfo *oldep_ptr = NULL;
278  USBTRACE("MS ConfigureDevice\r\n");
279  ClearAllEP();
280  delay(2000);
281  AddressPool &addrPool = pUsb->GetAddressPool();
282 
283 
284  if (bAddress)
286 
287  // <TECHNICAL>
288  // Get pointer to pseudo device with address 0 assigned
289  p = addrPool.GetUsbDevicePtr(0);
290  if (!p) {
292  }
293 
294  if (!p->epinfo) {
295  USBTRACE("epinfo\r\n");
297  }
298 
299  // Save old pointer to EP_RECORD of address 0
300  oldep_ptr = p->epinfo;
301 
302  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
303  p->epinfo = epInfo;
304 
305  p->lowspeed = lowspeed;
306  // Get device descriptor
307  rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
308 
309  // Restore p->epinfo
310  p->epinfo = oldep_ptr;
311 
312  if (rcode) {
313  goto FailGetDevDescr;
314  }
315  // Allocate new address according to device class
316  bAddress = addrPool.AllocAddress(parent, false, port);
317 
318  if (!bAddress)
320 
321  // Extract Max Packet Size from the device descriptor
322  epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
323  // Steal and abuse from epInfo structure to save on memory.
324  epInfo[1].epAddr = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
325  // </TECHNICAL>
327 
328 FailGetDevDescr:
329 #ifdef DEBUG_USB_HOST
330  NotifyFailGetDevDescr(rcode);
331 #endif
333 
334 Fail:
335  Release();
336  return rcode;
337 };
338 
346 uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
347  uint8_t rcode;
348  uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
349  epInfo[1].epAddr = 0;
350  USBTRACE("MS Init\r\n");
351 
352  AddressPool &addrPool = pUsb->GetAddressPool();
353  UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
354 
355  if (!p)
357 
358  // Assign new address to the device
359  delay(2000);
360  rcode = pUsb->setAddr(0, 0, bAddress);
361 
362  if (rcode) {
363  p->lowspeed = false;
364  addrPool.FreeAddress(bAddress);
365  bAddress = 0;
366  USBTRACE2("setAddr:", rcode);
367  return rcode;
368  }
369 
370  USBTRACE2("Addr:", bAddress);
371 
372  p->lowspeed = false;
373 
374  p = addrPool.GetUsbDevicePtr(bAddress);
375 
376  if (!p)
378 
379  p->lowspeed = lowspeed;
380 
381  // Assign epInfo to epinfo pointer
382  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
383 
384  if (rcode)
385  goto FailSetDevTblEntry;
386 
387  USBTRACE2("NC:", num_of_conf);
388 
389  for (uint8_t i = 0; i < num_of_conf; i++) {
395  CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);
396 
397  rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
398 
399  if (rcode)
400  goto FailGetConfDescr;
401 
402  if (bNumEP > 1)
403  break;
404  } // for
405 
406  if (bNumEP < 3)
408 
409  // Assign epInfo to epinfo pointer
411 
412  USBTRACE("MS ConfigureDevice\r\n");
413  USBTRACE2("Conf:", bConfNum);
414 
415  // Set Configuration Value
416  rcode = pUsb->setConf(bAddress, 0, bConfNum);
417 
418  if (rcode)
419  goto FailSetConfDescr;
420 
421  //Linux does a 1sec delay after this.
422  delay(1000);
423 
424  rcode = GetMaxLUN(&bMaxLUN);
425  if (rcode)
426  goto FailGetMaxLUN;
427 
429  ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
430 
431  delay(1000); // Delay a bit for slow firmware.
432 
433  //bTheLUN = bMaxLUN;
434 
435  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
436  InquiryResponse response;
437  rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
438  if (rcode) {
439  ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
440  } else {
441  uint8_t tries = 0xf0;
442  while (rcode = TestUnitReady(lun)) {
443  if (rcode == 0x08) break; // break on no media, this is OK to do.
444  // try to lock media and spin up
445  if (tries < 14) {
446  LockMedia(lun, 1);
447  MediaCTL(lun, 1); // I actually have a USB stick that needs this!
448  } else delay(2 * (tries + 1));
449  tries++;
450  if (!tries) break;
451  }
452  if (!rcode) {
453  delay(1000);
454  LUNOk[lun] = CheckLUN(lun);
455  if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
456  }
457  }
458  }
459 
460 
461 #if 0
462  {
463  bool good;
464  for (uint8_t i = 1; i == 0; i++) {
465  good = false;
466  CheckMedia();
467  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) good |= LUNOk[lun];
468  if (good) break;
469  delay(118); // 255 loops =~ 30 seconds to allow for spin up, as per SCSI spec.
470  }
471  }
472 #else
473  CheckMedia();
474 #endif
475 
476  rcode = OnInit();
477 
478  if (rcode)
479  goto FailOnInit;
480 
481  USBTRACE("MS configured\r\n\r\n");
482 
483  bPollEnable = true;
484 
485  //USBTRACE("Poll enabled\r\n");
486  return 0;
487 
488 FailSetConfDescr:
489 #ifdef DEBUG_USB_HOST
491  goto Fail;
492 #endif
493 
494 FailOnInit:
495 #ifdef DEBUG_USB_HOST
496  USBTRACE("OnInit:");
497  goto Fail;
498 #endif
499 
500 FailGetMaxLUN:
501 #ifdef DEBUG_USB_HOST
502  USBTRACE("GetMaxLUN:");
503  goto Fail;
504 #endif
505 
506 FailInvalidSectorSize:
507 #ifdef DEBUG_USB_HOST
508  USBTRACE("Sector Size is NOT VALID: ");
509  goto Fail;
510 #endif
511 
512 FailSetDevTblEntry:
513 #ifdef DEBUG_USB_HOST
515  goto Fail;
516 #endif
517 
518 FailGetConfDescr:
519 #ifdef DEBUG_USB_HOST
521 #endif
522 
523 Fail:
524 #ifdef DEBUG_USB_HOST
525  NotifyFail(rcode);
526 #endif
527  Release();
528  return rcode;
529 }
530 
536 uint8_t BulkOnly::Release() {
537  ClearAllEP();
539  return 0;
540 }
541 
548 boolean BulkOnly::CheckLUN(uint8_t lun) {
549  uint8_t rcode;
550  Capacity capacity;
551  for (uint8_t i = 0; i<sizeof (Capacity); i++) capacity.data[i] = 0;
552 
553  rcode = ReadCapacity(lun, sizeof (Capacity), (uint8_t*) & capacity);
554  if (rcode) {
555  //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
556  return false;
557  }
558  ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
559  for (uint8_t i = 0; i<sizeof (Capacity); i++)
560  PrintHex<uint8_t > (capacity.data[i], 0x80);
561  Notify(PSTR("\r\n\r\n"), 0x80);
562  // Only 512/1024/2048/4096 are valid values!
563  uint32_t c = ((uint32_t)capacity.data[4] << 24) + ((uint32_t)capacity.data[5] << 16) + ((uint32_t)capacity.data[6] << 8) + (uint32_t)capacity.data[7];
564  if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
565  return false;
566  }
567  // Store capacity information.
568  CurrentSectorSize[lun] = (uint16_t)(c & 0xFFFF);
569  CurrentCapacity[lun] = ((uint32_t)capacity.data[0] << 24) + ((uint32_t)capacity.data[1] << 16) + ((uint32_t)capacity.data[2] << 8) + (uint32_t)capacity.data[3];
570  if (CurrentCapacity[lun] == 0xffffffffLU || CurrentCapacity[lun] == 0x00LU) {
571  // Buggy firmware will report 0xffffffff or 0 for no media
572  if (CurrentCapacity[lun])
573  ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
574  return false;
575  }
576  delay(20);
577  Page3F(lun);
578  if (!TestUnitReady(lun)) return true;
579  return false;
580 }
581 
582 
588 void BulkOnly::CheckMedia() {
589  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
590  if (TestUnitReady(lun)) {
591  LUNOk[lun] = false;
592  continue;
593  }
594  if (!LUNOk[lun])
595  LUNOk[lun] = CheckLUN(lun);
596  }
597 #if 0
598  printf("}}}}}}}}}}}}}}}}STATUS ");
599  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
600  if (LUNOk[lun])
601  printf("#");
602  else printf(".");
603  }
604  printf("\r\n");
605 #endif
606  qNextPollTime = millis() + 2000;
607 }
608 
614 uint8_t BulkOnly::Poll() {
615  uint8_t rcode = 0;
616 
617  if (!bPollEnable)
618  return 0;
619 
620  if (qNextPollTime <= millis()) {
621  CheckMedia();
622  }
623  rcode = 0;
624 
625  return rcode;
626 }
627 
629 
630 
631 // SCSI code
632 
633 
635 
642 uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
643  uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
644 
645  if (ret == hrSTALL)
646  *plun = 0;
647 
648  return 0;
649 }
650 
651 
660 uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
661  Notify(PSTR("\r\nInquiry\r\n"), 0x80);
662  Notify(PSTR("---------\r\n"), 0x80);
663 
665  SetCurLUN(lun);
667  cbw.dCBWTag = ++dCBWTag;
668  cbw.dCBWDataTransferLength = bsize;
670  cbw.bmCBWLUN = lun;
671  cbw.bmCBWCBLength = 6;
672 
673  for (uint8_t i = 0; i < 16; i++)
674  cbw.CBWCB[i] = 0;
675 
676  cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
677  cbw.CBWCB[1] = lun << 5;
678  cbw.CBWCB[4] = bsize;
679 
680  uint8_t rc = HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
681 #if 0
682  if (!rc) {
683  printf("LUN %i `", lun);
684  for (int i = 8; i < 36; i++) printf("%c", buf[i]);
685  printf("'\r\nQualifier %1.1X ", (buf[0]&0xE0) >> 5);
686  printf("Device type %2.2X ", buf[0]&0x1f);
687  printf("RMB %1.1X ", buf[1]&0x80 >> 7);
688  printf("SSCS% 1.1X ", buf[5]&0x80 >> 7);
689  uint8_t sv = buf[2];
690  printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
691  switch (sv) {
692  case 0:
693  printf("No specific");
694  break;
695  /*
696  case 1:
697  printf("");
698  break;
699  */
700  case 2:
701  printf("ANSI 2");
702  break;
703  case 3:
704  printf("ANSI INCITS 301-1997 (SPC)");
705  break;
706  case 4:
707  printf("ANSI INCITS 351-2001 (SPC-2)");
708  break;
709  case 5:
710  printf("ANSI INCITS 408-2005 (SPC-4)");
711  break;
712  case 6:
713  printf("T10/1731-D (SPC-4)");
714  break;
715  default:
716  printf("unknown");
717  }
718  printf(" standards.\r\n");
719  }
720 #endif
721  return rc;
722 }
723 
732 uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
733  Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
734  Notify(PSTR("----------------\r\n"), 0x80);
735 
737  SetCurLUN(lun);
738 
740  cbw.dCBWTag = ++dCBWTag;
741  cbw.dCBWDataTransferLength = size;
743  cbw.bmCBWLUN = lun;
744  cbw.bmCBWCBLength = 6;
745 
746  for (uint8_t i = 0; i < 16; i++)
747  cbw.CBWCB[i] = 0;
748 
749  cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
750  cbw.CBWCB[1] = lun << 5;
751  cbw.CBWCB[4] = size;
752 
753  return Transaction(&cbw, size, buf, 0);
754 }
755 
764 uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
765  Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
766  Notify(PSTR("---------------\r\n"), 0x80);
768 
769  SetCurLUN(lun);
771  cbw.dCBWTag = ++dCBWTag;
772  cbw.dCBWDataTransferLength = bsize;
774  cbw.bmCBWLUN = lun;
775  cbw.bmCBWCBLength = 10;
776 
777  for (uint8_t i = 0; i < 16; i++)
778  cbw.CBWCB[i] = 0;
779 
781  cbw.CBWCB[1] = lun << 5;
782 
783  return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
784 }
785 
792 uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
793  SetCurLUN(lun);
794  if (!bAddress)
796 
797  Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
798  Notify(PSTR("-----------------\r\n"), 0x80);
799 
801  uint8_t rc;
802 
804  cbw.dCBWTag = ++dCBWTag;
805  cbw.dCBWDataTransferLength = 0;
807  cbw.bmCBWLUN = lun;
808  cbw.bmCBWCBLength = 6;
809 
810  for (uint8_t i = 0; i < 16; i++)
811  cbw.CBWCB[i] = 0;
812 
814  cbw.CBWCB[1] = lun;
815  rc = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
816  return (rc);
817 }
818 
827 uint8_t BulkOnly::Page3F(uint8_t lun) {
828  uint8_t buf[192];
829  for (int i = 0; i < 192; i++) {
830  buf[i] = 0x00;
831  }
832  WriteOk[lun] = true;
833  uint8_t rc = ModeSense(lun, 0, 0x3f, 0, 192, buf);
834  if (!rc) {
835  WriteOk[lun] = ((buf[2] & 0x80) == 0);
836  Notify(PSTR("Mode Sense: "), 0x80);
837  for (int i = 0; i < 4; i++) {
838  PrintHex<uint8_t > (buf[i], 0x80);
839  Notify(PSTR(" "), 0x80);
840  }
841  Notify(PSTR("\r\n"), 0x80);
842  }
843  return rc;
844 }
845 
846 
847 
849 
850 
851 // USB code
852 
853 
855 
856 
857 
864 uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
865  if (index == 0)
866  return 0;
867 
868  uint8_t ret = 0;
869 
871  USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL))
872  == 0x01) delay(6);
873 
874  if (ret) {
875  ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
876  ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
877  return ret;
878  }
879  epInfo[index].bmSndToggle = 0;
880  epInfo[index].bmRcvToggle = 0;
881  // epAttribs = 0;
882  return 0;
883 }
884 
889 void BulkOnly::Reset() {
890  while (pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
891 }
892 
898 uint8_t BulkOnly::ResetRecovery() {
899  Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
900  Notify(PSTR("-----------------\r\n"), 0x80);
901 
902  delay(6);
903  Reset();
904  delay(6);
905  ClearEpHalt(epDataInIndex);
906  delay(6);
907  bLastUsbError = ClearEpHalt(epDataOutIndex);
908  delay(6);
909  return bLastUsbError;
910 }
911 
917 void BulkOnly::ClearAllEP() {
918  for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
919  epInfo[i].epAddr = 0;
920  epInfo[i].maxPktSize = (i) ? 0 : 8;
921  epInfo[i].epAttribs = 0;
922 
924  }
925 
926  for (uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) LUNOk[i] = false;
927  bIface = 0;
928  bNumEP = 1;
929 
930  bAddress = 0;
931  qNextPollTime = 0;
932  bPollEnable = false;
933  bLastUsbError = 0;
934  bMaxLUN = 0;
935  bTheLUN = 0;
936 }
937 
938 
946 bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
947  if (pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
948  Notify(PSTR("CSW:Sig error\r\n"), 0x80);
949  //printf("%lx != %lx\r\n", MASS_CSW_SIGNATURE, pcsw->dCSWSignature);
950  return false;
951  }
952  if (pcsw->dCSWTag != pcbw->dCBWTag) {
953  Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
954  //printf("%lx != %lx\r\n", pcsw->dCSWTag, pcbw->dCBWTag);
955  return false;
956  }
957  return true;
958 }
959 
967 uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
968  uint8_t count = 3;
969 
970  bLastUsbError = error;
971  //if (error)
972  //ClearEpHalt(index);
973  while (error && count) {
974  if (error != hrSUCCESS) {
975  ErrorMessage<uint8_t > (PSTR("USB Error"), error);
976  ErrorMessage<uint8_t > (PSTR("Index"), index);
977  }
978  switch (error) {
979  // case hrWRONGPID:
980  case hrSUCCESS:
981  return MASS_ERR_SUCCESS;
982  case hrBUSY:
983  // SIE is busy, just hang out and try again.
984  return MASS_ERR_UNIT_BUSY;
985  case hrTIMEOUT:
987  case hrSTALL:
988  if (index == 0)
989  return MASS_ERR_STALL;
990  ClearEpHalt(index);
991  if (index != epDataInIndex)
992  return MASS_ERR_WRITE_STALL;
993  return MASS_ERR_STALL;
994 
995  case hrNAK:
996  if (index == 0)
997  return MASS_ERR_UNIT_BUSY;
998  return MASS_ERR_UNIT_BUSY;
999  //ClearEpHalt(index);
1000  //ResetRecovery();
1001  //if (index != epDataInIndex)
1002  // return MASS_ERR_WRITE_NAKS;
1003  //return MASS_ERR_READ_NAKS;
1004  case hrTOGERR:
1005  // Handle a very super rare corner case, where toggles become de-synched.
1006  // I have only ran into one device that has this firmware bug, and this is
1007  // the only clean way to get back into sync with the buggy device firmware.
1008  // --AJK
1009  if (bAddress && bConfNum) {
1010  error = pUsb->setConf(bAddress, 0, bConfNum);
1011 
1012  if (error)
1013  break;
1014  }
1015  return MASS_ERR_SUCCESS;
1016  default:
1017  ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
1019  }
1020  count--;
1021  } // while
1022 
1023  return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
1024 }
1025 
1035 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, uint8_t flags) {
1036  uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
1037  boolean write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
1038  boolean callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
1039  uint8_t ret = 0;
1040  uint8_t usberr;
1041  CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
1042  // Fix reserved bits.
1043  pcbw->bmReserved1 = 0;
1044  pcbw->bmReserved2 = 0;
1045  ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
1046 
1047  while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
1048 
1049  ret = HandleUsbError(usberr, epDataOutIndex);
1050  //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
1051  if (ret) {
1052  ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
1053  } else {
1054  if (bytes) {
1055  if (!write) {
1056  if (callback) {
1057  uint8_t rbuf[bytes];
1058  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
1059  if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
1060  } else {
1061  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1062  }
1063  ret = HandleUsbError(usberr, epDataInIndex);
1064  } else {
1065  while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1066  ret = HandleUsbError(usberr, epDataOutIndex);
1067  }
1068  if (ret) {
1069  ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
1070  }
1071  }
1072  }
1073 
1074  //if (!ret || ret == MASS_ERR_WRITE_STALL || ret == MASS_ERR_STALL) {
1075  {
1076  bytes = sizeof (CommandStatusWrapper);
1077  int tries = 2;
1078  while (tries--) {
1079  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
1080  if (!usberr) break;
1081  ClearEpHalt(epDataInIndex);
1082  //HandleUsbError(usberr, epDataInIndex);
1083  if (tries) ResetRecovery();
1084  }
1085  if (!ret) {
1086  Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
1087  Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
1088  } else {
1089  // Throw away csw, IT IS NOT OF ANY USE.
1090  //HandleUsbError(usberr, epDataInIndex);
1091  ResetRecovery();
1092  return ret;
1093  }
1094  ret = HandleUsbError(usberr, epDataInIndex);
1095  if (ret) {
1096  ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
1097  }
1098  if (usberr == hrSUCCESS) {
1099  if (IsValidCSW(&csw, pcbw)) {
1100  //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
1101  //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
1102  //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
1103  Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
1104  return csw.bCSWStatus;
1105  } else {
1106  Notify(PSTR("Invalid CSW\r\n"), 0x80);
1107  ResetRecovery();
1108  //return MASS_ERR_SUCCESS;
1109  return MASS_ERR_INVALID_CSW;
1110  }
1111  }
1112 
1113  }
1114  return ret;
1115 }
1116 
1128 uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
1129  Notify(PSTR("\r\rModeSense\r\n"), 0x80);
1130  Notify(PSTR("------------\r\n"), 0x80);
1131 
1132  CommandBlockWrapper cbw;
1133  SetCurLUN(lun);
1134 
1136  cbw.dCBWTag = ++dCBWTag;
1137  cbw.dCBWDataTransferLength = ((uint32_t)len);
1139  cbw.bmCBWLUN = lun;
1140  cbw.bmCBWCBLength = 6;
1141 
1142  for (uint8_t i = 0; i < 16; i++)
1143  cbw.CBWCB[i] = 0;
1144 
1145  cbw.CBWCB[0] = SCSI_CMD_MODE_SENSE_6;
1146  cbw.CBWCB[2] = ((pc << 6) | page);
1147  cbw.CBWCB[3] = subpage;
1148  cbw.CBWCB[4] = len;
1149 
1150  return HandleSCSIError(Transaction(&cbw, 512, pbuf, 0));
1151 }
1152 
1159 uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
1160  if (lun > bMaxLUN)
1161  return MASS_ERR_INVALID_LUN;
1162  bTheLUN = lun;
1163  return MASS_ERR_SUCCESS;
1164 };
1165 
1172 uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
1173  uint8_t ret = 0;
1174 
1175  switch (status) {
1176  case 0: return MASS_ERR_SUCCESS;
1177  //case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
1178  // case 0x05/0x14: we stalled out
1179  // case 0x15/0x16: we naked out.
1180  case 2:
1181  ErrorMessage<uint8_t > (PSTR("Phase Error"), status);
1182  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1183  ResetRecovery();
1185  case 1:
1186  ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
1187  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1189 
1190  ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
1191 
1192  if (ret) {
1193  //ResetRecovery();
1195  }
1196  ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
1197  if (rsp.bResponseCode & 0x80) {
1198  Notify(PSTR("Information field: "), 0x80);
1199  for (int i = 0; i < 4; i++) {
1200  PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
1201  Notify(PSTR(" "), 0x80);
1202  }
1203  Notify(PSTR("\r\n"), 0x80);
1204  }
1205  ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
1206  ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
1207  ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
1208  // warning, this is not testing ASQ, only SK and ASC.
1209  switch (rsp.bmSenseKey) {
1210  /* bug...
1211  case 0:
1212  return MASS_ERR_SUCCESS;
1213  */
1214  case SCSI_S_UNIT_ATTENTION:
1215  switch (rsp.bAdditionalSenseCode) {
1217  return MASS_ERR_MEDIA_CHANGED;
1218  default:
1219  return MASS_ERR_UNIT_NOT_READY;
1220  }
1221  case SCSI_S_NOT_READY:
1222  switch (rsp.bAdditionalSenseCode) {
1224  return MASS_ERR_NO_MEDIA;
1225  //return MASS_ERR_SUCCESS;
1226  default:
1227  return MASS_ERR_UNIT_NOT_READY;
1228  }
1230  switch (rsp.bAdditionalSenseCode) {
1232  return MASS_ERR_BAD_LBA;
1233  default:
1235  }
1236  default:
1238  }
1239 
1240  default:
1241  // Should have been handled already in HandleUsbError.
1242  // ResetRecovery();
1243  ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
1244  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1245  return status; //MASS_ERR_GENERAL_SCSI_ERROR;
1246  } // switch
1247 }
1248 
1249 
1251 
1252 
1253 // Debugging code
1254 
1255 
1257 
1258 
1268 void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) {
1269  ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
1270  ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
1271  ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
1272 
1273  bConfNum = conf;
1274 
1275  uint8_t index;
1276 
1277  if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
1278  index = epInterruptInIndex;
1279  else
1280  if ((pep->bmAttributes & 0x02) == 2)
1281  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
1282  else
1283  return;
1284 
1285  // Fill in the endpoint info structure
1286  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
1287  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
1288  epInfo[index].epAttribs = 0;
1289 
1290  bNumEP++;
1291 
1293 }
1294 
1300  Notify(PSTR("Endpoint descriptor:"), 0x80);
1301  Notify(PSTR("\r\nLength:\t\t"), 0x80);
1302  PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
1303  Notify(PSTR("\r\nType:\t\t"), 0x80);
1304  PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
1305  Notify(PSTR("\r\nAddress:\t"), 0x80);
1306  PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
1307  Notify(PSTR("\r\nAttributes:\t"), 0x80);
1308  PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
1309  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
1310  PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
1311  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
1312  PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
1313  Notify(PSTR("\r\n"), 0x80);
1314 }
1315 
1316 
1318 
1319 
1320 // misc/to kill/to-do
1321 
1322 
1324 
1325 
1326 /* We won't be needing this... */
1327 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
1328  if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
1329 #if 0
1330  Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
1331  Notify(PSTR("---------\r\n"), 0x80);
1332 
1333  CommandBlockWrapper cbw;
1334 
1336  cbw.dCBWTag = ++dCBWTag;
1337  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
1339  cbw.bmCBWLUN = lun;
1340  cbw.bmCBWCBLength = 10;
1341 
1342  for (uint8_t i = 0; i < 16; i++)
1343  cbw.CBWCB[i] = 0;
1344 
1345  cbw.CBWCB[0] = SCSI_CMD_READ_10;
1346  cbw.CBWCB[8] = blocks;
1347  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
1348  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
1349  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
1350  cbw.CBWCB[5] = (addr & 0xff);
1351 
1352  return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
1353 #endif
1354 }
1355 
1356 #if 0
1357 // TO-DO: Unify CBW creation as much as possible.
1358 // Make and submit CBW.
1359 // if stalled, delay retry
1360 // exit on 100 retries, or anything except stall.
1361 
1362 uint8_t SubmitCBW(uint8_t cmd, uint8_t cmdsz, uint8_t lun, uint16_t bsize, uint8_t *buf, uint8_t flags) {
1363  CommandBlockWrapper cbw;
1364  SetCurLUN(lun);
1366  cbw.dCBWTag = ++dCBWTag;
1367  cbw.dCBWDataTransferLength = bsize;
1368  cbw.bmCBWFlags = flags;
1369  cbw.bmCBWLUN = lun;
1370  cbw.bmCBWCBLength = cmdsz;
1371  for (uint8_t i = 0; i < 16; i++) cbw.CBWCB[i] = 0;
1372  cbw.CBWCB[0] = cmd;
1373  cbw.CBWCB[1] = lun << 5;
1374  cbw.CBWCB[4] = bsize;
1375 }
1376 #endif