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