]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp
lufa: usb-usb: Use LUFA startup instead of cusotom
[max/tmk_keyboard.git] / tmk_core / protocol / usb_hid / USB_Host_Shield_2.0 / masstorage.cpp
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
24 ////////////////////////////////////////////////////////////////////////////////
25
26 // Interface code
27
28 ////////////////////////////////////////////////////////////////////////////////
29
30 /**
31  * Get the capacity of the media
32  *
33  * @param lun Logical Unit Number
34  * @return media capacity
35  */
36 uint32_t BulkOnly::GetCapacity(uint8_t lun) {
37         if(LUNOk[lun])
38                 return CurrentCapacity[lun];
39         return 0LU;
40 }
41
42 /**
43  * Get the sector (block) size used on the media
44  *
45  * @param lun Logical Unit Number
46  * @return media sector size
47  */
48 uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
49         if(LUNOk[lun])
50                 return CurrentSectorSize[lun];
51         return 0U;
52 }
53
54 /**
55  * Test if LUN is ready for use
56  *
57  * @param lun Logical Unit Number
58  * @return true if LUN is ready for use
59  */
60 bool BulkOnly::LUNIsGood(uint8_t lun) {
61         return LUNOk[lun];
62 }
63
64 /**
65  * Test if LUN is write protected
66  *
67  * @param lun Logical Unit Number
68  * @return cached status of write protect switch
69  */
70 bool BulkOnly::WriteProtected(uint8_t lun) {
71         return WriteOk[lun];
72 }
73
74 /**
75  * Wrap and execute a SCSI CDB with length of 6
76  *
77  * @param cdb CDB to execute
78  * @param buf_size Size of expected transaction
79  * @param buf Buffer
80  * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
81  * @return
82  */
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
90 /**
91  * Wrap and execute a SCSI CDB with length of 10
92  *
93  * @param cdb CDB to execute
94  * @param buf_size Size of expected transaction
95  * @param buf Buffer
96  * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
97  * @return
98  */
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
106 /**
107  * Lock or Unlock the tray or door on device.
108  * Caution: Some devices with buggy firmware will lock up.
109  *
110  * @param lun Logical Unit Number
111  * @param lock 1 to lock, 0 to unlock
112  * @return
113  */
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
122 /**
123  * Media control, for spindle motor and media tray or door.
124  * This includes CDROM, TAPE and anything with a media loader.
125  *
126  * @param lun Logical Unit Number
127  * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media
128  * @return 0 on success
129  */
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
144 /**
145  * Read data from media
146  *
147  * @param lun Logical Unit Number
148  * @param addr LBA address on media to read
149  * @param bsize size of a block (we should probably use the cached size)
150  * @param blocks how many blocks to read
151  * @param buf memory that is able to hold the requested data
152  * @return 0 on success
153  */
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
178 /**
179  * Write data to media
180  *
181  * @param lun Logical Unit Number
182  * @param addr LBA address on media to write
183  * @param bsize size of a block (we should probably use the cached size)
184  * @param blocks how many blocks to write
185  * @param buf memory that contains the data to write
186  * @return 0 on success
187  */
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
216 ////////////////////////////////////////////////////////////////////////////////
217
218 // Main driver code
219
220 ////////////////////////////////////////////////////////////////////////////////
221
222 BulkOnly::BulkOnly(USB *p) :
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
237 /**
238  * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success
239  * We need to standardize either the rcode, or change the API to return values
240  * so a signal that additional actions are required can be produced.
241  * Some of these codes do exist already.
242  *
243  * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance.
244  * Doing so would save some program memory when using multiple drivers.
245  *
246  * @param parent USB address of parent
247  * @param port address of port on parent
248  * @param lowspeed true if device is low speed
249  * @return
250  */
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)
266                 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
267
268         // <TECHNICAL>
269         // Get pointer to pseudo device with address 0 assigned
270         p = addrPool.GetUsbDevicePtr(0);
271         if(!p) {
272                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
273         }
274
275         if(!p->epinfo) {
276                 USBTRACE("epinfo\r\n");
277                 return USB_ERROR_EPINFO_IS_NULL;
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)
300                 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
301
302         // Extract Max Packet Size from the device descriptor
303         epInfo[0].maxPktSize = udd->bMaxPacketSize0;
304         // Steal and abuse from epInfo structure to save on memory.
305         epInfo[1].epAddr = udd->bNumConfigurations;
306         // </TECHNICAL>
307         return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
308
309 FailGetDevDescr:
310 #ifdef DEBUG_USB_HOST
311         NotifyFailGetDevDescr(rcode);
312 #endif
313         rcode = USB_ERROR_FailGetDevDescr;
314
315         Release();
316         return rcode;
317 };
318
319 /**
320  *
321  * @param parent (not used)
322  * @param port (not used)
323  * @param lowspeed true if device is low speed
324  * @return 0 for success
325  */
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)
336                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
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)
357                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
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++) {
370                 ConfigDescParser< USB_CLASS_MASS_STORAGE,
371                         MASS_SUBCLASS_SCSI,
372                         MASS_PROTO_BBB,
373                         CP_MASK_COMPARE_CLASS |
374                         CP_MASK_COMPARE_SUBCLASS |
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)
387                 return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
388
389         // Assign epInfo to epinfo pointer
390         pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
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
407         if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
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
493         NotifyFailSetConfDescr();
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
517         NotifyFailSetDevTblEntry();
518         goto Fail;
519 #endif
520
521 FailGetConfDescr:
522 #ifdef DEBUG_USB_HOST
523         NotifyFailGetConfDescr();
524 #endif
525
526 #ifdef DEBUG_USB_HOST
527 Fail:
528         NotifyFail(rcode);
529 #endif
530         Release();
531         return rcode;
532 }
533
534 /**
535  * For driver use only.
536  *
537  * @param conf
538  * @param iface
539  * @param alt
540  * @param proto
541  * @param pep
542  */
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].epAttribs = 0;
559
560                 bNumEP++;
561
562                 PrintEndpointDescriptor(pep);
563
564         }
565 #else
566         if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
567                 index = epInterruptInIndex;
568         else
569                 if((pep->bmAttributes & 0x02) == 2)
570                 index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
571         else
572                 return;
573
574         // Fill in the endpoint info structure
575         epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
576         epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
577         epInfo[index].epAttribs = 0;
578
579         bNumEP++;
580
581         PrintEndpointDescriptor(pep);
582 #endif
583 }
584
585 /**
586  * For driver use only.
587  *
588  * @return
589  */
590 uint8_t BulkOnly::Release() {
591         ClearAllEP();
592         pUsb->GetAddressPool().FreeAddress(bAddress);
593         return 0;
594 }
595
596 /**
597  * For driver use only.
598  *
599  * @param lun Logical Unit Number
600  * @return true if LUN is ready for use.
601  */
602 bool BulkOnly::CheckLUN(uint8_t lun) {
603         uint8_t rcode;
604         Capacity capacity;
605         for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
606
607         rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
608         if(rcode) {
609                 //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
610                 return false;
611         }
612         ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
613         for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
614                 D_PrintHex<uint8_t > (capacity.data[i], 0x80);
615         Notify(PSTR("\r\n\r\n"), 0x80);
616         // Only 512/1024/2048/4096 are valid values!
617         uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
618         if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
619                 return false;
620         }
621         // Store capacity information.
622         CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
623
624         CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
625         if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) {
626                 // Buggy firmware will report 0xffffffff or 0 for no media
627                 if(CurrentCapacity[lun])
628                         ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
629                 return false;
630         }
631         delay(20);
632         Page3F(lun);
633         if(!TestUnitReady(lun)) return true;
634         return false;
635 }
636
637 /**
638  * For driver use only.
639  *
640  * Scan for media change on all LUNs
641  */
642 void BulkOnly::CheckMedia() {
643         for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
644                 if(TestUnitReady(lun)) {
645                         LUNOk[lun] = false;
646                         continue;
647                 }
648                 if(!LUNOk[lun])
649                         LUNOk[lun] = CheckLUN(lun);
650         }
651 #if 0
652         printf("}}}}}}}}}}}}}}}}STATUS ");
653         for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
654                 if(LUNOk[lun])
655                         printf("#");
656                 else printf(".");
657         }
658         printf("\r\n");
659 #endif
660         qNextPollTime = millis() + 2000;
661 }
662
663 /**
664  * For driver use only.
665  *
666  * @return
667  */
668 uint8_t BulkOnly::Poll() {
669         //uint8_t rcode = 0;
670
671         if(!bPollEnable)
672                 return 0;
673
674         if((long)(millis() - qNextPollTime) >= 0L) {
675                 CheckMedia();
676         }
677         //rcode = 0;
678
679         return 0;
680 }
681
682 ////////////////////////////////////////////////////////////////////////////////
683
684
685 // SCSI code
686
687
688 ////////////////////////////////////////////////////////////////////////////////
689
690 /**
691  * For driver use only.
692  *
693  * @param plun
694  * @return
695  */
696 uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
697         uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
698
699         if(ret == hrSTALL)
700                 *plun = 0;
701
702         return 0;
703 }
704
705 /**
706  * For driver use only. Used during Driver Init
707  *
708  * @param lun Logical Unit Number
709  * @param bsize
710  * @param buf
711  * @return
712  */
713 uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
714         Notify(PSTR("\r\nInquiry\r\n"), 0x80);
715         Notify(PSTR("---------\r\n"), 0x80);
716
717         CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0);
718         uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
719
720         return rc;
721 }
722
723 /**
724  * For driver use only.
725  *
726  * @param lun Logical Unit Number
727  * @return
728  */
729 uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
730         //SetCurLUN(lun);
731         if(!bAddress)
732                 return MASS_ERR_UNIT_NOT_READY;
733
734         Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
735         Notify(PSTR("-----------------\r\n"), 0x80);
736
737         CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);
738         return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN);
739
740 }
741
742 /**
743  * For driver use only.
744  *
745  * @param lun Logical Unit Number
746  * @param pc
747  * @param page
748  * @param subpage
749  * @param len
750  * @param pbuf
751  * @return
752  */
753 uint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
754         Notify(PSTR("\r\rModeSense\r\n"), 0x80);
755         Notify(PSTR("------------\r\n"), 0x80);
756
757         CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0);
758         return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN);
759 }
760
761 /**
762  * For driver use only.
763  *
764  * @param lun Logical Unit Number
765  * @param bsize
766  * @param buf
767  * @return
768  */
769 uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
770         Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
771         Notify(PSTR("---------------\r\n"), 0x80);
772
773         CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun);
774         return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN);
775 }
776
777 /**
778  * For driver use only.
779  *
780  * Page 3F contains write protect status.
781  *
782  * @param lun Logical Unit Number to test.
783  * @return Write protect switch status.
784  */
785 uint8_t BulkOnly::Page3F(uint8_t lun) {
786         uint8_t buf[192];
787         for(int i = 0; i < 192; i++) {
788                 buf[i] = 0x00;
789         }
790         WriteOk[lun] = true;
791         uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
792         if(!rc) {
793                 WriteOk[lun] = ((buf[2] & 0x80) == 0);
794                 Notify(PSTR("Mode Sense: "), 0x80);
795                 for(int i = 0; i < 4; i++) {
796                         D_PrintHex<uint8_t > (buf[i], 0x80);
797                         Notify(PSTR(" "), 0x80);
798                 }
799                 Notify(PSTR("\r\n"), 0x80);
800         }
801         return rc;
802 }
803
804 /**
805  * For driver use only.
806  *
807  * @param lun Logical Unit Number
808  * @param size
809  * @param buf
810  * @return
811  */
812 uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
813         Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
814         Notify(PSTR("----------------\r\n"), 0x80);
815
816         CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0);
817         CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
818         //SetCurLUN(lun);
819         return Transaction(&cbw, size, buf);
820 }
821
822
823 ////////////////////////////////////////////////////////////////////////////////
824
825
826 // USB code
827
828
829 ////////////////////////////////////////////////////////////////////////////////
830
831 /**
832  * For driver use only.
833  *
834  * @param index
835  * @return
836  */
837 uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
838         if(index == 0)
839                 return 0;
840
841         uint8_t ret = 0;
842
843         while((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01))
844                 delay(6);
845
846         if(ret) {
847                 ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
848                 ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
849                 return ret;
850         }
851         epInfo[index].bmSndToggle = 0;
852         epInfo[index].bmRcvToggle = 0;
853         // epAttribs = 0;
854         return 0;
855 }
856
857 /**
858  * For driver use only.
859  *
860  */
861 void BulkOnly::Reset() {
862         while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
863 }
864
865 /**
866  * For driver use only.
867  *
868  * @return 0 if successful
869  */
870 uint8_t BulkOnly::ResetRecovery() {
871         Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
872         Notify(PSTR("-----------------\r\n"), 0x80);
873
874         delay(6);
875         Reset();
876         delay(6);
877         ClearEpHalt(epDataInIndex);
878         delay(6);
879         bLastUsbError = ClearEpHalt(epDataOutIndex);
880         delay(6);
881         return bLastUsbError;
882 }
883
884 /**
885  * For driver use only.
886  *
887  * Clear all EP data and clear all LUN status
888  */
889 void BulkOnly::ClearAllEP() {
890         for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
891                 epInfo[i].epAddr = 0;
892                 epInfo[i].maxPktSize = (i) ? 0 : 8;
893                 epInfo[i].epAttribs = 0;
894
895                 epInfo[i].bmNakPower = USB_NAK_DEFAULT;
896         }
897
898         for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
899                 LUNOk[i] = false;
900                 WriteOk[i] = false;
901                 CurrentCapacity[i] = 0lu;
902                 CurrentSectorSize[i] = 0;
903         }
904
905         bIface = 0;
906         bNumEP = 1;
907         bAddress = 0;
908         qNextPollTime = 0;
909         bPollEnable = false;
910         bLastUsbError = 0;
911         bMaxLUN = 0;
912         bTheLUN = 0;
913 }
914
915 /**
916  * For driver use only.
917  *
918  * @param pcsw
919  * @param pcbw
920  * @return
921  */
922 bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
923         if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
924                 Notify(PSTR("CSW:Sig error\r\n"), 0x80);
925                 return false;
926         }
927         if(pcsw->dCSWTag != pcbw->dCBWTag) {
928                 Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
929                 return false;
930         }
931         return true;
932 }
933
934 /**
935  * For driver use only.
936  *
937  * @param error
938  * @param index
939  * @return
940  */
941 uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
942         uint8_t count = 3;
943
944         bLastUsbError = error;
945         //if (error)
946         //ClearEpHalt(index);
947         while(error && count) {
948                 if(error != hrSUCCESS) {
949                         ErrorMessage<uint8_t > (PSTR("USB Error"), error);
950                         ErrorMessage<uint8_t > (PSTR("Index"), index);
951                 }
952                 switch(error) {
953                                 // case hrWRONGPID:
954                         case hrSUCCESS:
955                                 return MASS_ERR_SUCCESS;
956                         case hrBUSY:
957                                 // SIE is busy, just hang out and try again.
958                                 return MASS_ERR_UNIT_BUSY;
959                         case hrTIMEOUT:
960                         case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED;
961                         case hrSTALL:
962                                 if(index == 0)
963                                         return MASS_ERR_STALL;
964                                 ClearEpHalt(index);
965                                 if(index != epDataInIndex)
966                                         return MASS_ERR_WRITE_STALL;
967                                 return MASS_ERR_STALL;
968
969                         case hrNAK:
970                                 if(index == 0)
971                                         return MASS_ERR_UNIT_BUSY;
972                                 return MASS_ERR_UNIT_BUSY;
973
974                         case hrTOGERR:
975                                 // Handle a very super rare corner case, where toggles become de-synched.
976                                 // I have only ran into one device that has this firmware bug, and this is
977                                 // the only clean way to get back into sync with the buggy device firmware.
978                                 //   --AJK
979                                 if(bAddress && bConfNum) {
980                                         error = pUsb->setConf(bAddress, 0, bConfNum);
981
982                                         if(error)
983                                                 break;
984                                 }
985                                 return MASS_ERR_SUCCESS;
986                         default:
987                                 ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
988                                 return MASS_ERR_GENERAL_USB_ERROR;
989                 }
990                 count--;
991         } // while
992
993         return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
994 }
995
996 #if MS_WANT_PARSER
997
998 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
999         return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
1000 }
1001 #endif
1002
1003 /**
1004  * For driver use only.
1005  *
1006  * @param pcbw
1007  * @param buf_size
1008  * @param buf
1009  * @param flags
1010  * @return
1011  */
1012 uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
1013 #if MS_WANT_PARSER
1014         , uint8_t flags
1015 #endif
1016         ) {
1017
1018 #if MS_WANT_PARSER
1019         uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
1020         printf("Transfersize %i\r\n", bytes);
1021         delay(1000);
1022
1023         bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
1024 #else
1025         uint16_t bytes = buf_size;
1026 #endif
1027         bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
1028         uint8_t ret = 0;
1029         uint8_t usberr;
1030         CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
1031         SetCurLUN(pcbw->bmCBWLUN);
1032         ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
1033
1034         while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
1035
1036         ret = HandleUsbError(usberr, epDataOutIndex);
1037         //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
1038         if(ret) {
1039                 ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
1040         } else {
1041                 if(bytes) {
1042                         if(!write) {
1043 #if MS_WANT_PARSER
1044                                 if(callback) {
1045                                         uint8_t rbuf[bytes];
1046                                         while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
1047                                         if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
1048                                 } else {
1049 #endif
1050                                         while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1051 #if MS_WANT_PARSER
1052
1053                                 }
1054 #endif
1055                                 ret = HandleUsbError(usberr, epDataInIndex);
1056                         } else {
1057                                 while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
1058                                 ret = HandleUsbError(usberr, epDataOutIndex);
1059                         }
1060                         if(ret) {
1061                                 ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
1062                         }
1063                 }
1064         }
1065
1066         {
1067                 bytes = sizeof (CommandStatusWrapper);
1068                 int tries = 2;
1069                 while(tries--) {
1070                         while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
1071                         if(!usberr) break;
1072                         ClearEpHalt(epDataInIndex);
1073                         if(tries) ResetRecovery();
1074                 }
1075                 if(!ret) {
1076                         Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
1077                         Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
1078                 } else {
1079                         // Throw away csw, IT IS NOT OF ANY USE.
1080                         ResetRecovery();
1081                         return ret;
1082                 }
1083                 ret = HandleUsbError(usberr, epDataInIndex);
1084                 if(ret) {
1085                         ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
1086                 }
1087                 if(usberr == hrSUCCESS) {
1088                         if(IsValidCSW(&csw, pcbw)) {
1089                                 //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
1090                                 //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
1091                                 //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
1092                                 Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
1093                                 return csw.bCSWStatus;
1094                         } else {
1095                                 // NOTE! Sometimes this is caused by the reported residue being wrong.
1096                                 // Get a different device. It isn't compliant, and should have never passed Q&A.
1097                                 // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
1098                                 // Other devices that exhibit this behavior exist in the wild too.
1099                                 // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk
1100                                 Notify(PSTR("Invalid CSW\r\n"), 0x80);
1101                                 ResetRecovery();
1102                                 //return MASS_ERR_SUCCESS;
1103                                 return MASS_ERR_INVALID_CSW;
1104                         }
1105                 }
1106         }
1107         return ret;
1108 }
1109
1110 /**
1111  * For driver use only.
1112  *
1113  * @param lun Logical Unit Number
1114  * @return
1115  */
1116 uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
1117         if(lun > bMaxLUN)
1118                 return MASS_ERR_INVALID_LUN;
1119         bTheLUN = lun;
1120         return MASS_ERR_SUCCESS;
1121 };
1122
1123 /**
1124  * For driver use only.
1125  *
1126  * @param status
1127  * @return
1128  */
1129 uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
1130         uint8_t ret = 0;
1131
1132         switch(status) {
1133                 case 0: return MASS_ERR_SUCCESS;
1134
1135                 case 2:
1136                         ErrorMessage<uint8_t > (PSTR("Phase Error"), status);
1137                         ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1138                         ResetRecovery();
1139                         return MASS_ERR_GENERAL_SCSI_ERROR;
1140
1141                 case 1:
1142                         ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
1143                         ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1144                         RequestSenseResponce rsp;
1145
1146                         ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
1147
1148                         if(ret) {
1149                                 return MASS_ERR_GENERAL_SCSI_ERROR;
1150                         }
1151                         ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
1152                         if(rsp.bResponseCode & 0x80) {
1153                                 Notify(PSTR("Information field: "), 0x80);
1154                                 for(int i = 0; i < 4; i++) {
1155                                         D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
1156                                         Notify(PSTR(" "), 0x80);
1157                                 }
1158                                 Notify(PSTR("\r\n"), 0x80);
1159                         }
1160                         ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
1161                         ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
1162                         ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
1163                         // warning, this is not testing ASQ, only SK and ASC.
1164                         switch(rsp.bmSenseKey) {
1165                                 case SCSI_S_UNIT_ATTENTION:
1166                                         switch(rsp.bAdditionalSenseCode) {
1167                                                 case SCSI_ASC_MEDIA_CHANGED:
1168                                                         return MASS_ERR_MEDIA_CHANGED;
1169                                                 default:
1170                                                         return MASS_ERR_UNIT_NOT_READY;
1171                                         }
1172                                 case SCSI_S_NOT_READY:
1173                                         switch(rsp.bAdditionalSenseCode) {
1174                                                 case SCSI_ASC_MEDIUM_NOT_PRESENT:
1175                                                         return MASS_ERR_NO_MEDIA;
1176                                                 default:
1177                                                         return MASS_ERR_UNIT_NOT_READY;
1178                                         }
1179                                 case SCSI_S_ILLEGAL_REQUEST:
1180                                         switch(rsp.bAdditionalSenseCode) {
1181                                                 case SCSI_ASC_LBA_OUT_OF_RANGE:
1182                                                         return MASS_ERR_BAD_LBA;
1183                                                 default:
1184                                                         return MASS_ERR_CMD_NOT_SUPPORTED;
1185                                         }
1186                                 default:
1187                                         return MASS_ERR_GENERAL_SCSI_ERROR;
1188                         }
1189
1190                         // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
1191                         //    case 0x05/0x14: we stalled out
1192                         //    case 0x15/0x16: we naked out.
1193                 default:
1194                         ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
1195                         ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
1196                         return status;
1197         } // switch
1198 }
1199
1200
1201 ////////////////////////////////////////////////////////////////////////////////
1202
1203
1204 // Debugging code
1205
1206
1207 ////////////////////////////////////////////////////////////////////////////////
1208
1209 /**
1210  *
1211  * @param ep_ptr
1212  */
1213 void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
1214         Notify(PSTR("Endpoint descriptor:"), 0x80);
1215         Notify(PSTR("\r\nLength:\t\t"), 0x80);
1216         D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
1217         Notify(PSTR("\r\nType:\t\t"), 0x80);
1218         D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
1219         Notify(PSTR("\r\nAddress:\t"), 0x80);
1220         D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
1221         Notify(PSTR("\r\nAttributes:\t"), 0x80);
1222         D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
1223         Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
1224         D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
1225         Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
1226         D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
1227         Notify(PSTR("\r\n"), 0x80);
1228 }
1229
1230
1231 ////////////////////////////////////////////////////////////////////////////////
1232
1233
1234 // misc/to kill/to-do
1235
1236
1237 ////////////////////////////////////////////////////////////////////////////////
1238
1239 /* We won't be needing this... */
1240 uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
1241 #if MS_WANT_PARSER
1242         if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
1243         Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
1244         Notify(PSTR("---------\r\n"), 0x80);
1245
1246         CommandBlockWrapper cbw = CommandBlockWrapper();
1247
1248         cbw.dCBWSignature = MASS_CBW_SIGNATURE;
1249         cbw.dCBWTag = ++dCBWTag;
1250         cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
1251         cbw.bmCBWFlags = MASS_CMD_DIR_IN,
1252                 cbw.bmCBWLUN = lun;
1253         cbw.bmCBWCBLength = 10;
1254
1255         cbw.CBWCB[0] = SCSI_CMD_READ_10;
1256         cbw.CBWCB[8] = blocks;
1257         cbw.CBWCB[2] = ((addr >> 24) & 0xff);
1258         cbw.CBWCB[3] = ((addr >> 16) & 0xff);
1259         cbw.CBWCB[4] = ((addr >> 8) & 0xff);
1260         cbw.CBWCB[5] = (addr & 0xff);
1261
1262         return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
1263 #else
1264         return MASS_ERR_NOT_IMPLEMENTED;
1265 #endif
1266 }