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  if (pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
9  Notify(PSTR("CSW:Sig error\r\n"), 0x80);
10  return false;
11  }
12  if (pcsw->dCSWTag != pcbw->dCBWTag) {
13  Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
14  return false;
15  }
16  return true;
17 }
18 
20 pUsb(p),
21 bAddress(0),
22 bIface(0),
23 bNumEP(1),
24 qNextPollTime(0),
25 bPollEnable(false),
26 dCBWTag(0),
27 bLastUsbError(0) {
28  for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
29  epInfo[i].epAddr = 0;
30  epInfo[i].maxPktSize = (i) ? 0 : 8;
31  epInfo[i].epAttribs = 0;
32 
33  if (!i)
35  }
36  if (pUsb)
38 }
39 
40 uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
41 
42  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
43 
44  uint8_t buf[constBufSize];
45  uint8_t rcode;
46  UsbDevice *p = NULL;
47  EpInfo *oldep_ptr = NULL;
48  uint8_t num_of_conf; // number of configurations
49 
50  for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
51  epInfo[i].epAddr = 0;
52  epInfo[i].maxPktSize = (i) ? 0 : 8;
53  epInfo[i].epAttribs = 0;
54 
55  if (!i)
57  }
58 
59  AddressPool &addrPool = pUsb->GetAddressPool();
60 
61 
62  if (bAddress)
64 
65  USBTRACE("MS Init\r\n");
66  // Get pointer to pseudo device with address 0 assigned
67  p = addrPool.GetUsbDevicePtr(0);
68 
69  if (!p) {
71  }
72 
73  if (!p->epinfo) {
74  USBTRACE("epinfo\r\n");
76  }
77 
78  // Save old pointer to EP_RECORD of address 0
79  oldep_ptr = p->epinfo;
80 
81  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
82  p->epinfo = epInfo;
83 
84  p->lowspeed = lowspeed;
85  // Get device descriptor
86  rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
87 
88  // Restore p->epinfo
89  p->epinfo = oldep_ptr;
90 
91  if (rcode) {
92  goto FailGetDevDescr;
93  }
94  // Allocate new address according to device class
95  bAddress = addrPool.AllocAddress(parent, false, port);
96 
97  if (!bAddress)
99 
100  // Extract Max Packet Size from the device descriptor
101  epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
102 
103  // Assign new address to the device
104  rcode = pUsb->setAddr(0, 0, bAddress);
105 
106  if (rcode) {
107  p->lowspeed = false;
108  addrPool.FreeAddress(bAddress);
109  bAddress = 0;
110  USBTRACE2("setAddr:", rcode);
111  return rcode;
112  }
113 
114  USBTRACE2("Addr:", bAddress);
115 
116  p->lowspeed = false;
117 
118  p = addrPool.GetUsbDevicePtr(bAddress);
119 
120  if (!p)
122 
123  p->lowspeed = lowspeed;
124 
125  num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
126 
127  // Assign epInfo to epinfo pointer
128  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
129 
130  if (rcode)
131  goto FailSetDevTblEntry;
132 
133  USBTRACE2("NC:", num_of_conf);
134 
135  for (uint8_t i = 0; i < num_of_conf; i++) {
141  CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);
142 
143  rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
144 
145  if (rcode)
146  goto FailGetConfDescr;
147 
148  if (bNumEP > 1)
149  break;
150  } // for
151 
152  if (bNumEP < 3)
154 
155  // Assign epInfo to epinfo pointer
157 
158  USBTRACE2("Conf:", bConfNum);
159 
160  // Set Configuration Value
161  rcode = pUsb->setConf(bAddress, 0, bConfNum);
162 
163  if (rcode)
164  goto FailSetConfDescr;
165 
166  delay(10000);
167 
168  rcode = GetMaxLUN(&bMaxLUN);
169  if (rcode)
170  goto FailGetMaxLUN;
171 
172  ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
173 
174  delay(10);
175 
176  bTheLUN = bMaxLUN;
177 
178  //if (bMaxLUN > 0)
179  {
180  for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
181  ErrorMessage<uint8_t > (PSTR("\r\nLUN"), lun);
182  Notify(PSTR("--------\r\n"), 0x80);
183 
184  uint8_t count = 0;
185 
186  MediaCTL(lun, 0x01);
187  while (rcode = TestUnitReady(lun)) {
188  if (rcode == MASS_ERR_NO_MEDIA)
189  break;
190 
191  if (rcode == MASS_ERR_DEVICE_DISCONNECTED)
192  goto Fail;
193 
194  if (!count)
195  Notify(PSTR("Not ready...\r\n"), 0x80);
196 
197  if (count == 0xff)
198  break;
199 
200  delay(100);
201  count++;
202  }
203  if (count == 0xff)
204  continue;
205 
206  rcode = 0;
207  InquiryResponse response;
208  rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
209 
210  if (rcode)
211  ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
212 
213  rcode = 0;
214  Capacity capacity;
215  rcode = ReadCapacity(lun, sizeof (Capacity), (uint8_t*) & capacity);
216 
217  if (rcode)
218  ErrorMessage<uint8_t > (PSTR("ReadCapacity"), rcode);
219  else {
220  for (uint8_t i = 0; i<sizeof (Capacity); i++)
221  PrintHex<uint8_t > (capacity.data[i], 0x80);
222  Notify(PSTR("\r\n\r\n"), 0x80);
223  // Only 512/1024/2048/4096 are valid values!
224  uint32_t c = ((uint32_t)capacity.data[4] << 24) + ((uint32_t)capacity.data[5] << 16) + ((uint32_t)capacity.data[6] << 8) + (uint32_t)capacity.data[7];
225  if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
226  rcode = 255;
227  goto FailInvalidSectorSize;
228  }
229  }
230 
231  rcode = 0;
232 #if 0
233  {
234  uint8_t buf[512];
235  rcode = Read(lun, 0, 512, 1, buf);
236 
237  if (rcode)
238  ErrorMessage<uint8_t > (PSTR("Read"), rcode);
239  else {
240  Notify(PSTR("Read: OK\r\n\r\n"), 0x80);
241  /*
242  for(int i=0; i<512; i++) {
243  PrintHex<uint8_t>(buf[i], 0x80);
244  Notify(PSTR(" "), 0x80);
245  }
246  Notify(PSTR("\r\n\r\n"), 0x80);
247  */
248  }
249  }
250  {
251  uint8_t buf[192];
252  rcode = ModeSense(lun, 0, 0x3f, 0, 192, buf);
253 
254  if (rcode)
255  ErrorMessage<uint8_t > (PSTR("ModeSense"), rcode);
256  else
257  Notify(PSTR("ModeSense: OK\r\n\r\n"), 0x80);
258  }
259 #endif
260  }
261  Notify(PSTR("==========\r\n"), 0x80);
262  }
263 
264  if (TestUnitReady(bTheLUN)) {
265  Notify(PSTR("Unit not ready\r\n"), 0x80);
266 
267  rcode = MASS_ERR_UNIT_NOT_READY;
268  //goto FailOnInit;
269  }
270 
271  rcode = OnInit();
272 
273  if (rcode)
274  goto FailOnInit;
275 
276  USBTRACE("MS configured\r\n\r\n");
277 
278  bPollEnable = true;
279 
280  //USBTRACE("Poll enabled\r\n");
281  return 0;
282 
283 FailGetDevDescr:
285  goto Fail;
286 
287 FailSetDevTblEntry:
289  goto Fail;
290 
291 FailGetConfDescr:
293  goto Fail;
294 
295 FailSetConfDescr:
297  goto Fail;
298 
299 FailOnInit:
300  USBTRACE("OnInit:");
301  goto Fail;
302 
303 FailGetMaxLUN:
304  USBTRACE("GetMaxLUN:");
305  goto Fail;
306 
307 FailInquiry:
308  USBTRACE("Inquiry:");
309  goto Fail;
310 
311 FailReadCapacity:
312  USBTRACE("ReadCapacity:");
313  goto Fail;
314 
315 FailInvalidSectorSize:
316  USBTRACE("Sector Size is NOT VALID: ");
317  goto Fail;
318 
319 FailRead0:
320  USBTRACE("Read0:");
321  goto Fail;
322 
323 FailModeSense0:
324  USBTRACE("ModeSense0:");
325  goto Fail;
326 
327 FailModeSense1:
328  USBTRACE("ModeSense1:");
329 
330 Fail:
331  NotifyFail(rcode);
332  Release();
333  return rcode;
334 }
335 
336 void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
337  ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
338  ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
339  ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
340 
341  bConfNum = conf;
342 
343  uint8_t index;
344 
345  if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
346  index = epInterruptInIndex;
347  else
348  if ((pep->bmAttributes & 0x02) == 2)
349  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
350  else
351  return;
352 
353  // Fill in the endpoint info structure
354  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
355  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
356  epInfo[index].epAttribs = 0;
357 
358  bNumEP++;
359 
361 }
362 
363 uint8_t BulkOnly::Release() {
365 
366  bIface = 0;
367  bNumEP = 1;
368 
369  bAddress = 0;
370  qNextPollTime = 0;
371  bPollEnable = false;
372  bLastUsbError = 0;
373  bMaxLUN = 0;
374  bTheLUN = 0;
375  dCBWTag = 0;
376  return 0;
377 }
378 
379 uint8_t BulkOnly::Poll() {
380  uint8_t rcode = 0;
381 
382  if (!bPollEnable)
383  return 0;
384 
385  return rcode;
386 }
387 
388 uint8_t BulkOnly::Reset() {
389  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL));
390 }
391 
392 uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
393  uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
394 
395  if (ret == hrSTALL)
396  *plun = 0;
397 
398  return 0;
399 }
400 
401 uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
402  uint8_t count = 3;
403 
404  bLastUsbError = error;
405 
406  while (error && count) {
407  if (error != hrSUCCESS) {
408  ErrorMessage<uint8_t > (PSTR("USB Error"), error);
409  ErrorMessage<uint8_t > (PSTR("Index"), index);
410  }
411  switch (error) {
412  case hrSUCCESS: return MASS_ERR_SUCCESS;
413  case hrBUSY: return MASS_ERR_UNIT_BUSY;
414  case hrTIMEOUT:
416  case hrSTALL:
417  if (index == 0)
418  return MASS_ERR_SUCCESS;
419 
420  error = ClearEpHalt(index);
421  //return MASS_ERR_STALL;
422  return MASS_ERR_SUCCESS;
423 
424  //error = ClearEpHalt(index);
425  //break;
426  case hrTOGERR:
427  if (bAddress && bConfNum) {
428  error = pUsb->setConf(bAddress, 0, bConfNum);
429 
430  if (error)
431  break;
432  }
433  return MASS_ERR_SUCCESS;
434  default:
435  ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
437  }
438  count--;
439  } // while
440 
441  return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
442 }
443 
444 uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
445  if (index == 0)
446  return 0;
447 
448  uint8_t ret = 0;
449 
451  USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL));
452 
456  if (ret) {
457  ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
458  ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
459  return ret;
460  }
461  epInfo[index].epAttribs = 0;
462  return 0;
463 }
464 
466  Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
467  Notify(PSTR("-----------------\r\n"), 0x80);
468 
469  bLastUsbError = Reset();
470 
471  if (bLastUsbError) {
472  return bLastUsbError;
473  }
474  delay(6);
475 
477 
478  if (bLastUsbError) {
479  return bLastUsbError;
480  }
481  delay(6);
482 
484 
485  delay(6);
486 
487  return bLastUsbError;
488 }
489 
490 uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
491  Notify(PSTR("\r\nInquiry\r\n"), 0x80);
492  Notify(PSTR("---------\r\n"), 0x80);
493 
495 
497  cbw.dCBWTag = ++dCBWTag;
498  cbw.dCBWDataTransferLength = bsize;
500  cbw.bmCBWLUN = lun;
501  cbw.bmCBWCBLength = 6;
502 
503  for (uint8_t i = 0; i < 16; i++)
504  cbw.CBWCB[i] = 0;
505 
506  cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
507  cbw.CBWCB[4] = bsize;
508 
509  return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
510 }
511 
512 uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
513  Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
514  Notify(PSTR("----------------\r\n"), 0x80);
515 
517 
519  cbw.dCBWTag = ++dCBWTag;
520  cbw.dCBWDataTransferLength = size;
522  cbw.bmCBWLUN = lun;
523  cbw.bmCBWCBLength = 6;
524 
525  for (uint8_t i = 0; i < 16; i++)
526  cbw.CBWCB[i] = 0;
527 
528  cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
529  cbw.CBWCB[4] = size;
530 
531  return HandleSCSIError(Transaction(&cbw, size, buf, 0));
532 }
533 
534 uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
535  Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
536  Notify(PSTR("---------------\r\n"), 0x80);
537 
539 
541  cbw.dCBWTag = ++dCBWTag;
542  cbw.dCBWDataTransferLength = bsize;
544  cbw.bmCBWLUN = lun;
545  cbw.bmCBWCBLength = 10;
546 
547  for (uint8_t i = 0; i < 16; i++)
548  cbw.CBWCB[i] = 0;
549 
551  //cbw.CBWCB[4] = bsize;
552 
553  return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
554 }
555 
556 uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
557  if (!bAddress) // || !bPollEnable)
559 
560  Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
561  Notify(PSTR("-----------------\r\n"), 0x80);
562 
564 
566  cbw.dCBWTag = ++dCBWTag;
567  cbw.dCBWDataTransferLength = 0;
569  cbw.bmCBWLUN = lun;
570  cbw.bmCBWCBLength = 6;
571 
572  for (uint8_t i = 0; i < 16; i++)
573  cbw.CBWCB[i] = 0;
574 
576 
577  return HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
578 }
579 
580 /* Media control: 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media */
581 uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
582  uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
583  if (bAddress) {
585 
587  cbw.dCBWTag = ++dCBWTag;
588  cbw.dCBWDataTransferLength = 0;
590  cbw.bmCBWLUN = lun;
591  cbw.bmCBWCBLength = 6;
592 
593  for (uint8_t i = 0; i < 16; i++)
594  cbw.CBWCB[i] = 0;
595 
597  cbw.CBWCB[4] = ctl & 0x03;
598 
599  rcode = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
600  }
601  return rcode;
602 }
603 
604 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
605  Notify(PSTR("\r\nRead\r\n"), 0x80);
606  Notify(PSTR("---------\r\n"), 0x80);
607 
609 
611  cbw.dCBWTag = ++dCBWTag;
612  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
614  cbw.bmCBWLUN = lun;
615  cbw.bmCBWCBLength = 10;
616 
617  for (uint8_t i = 0; i < 16; i++)
618  cbw.CBWCB[i] = 0;
619 
620  cbw.CBWCB[0] = SCSI_CMD_READ_10;
621  cbw.CBWCB[8] = blocks;
622  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
623  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
624  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
625  cbw.CBWCB[5] = (addr & 0xff);
626  return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
627 }
628 
629 /* We won't be needing this... */
630 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs) {
631 #if 0
632  Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
633  Notify(PSTR("---------\r\n"), 0x80);
634 
636 
638  cbw.dCBWTag = ++dCBWTag;
639  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
641  cbw.bmCBWLUN = lun;
642  cbw.bmCBWCBLength = 10;
643 
644  for (uint8_t i = 0; i < 16; i++)
645  cbw.CBWCB[i] = 0;
646 
647  cbw.CBWCB[0] = SCSI_CMD_READ_10;
648  cbw.CBWCB[8] = blocks;
649  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
650  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
651  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
652  cbw.CBWCB[5] = (addr & 0xff);
653 
654  return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
655 #endif
656 }
657 
658 uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf) {
659  Notify(PSTR("\r\nWrite\r\n"), 0x80);
660  Notify(PSTR("---------\r\n"), 0x80);
661 
662  //MediaCTL(lun, 0x01);
664 
666  cbw.dCBWTag = ++dCBWTag;
667  cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
669  cbw.bmCBWLUN = lun;
670  cbw.bmCBWCBLength = 10;
671 
672  for (uint8_t i = 0; i < 16; i++)
673  cbw.CBWCB[i] = 0;
674 
675  cbw.CBWCB[0] = SCSI_CMD_WRITE_10;
676  cbw.CBWCB[8] = 1;
677  cbw.CBWCB[5] = (addr & 0xff);
678  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
679  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
680  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
681 
682  return HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0));
683 }
684 
685 uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *pbuf) {
686  Notify(PSTR("\r\rModeSense\r\n"), 0x80);
687  Notify(PSTR("------------\r\n"), 0x80);
688 
690 
692  cbw.dCBWTag = ++dCBWTag;
693  cbw.dCBWDataTransferLength = len;
695  cbw.bmCBWLUN = lun;
696  cbw.bmCBWCBLength = 6;
697 
698  for (uint8_t i = 0; i < 16; i++)
699  cbw.CBWCB[i] = 0;
700 
701  cbw.CBWCB[0] = SCSI_CMD_MODE_SENSE_6;
702  cbw.CBWCB[2] = ((pc << 6) | page);
703  cbw.CBWCB[3] = subpage;
704  cbw.CBWCB[4] = len;
705 
706  return HandleSCSIError(Transaction(&cbw, 512, pbuf, 0));
707 }
708 
709 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, uint8_t flags) {
710  uint16_t read;
711  uint8_t ret = 0;
712 
713  ErrorMessage<uint8_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
714 
716 
717  if (ret) {
718  ErrorMessage<uint8_t > (PSTR("CBW"), ret);
719  return ret;
720  }
721  Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
722 
723  ret = 0;
724 
725  read = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
726 
727  if (read) {
728  if (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) {
730  uint8_t rbuf[read];
731  uint8_t err = 0;
732  ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, rbuf);
733  if (ret == hrSUCCESS) ((USBReadParser*)buf)->Parse(read, rbuf, 0);
734  if (ret == hrSTALL) err = ClearEpHalt(epDataInIndex);
735  if (ret) {
736  ErrorMessage<uint8_t > (PSTR("RDR"), err);
738  }
739  } else
740  ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)buf);
741  } else
742  ret = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*)buf);
743 
744  ret = HandleUsbError(ret, (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) ? epDataInIndex : epDataOutIndex);
745 
746  if (ret) {
747  ErrorMessage<uint8_t > (PSTR("DAT"), ret);
749  }
750 
751  Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
752  }
753 
754  uint8_t count = 2;
755 
756  while (count) {
758  read = sizeof (CommandStatusWrapper);
759 
760  ret = HandleUsbError(pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*) & csw), epDataInIndex);
761 
762  if (ret) {
763  ErrorMessage<uint8_t > (PSTR("CSW"), ret);
764  count--;
765  continue; //return ret;
766  }
767  if (IsValidCSW(&csw, pcbw)) {
768  ErrorMessage<uint8_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
769  ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
770  ErrorMessage<uint8_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
771  Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
772  return csw.bCSWStatus;
773  } else {
774  Notify(PSTR("Invalid CSW\r\n"), 0x80);
775  ResetRecovery();
776  return MASS_ERR_SUCCESS; //MASS_ERR_INVALID_CSW;
777  }
778  count--;
779  }
780  if (count)
781  ResetRecovery();
782 
783  return MASS_ERR_SUCCESS;
784 }
785 
786 uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
787  if (lun > bMaxLUN)
788  return MASS_ERR_INVALID_LUN;
789 
790  bTheLUN = lun;
791  return MASS_ERR_SUCCESS;
792 };
793 
794 uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
795  uint8_t ret = 0;
796 
797  switch (status) {
798  case 0: return MASS_ERR_SUCCESS;
799  //case 4: return MASS_ERR_UNIT_BUSY;
800  case 2:
801  ErrorMessage<uint8_t > (PSTR("Phase"), status);
802  ResetRecovery();
804  case 1:
805  ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
807 
808  ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
809 
810  if (ret)
812 
813  ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
814  ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
815  ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
816  ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
817  switch (rsp.bmSenseKey) {
818  case 0:
819  return MASS_ERR_SUCCESS;
820  case SCSI_S_NOT_READY:
821  switch (rsp.bAdditionalSenseCode) {
823  return MASS_ERR_NO_MEDIA;
824  default:
826  }
828  switch (rsp.bAdditionalSenseCode) {
830  return MASS_ERR_BAD_LBA;
831  default:
833  }
834  default: return MASS_ERR_GENERAL_SCSI_ERROR;
835  }
836 
837  default:
838  Reset();
839  ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
840  return status; //MASS_ERR_GENERAL_SCSI_ERROR;
841  } // switch
842 }
843 
845  Notify(PSTR("Endpoint descriptor:"), 0x80);
846  Notify(PSTR("\r\nLength:\t\t"), 0x80);
847  PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
848  Notify(PSTR("\r\nType:\t\t"), 0x80);
849  PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
850  Notify(PSTR("\r\nAddress:\t"), 0x80);
851  PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
852  Notify(PSTR("\r\nAttributes:\t"), 0x80);
853  PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
854  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
855  PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
856  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
857  PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
858  Notify(PSTR("\r\n"), 0x80);
859 }