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 
66 uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
67  // promote buf_size to 32bits.
68  CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
69  //SetCurLUN(cdb->LUN);
70  return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
71 }
72 
82 uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
83  // promote buf_size to 32bits.
84  CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
85  //SetCurLUN(cdb->LUN);
86  return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
87 }
88 
97 uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
98  Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
99  Notify(PSTR("---------\r\n"), 0x80);
100 
101  CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock);
102  return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN);
103 }
104 
113 uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
114  Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
115  Notify(PSTR("-----------------\r\n"), 0x80);
116 
117  uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
118  if (bAddress) {
119  CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
120  rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);
121  } else {
122  SetCurLUN(lun);
123  }
124  return rcode;
125 }
126 
137 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
138  if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
139  Notify(PSTR("\r\nRead LUN:\t"), 0x80);
140  D_PrintHex<uint8_t > (lun, 0x90);
141  Notify(PSTR("\r\nLBA:\t\t"), 0x90);
142  D_PrintHex<uint32_t > (addr, 0x90);
143  Notify(PSTR("\r\nblocks:\t\t"), 0x90);
144  D_PrintHex<uint8_t > (blocks, 0x90);
145  Notify(PSTR("\r\nblock size:\t"), 0x90);
146  D_PrintHex<uint16_t > (bsize, 0x90);
147  Notify(PSTR("\r\n---------\r\n"), 0x80);
148  CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr);
149 
150 again:
151  uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN);
152 
153  if (er == MASS_ERR_STALL) {
154  MediaCTL(lun, 1);
155  delay(150);
156  if (!TestUnitReady(lun)) goto again;
157  }
158  return er;
159 }
160 
171 uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
172  if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
173  if (!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
174  Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
175  D_PrintHex<uint8_t > (lun, 0x90);
176  Notify(PSTR("\r\nLBA:\t\t"), 0x90);
177  D_PrintHex<uint32_t > (addr, 0x90);
178  Notify(PSTR("\r\nblocks:\t\t"), 0x90);
179  D_PrintHex<uint8_t > (blocks, 0x90);
180  Notify(PSTR("\r\nblock size:\t"), 0x90);
181  D_PrintHex<uint16_t > (bsize, 0x90);
182  Notify(PSTR("\r\n---------\r\n"), 0x80);
183  CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr);
184 
185 again:
186  uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT);
187 
188  if (er == MASS_ERR_WRITE_STALL) {
189  MediaCTL(lun, 1);
190  delay(150);
191  if (!TestUnitReady(lun)) goto again;
192  }
193  return er;
194 }
195 
196 // End of user functions, the remaining code below is driver internals.
197 // Only developer serviceable parts below!
198 
200 
201 // Main driver code
202 
204 
206 pUsb(p),
207 bAddress(0),
208 bIface(0),
209 bNumEP(1),
210 qNextPollTime(0),
211 bPollEnable(false),
212 //dCBWTag(0),
213 bLastUsbError(0) {
214  ClearAllEP();
215  dCBWTag = 0;
216  if (pUsb)
217  pUsb->RegisterDeviceClass(this);
218 }
219 
234 uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
235 
236  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
237 
238  uint8_t buf[constBufSize];
239  uint8_t rcode;
240  UsbDevice *p = NULL;
241  EpInfo *oldep_ptr = NULL;
242  USBTRACE("MS ConfigureDevice\r\n");
243  ClearAllEP();
244  AddressPool &addrPool = pUsb->GetAddressPool();
245 
246 
247  if (bAddress)
249 
250  // <TECHNICAL>
251  // Get pointer to pseudo device with address 0 assigned
252  p = addrPool.GetUsbDevicePtr(0);
253  if (!p) {
255  }
256 
257  if (!p->epinfo) {
258  USBTRACE("epinfo\r\n");
260  }
261 
262  // Save old pointer to EP_RECORD of address 0
263  oldep_ptr = p->epinfo;
264 
265  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
266  p->epinfo = epInfo;
267 
268  p->lowspeed = lowspeed;
269  // Get device descriptor
270  rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
271 
272  // Restore p->epinfo
273  p->epinfo = oldep_ptr;
274 
275  if (rcode) {
276  goto FailGetDevDescr;
277  }
278  // Allocate new address according to device class
279  bAddress = addrPool.AllocAddress(parent, false, port);
280 
281  if (!bAddress)
283 
284  // Extract Max Packet Size from the device descriptor
285  epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
286  // Steal and abuse from epInfo structure to save on memory.
287  epInfo[1].epAddr = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
288  // </TECHNICAL>
290 
291 FailGetDevDescr:
292 #ifdef DEBUG_USB_HOST
293  NotifyFailGetDevDescr(rcode);
294 #endif
296 
297 Fail:
298  Release();
299  return rcode;
300 };
301 
309 uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
310  uint8_t rcode;
311  uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
312  epInfo[1].epAddr = 0;
313  USBTRACE("MS Init\r\n");
314 
315  AddressPool &addrPool = pUsb->GetAddressPool();
316  UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
317 
318  if (!p)
320 
321  // Assign new address to the device
322  delay(2000);
323  rcode = pUsb->setAddr(0, 0, bAddress);
324 
325  if (rcode) {
326  p->lowspeed = false;
327  addrPool.FreeAddress(bAddress);
328  bAddress = 0;
329  USBTRACE2("setAddr:", rcode);
330  return rcode;
331  }
332 
333  USBTRACE2("Addr:", bAddress);
334 
335  p->lowspeed = false;
336 
337  p = addrPool.GetUsbDevicePtr(bAddress);
338 
339  if (!p)
341 
342  p->lowspeed = lowspeed;
343 
344  // Assign epInfo to epinfo pointer
345  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
346 
347  if (rcode)
348  goto FailSetDevTblEntry;
349 
350  USBTRACE2("NC:", num_of_conf);
351 
352  for (uint8_t i = 0; i < num_of_conf; i++) {
358  CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);
359 
360  rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
361 
362  if (rcode)
363  goto FailGetConfDescr;
364 
365  if (bNumEP > 1)
366  break;
367  }
368 
369  if (bNumEP < 3)
371 
372  // Assign epInfo to epinfo pointer
374 
375  USBTRACE2("Conf:", bConfNum);
376 
377  // Set Configuration Value
378  rcode = pUsb->setConf(bAddress, 0, bConfNum);
379 
380  if (rcode)
381  goto FailSetConfDescr;
382 
383  //Linux does a 1sec delay after this.
384  delay(1000);
385 
386  rcode = GetMaxLUN(&bMaxLUN);
387  if (rcode)
388  goto FailGetMaxLUN;
389 
391  ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
392 
393  delay(1000); // Delay a bit for slow firmware.
394 
395  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
396  InquiryResponse response;
397  rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
398  if (rcode) {
399  ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
400  } else {
401 #if 0
402  printf("LUN %i `", lun);
403  uint8_t *buf = response.VendorID;
404  for (int i = 0; i < 28; i++) printf("%c", buf[i]);
405  printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
406  printf("Device type %2.2X ", response.DeviceType);
407  printf("RMB %1.1X ", response.Removable);
408  printf("SSCS %1.1X ", response.SCCS);
409  uint8_t sv = response.Version;
410  printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
411  switch (sv) {
412  case 0:
413  printf("No specific");
414  break;
415  case 1:
416  printf("ANSI X3.131-1986 (ANSI 1)");
417  break;
418  case 2:
419  printf("ANSI X3.131-1994 (ANSI 2)");
420  break;
421  case 3:
422  printf("ANSI INCITS 301-1997 (SPC)");
423  break;
424  case 4:
425  printf("ANSI INCITS 351-2001 (SPC-2)");
426  break;
427  case 5:
428  printf("ANSI INCITS 408-2005 (SPC-4)");
429  break;
430  case 6:
431  printf("T10/1731-D (SPC-4)");
432  break;
433  default:
434  printf("unknown");
435  }
436  printf(" standards.\r\n");
437 #endif
438  uint8_t tries = 0xf0;
439  while (rcode = TestUnitReady(lun)) {
440  if (rcode == 0x08) break; // break on no media, this is OK to do.
441  // try to lock media and spin up
442  if (tries < 14) {
443  LockMedia(lun, 1);
444  MediaCTL(lun, 1); // I actually have a USB stick that needs this!
445  } else delay(2 * (tries + 1));
446  tries++;
447  if (!tries) break;
448  }
449  if (!rcode) {
450  delay(1000);
451  LUNOk[lun] = CheckLUN(lun);
452  if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
453  }
454  }
455  }
456 
457 
458  CheckMedia();
459 
460  rcode = OnInit();
461 
462  if (rcode)
463  goto FailOnInit;
464 
465 #ifdef DEBUG_USB_HOST
466  USBTRACE("MS configured\r\n\r\n");
467 #endif
468 
469  bPollEnable = true;
470 
471  //USBTRACE("Poll enabled\r\n");
472  return 0;
473 
474 FailSetConfDescr:
475 #ifdef DEBUG_USB_HOST
477  goto Fail;
478 #endif
479 
480 FailOnInit:
481 #ifdef DEBUG_USB_HOST
482  USBTRACE("OnInit:");
483  goto Fail;
484 #endif
485 
486 FailGetMaxLUN:
487 #ifdef DEBUG_USB_HOST
488  USBTRACE("GetMaxLUN:");
489  goto Fail;
490 #endif
491 
492 FailInvalidSectorSize:
493 #ifdef DEBUG_USB_HOST
494  USBTRACE("Sector Size is NOT VALID: ");
495  goto Fail;
496 #endif
497 
498 FailSetDevTblEntry:
499 #ifdef DEBUG_USB_HOST
501  goto Fail;
502 #endif
503 
504 FailGetConfDescr:
505 #ifdef DEBUG_USB_HOST
507 #endif
508 
509 Fail:
510 #ifdef DEBUG_USB_HOST
511  NotifyFail(rcode);
512 #endif
513  Release();
514  return rcode;
515 }
516 
526 void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) {
527  ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
528  ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
529  ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
530 
531  bConfNum = conf;
532 
533  uint8_t index;
534 
535  if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
536  index = epInterruptInIndex;
537  else
538  if ((pep->bmAttributes & 0x02) == 2)
539  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
540  else
541  return;
542 
543  // Fill in the endpoint info structure
544  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
545  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
546  epInfo[index].epAttribs = 0;
547 
548  bNumEP++;
549 
551 }
552 
558 uint8_t BulkOnly::Release() {
559  ClearAllEP();
561  return 0;
562 }
563 
570 boolean BulkOnly::CheckLUN(uint8_t lun) {
571  uint8_t rcode;
572  Capacity capacity;
573  for (uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
574 
575  rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
576  if (rcode) {
577  //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
578  return false;
579  }
580  ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
581  for (uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
582  D_PrintHex<uint8_t > (capacity.data[i], 0x80);
583  Notify(PSTR("\r\n\r\n"), 0x80);
584  // Only 512/1024/2048/4096 are valid values!
585  uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
586  if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
587  return false;
588  }
589  // Store capacity information.
590  CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
591 
592  CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
593  if (CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) {
594  // Buggy firmware will report 0xffffffff or 0 for no media
595  if (CurrentCapacity[lun])
596  ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
597  return false;
598  }
599  delay(20);
600  Page3F(lun);
601  if (!TestUnitReady(lun)) return true;
602  return false;
603 }
604 
610 void BulkOnly::CheckMedia() {
611  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
612  if (TestUnitReady(lun)) {
613  LUNOk[lun] = false;
614  continue;
615  }
616  if (!LUNOk[lun])
617  LUNOk[lun] = CheckLUN(lun);
618  }
619 #if 0
620  printf("}}}}}}}}}}}}}}}}STATUS ");
621  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
622  if (LUNOk[lun])
623  printf("#");
624  else printf(".");
625  }
626  printf("\r\n");
627 #endif
628  qNextPollTime = millis() + 2000;
629 }
630 
636 uint8_t BulkOnly::Poll() {
637  //uint8_t rcode = 0;
638 
639  if (!bPollEnable)
640  return 0;
641 
642  if (qNextPollTime <= millis()) {
643  CheckMedia();
644  }
645  //rcode = 0;
646 
647  return 0;
648 }
649 
651 
652 
653 // SCSI code
654 
655 
657 
664 uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
665  uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
666 
667  if (ret == hrSTALL)
668  *plun = 0;
669 
670  return 0;
671 }
672 
681 uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
682  Notify(PSTR("\r\nInquiry\r\n"), 0x80);
683  Notify(PSTR("---------\r\n"), 0x80);
684 
685  CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0);
686  uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
687 
688  return rc;
689 }
690 
697 uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
698  //SetCurLUN(lun);
699  if (!bAddress)
701 
702  Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
703  Notify(PSTR("-----------------\r\n"), 0x80);
704 
705  CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);
706  return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN);
707 
708 }
709 
721 uint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
722  Notify(PSTR("\r\rModeSense\r\n"), 0x80);
723  Notify(PSTR("------------\r\n"), 0x80);
724 
725  CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0);
726  return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN);
727 }
728 
737 uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
738  Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
739  Notify(PSTR("---------------\r\n"), 0x80);
740 
742  return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN);
743 }
744 
753 uint8_t BulkOnly::Page3F(uint8_t lun) {
754  uint8_t buf[192];
755  for (int i = 0; i < 192; i++) {
756  buf[i] = 0x00;
757  }
758  WriteOk[lun] = true;
759  uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
760  if (!rc) {
761  WriteOk[lun] = ((buf[2] & 0x80) == 0);
762  Notify(PSTR("Mode Sense: "), 0x80);
763  for (int i = 0; i < 4; i++) {
764  D_PrintHex<uint8_t > (buf[i], 0x80);
765  Notify(PSTR(" "), 0x80);
766  }
767  Notify(PSTR("\r\n"), 0x80);
768  }
769  return rc;
770 }
771 
780 uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
781  Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
782  Notify(PSTR("----------------\r\n"), 0x80);
783 
784  CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0);
785  CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
786  //SetCurLUN(lun);
787  return Transaction(&cbw, size, buf);
788 }
789 
790 
792 
793 
794 // USB code
795 
796 
798 
805 uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
806  if (index == 0)
807  return 0;
808 
809  uint8_t ret = 0;
810 
812  USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL))
813  == 0x01) delay(6);
814 
815  if (ret) {
816  ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
817  ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
818  return ret;
819  }
820  epInfo[index].bmSndToggle = 0;
821  epInfo[index].bmRcvToggle = 0;
822  // epAttribs = 0;
823  return 0;
824 }
825 
830 void BulkOnly::Reset() {
831  while (pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
832 }
833 
839 uint8_t BulkOnly::ResetRecovery() {
840  Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
841  Notify(PSTR("-----------------\r\n"), 0x80);
842 
843  delay(6);
844  Reset();
845  delay(6);
846  ClearEpHalt(epDataInIndex);
847  delay(6);
848  bLastUsbError = ClearEpHalt(epDataOutIndex);
849  delay(6);
850  return bLastUsbError;
851 }
852 
858 void BulkOnly::ClearAllEP() {
859  for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
860  epInfo[i].epAddr = 0;
861  epInfo[i].maxPktSize = (i) ? 0 : 8;
862  epInfo[i].epAttribs = 0;
863 
865  }
866 
867  for (uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
868  LUNOk[i] = false;
869  WriteOk[i] = false;
870  CurrentCapacity[i] = 0lu;
871  CurrentSectorSize[i] = 0;
872  }
873 
874  bIface = 0;
875  bNumEP = 1;
876  bAddress = 0;
877  qNextPollTime = 0;
878  bPollEnable = false;
879  bLastUsbError = 0;
880  bMaxLUN = 0;
881  bTheLUN = 0;
882 }
883 
891 bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
892  if (pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
893  Notify(PSTR("CSW:Sig error\r\n"), 0x80);
894  return false;
895  }
896  if (pcsw->dCSWTag != pcbw->dCBWTag) {
897  Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
898  return false;
899  }
900  return true;
901 }
902 
910 uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
911  uint8_t count = 3;
912 
913  bLastUsbError = error;
914  //if (error)
915  //ClearEpHalt(index);
916  while (error && count) {
917  if (error != hrSUCCESS) {
918  ErrorMessage<uint8_t > (PSTR("USB Error"), error);
919  ErrorMessage<uint8_t > (PSTR("Index"), index);
920  }
921  switch (error) {
922  // case hrWRONGPID:
923  case hrSUCCESS:
924  return MASS_ERR_SUCCESS;
925  case hrBUSY:
926  // SIE is busy, just hang out and try again.
927  return MASS_ERR_UNIT_BUSY;
928  case hrTIMEOUT:
930  case hrSTALL:
931  if (index == 0)
932  return MASS_ERR_STALL;
933  ClearEpHalt(index);
934  if (index != epDataInIndex)
935  return MASS_ERR_WRITE_STALL;
936  return MASS_ERR_STALL;
937 
938  case hrNAK:
939  if (index == 0)
940  return MASS_ERR_UNIT_BUSY;
941  return MASS_ERR_UNIT_BUSY;
942 
943  case hrTOGERR:
944  // Handle a very super rare corner case, where toggles become de-synched.
945  // I have only ran into one device that has this firmware bug, and this is
946  // the only clean way to get back into sync with the buggy device firmware.
947  // --AJK
948  if (bAddress && bConfNum) {
949  error = pUsb->setConf(bAddress, 0, bConfNum);
950 
951  if (error)
952  break;
953  }
954  return MASS_ERR_SUCCESS;
955  default:
956  ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
958  }
959  count--;
960  } // while
961 
962  return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
963 }
964 
965 #if MS_WANT_PARSER
966 
967 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
968  return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
969 }
970 #endif
971 
981 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
982 #if MS_WANT_PARSER
983  , uint8_t flags
984 #endif
985  ) {
986 
987 #if MS_WANT_PARSER
988  uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
989  printf("Transfersize %i\r\n", bytes);
990  delay(1000);
991 
992  boolean callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
993 #else
994  uint16_t bytes = buf_size;
995 #endif
996  boolean write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
997  uint8_t ret = 0;
998  uint8_t usberr;
999  CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
1000  SetCurLUN(pcbw->bmCBWLUN);
1001  ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
1002 
1003  while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
1004 
1005  ret = HandleUsbError(usberr, epDataOutIndex);
1006  //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
1007  if (ret) {
1008  ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
1009  } else {
1010  if (bytes) {
1011  if (!write) {
1012 #if MS_WANT_PARSER
1013  if (callback) {
1014  uint8_t rbuf[bytes];
1015  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
1016  if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
1017  } else {
1018 #endif
1019  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1020 #if MS_WANT_PARSER
1021 
1022  }
1023 #endif
1024  ret = HandleUsbError(usberr, epDataInIndex);
1025  } else {
1026  while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1027  ret = HandleUsbError(usberr, epDataOutIndex);
1028  }
1029  if (ret) {
1030  ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
1031  }
1032  }
1033  }
1034 
1035  {
1036  bytes = sizeof (CommandStatusWrapper);
1037  int tries = 2;
1038  while (tries--) {
1039  while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
1040  if (!usberr) break;
1041  ClearEpHalt(epDataInIndex);
1042  if (tries) ResetRecovery();
1043  }
1044  if (!ret) {
1045  Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
1046  Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
1047  } else {
1048  // Throw away csw, IT IS NOT OF ANY USE.
1049  ResetRecovery();
1050  return ret;
1051  }
1052  ret = HandleUsbError(usberr, epDataInIndex);
1053  if (ret) {
1054  ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
1055  }
1056  if (usberr == hrSUCCESS) {
1057  if (IsValidCSW(&csw, pcbw)) {
1058  //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
1059  //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
1060  //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
1061  Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
1062  return csw.bCSWStatus;
1063  } else {
1064  // NOTE! Sometimes this is caused by the reported residue being wrong.
1065  // Get a different device. It isn't compliant, and should have never passed Q&A.
1066  // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
1067  // Other devices that exhibit this behavior exist in the wild too.
1068  // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk
1069  Notify(PSTR("Invalid CSW\r\n"), 0x80);
1070  ResetRecovery();
1071  //return MASS_ERR_SUCCESS;
1072  return MASS_ERR_INVALID_CSW;
1073  }
1074  }
1075  }
1076  return ret;
1077 }
1078 
1085 uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
1086  if (lun > bMaxLUN)
1087  return MASS_ERR_INVALID_LUN;
1088  bTheLUN = lun;
1089  return MASS_ERR_SUCCESS;
1090 };
1091 
1098 uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
1099  uint8_t ret = 0;
1100 
1101  switch (status) {
1102  case 0: return MASS_ERR_SUCCESS;
1103 
1104  case 2:
1105  ErrorMessage<uint8_t > (PSTR("Phase Error"), status);
1106  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1107  ResetRecovery();
1109 
1110  case 1:
1111  ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
1112  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1114 
1115  ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
1116 
1117  if (ret) {
1119  }
1120  ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
1121  if (rsp.bResponseCode & 0x80) {
1122  Notify(PSTR("Information field: "), 0x80);
1123  for (int i = 0; i < 4; i++) {
1124  D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
1125  Notify(PSTR(" "), 0x80);
1126  }
1127  Notify(PSTR("\r\n"), 0x80);
1128  }
1129  ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
1130  ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
1131  ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
1132  // warning, this is not testing ASQ, only SK and ASC.
1133  switch (rsp.bmSenseKey) {
1134  case SCSI_S_UNIT_ATTENTION:
1135  switch (rsp.bAdditionalSenseCode) {
1137  return MASS_ERR_MEDIA_CHANGED;
1138  default:
1139  return MASS_ERR_UNIT_NOT_READY;
1140  }
1141  case SCSI_S_NOT_READY:
1142  switch (rsp.bAdditionalSenseCode) {
1144  return MASS_ERR_NO_MEDIA;
1145  default:
1146  return MASS_ERR_UNIT_NOT_READY;
1147  }
1149  switch (rsp.bAdditionalSenseCode) {
1151  return MASS_ERR_BAD_LBA;
1152  default:
1154  }
1155  default:
1157  }
1158 
1159  // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
1160  // case 0x05/0x14: we stalled out
1161  // case 0x15/0x16: we naked out.
1162  default:
1163  ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
1164  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1165  return status;
1166  } // switch
1167 }
1168 
1169 
1171 
1172 
1173 // Debugging code
1174 
1175 
1177 
1183  Notify(PSTR("Endpoint descriptor:"), 0x80);
1184  Notify(PSTR("\r\nLength:\t\t"), 0x80);
1185  D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
1186  Notify(PSTR("\r\nType:\t\t"), 0x80);
1187  D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
1188  Notify(PSTR("\r\nAddress:\t"), 0x80);
1189  D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
1190  Notify(PSTR("\r\nAttributes:\t"), 0x80);
1191  D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
1192  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
1193  D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
1194  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
1195  D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
1196  Notify(PSTR("\r\n"), 0x80);
1197 }
1198 
1199 
1201 
1202 
1203 // misc/to kill/to-do
1204 
1205 
1207 
1208 /* We won't be needing this... */
1209 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
1210 #if MS_WANT_PARSER
1211  if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
1212  Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
1213  Notify(PSTR("---------\r\n"), 0x80);
1214 
1216 
1218  cbw.dCBWTag = ++dCBWTag;
1219  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
1221  cbw.bmCBWLUN = lun;
1222  cbw.bmCBWCBLength = 10;
1223 
1224  cbw.CBWCB[0] = SCSI_CMD_READ_10;
1225  cbw.CBWCB[8] = blocks;
1226  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
1227  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
1228  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
1229  cbw.CBWCB[5] = (addr & 0xff);
1230 
1231  return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
1232 #else
1233  return MASS_ERR_NOT_IMPLEMENTED;
1234 #endif
1235 }
#define MASS_ERR_UNIT_BUSY
Definition: masstorage.h:137
#define SCSI_S_ILLEGAL_REQUEST
Definition: masstorage.h:127
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:764
uint8_t bmRcvToggle
Definition: address.h:41
uint8_t MediaCTL(uint8_t lun, uint8_t ctl)
Definition: masstorage.cpp:113
#define MASS_ERR_STALL
Definition: masstorage.h:138
#define USB_SETUP_HOST_TO_DEVICE
Definition: usb_ch9.h:51
uint8_t VendorID[8]
Definition: masstorage.h:348
EpInfo * epinfo
Definition: address.h:76
static const uint8_t epDataOutIndex
Definition: masstorage.h:448
#define CP_MASK_COMPARE_PROTOCOL
#define MASS_CMD_DIR_OUT
Definition: masstorage.h:42
bool lowspeed
Definition: address.h:79
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:67
#define hrSTALL
Definition: max3421e.h:217
uint8_t bmNakPower
Definition: address.h:42
unsigned Removable
Definition: masstorage.h:310
bool LUNOk[MASS_MAX_SUPPORTED_LUN]
Definition: masstorage.h:468
uint8_t CBWCB[16]
Definition: masstorage.h:380
#define SCSI_ASC_MEDIA_CHANGED
Definition: masstorage.h:130
static const uint8_t epInterruptInIndex
Definition: masstorage.h:449
#define MASS_ERR_MEDIA_CHANGED
Definition: masstorage.h:143
CDB10 CDB10_t
Definition: masstorage.h:237
#define MASS_ERR_NO_MEDIA
Definition: masstorage.h:141
#define USB_CLASS_MASS_STORAGE
Definition: UsbCore.h:47
#define MASS_SUBCLASS_SCSI
Definition: masstorage.h:21
#define SCSI_CMD_PREVENT_REMOVAL
Definition: masstorage.h:62
#define SCSI_S_UNIT_ATTENTION
Definition: masstorage.h:128
#define MASS_ERR_BAD_LBA
Definition: masstorage.h:142
uint8_t bAddress
Definition: masstorage.h:452
#define MS_WANT_PARSER
Definition: masstorage.h:6
#define USB_REQUEST_CLEAR_FEATURE
Definition: usb_ch9.h:34
#define NotifyFail(...)
Definition: message.h:55
uint32_t dCBWTag
Definition: masstorage.h:461
uint8_t bConfNum
Definition: masstorage.h:453
virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed)
Definition: masstorage.cpp:234
#define MASS_ERR_INVALID_CSW
Definition: masstorage.h:140
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:798
#define SCSI_CMD_TEST_UNIT_READY
Definition: masstorage.h:53
#define MASS_ERR_WRITE_PROTECTED
Definition: masstorage.h:150
uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]
Definition: masstorage.h:466
virtual uint8_t Poll()
Definition: masstorage.cpp:636
bool WriteOk[MASS_MAX_SUPPORTED_LUN]
Definition: masstorage.h:469
#define MASS_MAX_SUPPORTED_LUN
Definition: settings.h:47
uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir)
Definition: masstorage.cpp:82
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)
virtual uint8_t Release()
Definition: masstorage.cpp:558
#define MASS_TRANS_FLG_CALLBACK
Definition: masstorage.h:156
#define USB_ERROR_FailGetDevDescr
Definition: UsbCore.h:73
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf)
Definition: masstorage.cpp:137
#define NotifyFailGetDevDescr(...)
Definition: message.h:50
#define hrJERR
Definition: max3421e.h:225
uint32_t dCBWDataTransferLength
Definition: masstorage.h:356
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition: Usb.cpp:64
#define CP_MASK_COMPARE_CLASS
uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir)
Definition: masstorage.cpp:66
#define hrSUCCESS
Definition: max3421e.h:212
#define MASS_ERR_GENERAL_USB_ERROR
Definition: masstorage.h:153
virtual void FreeAddress(uint8_t addr)=0
#define MASS_CMD_DIR_IN
Definition: masstorage.h:43
uint32_t GetCapacity(uint8_t lun)
Definition: masstorage.cpp:19
uint8_t epAttribs
Definition: address.h:37
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
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
#define Notify(...)
Definition: message.h:44
#define USB_FEATURE_ENDPOINT_HALT
Definition: usb_ch9.h:45
#define USBTRACE2(s, r)
Definition: macros.h:61
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:793
#define NotifyFailGetConfDescr(...)
Definition: message.h:52
uint8_t bLastUsbError
Definition: masstorage.h:463
#define SCSI_CMD_READ_10
Definition: masstorage.h:66
static const uint8_t epDataInIndex
Definition: masstorage.h:447
uint8_t epAddr
Definition: address.h:33
uint8_t PeripheralQualifier
Definition: masstorage.h:307
uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]
Definition: masstorage.h:467
#define USB_SETUP_RECIPIENT_ENDPOINT
Definition: usb_ch9.h:58
#define MASS_MAX_ENDPOINTS
Definition: masstorage.h:160
#define SCSI_ASC_MEDIUM_NOT_PRESENT
Definition: masstorage.h:131
virtual uint8_t OnInit()
Definition: masstorage.h:475
uint32_t qNextPollTime
Definition: masstorage.h:456
#define MASS_PROTO_BBB
Definition: masstorage.h:29
bool LUNIsGood(uint8_t lun)
Definition: masstorage.cpp:43
#define bmREQ_MASSOUT
Definition: masstorage.h:11
#define hrBUSY
Definition: max3421e.h:213
#define MASS_REQ_GET_MAX_LUN
Definition: masstorage.h:36
Definition: address.h:32
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
Definition: Usb.cpp:290
#define MASS_ERR_NOT_IMPLEMENTED
Definition: masstorage.h:151
uint16_t GetSectorSize(uint8_t lun)
Definition: masstorage.cpp:31
#define hrNAK
Definition: max3421e.h:216
#define MASS_ERR_SUCCESS
Definition: masstorage.h:134
#define MASS_ERR_GENERAL_SCSI_ERROR
Definition: masstorage.h:152
uint16_t wMaxPacketSize
Definition: usb_ch9.h:146
#define MASS_ERR_DEVICE_DISCONNECTED
Definition: masstorage.h:144
bool bPollEnable
Definition: masstorage.h:457
#define CP_MASK_COMPARE_SUBCLASS
uint8_t LockMedia(uint8_t lun, uint8_t lock)
Definition: masstorage.cpp:97
CDB6 CDB6_t
Definition: masstorage.h:203
EpInfo epInfo[MASS_MAX_ENDPOINTS]
Definition: masstorage.h:459
#define MASS_ERR_WRITE_STALL
Definition: masstorage.h:147
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
uint8_t bEndpointAddress
Definition: usb_ch9.h:144
unsigned SCCS
Definition: masstorage.h:328
uint8_t bmSndToggle
Definition: address.h:40
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:69
uint8_t bTheLUN
Definition: masstorage.h:465
BulkOnly(USB *p)
Definition: masstorage.cpp:205
#define SCSI_S_NOT_READY
Definition: masstorage.h:125
#define SCSI_CMD_START_STOP_UNIT
Definition: masstorage.h:61
#define bmREQ_MASSIN
Definition: masstorage.h:12
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:66
uint8_t DeviceType
Definition: masstorage.h:306
uint8_t bIface
Definition: masstorage.h:454
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data)
Definition: Usb.cpp:206
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:61
#define hrTIMEOUT
Definition: max3421e.h:226
#define MASS_ERR_UNIT_NOT_READY
Definition: masstorage.h:136
#define SCSI_CMD_READ_CAPACITY_10
Definition: masstorage.h:65
#define USB_NAK_DEFAULT
Definition: address.h:28
#define MASS_ERR_CMD_NOT_SUPPORTED
Definition: masstorage.h:139
#define MASS_CSW_SIGNATURE
Definition: masstorage.h:40
uint8_t bMaxLUN
Definition: masstorage.h:464
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:64
uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf)
Definition: masstorage.cpp:171
#define SCSI_CMD_INQUIRY
Definition: masstorage.h:58
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: masstorage.cpp:526
uint8_t maxPktSize
Definition: address.h:34
AddressPool & GetAddressPool()
Definition: UsbCore.h:168
#define SCSI_ASC_LBA_OUT_OF_RANGE
Definition: masstorage.h:129
#define USB_SETUP_TYPE_STANDARD
Definition: usb_ch9.h:53
Definition: UsbCore.h:152
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: masstorage.cpp:309
uint8_t data[8]
Definition: masstorage.h:163
boolean WriteProtected(uint8_t lun)
Definition: masstorage.cpp:53
uint32_t dCSWSignature
Definition: masstorage.h:420
#define BMAKE32(__usc3__, __usc2__, __usc1__, __usc0__)
Definition: macros.h:53
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition: UsbCore.h:172
#define NotifyFailSetConfDescr(...)
Definition: message.h:53
uint8_t Version
Definition: masstorage.h:312
#define hrTOGERR
Definition: max3421e.h:218
#define MASS_CBW_SIGNATURE
Definition: masstorage.h:39
#define MASS_ERR_INVALID_LUN
Definition: masstorage.h:146
#define MASS_REQ_BOMSR
Definition: masstorage.h:37
uint8_t bNumEP
Definition: masstorage.h:455
USB * pUsb
Definition: masstorage.h:451
#define USBTRACE(s)
Definition: macros.h:60
#define SCSI_CMD_REQUEST_SENSE
Definition: masstorage.h:54
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition: Usb.cpp:759
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:51
#define SCSI_CMD_WRITE_10
Definition: masstorage.h:67
#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET
Definition: UsbCore.h:72