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  D_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  D_PrintHex<uint32_t > (addr, 0x90);
141  Notify(PSTR("\r\nblocks:\t\t"), 0x90);
142  D_PrintHex<uint8_t > (blocks, 0x90);
143  Notify(PSTR("\r\nblock size:\t"), 0x90);
144  D_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  D_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  D_PrintHex<uint32_t > (addr, 0x90);
194  Notify(PSTR("\r\nblocks:\t\t"), 0x90);
195  D_PrintHex<uint8_t > (blocks, 0x90);
196  Notify(PSTR("\r\nblock size:\t"), 0x90);
197  D_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  USBTRACE2("Conf:", bConfNum);
413 
414  // Set Configuration Value
415  rcode = pUsb->setConf(bAddress, 0, bConfNum);
416 
417  if (rcode)
418  goto FailSetConfDescr;
419 
420  //Linux does a 1sec delay after this.
421  delay(1000);
422 
423  rcode = GetMaxLUN(&bMaxLUN);
424  if (rcode)
425  goto FailGetMaxLUN;
426 
428  ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
429 
430  delay(1000); // Delay a bit for slow firmware.
431 
432  //bTheLUN = bMaxLUN;
433 
434  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
435  InquiryResponse response;
436  rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
437  if (rcode) {
438  ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
439  } else {
440  uint8_t tries = 0xf0;
441  while (rcode = TestUnitReady(lun)) {
442  if (rcode == 0x08) break; // break on no media, this is OK to do.
443  // try to lock media and spin up
444  if (tries < 14) {
445  LockMedia(lun, 1);
446  MediaCTL(lun, 1); // I actually have a USB stick that needs this!
447  } else delay(2 * (tries + 1));
448  tries++;
449  if (!tries) break;
450  }
451  if (!rcode) {
452  delay(1000);
453  LUNOk[lun] = CheckLUN(lun);
454  if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
455  }
456  }
457  }
458 
459 
460 #if 0
461  {
462  bool good;
463  for (uint8_t i = 1; i == 0; i++) {
464  good = false;
465  CheckMedia();
466  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) good |= LUNOk[lun];
467  if (good) break;
468  delay(118); // 255 loops =~ 30 seconds to allow for spin up, as per SCSI spec.
469  }
470  }
471 #else
472  CheckMedia();
473 #endif
474 
475  rcode = OnInit();
476 
477  if (rcode)
478  goto FailOnInit;
479 
480  USBTRACE("MS configured\r\n\r\n");
481 
482  bPollEnable = true;
483 
484  //USBTRACE("Poll enabled\r\n");
485  return 0;
486 
487 FailSetConfDescr:
488 #ifdef DEBUG_USB_HOST
490  goto Fail;
491 #endif
492 
493 FailOnInit:
494 #ifdef DEBUG_USB_HOST
495  USBTRACE("OnInit:");
496  goto Fail;
497 #endif
498 
499 FailGetMaxLUN:
500 #ifdef DEBUG_USB_HOST
501  USBTRACE("GetMaxLUN:");
502  goto Fail;
503 #endif
504 
505 FailInvalidSectorSize:
506 #ifdef DEBUG_USB_HOST
507  USBTRACE("Sector Size is NOT VALID: ");
508  goto Fail;
509 #endif
510 
511 FailSetDevTblEntry:
512 #ifdef DEBUG_USB_HOST
514  goto Fail;
515 #endif
516 
517 FailGetConfDescr:
518 #ifdef DEBUG_USB_HOST
520 #endif
521 
522 Fail:
523 #ifdef DEBUG_USB_HOST
524  NotifyFail(rcode);
525 #endif
526  Release();
527  return rcode;
528 }
529 
539 void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) {
540  ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
541  ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
542  ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
543 
544  bConfNum = conf;
545 
546  uint8_t index;
547 
548  if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
549  index = epInterruptInIndex;
550  else
551  if ((pep->bmAttributes & 0x02) == 2)
552  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
553  else
554  return;
555 
556  // Fill in the endpoint info structure
557  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
558  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
559  epInfo[index].epAttribs = 0;
560 
561  bNumEP++;
562 
564 }
565 
571 uint8_t BulkOnly::Release() {
572  ClearAllEP();
574  return 0;
575 }
576 
583 boolean BulkOnly::CheckLUN(uint8_t lun) {
584  uint8_t rcode;
585  Capacity capacity;
586  for (uint8_t i = 0; i<sizeof (Capacity); i++) capacity.data[i] = 0;
587 
588  rcode = ReadCapacity(lun, sizeof (Capacity), (uint8_t*) & capacity);
589  if (rcode) {
590  //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
591  return false;
592  }
593  ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
594  for (uint8_t i = 0; i<sizeof (Capacity); i++)
595  D_PrintHex<uint8_t > (capacity.data[i], 0x80);
596  Notify(PSTR("\r\n\r\n"), 0x80);
597  // Only 512/1024/2048/4096 are valid values!
598  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];
599  if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
600  return false;
601  }
602  // Store capacity information.
603  CurrentSectorSize[lun] = (uint16_t)(c & 0xFFFF);
604  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];
605  if (CurrentCapacity[lun] == 0xffffffffLU || CurrentCapacity[lun] == 0x00LU) {
606  // Buggy firmware will report 0xffffffff or 0 for no media
607  if (CurrentCapacity[lun])
608  ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
609  return false;
610  }
611  delay(20);
612  Page3F(lun);
613  if (!TestUnitReady(lun)) return true;
614  return false;
615 }
616 
617 
623 void BulkOnly::CheckMedia() {
624  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
625  if (TestUnitReady(lun)) {
626  LUNOk[lun] = false;
627  continue;
628  }
629  if (!LUNOk[lun])
630  LUNOk[lun] = CheckLUN(lun);
631  }
632 #if 0
633  printf("}}}}}}}}}}}}}}}}STATUS ");
634  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
635  if (LUNOk[lun])
636  printf("#");
637  else printf(".");
638  }
639  printf("\r\n");
640 #endif
641  qNextPollTime = millis() + 2000;
642 }
643 
649 uint8_t BulkOnly::Poll() {
650  uint8_t rcode = 0;
651 
652  if (!bPollEnable)
653  return 0;
654 
655  if (qNextPollTime <= millis()) {
656  CheckMedia();
657  }
658  rcode = 0;
659 
660  return rcode;
661 }
662 
664 
665 
666 // SCSI code
667 
668 
670 
677 uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
678  uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
679 
680  if (ret == hrSTALL)
681  *plun = 0;
682 
683  return 0;
684 }
685 
686 
695 uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
696  Notify(PSTR("\r\nInquiry\r\n"), 0x80);
697  Notify(PSTR("---------\r\n"), 0x80);
698 
700  SetCurLUN(lun);
702  cbw.dCBWTag = ++dCBWTag;
703  cbw.dCBWDataTransferLength = bsize;
705  cbw.bmCBWLUN = lun;
706  cbw.bmCBWCBLength = 6;
707 
708  for (uint8_t i = 0; i < 16; i++)
709  cbw.CBWCB[i] = 0;
710 
711  cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
712  cbw.CBWCB[1] = lun << 5;
713  cbw.CBWCB[4] = bsize;
714 
715  uint8_t rc = HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
716 #if 0
717  if (!rc) {
718  printf("LUN %i `", lun);
719  for (int i = 8; i < 36; i++) printf("%c", buf[i]);
720  printf("'\r\nQualifier %1.1X ", (buf[0]&0xE0) >> 5);
721  printf("Device type %2.2X ", buf[0]&0x1f);
722  printf("RMB %1.1X ", buf[1]&0x80 >> 7);
723  printf("SSCS% 1.1X ", buf[5]&0x80 >> 7);
724  uint8_t sv = buf[2];
725  printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
726  switch (sv) {
727  case 0:
728  printf("No specific");
729  break;
730  /*
731  case 1:
732  printf("");
733  break;
734  */
735  case 2:
736  printf("ANSI 2");
737  break;
738  case 3:
739  printf("ANSI INCITS 301-1997 (SPC)");
740  break;
741  case 4:
742  printf("ANSI INCITS 351-2001 (SPC-2)");
743  break;
744  case 5:
745  printf("ANSI INCITS 408-2005 (SPC-4)");
746  break;
747  case 6:
748  printf("T10/1731-D (SPC-4)");
749  break;
750  default:
751  printf("unknown");
752  }
753  printf(" standards.\r\n");
754  }
755 #endif
756  return rc;
757 }
758 
767 uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
768  Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
769  Notify(PSTR("----------------\r\n"), 0x80);
770 
772  SetCurLUN(lun);
773 
775  cbw.dCBWTag = ++dCBWTag;
776  cbw.dCBWDataTransferLength = size;
778  cbw.bmCBWLUN = lun;
779  cbw.bmCBWCBLength = 6;
780 
781  for (uint8_t i = 0; i < 16; i++)
782  cbw.CBWCB[i] = 0;
783 
784  cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
785  cbw.CBWCB[1] = lun << 5;
786  cbw.CBWCB[4] = size;
787 
788  return Transaction(&cbw, size, buf, 0);
789 }
790 
799 uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
800  Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
801  Notify(PSTR("---------------\r\n"), 0x80);
803 
804  SetCurLUN(lun);
806  cbw.dCBWTag = ++dCBWTag;
807  cbw.dCBWDataTransferLength = bsize;
809  cbw.bmCBWLUN = lun;
810  cbw.bmCBWCBLength = 10;
811 
812  for (uint8_t i = 0; i < 16; i++)
813  cbw.CBWCB[i] = 0;
814 
816  cbw.CBWCB[1] = lun << 5;
817 
818  return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
819 }
820 
827 uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
828  SetCurLUN(lun);
829  if (!bAddress)
831 
832  Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
833  Notify(PSTR("-----------------\r\n"), 0x80);
834 
836  uint8_t rc;
837 
839  cbw.dCBWTag = ++dCBWTag;
840  cbw.dCBWDataTransferLength = 0;
842  cbw.bmCBWLUN = lun;
843  cbw.bmCBWCBLength = 6;
844 
845  for (uint8_t i = 0; i < 16; i++)
846  cbw.CBWCB[i] = 0;
847 
849  cbw.CBWCB[1] = lun;
850  rc = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
851  return (rc);
852 }
853 
862 uint8_t BulkOnly::Page3F(uint8_t lun) {
863  uint8_t buf[192];
864  for (int i = 0; i < 192; i++) {
865  buf[i] = 0x00;
866  }
867  WriteOk[lun] = true;
868  uint8_t rc = ModeSense(lun, 0, 0x3f, 0, 192, buf);
869  if (!rc) {
870  WriteOk[lun] = ((buf[2] & 0x80) == 0);
871  Notify(PSTR("Mode Sense: "), 0x80);
872  for (int i = 0; i < 4; i++) {
873  D_PrintHex<uint8_t > (buf[i], 0x80);
874  Notify(PSTR(" "), 0x80);
875  }
876  Notify(PSTR("\r\n"), 0x80);
877  }
878  return rc;
879 }
880 
881 
882 
884 
885 
886 // USB code
887 
888 
890 
891 
892 
899 uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
900  if (index == 0)
901  return 0;
902 
903  uint8_t ret = 0;
904 
906  USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL))
907  == 0x01) delay(6);
908 
909  if (ret) {
910  ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
911  ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
912  return ret;
913  }
914  epInfo[index].bmSndToggle = 0;
915  epInfo[index].bmRcvToggle = 0;
916  // epAttribs = 0;
917  return 0;
918 }
919 
924 void BulkOnly::Reset() {
925  while (pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
926 }
927 
933 uint8_t BulkOnly::ResetRecovery() {
934  Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
935  Notify(PSTR("-----------------\r\n"), 0x80);
936 
937  delay(6);
938  Reset();
939  delay(6);
940  ClearEpHalt(epDataInIndex);
941  delay(6);
942  bLastUsbError = ClearEpHalt(epDataOutIndex);
943  delay(6);
944  return bLastUsbError;
945 }
946 
952 void BulkOnly::ClearAllEP() {
953  for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
954  epInfo[i].epAddr = 0;
955  epInfo[i].maxPktSize = (i) ? 0 : 8;
956  epInfo[i].epAttribs = 0;
957 
959  }
960 
961  for (uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) LUNOk[i] = false;
962  bIface = 0;
963  bNumEP = 1;
964 
965  bAddress = 0;
966  qNextPollTime = 0;
967  bPollEnable = false;
968  bLastUsbError = 0;
969  bMaxLUN = 0;
970  bTheLUN = 0;
971 }
972 
973 
981 bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
982  if (pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
983  Notify(PSTR("CSW:Sig error\r\n"), 0x80);
984  //printf("%lx != %lx\r\n", MASS_CSW_SIGNATURE, pcsw->dCSWSignature);
985  return false;
986  }
987  if (pcsw->dCSWTag != pcbw->dCBWTag) {
988  Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
989  //printf("%lx != %lx\r\n", pcsw->dCSWTag, pcbw->dCBWTag);
990  return false;
991  }
992  return true;
993 }
994 
1002 uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
1003  uint8_t count = 3;
1004 
1005  bLastUsbError = error;
1006  //if (error)
1007  //ClearEpHalt(index);
1008  while (error && count) {
1009  if (error != hrSUCCESS) {
1010  ErrorMessage<uint8_t > (PSTR("USB Error"), error);
1011  ErrorMessage<uint8_t > (PSTR("Index"), index);
1012  }
1013  switch (error) {
1014  // case hrWRONGPID:
1015  case hrSUCCESS:
1016  return MASS_ERR_SUCCESS;
1017  case hrBUSY:
1018  // SIE is busy, just hang out and try again.
1019  return MASS_ERR_UNIT_BUSY;
1020  case hrTIMEOUT:
1021  case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED;
1022  case hrSTALL:
1023  if (index == 0)
1024  return MASS_ERR_STALL;
1025  ClearEpHalt(index);
1026  if (index != epDataInIndex)
1027  return MASS_ERR_WRITE_STALL;
1028  return MASS_ERR_STALL;
1029 
1030  case hrNAK:
1031  if (index == 0)
1032  return MASS_ERR_UNIT_BUSY;
1033  return MASS_ERR_UNIT_BUSY;
1034  //ClearEpHalt(index);
1035  //ResetRecovery();
1036  //if (index != epDataInIndex)
1037  // return MASS_ERR_WRITE_NAKS;
1038  //return MASS_ERR_READ_NAKS;
1039  case hrTOGERR:
1040  // Handle a very super rare corner case, where toggles become de-synched.
1041  // I have only ran into one device that has this firmware bug, and this is
1042  // the only clean way to get back into sync with the buggy device firmware.
1043  // --AJK
1044  if (bAddress && bConfNum) {
1045  error = pUsb->setConf(bAddress, 0, bConfNum);
1046 
1047  if (error)
1048  break;
1049  }
1050  return MASS_ERR_SUCCESS;
1051  default:
1052  ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
1054  }
1055  count--;
1056  } // while
1057 
1058  return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
1059 }
1060 
1070 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, uint8_t flags) {
1071  uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
1072  boolean write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
1073  boolean callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
1074  uint8_t ret = 0;
1075  uint8_t usberr;
1076  CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
1077  // Fix reserved bits.
1078  pcbw->bmReserved1 = 0;
1079  pcbw->bmReserved2 = 0;
1080  ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
1081 
1082  while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
1083 
1084  ret = HandleUsbError(usberr, epDataOutIndex);
1085  //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
1086  if (ret) {
1087  ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
1088  } else {
1089  if (bytes) {
1090  if (!write) {
1091  if (callback) {
1092  uint8_t rbuf[bytes];
1093  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
1094  if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
1095  } else {
1096  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1097  }
1098  ret = HandleUsbError(usberr, epDataInIndex);
1099  } else {
1100  while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1101  ret = HandleUsbError(usberr, epDataOutIndex);
1102  }
1103  if (ret) {
1104  ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
1105  }
1106  }
1107  }
1108 
1109  //if (!ret || ret == MASS_ERR_WRITE_STALL || ret == MASS_ERR_STALL) {
1110  {
1111  bytes = sizeof (CommandStatusWrapper);
1112  int tries = 2;
1113  while (tries--) {
1114  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
1115  if (!usberr) break;
1116  ClearEpHalt(epDataInIndex);
1117  //HandleUsbError(usberr, epDataInIndex);
1118  if (tries) ResetRecovery();
1119  }
1120  if (!ret) {
1121  Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
1122  Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
1123  } else {
1124  // Throw away csw, IT IS NOT OF ANY USE.
1125  //HandleUsbError(usberr, epDataInIndex);
1126  ResetRecovery();
1127  return ret;
1128  }
1129  ret = HandleUsbError(usberr, epDataInIndex);
1130  if (ret) {
1131  ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
1132  }
1133  if (usberr == hrSUCCESS) {
1134  if (IsValidCSW(&csw, pcbw)) {
1135  //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
1136  //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
1137  //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
1138  Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
1139  return csw.bCSWStatus;
1140  } else {
1141  Notify(PSTR("Invalid CSW\r\n"), 0x80);
1142  ResetRecovery();
1143  //return MASS_ERR_SUCCESS;
1144  return MASS_ERR_INVALID_CSW;
1145  }
1146  }
1147 
1148  }
1149  return ret;
1150 }
1151 
1163 uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
1164  Notify(PSTR("\r\rModeSense\r\n"), 0x80);
1165  Notify(PSTR("------------\r\n"), 0x80);
1166 
1167  CommandBlockWrapper cbw;
1168  SetCurLUN(lun);
1169 
1171  cbw.dCBWTag = ++dCBWTag;
1172  cbw.dCBWDataTransferLength = ((uint32_t)len);
1174  cbw.bmCBWLUN = lun;
1175  cbw.bmCBWCBLength = 6;
1176 
1177  for (uint8_t i = 0; i < 16; i++)
1178  cbw.CBWCB[i] = 0;
1179 
1180  cbw.CBWCB[0] = SCSI_CMD_MODE_SENSE_6;
1181  cbw.CBWCB[2] = ((pc << 6) | page);
1182  cbw.CBWCB[3] = subpage;
1183  cbw.CBWCB[4] = len;
1184 
1185  return HandleSCSIError(Transaction(&cbw, 512, pbuf, 0));
1186 }
1187 
1194 uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
1195  if (lun > bMaxLUN)
1196  return MASS_ERR_INVALID_LUN;
1197  bTheLUN = lun;
1198  return MASS_ERR_SUCCESS;
1199 };
1200 
1207 uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
1208  uint8_t ret = 0;
1209 
1210  switch (status) {
1211  case 0: return MASS_ERR_SUCCESS;
1212  //case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
1213  // case 0x05/0x14: we stalled out
1214  // case 0x15/0x16: we naked out.
1215  case 2:
1216  ErrorMessage<uint8_t > (PSTR("Phase Error"), status);
1217  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1218  ResetRecovery();
1220  case 1:
1221  ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
1222  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1224 
1225  ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
1226 
1227  if (ret) {
1228  //ResetRecovery();
1230  }
1231  ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
1232  if (rsp.bResponseCode & 0x80) {
1233  Notify(PSTR("Information field: "), 0x80);
1234  for (int i = 0; i < 4; i++) {
1235  D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
1236  Notify(PSTR(" "), 0x80);
1237  }
1238  Notify(PSTR("\r\n"), 0x80);
1239  }
1240  ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
1241  ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
1242  ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
1243  // warning, this is not testing ASQ, only SK and ASC.
1244  switch (rsp.bmSenseKey) {
1245  /* bug...
1246  case 0:
1247  return MASS_ERR_SUCCESS;
1248  */
1249  case SCSI_S_UNIT_ATTENTION:
1250  switch (rsp.bAdditionalSenseCode) {
1252  return MASS_ERR_MEDIA_CHANGED;
1253  default:
1254  return MASS_ERR_UNIT_NOT_READY;
1255  }
1256  case SCSI_S_NOT_READY:
1257  switch (rsp.bAdditionalSenseCode) {
1259  return MASS_ERR_NO_MEDIA;
1260  //return MASS_ERR_SUCCESS;
1261  default:
1262  return MASS_ERR_UNIT_NOT_READY;
1263  }
1265  switch (rsp.bAdditionalSenseCode) {
1267  return MASS_ERR_BAD_LBA;
1268  default:
1270  }
1271  default:
1273  }
1274 
1275  default:
1276  // Should have been handled already in HandleUsbError.
1277  // ResetRecovery();
1278  ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
1279  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1280  return status; //MASS_ERR_GENERAL_SCSI_ERROR;
1281  } // switch
1282 }
1283 
1284 
1286 
1287 
1288 // Debugging code
1289 
1290 
1292 
1293 
1299  Notify(PSTR("Endpoint descriptor:"), 0x80);
1300  Notify(PSTR("\r\nLength:\t\t"), 0x80);
1301  D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
1302  Notify(PSTR("\r\nType:\t\t"), 0x80);
1303  D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
1304  Notify(PSTR("\r\nAddress:\t"), 0x80);
1305  D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
1306  Notify(PSTR("\r\nAttributes:\t"), 0x80);
1307  D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
1308  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
1309  D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
1310  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
1311  D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
1312  Notify(PSTR("\r\n"), 0x80);
1313 }
1314 
1315 
1317 
1318 
1319 // misc/to kill/to-do
1320 
1321 
1323 
1324 
1325 /* We won't be needing this... */
1326 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
1327  if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
1328 #if 0
1329  Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
1330  Notify(PSTR("---------\r\n"), 0x80);
1331 
1332  CommandBlockWrapper cbw;
1333 
1335  cbw.dCBWTag = ++dCBWTag;
1336  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
1338  cbw.bmCBWLUN = lun;
1339  cbw.bmCBWCBLength = 10;
1340 
1341  for (uint8_t i = 0; i < 16; i++)
1342  cbw.CBWCB[i] = 0;
1343 
1344  cbw.CBWCB[0] = SCSI_CMD_READ_10;
1345  cbw.CBWCB[8] = blocks;
1346  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
1347  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
1348  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
1349  cbw.CBWCB[5] = (addr & 0xff);
1350 
1351  return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
1352 #endif
1353 }
1354 
1355 #if 0
1356 // TO-DO: Unify CBW creation as much as possible.
1357 // Make and submit CBW.
1358 // if stalled, delay retry
1359 // exit on 100 retries, or anything except stall.
1360 
1361 uint8_t SubmitCBW(uint8_t cmd, uint8_t cmdsz, uint8_t lun, uint16_t bsize, uint8_t *buf, uint8_t flags) {
1362  CommandBlockWrapper cbw;
1363  SetCurLUN(lun);
1365  cbw.dCBWTag = ++dCBWTag;
1366  cbw.dCBWDataTransferLength = bsize;
1367  cbw.bmCBWFlags = flags;
1368  cbw.bmCBWLUN = lun;
1369  cbw.bmCBWCBLength = cmdsz;
1370  for (uint8_t i = 0; i < 16; i++) cbw.CBWCB[i] = 0;
1371  cbw.CBWCB[0] = cmd;
1372  cbw.CBWCB[1] = lun << 5;
1373  cbw.CBWCB[4] = bsize;
1374 }
1375 #endif