USB Host Shield 2.0
masstorage.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2 
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9 
10 Contact information
11 -------------------
12 
13 Circuits At Home, LTD
14 Web : http://www.circuitsathome.com
15 e-mail : support@circuitsathome.com
16  */
17 
18 #include "masstorage.h"
19 
20 const uint8_t BulkOnly::epDataInIndex = 1;
21 const uint8_t BulkOnly::epDataOutIndex = 2;
22 const uint8_t BulkOnly::epInterruptInIndex = 3;
23 
25 
26 // Interface code
27 
29 
36 uint32_t BulkOnly::GetCapacity(uint8_t lun) {
37  if(LUNOk[lun])
38  return CurrentCapacity[lun];
39  return 0LU;
40 }
41 
48 uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
49  if(LUNOk[lun])
50  return CurrentSectorSize[lun];
51  return 0U;
52 }
53 
60 bool BulkOnly::LUNIsGood(uint8_t lun) {
61  return LUNOk[lun];
62 }
63 
70 bool BulkOnly::WriteProtected(uint8_t lun) {
71  return WriteOk[lun];
72 }
73 
83 uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
84  // promote buf_size to 32bits.
85  CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
86  //SetCurLUN(cdb->LUN);
87  return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
88 }
89 
99 uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
100  // promote buf_size to 32bits.
101  CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
102  //SetCurLUN(cdb->LUN);
103  return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
104 }
105 
114 uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
115  Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
116  Notify(PSTR("---------\r\n"), 0x80);
117 
118  CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock);
119  return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN);
120 }
121 
130 uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
131  Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
132  Notify(PSTR("-----------------\r\n"), 0x80);
133 
134  uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
135  if(bAddress) {
136  CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
137  rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);
138  } else {
139  SetCurLUN(lun);
140  }
141  return rcode;
142 }
143 
154 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
155  if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
156  Notify(PSTR("\r\nRead LUN:\t"), 0x80);
157  D_PrintHex<uint8_t > (lun, 0x90);
158  Notify(PSTR("\r\nLBA:\t\t"), 0x90);
159  D_PrintHex<uint32_t > (addr, 0x90);
160  Notify(PSTR("\r\nblocks:\t\t"), 0x90);
161  D_PrintHex<uint8_t > (blocks, 0x90);
162  Notify(PSTR("\r\nblock size:\t"), 0x90);
163  D_PrintHex<uint16_t > (bsize, 0x90);
164  Notify(PSTR("\r\n---------\r\n"), 0x80);
165  CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr);
166 
167 again:
168  uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN);
169 
170  if(er == MASS_ERR_STALL) {
171  MediaCTL(lun, 1);
172  delay(150);
173  if(!TestUnitReady(lun)) goto again;
174  }
175  return er;
176 }
177 
188 uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
189  if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
190  if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
191  Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
192  D_PrintHex<uint8_t > (lun, 0x90);
193  Notify(PSTR("\r\nLBA:\t\t"), 0x90);
194  D_PrintHex<uint32_t > (addr, 0x90);
195  Notify(PSTR("\r\nblocks:\t\t"), 0x90);
196  D_PrintHex<uint8_t > (blocks, 0x90);
197  Notify(PSTR("\r\nblock size:\t"), 0x90);
198  D_PrintHex<uint16_t > (bsize, 0x90);
199  Notify(PSTR("\r\n---------\r\n"), 0x80);
200  CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr);
201 
202 again:
203  uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT);
204 
205  if(er == MASS_ERR_WRITE_STALL) {
206  MediaCTL(lun, 1);
207  delay(150);
208  if(!TestUnitReady(lun)) goto again;
209  }
210  return er;
211 }
212 
213 // End of user functions, the remaining code below is driver internals.
214 // Only developer serviceable parts below!
215 
217 
218 // Main driver code
219 
221 
223 pUsb(p),
224 bAddress(0),
225 bIface(0),
226 bNumEP(1),
227 qNextPollTime(0),
228 bPollEnable(false),
229 //dCBWTag(0),
230 bLastUsbError(0) {
231  ClearAllEP();
232  dCBWTag = 0;
233  if(pUsb)
234  pUsb->RegisterDeviceClass(this);
235 }
236 
251 uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
252 
253  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
254 
255  uint8_t buf[constBufSize];
256  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
257  uint8_t rcode;
258  UsbDevice *p = NULL;
259  EpInfo *oldep_ptr = NULL;
260  USBTRACE("MS ConfigureDevice\r\n");
261  ClearAllEP();
262  AddressPool &addrPool = pUsb->GetAddressPool();
263 
264 
265  if(bAddress)
267 
268  // <TECHNICAL>
269  // Get pointer to pseudo device with address 0 assigned
270  p = addrPool.GetUsbDevicePtr(0);
271  if(!p) {
273  }
274 
275  if(!p->epinfo) {
276  USBTRACE("epinfo\r\n");
278  }
279 
280  // Save old pointer to EP_RECORD of address 0
281  oldep_ptr = p->epinfo;
282 
283  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
284  p->epinfo = epInfo;
285 
286  p->lowspeed = lowspeed;
287  // Get device descriptor
288  rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
289 
290  // Restore p->epinfo
291  p->epinfo = oldep_ptr;
292 
293  if(rcode) {
294  goto FailGetDevDescr;
295  }
296  // Allocate new address according to device class
297  bAddress = addrPool.AllocAddress(parent, false, port);
298 
299  if(!bAddress)
301 
302  // Extract Max Packet Size from the device descriptor
304  // Steal and abuse from epInfo structure to save on memory.
305  epInfo[1].epAddr = udd->bNumConfigurations;
306  // </TECHNICAL>
308 
309 FailGetDevDescr:
310 #ifdef DEBUG_USB_HOST
311  NotifyFailGetDevDescr(rcode);
312 #endif
314 
315  Release();
316  return rcode;
317 };
318 
326 uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
327  uint8_t rcode;
328  uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
329  epInfo[1].epAddr = 0;
330  USBTRACE("MS Init\r\n");
331 
332  AddressPool &addrPool = pUsb->GetAddressPool();
333  UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
334 
335  if(!p)
337 
338  // Assign new address to the device
339  delay(2000);
340  rcode = pUsb->setAddr(0, 0, bAddress);
341 
342  if(rcode) {
343  p->lowspeed = false;
344  addrPool.FreeAddress(bAddress);
345  bAddress = 0;
346  USBTRACE2("setAddr:", rcode);
347  return rcode;
348  }
349 
350  USBTRACE2("Addr:", bAddress);
351 
352  p->lowspeed = false;
353 
354  p = addrPool.GetUsbDevicePtr(bAddress);
355 
356  if(!p)
358 
359  p->lowspeed = lowspeed;
360 
361  // Assign epInfo to epinfo pointer
362  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
363 
364  if(rcode)
365  goto FailSetDevTblEntry;
366 
367  USBTRACE2("NC:", num_of_conf);
368 
369  for(uint8_t i = 0; i < num_of_conf; i++) {
375  CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);
376 
377  rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
378 
379  if(rcode)
380  goto FailGetConfDescr;
381 
382  if(bNumEP > 1)
383  break;
384  }
385 
386  if(bNumEP < 3)
388 
389  // Assign epInfo to epinfo pointer
391 
392  USBTRACE2("Conf:", bConfNum);
393 
394  // Set Configuration Value
395  rcode = pUsb->setConf(bAddress, 0, bConfNum);
396 
397  if(rcode)
398  goto FailSetConfDescr;
399 
400  //Linux does a 1sec delay after this.
401  delay(1000);
402 
403  rcode = GetMaxLUN(&bMaxLUN);
404  if(rcode)
405  goto FailGetMaxLUN;
406 
408  ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
409 
410  delay(1000); // Delay a bit for slow firmware.
411 
412  for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
413  InquiryResponse response;
414  rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
415  if(rcode) {
416  ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
417  } else {
418 #if 0
419  printf("LUN %i `", lun);
420  uint8_t *buf = response.VendorID;
421  for(int i = 0; i < 28; i++) printf("%c", buf[i]);
422  printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
423  printf("Device type %2.2X ", response.DeviceType);
424  printf("RMB %1.1X ", response.Removable);
425  printf("SSCS %1.1X ", response.SCCS);
426  uint8_t sv = response.Version;
427  printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
428  switch(sv) {
429  case 0:
430  printf("No specific");
431  break;
432  case 1:
433  printf("ANSI X3.131-1986 (ANSI 1)");
434  break;
435  case 2:
436  printf("ANSI X3.131-1994 (ANSI 2)");
437  break;
438  case 3:
439  printf("ANSI INCITS 301-1997 (SPC)");
440  break;
441  case 4:
442  printf("ANSI INCITS 351-2001 (SPC-2)");
443  break;
444  case 5:
445  printf("ANSI INCITS 408-2005 (SPC-4)");
446  break;
447  case 6:
448  printf("T10/1731-D (SPC-4)");
449  break;
450  default:
451  printf("unknown");
452  }
453  printf(" standards.\r\n");
454 #endif
455  uint8_t tries = 0xf0;
456  while((rcode = TestUnitReady(lun))) {
457  if(rcode == 0x08) break; // break on no media, this is OK to do.
458  // try to lock media and spin up
459  if(tries < 14) {
460  LockMedia(lun, 1);
461  MediaCTL(lun, 1); // I actually have a USB stick that needs this!
462  } else delay(2 * (tries + 1));
463  tries++;
464  if(!tries) break;
465  }
466  if(!rcode) {
467  delay(1000);
468  LUNOk[lun] = CheckLUN(lun);
469  if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
470  }
471  }
472  }
473 
474 
475  CheckMedia();
476 
477  rcode = OnInit();
478 
479  if(rcode)
480  goto FailOnInit;
481 
482 #ifdef DEBUG_USB_HOST
483  USBTRACE("MS configured\r\n\r\n");
484 #endif
485 
486  bPollEnable = true;
487 
488  //USBTRACE("Poll enabled\r\n");
489  return 0;
490 
491 FailSetConfDescr:
492 #ifdef DEBUG_USB_HOST
494  goto Fail;
495 #endif
496 
497 FailOnInit:
498 #ifdef DEBUG_USB_HOST
499  USBTRACE("OnInit:");
500  goto Fail;
501 #endif
502 
503 FailGetMaxLUN:
504 #ifdef DEBUG_USB_HOST
505  USBTRACE("GetMaxLUN:");
506  goto Fail;
507 #endif
508 
509  //#ifdef DEBUG_USB_HOST
510  //FailInvalidSectorSize:
511  // USBTRACE("Sector Size is NOT VALID: ");
512  // goto Fail;
513  //#endif
514 
515 FailSetDevTblEntry:
516 #ifdef DEBUG_USB_HOST
518  goto Fail;
519 #endif
520 
521 FailGetConfDescr:
522 #ifdef DEBUG_USB_HOST
524 #endif
525 
526 #ifdef DEBUG_USB_HOST
527 Fail:
528  NotifyFail(rcode);
529 #endif
530  Release();
531  return rcode;
532 }
533 
543 void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) {
544  ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
545  ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
546  ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
547 
548  bConfNum = conf;
549 
550  uint8_t index;
551 
552 #if 1
553  if((pep->bmAttributes & 0x02) == 2) {
554  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
555  // Fill in the endpoint info structure
556  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
557  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
558  epInfo[index].bmSndToggle = 0;
559  epInfo[index].bmRcvToggle = 0;
560 
561  bNumEP++;
562 
564 
565  }
566 #else
567  if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
568  index = epInterruptInIndex;
569  else
570  if((pep->bmAttributes & 0x02) == 2)
571  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
572  else
573  return;
574 
575  // Fill in the endpoint info structure
576  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
577  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
578  epInfo[index].bmSndToggle = 0;
579  epInfo[index].bmRcvToggle = 0;
580 
581  bNumEP++;
582 
584 #endif
585 }
586 
592 uint8_t BulkOnly::Release() {
593  ClearAllEP();
595  return 0;
596 }
597 
604 bool BulkOnly::CheckLUN(uint8_t lun) {
605  uint8_t rcode;
606  Capacity capacity;
607  for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
608 
609  rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
610  if(rcode) {
611  //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
612  return false;
613  }
614  ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
615  for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
616  D_PrintHex<uint8_t > (capacity.data[i], 0x80);
617  Notify(PSTR("\r\n\r\n"), 0x80);
618  // Only 512/1024/2048/4096 are valid values!
619  uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
620  if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
621  return false;
622  }
623  // Store capacity information.
624  CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
625 
626  CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
627  if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) {
628  // Buggy firmware will report 0xffffffff or 0 for no media
629  if(CurrentCapacity[lun])
630  ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
631  return false;
632  }
633  delay(20);
634  Page3F(lun);
635  if(!TestUnitReady(lun)) return true;
636  return false;
637 }
638 
644 void BulkOnly::CheckMedia() {
645  for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
646  if(TestUnitReady(lun)) {
647  LUNOk[lun] = false;
648  continue;
649  }
650  if(!LUNOk[lun])
651  LUNOk[lun] = CheckLUN(lun);
652  }
653 #if 0
654  printf("}}}}}}}}}}}}}}}}STATUS ");
655  for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
656  if(LUNOk[lun])
657  printf("#");
658  else printf(".");
659  }
660  printf("\r\n");
661 #endif
662  qNextPollTime = millis() + 2000;
663 }
664 
670 uint8_t BulkOnly::Poll() {
671  //uint8_t rcode = 0;
672 
673  if(!bPollEnable)
674  return 0;
675 
676  if((long)(millis() - qNextPollTime) >= 0L) {
677  CheckMedia();
678  }
679  //rcode = 0;
680 
681  return 0;
682 }
683 
685 
686 
687 // SCSI code
688 
689 
691 
698 uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
699  uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
700 
701  if(ret == hrSTALL)
702  *plun = 0;
703 
704  return 0;
705 }
706 
715 uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
716  Notify(PSTR("\r\nInquiry\r\n"), 0x80);
717  Notify(PSTR("---------\r\n"), 0x80);
718 
719  CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0);
720  uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
721 
722  return rc;
723 }
724 
731 uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
732  //SetCurLUN(lun);
733  if(!bAddress)
735 
736  Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
737  Notify(PSTR("-----------------\r\n"), 0x80);
738 
739  CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);
740  return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN);
741 
742 }
743 
755 uint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
756  Notify(PSTR("\r\rModeSense\r\n"), 0x80);
757  Notify(PSTR("------------\r\n"), 0x80);
758 
759  CDB6_t cdb = CDB6_t(SCSI_CMD_MODE_SENSE_6, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0);
760  return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN);
761 }
762 
771 uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
772  Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
773  Notify(PSTR("---------------\r\n"), 0x80);
774 
776  return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN);
777 }
778 
787 uint8_t BulkOnly::Page3F(uint8_t lun) {
788  uint8_t buf[192];
789  for(int i = 0; i < 192; i++) {
790  buf[i] = 0x00;
791  }
792  WriteOk[lun] = true;
793  uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
794  if(!rc) {
795  WriteOk[lun] = ((buf[2] & 0x80) == 0);
796  Notify(PSTR("Mode Sense: "), 0x80);
797  for(int i = 0; i < 4; i++) {
798  D_PrintHex<uint8_t > (buf[i], 0x80);
799  Notify(PSTR(" "), 0x80);
800  }
801  Notify(PSTR("\r\n"), 0x80);
802  }
803  return rc;
804 }
805 
814 uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
815  Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
816  Notify(PSTR("----------------\r\n"), 0x80);
817 
818  CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0);
819  CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
820  //SetCurLUN(lun);
821  return Transaction(&cbw, size, buf);
822 }
823 
824 
826 
827 
828 // USB code
829 
830 
832 
839 uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
840  if(index == 0)
841  return 0;
842 
843  uint8_t ret = 0;
844 
846  delay(6);
847 
848  if(ret) {
849  ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
850  ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
851  return ret;
852  }
853  epInfo[index].bmSndToggle = 0;
854  epInfo[index].bmRcvToggle = 0;
855  return 0;
856 }
857 
862 void BulkOnly::Reset() {
863  while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
864 }
865 
871 uint8_t BulkOnly::ResetRecovery() {
872  Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
873  Notify(PSTR("-----------------\r\n"), 0x80);
874 
875  delay(6);
876  Reset();
877  delay(6);
878  ClearEpHalt(epDataInIndex);
879  delay(6);
880  bLastUsbError = ClearEpHalt(epDataOutIndex);
881  delay(6);
882  return bLastUsbError;
883 }
884 
890 void BulkOnly::ClearAllEP() {
891  for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
892  epInfo[i].epAddr = 0;
893  epInfo[i].maxPktSize = (i) ? 0 : 8;
894  epInfo[i].bmSndToggle = 0;
895  epInfo[i].bmRcvToggle = 0;
897  }
898 
899  for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
900  LUNOk[i] = false;
901  WriteOk[i] = false;
902  CurrentCapacity[i] = 0lu;
903  CurrentSectorSize[i] = 0;
904  }
905 
906  bIface = 0;
907  bNumEP = 1;
908  bAddress = 0;
909  qNextPollTime = 0;
910  bPollEnable = false;
911  bLastUsbError = 0;
912  bMaxLUN = 0;
913  bTheLUN = 0;
914 }
915 
923 bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
924  if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
925  Notify(PSTR("CSW:Sig error\r\n"), 0x80);
926  return false;
927  }
928  if(pcsw->dCSWTag != pcbw->dCBWTag) {
929  Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
930  return false;
931  }
932  return true;
933 }
934 
942 uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
943  uint8_t count = 3;
944 
945  bLastUsbError = error;
946  //if (error)
947  //ClearEpHalt(index);
948  while(error && count) {
949  if(error != hrSUCCESS) {
950  ErrorMessage<uint8_t > (PSTR("USB Error"), error);
951  ErrorMessage<uint8_t > (PSTR("Index"), index);
952  }
953  switch(error) {
954  // case hrWRONGPID:
955  case hrSUCCESS:
956  return MASS_ERR_SUCCESS;
957  case hrBUSY:
958  // SIE is busy, just hang out and try again.
959  return MASS_ERR_UNIT_BUSY;
960  case hrTIMEOUT:
962  case hrSTALL:
963  if(index == 0)
964  return MASS_ERR_STALL;
965  ClearEpHalt(index);
966  if(index != epDataInIndex)
967  return MASS_ERR_WRITE_STALL;
968  return MASS_ERR_STALL;
969 
970  case hrNAK:
971  if(index == 0)
972  return MASS_ERR_UNIT_BUSY;
973  return MASS_ERR_UNIT_BUSY;
974 
975  case hrTOGERR:
976  // Handle a very super rare corner case, where toggles become de-synched.
977  // I have only ran into one device that has this firmware bug, and this is
978  // the only clean way to get back into sync with the buggy device firmware.
979  // --AJK
980  if(bAddress && bConfNum) {
981  error = pUsb->setConf(bAddress, 0, bConfNum);
982 
983  if(error)
984  break;
985  }
986  return MASS_ERR_SUCCESS;
987  default:
988  ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
990  }
991  count--;
992  } // while
993 
994  return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
995 }
996 
997 #if MS_WANT_PARSER
998 
999 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
1000  return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
1001 }
1002 #endif
1003 
1013 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
1014 #if MS_WANT_PARSER
1015  , uint8_t flags
1016 #endif
1017  ) {
1018 
1019 #if MS_WANT_PARSER
1020  uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
1021  printf("Transfersize %i\r\n", bytes);
1022  delay(1000);
1023 
1024  bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
1025 #else
1026  uint16_t bytes = buf_size;
1027 #endif
1028  bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
1029  uint8_t ret = 0;
1030  uint8_t usberr;
1031  CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
1032  SetCurLUN(pcbw->bmCBWLUN);
1033  ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
1034 
1035  while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
1036 
1037  ret = HandleUsbError(usberr, epDataOutIndex);
1038  //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
1039  if(ret) {
1040  ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
1041  } else {
1042  if(bytes) {
1043  if(!write) {
1044 #if MS_WANT_PARSER
1045  if(callback) {
1046  uint8_t rbuf[bytes];
1047  while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
1048  if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
1049  } else {
1050 #endif
1051  while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1052 #if MS_WANT_PARSER
1053 
1054  }
1055 #endif
1056  ret = HandleUsbError(usberr, epDataInIndex);
1057  } else {
1058  while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1059  ret = HandleUsbError(usberr, epDataOutIndex);
1060  }
1061  if(ret) {
1062  ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
1063  }
1064  }
1065  }
1066 
1067  {
1068  bytes = sizeof (CommandStatusWrapper);
1069  int tries = 2;
1070  while(tries--) {
1071  while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
1072  if(!usberr) break;
1073  ClearEpHalt(epDataInIndex);
1074  if(tries) ResetRecovery();
1075  }
1076  if(!ret) {
1077  Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
1078  Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
1079  } else {
1080  // Throw away csw, IT IS NOT OF ANY USE.
1081  ResetRecovery();
1082  return ret;
1083  }
1084  ret = HandleUsbError(usberr, epDataInIndex);
1085  if(ret) {
1086  ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
1087  }
1088  if(usberr == hrSUCCESS) {
1089  if(IsValidCSW(&csw, pcbw)) {
1090  //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
1091  //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
1092  //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
1093  Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
1094  return csw.bCSWStatus;
1095  } else {
1096  // NOTE! Sometimes this is caused by the reported residue being wrong.
1097  // Get a different device. It isn't compliant, and should have never passed Q&A.
1098  // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
1099  // Other devices that exhibit this behavior exist in the wild too.
1100  // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk
1101  Notify(PSTR("Invalid CSW\r\n"), 0x80);
1102  ResetRecovery();
1103  //return MASS_ERR_SUCCESS;
1104  return MASS_ERR_INVALID_CSW;
1105  }
1106  }
1107  }
1108  return ret;
1109 }
1110 
1117 uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
1118  if(lun > bMaxLUN)
1119  return MASS_ERR_INVALID_LUN;
1120  bTheLUN = lun;
1121  return MASS_ERR_SUCCESS;
1122 };
1123 
1130 uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
1131  uint8_t ret = 0;
1132 
1133  switch(status) {
1134  case 0: return MASS_ERR_SUCCESS;
1135 
1136  case 2:
1137  ErrorMessage<uint8_t > (PSTR("Phase Error"), status);
1138  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1139  ResetRecovery();
1141 
1142  case 1:
1143  ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
1144  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1146 
1147  ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
1148 
1149  if(ret) {
1151  }
1152  ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
1153  if(rsp.bResponseCode & 0x80) {
1154  Notify(PSTR("Information field: "), 0x80);
1155  for(int i = 0; i < 4; i++) {
1156  D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
1157  Notify(PSTR(" "), 0x80);
1158  }
1159  Notify(PSTR("\r\n"), 0x80);
1160  }
1161  ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
1162  ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
1163  ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
1164  // warning, this is not testing ASQ, only SK and ASC.
1165  switch(rsp.bmSenseKey) {
1166  case SCSI_S_UNIT_ATTENTION:
1167  switch(rsp.bAdditionalSenseCode) {
1169  return MASS_ERR_MEDIA_CHANGED;
1170  default:
1171  return MASS_ERR_UNIT_NOT_READY;
1172  }
1173  case SCSI_S_NOT_READY:
1174  switch(rsp.bAdditionalSenseCode) {
1176  return MASS_ERR_NO_MEDIA;
1177  default:
1178  return MASS_ERR_UNIT_NOT_READY;
1179  }
1181  switch(rsp.bAdditionalSenseCode) {
1183  return MASS_ERR_BAD_LBA;
1184  default:
1186  }
1187  default:
1189  }
1190 
1191  // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
1192  // case 0x05/0x14: we stalled out
1193  // case 0x15/0x16: we naked out.
1194  default:
1195  ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
1196  ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1197  return status;
1198  } // switch
1199 }
1200 
1201 
1203 
1204 
1205 // Debugging code
1206 
1207 
1209 
1215  Notify(PSTR("Endpoint descriptor:"), 0x80);
1216  Notify(PSTR("\r\nLength:\t\t"), 0x80);
1217  D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
1218  Notify(PSTR("\r\nType:\t\t"), 0x80);
1219  D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
1220  Notify(PSTR("\r\nAddress:\t"), 0x80);
1221  D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
1222  Notify(PSTR("\r\nAttributes:\t"), 0x80);
1223  D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
1224  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
1225  D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
1226  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
1227  D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
1228  Notify(PSTR("\r\n"), 0x80);
1229 }
1230 
1231 
1233 
1234 
1235 // misc/to kill/to-do
1236 
1237 
1239 
1240 /* We won't be needing this... */
1241 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
1242 #if MS_WANT_PARSER
1243  if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
1244  Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
1245  Notify(PSTR("---------\r\n"), 0x80);
1246 
1248 
1250  cbw.dCBWTag = ++dCBWTag;
1251  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
1253  cbw.bmCBWLUN = lun;
1254  cbw.bmCBWCBLength = 10;
1255 
1256  cbw.CBWCB[0] = SCSI_CMD_READ_10;
1257  cbw.CBWCB[8] = blocks;
1258  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
1259  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
1260  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
1261  cbw.CBWCB[5] = (addr & 0xff);
1262 
1263  return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
1264 #else
1265  return MASS_ERR_NOT_IMPLEMENTED;
1266 #endif
1267 }
#define MASS_ERR_UNIT_BUSY
Definition: masstorage.h:154
#define SCSI_S_ILLEGAL_REQUEST
Definition: masstorage.h:144
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:771
uint8_t bmRcvToggle
Definition: address.h:41
uint8_t MediaCTL(uint8_t lun, uint8_t ctl)
Definition: masstorage.cpp:130
#define MASS_ERR_STALL
Definition: masstorage.h:155
#define USB_SETUP_HOST_TO_DEVICE
Definition: usb_ch9.h:51
uint8_t VendorID[8]
Definition: masstorage.h:365
EpInfo * epinfo
Definition: address.h:76
static const uint8_t epDataOutIndex
Definition: masstorage.h:465
#define CP_MASK_COMPARE_PROTOCOL
#define MASS_CMD_DIR_OUT
Definition: masstorage.h:59
bool lowspeed
Definition: address.h:79
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:83
#define hrSTALL
Definition: max3421e.h:212
uint8_t bmNakPower
Definition: address.h:42
unsigned Removable
Definition: masstorage.h:327
bool LUNOk[MASS_MAX_SUPPORTED_LUN]
Definition: masstorage.h:485
uint8_t CBWCB[16]
Definition: masstorage.h:397
#define SCSI_ASC_MEDIA_CHANGED
Definition: masstorage.h:147
static const uint8_t epInterruptInIndex
Definition: masstorage.h:466
#define MASS_ERR_MEDIA_CHANGED
Definition: masstorage.h:160
CDB10 CDB10_t
Definition: masstorage.h:254
#define MASS_ERR_NO_MEDIA
Definition: masstorage.h:158
#define USB_CLASS_MASS_STORAGE
Definition: UsbCore.h:63
#define MASS_SUBCLASS_SCSI
Definition: masstorage.h:38
#define SCSI_CMD_PREVENT_REMOVAL
Definition: masstorage.h:79
#define SCSI_S_UNIT_ATTENTION
Definition: masstorage.h:145
#define MASS_ERR_BAD_LBA
Definition: masstorage.h:159
uint8_t bMaxPacketSize0
Definition: usb_ch9.h:105
uint8_t bAddress
Definition: masstorage.h:469
#define MS_WANT_PARSER
Definition: masstorage.h:23
#define USB_REQUEST_CLEAR_FEATURE
Definition: usb_ch9.h:34
#define NotifyFail(...)
Definition: message.h:55
uint32_t dCBWTag
Definition: masstorage.h:478
uint8_t bConfNum
Definition: masstorage.h:470
uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed)
Definition: masstorage.cpp:251
#define MASS_ERR_INVALID_CSW
Definition: masstorage.h:157
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:810
#define SCSI_CMD_TEST_UNIT_READY
Definition: masstorage.h:70
#define MASS_ERR_WRITE_PROTECTED
Definition: masstorage.h:167
uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]
Definition: masstorage.h:483
uint8_t Poll()
Definition: masstorage.cpp:670
bool WriteOk[MASS_MAX_SUPPORTED_LUN]
Definition: masstorage.h:486
#define MASS_MAX_SUPPORTED_LUN
Definition: settings.h:64
uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir)
Definition: masstorage.cpp:99
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)
uint8_t Release()
Definition: masstorage.cpp:592
#define MASS_TRANS_FLG_CALLBACK
Definition: masstorage.h:173
#define USB_ERROR_FailGetDevDescr
Definition: UsbCore.h:89
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf)
Definition: masstorage.cpp:154
#define NotifyFailGetDevDescr(...)
Definition: message.h:50
#define hrJERR
Definition: max3421e.h:220
uint32_t dCBWDataTransferLength
Definition: masstorage.h:373
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:83
#define hrSUCCESS
Definition: max3421e.h:207
#define MASS_ERR_GENERAL_USB_ERROR
Definition: masstorage.h:170
virtual void FreeAddress(uint8_t addr)=0
#define MASS_CMD_DIR_IN
Definition: masstorage.h:60
uint32_t GetCapacity(uint8_t lun)
Definition: masstorage.cpp:36
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:77
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:801
#define NotifyFailGetConfDescr(...)
Definition: message.h:52
#define SCSI_CMD_MODE_SENSE_6
Definition: masstorage.h:77
uint8_t bLastUsbError
Definition: masstorage.h:480
#define SCSI_CMD_READ_10
Definition: masstorage.h:83
static const uint8_t epDataInIndex
Definition: masstorage.h:464
uint8_t epAddr
Definition: address.h:33
bool WriteProtected(uint8_t lun)
Definition: masstorage.cpp:70
uint8_t PeripheralQualifier
Definition: masstorage.h:324
uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]
Definition: masstorage.h:484
#define USB_SETUP_RECIPIENT_ENDPOINT
Definition: usb_ch9.h:58
#define MASS_MAX_ENDPOINTS
Definition: masstorage.h:177
#define SCSI_ASC_MEDIUM_NOT_PRESENT
Definition: masstorage.h:148
virtual uint8_t OnInit()
Definition: masstorage.h:492
uint32_t qNextPollTime
Definition: masstorage.h:473
#define MASS_PROTO_BBB
Definition: masstorage.h:46
bool LUNIsGood(uint8_t lun)
Definition: masstorage.cpp:60
#define bmREQ_MASSOUT
Definition: masstorage.h:28
#define hrBUSY
Definition: max3421e.h:208
#define MASS_REQ_GET_MAX_LUN
Definition: masstorage.h:53
Definition: address.h:32
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
Definition: Usb.cpp:293
#define MASS_ERR_NOT_IMPLEMENTED
Definition: masstorage.h:168
uint16_t GetSectorSize(uint8_t lun)
Definition: masstorage.cpp:48
#define hrNAK
Definition: max3421e.h:211
#define MASS_ERR_SUCCESS
Definition: masstorage.h:151
#define MASS_ERR_GENERAL_SCSI_ERROR
Definition: masstorage.h:169
uint16_t wMaxPacketSize
Definition: usb_ch9.h:146
#define MASS_ERR_DEVICE_DISCONNECTED
Definition: masstorage.h:161
bool bPollEnable
Definition: masstorage.h:474
#define CP_MASK_COMPARE_SUBCLASS
uint8_t LockMedia(uint8_t lun, uint8_t lock)
Definition: masstorage.cpp:114
CDB6 CDB6_t
Definition: masstorage.h:220
EpInfo epInfo[MASS_MAX_ENDPOINTS]
Definition: masstorage.h:476
#define MASS_ERR_WRITE_STALL
Definition: masstorage.h:164
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:345
uint8_t bmSndToggle
Definition: address.h:40
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:85
#define PSTR(str)
uint8_t bTheLUN
Definition: masstorage.h:482
BulkOnly(USB *p)
Definition: masstorage.cpp:222
#define SCSI_S_NOT_READY
Definition: masstorage.h:142
#define SCSI_CMD_START_STOP_UNIT
Definition: masstorage.h:78
#define bmREQ_MASSIN
Definition: masstorage.h:29
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:82
uint8_t DeviceType
Definition: masstorage.h:323
uint8_t bIface
Definition: masstorage.h:471
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:77
#define hrTIMEOUT
Definition: max3421e.h:221
#define MASS_ERR_UNIT_NOT_READY
Definition: masstorage.h:153
#define SCSI_CMD_READ_CAPACITY_10
Definition: masstorage.h:82
#define USB_NAK_DEFAULT
Definition: address.h:28
#define MASS_ERR_CMD_NOT_SUPPORTED
Definition: masstorage.h:156
#define MASS_CSW_SIGNATURE
Definition: masstorage.h:57
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval=0)
Definition: Usb.cpp:206
uint8_t bMaxLUN
Definition: masstorage.h:481
uint8_t bNumConfigurations
Definition: usb_ch9.h:112
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:80
uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf)
Definition: masstorage.cpp:188
#define SCSI_CMD_INQUIRY
Definition: masstorage.h:75
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: masstorage.cpp:543
uint8_t maxPktSize
Definition: address.h:34
AddressPool & GetAddressPool()
Definition: UsbCore.h:213
#define SCSI_ASC_LBA_OUT_OF_RANGE
Definition: masstorage.h:146
#define USB_SETUP_TYPE_STANDARD
Definition: usb_ch9.h:53
Definition: UsbCore.h:197
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: masstorage.cpp:326
uint8_t data[8]
Definition: masstorage.h:180
uint32_t dCSWSignature
Definition: masstorage.h:437
#define BMAKE32(__usc3__, __usc2__, __usc1__, __usc0__)
Definition: macros.h:68
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition: UsbCore.h:217
#define NotifyFailSetConfDescr(...)
Definition: message.h:53
uint8_t Version
Definition: masstorage.h:329
#define hrTOGERR
Definition: max3421e.h:213
#define MASS_CBW_SIGNATURE
Definition: masstorage.h:56
#define MASS_ERR_INVALID_LUN
Definition: masstorage.h:163
#define MASS_REQ_BOMSR
Definition: masstorage.h:54
uint8_t bNumEP
Definition: masstorage.h:472
USB * pUsb
Definition: masstorage.h:468
#define USBTRACE(s)
Definition: macros.h:75
#define SCSI_CMD_REQUEST_SENSE
Definition: masstorage.h:71
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition: Usb.cpp:766
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:51
#define SCSI_CMD_WRITE_10
Definition: masstorage.h:84
#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET
Definition: UsbCore.h:88