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 
4 //bool BulkReadParser::IsValidCSW(uint8_t size, uint8_t *pcsw)
5 //{
6 // if (size != 0x0d)
7 // {
8 // Notify(PSTR("CSW:Size error"));
9 // return false;
10 // }
11 // if (*((uint32_t*)pcsw) != MASS_CSW_SIGNATURE)
12 // {
13 // Notify(PSTR("CSW:Sig error"));
14 // return false;
15 // }
16 // //if (size != 0x0d || *((uint32_t*)pcsw) != MASS_CSW_SIGNATURE ||
17 // // ((CommandStatusWrapper*)pcsw)->dCSWTag != dCBWTag)
18 // // return false;
19 // return true;
20 //}
21 
22 //bool BulkReadParser::IsMeaningfulCSW(uint8_t size, uint8_t *pcsw)
23 //{
24 // if (((CommandStatusWrapper*)pcsw)->bCSWStatus < 2 &&
25 // ((CommandStatusWrapper*)pcsw)->dCSWDataResidue <= dCBWDataTransferLength )
26 // return true;
27 // if ( ((CommandStatusWrapper*)pcsw)->bCSWStatus == 2 )
28 // return true;
29 // return false;
30 //}
31 
32 //void BulkReadParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset)
33 //{
34 // if (offset == 0 && len > sizeof(CommandStatusWrapper))
35 // if (IsValidCSW(sizeof(CommandStatusWrapper), pbuf) && IsMeaningfulCSW(sizeof(CommandStatusWrapper), pbuf))
36 // {
37 // CommandStatusWrapper *pCSW = (CommandStatusWrapper*)pbuf;
38 //
39 // Serial.println("Sig:");
40 // PrintHex<uint32_t>(pCSW->dCSWSignature);
41 // Serial.println("Tag:");
42 // PrintHex<uint32_t>(pCSW->dCSWTag);
43 // Serial.println("Res:");
44 // PrintHex<uint32_t>(pCSW->dCSWDataResidue);
45 // Serial.println("Ret:");
46 // PrintHex<uint8_t>(pCSW->bCSWStatus);
47 // }
48 //}
49 
50 const uint8_t BulkOnly::epDataInIndex = 1;
51 const uint8_t BulkOnly::epDataOutIndex = 2;
52 const uint8_t BulkOnly::epInterruptInIndex = 3;
53 
54 BulkOnly::BulkOnly(USB *p /*, CDCAsyncOper *pasync*/) :
55  pUsb(p),
56  //pAsync(pasync),
57  bAddress(0),
58  qNextPollTime(0),
59  bPollEnable(false),
60  bIface(0),
61  bNumEP(1)
62 {
63  for(uint8_t i=0; i<MASS_MAX_ENDPOINTS; i++)
64  {
65  epInfo[i].epAddr = 0;
66  epInfo[i].maxPktSize = (i) ? 0 : 8;
67  epInfo[i].epAttribs = 0;
68 
69  if (!i)
71  }
72  if (pUsb)
74 }
75 
76 uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed)
77 {
78  const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR);
79 
80  uint8_t buf[constBufSize];
81  uint8_t rcode;
82  UsbDevice *p = NULL;
83  EpInfo *oldep_ptr = NULL;
84  uint8_t num_of_conf; // number of configurations
85 
86  AddressPool &addrPool = pUsb->GetAddressPool();
87 
88  USBTRACE("MS Init\r\n");
89 
90  if (bAddress)
92 
93  // Get pointer to pseudo device with address 0 assigned
94  p = addrPool.GetUsbDevicePtr(0);
95 
96  if (!p)
98 
99  if (!p->epinfo)
100  {
101  USBTRACE("epinfo\r\n");
103  }
104 
105  // Save old pointer to EP_RECORD of address 0
106  oldep_ptr = p->epinfo;
107 
108  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
109  p->epinfo = epInfo;
110 
111  p->lowspeed = lowspeed;
112 
113  // Get device descriptor
114  rcode = pUsb->getDevDescr( 0, 0, constBufSize, (uint8_t*)buf );
115 
116  // Restore p->epinfo
117  p->epinfo = oldep_ptr;
118 
119  if( rcode )
120  goto FailGetDevDescr;
121 
122  // Allocate new address according to device class
123  bAddress = addrPool.AllocAddress(parent, false, port);
124 
125  if (!bAddress)
127 
128  // Extract Max Packet Size from the device descriptor
129  epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
130 
131  // Assign new address to the device
132  rcode = pUsb->setAddr( 0, 0, bAddress );
133 
134  if (rcode)
135  {
136  p->lowspeed = false;
137  addrPool.FreeAddress(bAddress);
138  bAddress = 0;
139  USBTRACE2("setAddr:",rcode);
140  return rcode;
141  }
142 
143  USBTRACE2("Addr:", bAddress);
144 
145  p->lowspeed = false;
146 
147  p = addrPool.GetUsbDevicePtr(bAddress);
148 
149  if (!p)
151 
152  p->lowspeed = lowspeed;
153 
154  num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
155 
156  // Assign epInfo to epinfo pointer
157  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
158 
159  if (rcode)
160  goto FailSetDevTblEntry;
161 
162  USBTRACE2("NC:", num_of_conf);
163 
164  for (uint8_t i=0; i<num_of_conf; i++)
165  {
172  CP_MASK_COMPARE_PROTOCOL> BulkOnlyParser(this);
173 
174  rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
175  rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
176 
177 
178  if (bNumEP > 1)
179  break;
180  } // for
181 
182  if (bNumEP < 3)
184 
185  // Assign epInfo to epinfo pointer
187 
188  USBTRACE2("Conf:", bConfNum);
189 
190  // Set Configuration Value
191  rcode = pUsb->setConf(bAddress, 0, bConfNum);
192 
193  if (rcode)
194  goto FailSetConf;
195 
196  delay(5000);
197 
198  //rcode = pAsync->OnInit(this);
199 
200  //if (rcode)
201  // goto FailOnInit;
202 
203  rcode = GetMaxLUN(&bMaxLUN);
204 
205  if (rcode)
206  goto FailGetMaxLUN;
207 
208  delay(10);
209 
210  {
211  InquiryResponse response;
212  rcode = Inquiry(bMaxLUN, sizeof(InquiryResponse), (uint8_t*)&response);
213 
214  if (rcode)
215  goto FailInquiry;
216 
217  //if (response.DeviceType != 0)
218  // goto FailInvalidDevice;
219  }
220 
221  delay(10);
222 
223  USBTRACE("MS configured\r\n");
224 
225  bPollEnable = true;
226 
227  //USBTRACE("Poll enabled\r\n");
228  return 0;
229 
230 FailGetDevDescr:
231  USBTRACE("getDevDescr:");
232  goto Fail;
233 
234 FailSetDevTblEntry:
235  USBTRACE("setDevTblEn:");
236  goto Fail;
237 
238 FailGetConfDescr:
239  USBTRACE("getConf:");
240  goto Fail;
241 
242 FailSetConf:
243  USBTRACE("setConf:");
244  goto Fail;
245 
246 FailOnInit:
247  USBTRACE("OnInit:");
248  goto Fail;
249 
250 FailGetMaxLUN:
251  USBTRACE("GetMaxLUN:");
252  goto Fail;
253 
254 FailInquiry:
255  USBTRACE("Inquiry:");
256  goto Fail;
257 
258 Fail:
259  Serial.println(rcode, HEX);
260  Release();
261  return rcode;
262 }
263 
264 
265 void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
266 {
267  ErrorMessage<uint8_t>(PSTR("Conf.Val"), conf);
268  ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
269  ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
270 
271  bConfNum = conf;
272 
273  uint8_t index;
274 
275  if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
276  index = epInterruptInIndex;
277  else
278  if ((pep->bmAttributes & 0x02) == 2)
279  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
280  else
281  return;
282 
283  // Fill in the endpoint info structure
284  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
285  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
286  epInfo[index].epAttribs = 0;
287 
288  bNumEP ++;
289 
291 }
292 
294 {
296 
297  bIface = 0;
298  bNumEP = 1;
299 
300  bAddress = 0;
301  qNextPollTime = 0;
302  bPollEnable = false;
303  return 0;
304 }
305 
306 uint8_t BulkOnly::Poll()
307 {
308  uint8_t rcode = 0;
309 
310  if (!bPollEnable)
311  return 0;
312 
313  uint32_t time_now = millis();
314 
315  //if (qNextPollTime <= time_now)
316  //{
317  // qNextPollTime = time_now + 100;
318 
319  // uint8_t rcode;
320  // const uint8_t constBufSize = 16;
321  // uint8_t buf[constBufSize];
322 
323  // for (uint8_t i=0; i<constBufSize; i++)
324  // buf[i] = 0;
325 
326  // uint16_t read = (constBufSize > epInfo[epInterruptInIndex].maxPktSize)
327  // ? epInfo[epInterruptInIndex].maxPktSize : constBufSize;
328  // rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf);
329 
330  // if (rcode)
331  // return rcode;
332 
333  // for (uint8_t i=0; i<read; i++)
334  // {
335  // PrintHex<uint8_t>(buf[i]);
336  // Serial.print(" ");
337  // }
338  // USBTRACE("\r\n");
339  //}
340  return rcode;
341 }
342 
343 bool BulkOnly::IsValidCBW(uint8_t size, uint8_t *pcbw)
344 {
345  if (size != 0x1f || *((uint32_t*)pcbw) != MASS_CBW_SIGNATURE)
346  return false;
347  return true;
348 }
349 
350 bool BulkOnly::IsMeaningfulCBW(uint8_t size, uint8_t *pcbw)
351 {
352  if (((CommandBlockWrapper*)pcbw)->bmReserved1 != 0 ||
353  ((CommandBlockWrapper*)pcbw)->bmReserved2 != 0 ||
354  ((CommandBlockWrapper*)pcbw)->bmCBWLUN > bMaxLUN ||
355  ((CommandBlockWrapper*)pcbw)->bmCBWCBLength > 0x10 )
356  return false;
357  return true;
358 }
359 
361 {
362  return( pUsb->ctrlReq( bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL ));
363 }
364 
365 uint8_t BulkOnly::GetMaxLUN(uint8_t *plun)
366 {
367  uint8_t cnt = 3;
368 
369  bLastUsbError = pUsb->ctrlReq( bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL );
370 
371  delay(10);
372  //Serial.println(F("bLastUsbError: "));
373  //Serial.println(bLastUsbError);
374 
375  if (bLastUsbError == hrSTALL)
376  {
377  *plun = 0;
379  return MASS_ERR_SUCCESS;
380  }
381  if (bLastUsbError == hrJERR)
383  else if (bLastUsbError)
385  return MASS_ERR_SUCCESS;
386 }
387 
388 uint8_t BulkOnly::HandleUsbError(uint8_t index)
389 {
390  uint8_t count = 3;
391 
392  while (bLastUsbError && count)
393  {
394  switch (bLastUsbError)
395  {
396  case hrSUCCESS:
397  return MASS_ERR_SUCCESS;
398  case hrJERR:
401  case hrSTALL:
402  bLastUsbError = ClearEpHalt(index);
403  break;
404  default:
406  }
407  count --;
408  } // while
409 
410  return MASS_ERR_SUCCESS;
411 }
412 
413 uint8_t BulkOnly::ClearEpHalt(uint8_t index)
414 {
416  USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, epInfo[index].epAddr, 0, 0, NULL, NULL ));
417 }
418 
420 {
421  bLastUsbError = Reset();
422 
423  if (bLastUsbError)
424  return bLastUsbError;
425 
426  delay(6);
427 
429 
430  if (bLastUsbError)
431  return bLastUsbError;
432 
433  delay(6);
434 
436 
437  delay(6);
438 
439  return bLastUsbError;
440 }
441 
442 uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf)
443 {
444  CommandBlockWrapper cbw;
445 
447  cbw.dCBWTag = 0xdeadbeef;
448  cbw.dCBWDataTransferLength = bsize;
450  cbw.bmCBWLUN = lun;
451  cbw.bmCBWCBLength = 6;
452 
453  for (uint8_t i=0; i<16; i++)
454  cbw.CBWCB[i] = 0;
455 
456  cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
457  cbw.CBWCB[4] = bsize;
458 
459  return Transaction(&cbw, bsize, buf, 0);
460 }
461 
462 uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf)
463 {
464  CommandBlockWrapper cbw;
465 
467  cbw.dCBWTag = 0xdeadbeef;
468  cbw.dCBWDataTransferLength = size;
470  cbw.bmCBWLUN = lun;
471  cbw.bmCBWCBLength = 6;
472 
473  for (uint8_t i=0; i<16; i++)
474  cbw.CBWCB[i] = 0;
475 
476  cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
477  cbw.CBWCB[4] = size;
478 
479  return Transaction(&cbw, size, buf, 0);
480 }
481 
482 uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf)
483 {
484  CommandBlockWrapper cbw;
485 
487  cbw.dCBWTag = 0xdeadbeef;
488  cbw.dCBWDataTransferLength = bsize;
490  cbw.bmCBWLUN = lun;
491  cbw.bmCBWCBLength = 10;
492 
493  for (uint8_t i=0; i<16; i++)
494  cbw.CBWCB[i] = 0;
495 
497  cbw.CBWCB[4] = bsize;
498 
499  return Transaction(&cbw, bsize, buf, 0);
500 }
501 
502 uint8_t BulkOnly::TestUnitReady(uint8_t lun)
503 {
504  CommandBlockWrapper cbw;
505 
507  cbw.dCBWTag = 0xdeadbeef;
508  cbw.dCBWDataTransferLength = 0;
510  cbw.bmCBWLUN = lun;
511  cbw.bmCBWCBLength = 6;
512 
513  for (uint8_t i=0; i<16; i++)
514  cbw.CBWCB[i] = 0;
515 
517 
518  return Transaction(&cbw, 0, NULL, 0);
519 }
520 
521 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, USBReadParser *prs)
522 {
523  CommandBlockWrapper cbw;
524 
526  cbw.dCBWTag = 0xdeadbeef;
527  cbw.dCBWDataTransferLength = bsize;
529  cbw.bmCBWLUN = lun;
530  cbw.bmCBWCBLength = 10;
531 
532  for (uint8_t i=0; i<16; i++)
533  cbw.CBWCB[i] = 0;
534 
535  cbw.CBWCB[0] = SCSI_CMD_READ_10;
536  cbw.CBWCB[8] = 1;
537  cbw.CBWCB[5] = (addr & 0xff);
538  cbw.CBWCB[4] = ((addr >> 8) & 0xff);
539  cbw.CBWCB[3] = ((addr >> 16) & 0xff);
540  cbw.CBWCB[2] = ((addr >> 24) & 0xff);
541 
542  return Transaction(&cbw, bsize, prs, 1);
543 }
544 
545 uint8_t BulkOnly::Transaction(CommandBlockWrapper *cbw, uint16_t size, void *buf, uint8_t flags)
546 {
547  uint16_t read;
548  {
549  bLastUsbError = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof(CommandBlockWrapper), (uint8_t*)cbw);
550 
551  uint8_t ret = HandleUsbError(epDataOutIndex);
552 
553  if (ret)
554  {
555  ErrorMessage<uint8_t>(PSTR("CBW"), ret);
556  return ret;
557  }
558  }
559 
560  if (size && buf)
561  {
562  read = size;
563 
564  if (cbw->bmCBWFlags & MASS_CMD_DIR_IN)
565  {
567  {
568  const uint8_t bufSize = 64;
569  uint16_t total = size;
570  uint16_t count = 0;
571  uint8_t rbuf[bufSize];
572 
573  read = bufSize;
574 
575  while(count < total &&
576  ((bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)rbuf)) == hrSUCCESS)
577  )
578  {
579  ((USBReadParser*)buf)->Parse(read, rbuf, count);
580 
581  count += read;
582  read = bufSize;
583  }
584 
585  if (bLastUsbError == hrSTALL)
586  bLastUsbError = ClearEpHalt(epDataInIndex);
587 
588  if (bLastUsbError)
589  {
590  ErrorMessage<uint8_t>(PSTR("RDR"), bLastUsbError);
592  }
593  } // if ((flags & 1) == 1)
594  else
595  bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)buf);
596  } // if (cbw->bmCBWFlags & MASS_CMD_DIR_IN)
597 
598  else if (cbw->bmCBWFlags & MASS_CMD_DIR_OUT)
599  bLastUsbError = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*)buf);
600  }
601 
603 
604  if (ret)
605  {
606  ErrorMessage<uint8_t>(PSTR("RSP"), ret);
608  }
609  {
611  read = sizeof(CommandStatusWrapper);
612 
613  bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)&csw);
614 
615  uint8_t ret = HandleUsbError(epDataInIndex);
616 
617  if (ret)
618  {
619  ErrorMessage<uint8_t>(PSTR("CSW"), ret);
620  return ret;
621  }
622  //if (csw.bCSWStatus == MASS_ERR_PHASE_ERROR)
623  // bLastUsbError = ResetRecovery();
624 
625  return csw.bCSWStatus;
626  }
627  //return MASS_ERR_SUCCESS;
628 }
629 
631 {
632  Notify(PSTR("Endpoint descriptor:"));
633  Notify(PSTR("\r\nLength:\t\t"));
634  PrintHex<uint8_t>(ep_ptr->bLength);
635  Notify(PSTR("\r\nType:\t\t"));
636  PrintHex<uint8_t>(ep_ptr->bDescriptorType);
637  Notify(PSTR("\r\nAddress:\t"));
638  PrintHex<uint8_t>(ep_ptr->bEndpointAddress);
639  Notify(PSTR("\r\nAttributes:\t"));
640  PrintHex<uint8_t>(ep_ptr->bmAttributes);
641  Notify(PSTR("\r\nMaxPktSize:\t"));
642  PrintHex<uint16_t>(ep_ptr->wMaxPacketSize);
643  Notify(PSTR("\r\nPoll Intrv:\t"));
644  PrintHex<uint8_t>(ep_ptr->bInterval);
645  Notify(PSTR("\r\n"));
646 }