My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

masstorage.cpp 35KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219
  1. /**
  2. * Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *
  18. * Contact information
  19. * -------------------
  20. *
  21. * Circuits At Home, LTD
  22. * Web : http://www.circuitsathome.com
  23. * e-mail : support@circuitsathome.com
  24. */
  25. #include "../../../inc/MarlinConfigPre.h"
  26. #if ENABLED(USB_FLASH_DRIVE_SUPPORT)
  27. #include "masstorage.h"
  28. const uint8_t BulkOnly::epDataInIndex = 1;
  29. const uint8_t BulkOnly::epDataOutIndex = 2;
  30. const uint8_t BulkOnly::epInterruptInIndex = 3;
  31. ////////////////////////////////////////////////////////////////////////////////
  32. // Interface code
  33. ////////////////////////////////////////////////////////////////////////////////
  34. /**
  35. * Get the capacity of the media
  36. *
  37. * @param lun Logical Unit Number
  38. * @return media capacity
  39. */
  40. uint32_t BulkOnly::GetCapacity(uint8_t lun) {
  41. return LUNOk[lun] ? CurrentCapacity[lun] : 0UL;
  42. }
  43. /**
  44. * Get the sector (block) size used on the media
  45. *
  46. * @param lun Logical Unit Number
  47. * @return media sector size
  48. */
  49. uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
  50. return LUNOk[lun] ? CurrentSectorSize[lun] : 0U;
  51. }
  52. /**
  53. * Test if LUN is ready for use
  54. *
  55. * @param lun Logical Unit Number
  56. * @return true if LUN is ready for use
  57. */
  58. bool BulkOnly::LUNIsGood(uint8_t lun) { return LUNOk[lun]; }
  59. /**
  60. * Test if LUN is write protected
  61. *
  62. * @param lun Logical Unit Number
  63. * @return cached status of write protect switch
  64. */
  65. bool BulkOnly::WriteProtected(uint8_t lun) { return WriteOk[lun]; }
  66. /**
  67. * Wrap and execute a SCSI CDB with length of 6
  68. *
  69. * @param cdb CDB to execute
  70. * @param buf_size Size of expected transaction
  71. * @param buf Buffer
  72. * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
  73. * @return
  74. */
  75. uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
  76. // promote buf_size to 32bits.
  77. CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
  78. //SetCurLUN(cdb->LUN);
  79. return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
  80. }
  81. /**
  82. * Wrap and execute a SCSI CDB with length of 10
  83. *
  84. * @param cdb CDB to execute
  85. * @param buf_size Size of expected transaction
  86. * @param buf Buffer
  87. * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
  88. * @return
  89. */
  90. uint8_t BulkOnly::SCSITransaction10(CDB10_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. /**
  97. * Lock or Unlock the tray or door on device.
  98. * Caution: Some devices with buggy firmware will lock up.
  99. *
  100. * @param lun Logical Unit Number
  101. * @param lock 1 to lock, 0 to unlock
  102. * @return
  103. */
  104. uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
  105. Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
  106. Notify(PSTR("---------\r\n"), 0x80);
  107. CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock);
  108. return SCSITransaction6(&cdb, (uint16_t)0, nullptr, (uint8_t)MASS_CMD_DIR_IN);
  109. }
  110. /**
  111. * Media control, for spindle motor and media tray or door.
  112. * This includes CDROM, TAPE and anything with a media loader.
  113. *
  114. * @param lun Logical Unit Number
  115. * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media
  116. * @return 0 on success
  117. */
  118. uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
  119. Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
  120. Notify(PSTR("-----------------\r\n"), 0x80);
  121. uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
  122. if (bAddress) {
  123. CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
  124. rcode = SCSITransaction6(&cdb, (uint16_t)0, nullptr, (uint8_t)MASS_CMD_DIR_OUT);
  125. }
  126. else
  127. SetCurLUN(lun);
  128. return rcode;
  129. }
  130. /**
  131. * Read data from media
  132. *
  133. * @param lun Logical Unit Number
  134. * @param addr LBA address on media to read
  135. * @param bsize size of a block (we should probably use the cached size)
  136. * @param blocks how many blocks to read
  137. * @param buf memory that is able to hold the requested data
  138. * @return 0 on success
  139. */
  140. uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
  141. if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
  142. Notify(PSTR("\r\nRead LUN:\t"), 0x80);
  143. D_PrintHex<uint8_t> (lun, 0x90);
  144. Notify(PSTR("\r\nLBA:\t\t"), 0x90);
  145. D_PrintHex<uint32_t> (addr, 0x90);
  146. Notify(PSTR("\r\nblocks:\t\t"), 0x90);
  147. D_PrintHex<uint8_t> (blocks, 0x90);
  148. Notify(PSTR("\r\nblock size:\t"), 0x90);
  149. D_PrintHex<uint16_t> (bsize, 0x90);
  150. Notify(PSTR("\r\n---------\r\n"), 0x80);
  151. CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr);
  152. again:
  153. uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN);
  154. if (er == MASS_ERR_STALL) {
  155. MediaCTL(lun, 1);
  156. delay(150);
  157. if (!TestUnitReady(lun)) goto again;
  158. }
  159. return er;
  160. }
  161. /**
  162. * Write data to media
  163. *
  164. * @param lun Logical Unit Number
  165. * @param addr LBA address on media to write
  166. * @param bsize size of a block (we should probably use the cached size)
  167. * @param blocks how many blocks to write
  168. * @param buf memory that contains the data to write
  169. * @return 0 on success
  170. */
  171. uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
  172. if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
  173. if (!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
  174. Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
  175. D_PrintHex<uint8_t> (lun, 0x90);
  176. Notify(PSTR("\r\nLBA:\t\t"), 0x90);
  177. D_PrintHex<uint32_t> (addr, 0x90);
  178. Notify(PSTR("\r\nblocks:\t\t"), 0x90);
  179. D_PrintHex<uint8_t> (blocks, 0x90);
  180. Notify(PSTR("\r\nblock size:\t"), 0x90);
  181. D_PrintHex<uint16_t> (bsize, 0x90);
  182. Notify(PSTR("\r\n---------\r\n"), 0x80);
  183. CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr);
  184. again:
  185. uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT);
  186. if (er == MASS_ERR_WRITE_STALL) {
  187. MediaCTL(lun, 1);
  188. delay(150);
  189. if (!TestUnitReady(lun)) goto again;
  190. }
  191. return er;
  192. }
  193. // End of user functions, the remaining code below is driver internals.
  194. // Only developer serviceable parts below!
  195. ////////////////////////////////////////////////////////////////////////////////
  196. // Main driver code
  197. ////////////////////////////////////////////////////////////////////////////////
  198. BulkOnly::BulkOnly(USB *p) :
  199. pUsb(p),
  200. bAddress(0),
  201. bIface(0),
  202. bNumEP(1),
  203. qNextPollTime(0),
  204. bPollEnable(false),
  205. //dCBWTag(0),
  206. bLastUsbError(0) {
  207. ClearAllEP();
  208. dCBWTag = 0;
  209. if (pUsb) pUsb->RegisterDeviceClass(this);
  210. }
  211. /**
  212. * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success
  213. * We need to standardize either the rcode, or change the API to return values
  214. * so a signal that additional actions are required can be produced.
  215. * Some of these codes do exist already.
  216. *
  217. * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance.
  218. * Doing so would save some program memory when using multiple drivers.
  219. *
  220. * @param parent USB address of parent
  221. * @param port address of port on parent
  222. * @param lowspeed true if device is low speed
  223. * @return
  224. */
  225. uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
  226. const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
  227. uint8_t buf[constBufSize];
  228. USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
  229. uint8_t rcode;
  230. UsbDevice *p = nullptr;
  231. EpInfo *oldep_ptr = nullptr;
  232. USBTRACE("MS ConfigureDevice\r\n");
  233. ClearAllEP();
  234. AddressPool &addrPool = pUsb->GetAddressPool();
  235. if (bAddress) return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
  236. // <TECHNICAL>
  237. // Get pointer to pseudo device with address 0 assigned
  238. p = addrPool.GetUsbDevicePtr(0);
  239. if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
  240. if (!p->epinfo) {
  241. USBTRACE("epinfo\r\n");
  242. return USB_ERROR_EPINFO_IS_NULL;
  243. }
  244. // Save old pointer to EP_RECORD of address 0
  245. oldep_ptr = p->epinfo;
  246. // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
  247. p->epinfo = epInfo;
  248. p->lowspeed = lowspeed;
  249. // Get device descriptor
  250. rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
  251. // Restore p->epinfo
  252. p->epinfo = oldep_ptr;
  253. if (rcode) goto FailGetDevDescr;
  254. // Allocate new address according to device class
  255. bAddress = addrPool.AllocAddress(parent, false, port);
  256. if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
  257. // Extract Max Packet Size from the device descriptor
  258. epInfo[0].maxPktSize = udd->bMaxPacketSize0;
  259. // Steal and abuse from epInfo structure to save on memory.
  260. epInfo[1].epAddr = udd->bNumConfigurations;
  261. // </TECHNICAL>
  262. return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
  263. FailGetDevDescr:
  264. #ifdef DEBUG_USB_HOST
  265. NotifyFailGetDevDescr(rcode);
  266. #endif
  267. rcode = USB_ERROR_FailGetDevDescr;
  268. Release();
  269. return rcode;
  270. }
  271. /**
  272. * @param parent (not used)
  273. * @param port (not used)
  274. * @param lowspeed true if device is low speed
  275. * @return 0 for success
  276. */
  277. uint8_t BulkOnly::Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed) {
  278. uint8_t rcode;
  279. uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
  280. epInfo[1].epAddr = 0;
  281. USBTRACE("MS Init\r\n");
  282. AddressPool &addrPool = pUsb->GetAddressPool();
  283. UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
  284. if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
  285. // Assign new address to the device
  286. delay(2000);
  287. rcode = pUsb->setAddr(0, 0, bAddress);
  288. if (rcode) {
  289. p->lowspeed = false;
  290. addrPool.FreeAddress(bAddress);
  291. bAddress = 0;
  292. USBTRACE2("setAddr:", rcode);
  293. return rcode;
  294. }
  295. USBTRACE2("Addr:", bAddress);
  296. p->lowspeed = false;
  297. p = addrPool.GetUsbDevicePtr(bAddress);
  298. if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
  299. p->lowspeed = lowspeed;
  300. // Assign epInfo to epinfo pointer
  301. rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
  302. if (rcode) goto FailSetDevTblEntry;
  303. USBTRACE2("NC:", num_of_conf);
  304. for (uint8_t i = 0; i < num_of_conf; i++) {
  305. ConfigDescParser< USB_CLASS_MASS_STORAGE,
  306. MASS_SUBCLASS_SCSI,
  307. MASS_PROTO_BBB,
  308. CP_MASK_COMPARE_CLASS |
  309. CP_MASK_COMPARE_SUBCLASS |
  310. CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);
  311. rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
  312. if (rcode) goto FailGetConfDescr;
  313. if (bNumEP > 1) break;
  314. }
  315. if (bNumEP < 3) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
  316. // Assign epInfo to epinfo pointer
  317. pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
  318. USBTRACE2("Conf:", bConfNum);
  319. // Set Configuration Value
  320. rcode = pUsb->setConf(bAddress, 0, bConfNum);
  321. if (rcode) goto FailSetConfDescr;
  322. //Linux does a 1sec delay after this.
  323. delay(1000);
  324. rcode = GetMaxLUN(&bMaxLUN);
  325. if (rcode) goto FailGetMaxLUN;
  326. if (bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
  327. ErrorMessage<uint8_t> (PSTR("MaxLUN"), bMaxLUN);
  328. delay(1000); // Delay a bit for slow firmware.
  329. for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
  330. InquiryResponse response;
  331. rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
  332. if (rcode) {
  333. ErrorMessage<uint8_t> (PSTR("Inquiry"), rcode);
  334. }
  335. else {
  336. #if 0
  337. printf("LUN %i `", lun);
  338. uint8_t *buf = response.VendorID;
  339. for (int i = 0; i < 28; i++) printf("%c", buf[i]);
  340. printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
  341. printf("Device type %2.2X ", response.DeviceType);
  342. printf("RMB %1.1X ", response.Removable);
  343. printf("SSCS %1.1X ", response.SCCS);
  344. uint8_t sv = response.Version;
  345. printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
  346. switch (sv) {
  347. case 0:
  348. printf("No specific");
  349. break;
  350. case 1:
  351. printf("ANSI X3.131-1986 (ANSI 1)");
  352. break;
  353. case 2:
  354. printf("ANSI X3.131-1994 (ANSI 2)");
  355. break;
  356. case 3:
  357. printf("ANSI INCITS 301-1997 (SPC)");
  358. break;
  359. case 4:
  360. printf("ANSI INCITS 351-2001 (SPC-2)");
  361. break;
  362. case 5:
  363. printf("ANSI INCITS 408-2005 (SPC-4)");
  364. break;
  365. case 6:
  366. printf("T10/1731-D (SPC-4)");
  367. break;
  368. default: printf("unknown");
  369. }
  370. printf(" standards.\r\n");
  371. #endif
  372. uint8_t tries = 0xf0;
  373. while ((rcode = TestUnitReady(lun))) {
  374. if (rcode == 0x08) break; // break on no media, this is OK to do.
  375. // try to lock media and spin up
  376. if (tries < 14) {
  377. LockMedia(lun, 1);
  378. MediaCTL(lun, 1); // I actually have a USB stick that needs this!
  379. } else
  380. delay(2 * (tries + 1));
  381. tries++;
  382. if (!tries) break;
  383. }
  384. if (!rcode) {
  385. delay(1000);
  386. LUNOk[lun] = CheckLUN(lun);
  387. if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
  388. }
  389. }
  390. }
  391. CheckMedia();
  392. rcode = OnInit();
  393. if (rcode) goto FailOnInit;
  394. #ifdef DEBUG_USB_HOST
  395. USBTRACE("MS configured\r\n\r\n");
  396. #endif
  397. bPollEnable = true;
  398. //USBTRACE("Poll enabled\r\n");
  399. return 0;
  400. FailSetConfDescr:
  401. #ifdef DEBUG_USB_HOST
  402. NotifyFailSetConfDescr();
  403. goto Fail;
  404. #endif
  405. FailOnInit:
  406. #ifdef DEBUG_USB_HOST
  407. USBTRACE("OnInit:");
  408. goto Fail;
  409. #endif
  410. FailGetMaxLUN:
  411. #ifdef DEBUG_USB_HOST
  412. USBTRACE("GetMaxLUN:");
  413. goto Fail;
  414. #endif
  415. //#ifdef DEBUG_USB_HOST
  416. // FailInvalidSectorSize:
  417. // USBTRACE("Sector Size is NOT VALID: ");
  418. // goto Fail;
  419. //#endif
  420. FailSetDevTblEntry:
  421. #ifdef DEBUG_USB_HOST
  422. NotifyFailSetDevTblEntry();
  423. goto Fail;
  424. #endif
  425. FailGetConfDescr:
  426. #ifdef DEBUG_USB_HOST
  427. NotifyFailGetConfDescr();
  428. #endif
  429. #ifdef DEBUG_USB_HOST
  430. Fail:
  431. NotifyFail(rcode);
  432. #endif
  433. Release();
  434. return rcode;
  435. }
  436. /**
  437. * For driver use only.
  438. *
  439. * @param conf
  440. * @param iface
  441. * @param alt
  442. * @param proto
  443. * @param pep
  444. */
  445. void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR * pep) {
  446. ErrorMessage<uint8_t> (PSTR("Conf.Val"), conf);
  447. ErrorMessage<uint8_t> (PSTR("Iface Num"), iface);
  448. ErrorMessage<uint8_t> (PSTR("Alt.Set"), alt);
  449. bConfNum = conf;
  450. uint8_t index;
  451. #if 1
  452. if ((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) {
  453. index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
  454. // Fill in the endpoint info structure
  455. epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
  456. epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
  457. epInfo[index].bmSndToggle = 0;
  458. epInfo[index].bmRcvToggle = 0;
  459. bNumEP++;
  460. PrintEndpointDescriptor(pep);
  461. }
  462. #else
  463. if ((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80)
  464. index = epInterruptInIndex;
  465. else if ((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK)
  466. index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
  467. else
  468. return;
  469. // Fill in the endpoint info structure
  470. epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
  471. epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
  472. epInfo[index].bmSndToggle = 0;
  473. epInfo[index].bmRcvToggle = 0;
  474. bNumEP++;
  475. PrintEndpointDescriptor(pep);
  476. #endif
  477. }
  478. /**
  479. * For driver use only.
  480. *
  481. * @return
  482. */
  483. uint8_t BulkOnly::Release() {
  484. ClearAllEP();
  485. pUsb->GetAddressPool().FreeAddress(bAddress);
  486. return 0;
  487. }
  488. /**
  489. * For driver use only.
  490. *
  491. * @param lun Logical Unit Number
  492. * @return true if LUN is ready for use.
  493. */
  494. bool BulkOnly::CheckLUN(uint8_t lun) {
  495. uint8_t rcode;
  496. Capacity capacity;
  497. for (uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
  498. rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
  499. if (rcode) {
  500. //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
  501. return false;
  502. }
  503. ErrorMessage<uint8_t> (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
  504. for (uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
  505. D_PrintHex<uint8_t> (capacity.data[i], 0x80);
  506. Notify(PSTR("\r\n\r\n"), 0x80);
  507. // Only 512/1024/2048/4096 are valid values!
  508. uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
  509. if (c != 0x0200UL && c != 0x0400UL && c != 0x0800UL && c != 0x1000UL) return false;
  510. // Store capacity information.
  511. CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
  512. CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
  513. if (CurrentCapacity[lun] == /*0xFFFFFFFFUL */ 0x01UL || CurrentCapacity[lun] == 0x00UL) {
  514. // Buggy firmware will report 0xFFFFFFFF or 0 for no media
  515. if (CurrentCapacity[lun])
  516. ErrorMessage<uint8_t> (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
  517. return false;
  518. }
  519. delay(20);
  520. Page3F(lun);
  521. return !TestUnitReady(lun);
  522. }
  523. /**
  524. * For driver use only.
  525. *
  526. * Scan for media change on all LUNs
  527. */
  528. void BulkOnly::CheckMedia() {
  529. for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
  530. if (TestUnitReady(lun)) {
  531. LUNOk[lun] = false;
  532. continue;
  533. }
  534. if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
  535. }
  536. #if 0
  537. printf("}}}}}}}}}}}}}}}}STATUS ");
  538. for (uint8_t lun = 0; lun <= bMaxLUN; lun++)
  539. printf(LUNOk[lun] ? "#" : ".");
  540. printf("\r\n");
  541. #endif
  542. qNextPollTime = (uint32_t)millis() + 2000;
  543. }
  544. /**
  545. * For driver use only.
  546. *
  547. * @return
  548. */
  549. uint8_t BulkOnly::Poll() {
  550. //uint8_t rcode = 0;
  551. if (!bPollEnable) return 0;
  552. if ((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) CheckMedia();
  553. //rcode = 0;
  554. return 0;
  555. }
  556. ////////////////////////////////////////////////////////////////////////////////
  557. // SCSI code
  558. ////////////////////////////////////////////////////////////////////////////////
  559. /**
  560. * For driver use only.
  561. *
  562. * @param plun
  563. * @return
  564. */
  565. uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
  566. uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, nullptr);
  567. if (ret == hrSTALL)
  568. *plun = 0;
  569. return 0;
  570. }
  571. /**
  572. * For driver use only. Used during Driver Init
  573. *
  574. * @param lun Logical Unit Number
  575. * @param bsize
  576. * @param buf
  577. * @return
  578. */
  579. uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
  580. Notify(PSTR("\r\nInquiry\r\n"), 0x80);
  581. Notify(PSTR("---------\r\n"), 0x80);
  582. CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0UL, (uint8_t)bsize, 0);
  583. uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
  584. return rc;
  585. }
  586. /**
  587. * For driver use only.
  588. *
  589. * @param lun Logical Unit Number
  590. * @return
  591. */
  592. uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
  593. //SetCurLUN(lun);
  594. if (!bAddress)
  595. return MASS_ERR_UNIT_NOT_READY;
  596. Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
  597. Notify(PSTR("-----------------\r\n"), 0x80);
  598. CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);
  599. return SCSITransaction6(&cdb, 0, nullptr, (uint8_t)MASS_CMD_DIR_IN);
  600. }
  601. /**
  602. * For driver use only.
  603. *
  604. * @param lun Logical Unit Number
  605. * @param pc
  606. * @param page
  607. * @param subpage
  608. * @param len
  609. * @param pbuf
  610. * @return
  611. */
  612. uint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
  613. Notify(PSTR("\r\rModeSense\r\n"), 0x80);
  614. Notify(PSTR("------------\r\n"), 0x80);
  615. CDB6_t cdb = CDB6_t(SCSI_CMD_MODE_SENSE_6, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0);
  616. return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN);
  617. }
  618. /**
  619. * For driver use only.
  620. *
  621. * @param lun Logical Unit Number
  622. * @param bsize
  623. * @param buf
  624. * @return
  625. */
  626. uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
  627. Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
  628. Notify(PSTR("---------------\r\n"), 0x80);
  629. CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun);
  630. return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN);
  631. }
  632. /**
  633. * For driver use only.
  634. *
  635. * Page 3F contains write protect status.
  636. *
  637. * @param lun Logical Unit Number to test.
  638. * @return Write protect switch status.
  639. */
  640. uint8_t BulkOnly::Page3F(uint8_t lun) {
  641. uint8_t buf[192];
  642. for (int i = 0; i < 192; i++) {
  643. buf[i] = 0x00;
  644. }
  645. WriteOk[lun] = true;
  646. #if ENABLED(USB_FLASH_DRIVE_SUPPORT) && defined(SKIP_WRITE_PROTECT)
  647. return 0;
  648. #endif
  649. uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
  650. if (!rc) {
  651. WriteOk[lun] = ((buf[2] & 0x80) == 0);
  652. Notify(PSTR("Mode Sense: "), 0x80);
  653. for (int i = 0; i < 4; i++) {
  654. D_PrintHex<uint8_t> (buf[i], 0x80);
  655. Notify(PSTR(" "), 0x80);
  656. }
  657. Notify(PSTR("\r\n"), 0x80);
  658. }
  659. return rc;
  660. }
  661. /**
  662. * For driver use only.
  663. *
  664. * @param lun Logical Unit Number
  665. * @param size
  666. * @param buf
  667. * @return
  668. */
  669. uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
  670. Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
  671. Notify(PSTR("----------------\r\n"), 0x80);
  672. CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0UL, (uint8_t)size, 0);
  673. CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
  674. //SetCurLUN(lun);
  675. return Transaction(&cbw, size, buf);
  676. }
  677. ////////////////////////////////////////////////////////////////////////////////
  678. // USB code
  679. ////////////////////////////////////////////////////////////////////////////////
  680. /**
  681. * For driver use only.
  682. *
  683. * @param index
  684. * @return
  685. */
  686. uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
  687. if (index == 0)
  688. return 0;
  689. uint8_t ret = 0;
  690. 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, nullptr, nullptr)) == 0x01))
  691. delay(6);
  692. if (ret) {
  693. ErrorMessage<uint8_t> (PSTR("ClearEpHalt"), ret);
  694. ErrorMessage<uint8_t> (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
  695. return ret;
  696. }
  697. epInfo[index].bmSndToggle = 0;
  698. epInfo[index].bmRcvToggle = 0;
  699. return 0;
  700. }
  701. /**
  702. * For driver use only.
  703. *
  704. */
  705. void BulkOnly::Reset() {
  706. while (pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, nullptr, nullptr) == 0x01) delay(6);
  707. }
  708. /**
  709. * For driver use only.
  710. *
  711. * @return 0 if successful
  712. */
  713. uint8_t BulkOnly::ResetRecovery() {
  714. Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
  715. Notify(PSTR("-----------------\r\n"), 0x80);
  716. delay(6);
  717. Reset();
  718. delay(6);
  719. ClearEpHalt(epDataInIndex);
  720. delay(6);
  721. bLastUsbError = ClearEpHalt(epDataOutIndex);
  722. delay(6);
  723. return bLastUsbError;
  724. }
  725. /**
  726. * For driver use only.
  727. *
  728. * Clear all EP data and clear all LUN status
  729. */
  730. void BulkOnly::ClearAllEP() {
  731. for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
  732. epInfo[i].epAddr = 0;
  733. epInfo[i].maxPktSize = (i) ? 0 : 8;
  734. epInfo[i].bmSndToggle = 0;
  735. epInfo[i].bmRcvToggle = 0;
  736. epInfo[i].bmNakPower = USB_NAK_DEFAULT;
  737. }
  738. for (uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
  739. LUNOk[i] = false;
  740. WriteOk[i] = false;
  741. CurrentCapacity[i] = 0UL;
  742. CurrentSectorSize[i] = 0;
  743. }
  744. bIface = 0;
  745. bNumEP = 1;
  746. bAddress = 0;
  747. qNextPollTime = 0;
  748. bPollEnable = false;
  749. bLastUsbError = 0;
  750. bMaxLUN = 0;
  751. bTheLUN = 0;
  752. }
  753. /**
  754. * For driver use only.
  755. *
  756. * @param pcsw
  757. * @param pcbw
  758. * @return
  759. */
  760. bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
  761. if (pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
  762. Notify(PSTR("CSW:Sig error\r\n"), 0x80);
  763. return false;
  764. }
  765. if (pcsw->dCSWTag != pcbw->dCBWTag) {
  766. Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
  767. return false;
  768. }
  769. return true;
  770. }
  771. /**
  772. * For driver use only.
  773. *
  774. * @param error
  775. * @param index
  776. * @return
  777. */
  778. uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
  779. uint8_t count = 3;
  780. bLastUsbError = error;
  781. //if (error)
  782. //ClearEpHalt(index);
  783. while (error && count) {
  784. if (error != hrSUCCESS) {
  785. ErrorMessage<uint8_t> (PSTR("USB Error"), error);
  786. ErrorMessage<uint8_t> (PSTR("Index"), index);
  787. }
  788. switch (error) {
  789. // case hrWRONGPID:
  790. case hrSUCCESS: return MASS_ERR_SUCCESS;
  791. case hrBUSY: return MASS_ERR_UNIT_BUSY; // SIE is busy, just hang out and try again.
  792. case hrTIMEOUT:
  793. case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED;
  794. case hrSTALL:
  795. if (index) {
  796. ClearEpHalt(index);
  797. return (index == epDataInIndex) ? MASS_ERR_STALL : MASS_ERR_WRITE_STALL;
  798. }
  799. return MASS_ERR_STALL;
  800. case hrNAK:
  801. return index ? MASS_ERR_UNIT_BUSY : MASS_ERR_UNIT_BUSY;
  802. case hrTOGERR:
  803. // Handle a super rare corner case, where toggles become de-synced.
  804. // I've only run into one device that has this firmware bug, and this is
  805. // the only clean way to get back into sync with the buggy device firmware.
  806. // --AJK
  807. if (bAddress && bConfNum) {
  808. error = pUsb->setConf(bAddress, 0, bConfNum);
  809. if (error) break;
  810. }
  811. return MASS_ERR_SUCCESS;
  812. default:
  813. ErrorMessage<uint8_t> (PSTR("\r\nUSB"), error);
  814. return MASS_ERR_GENERAL_USB_ERROR;
  815. }
  816. count--;
  817. } // while
  818. return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
  819. }
  820. #if MS_WANT_PARSER
  821. uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
  822. return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
  823. }
  824. #endif
  825. /**
  826. * For driver use only.
  827. *
  828. * @param pcbw
  829. * @param buf_size
  830. * @param buf
  831. * @param flags
  832. * @return
  833. */
  834. uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
  835. #if MS_WANT_PARSER
  836. , uint8_t flags
  837. #endif
  838. ) {
  839. #if MS_WANT_PARSER
  840. uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
  841. printf("Transfersize %i\r\n", bytes);
  842. delay(1000);
  843. bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
  844. #else
  845. uint16_t bytes = buf_size;
  846. #endif
  847. bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
  848. uint8_t ret = 0;
  849. uint8_t usberr;
  850. CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
  851. SetCurLUN(pcbw->bmCBWLUN);
  852. ErrorMessage<uint32_t> (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
  853. while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
  854. ret = HandleUsbError(usberr, epDataOutIndex);
  855. //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
  856. if (ret)
  857. ErrorMessage<uint8_t> (PSTR("============================ CBW"), ret);
  858. else {
  859. if (bytes) {
  860. if (!write) {
  861. #if MS_WANT_PARSER
  862. if (callback) {
  863. uint8_t rbuf[bytes];
  864. while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
  865. if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
  866. }
  867. else
  868. #endif
  869. {
  870. while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
  871. }
  872. ret = HandleUsbError(usberr, epDataInIndex);
  873. }
  874. else {
  875. while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
  876. ret = HandleUsbError(usberr, epDataOutIndex);
  877. }
  878. if (ret) ErrorMessage<uint8_t> (PSTR("============================ DAT"), ret);
  879. }
  880. }
  881. bytes = sizeof (CommandStatusWrapper);
  882. int tries = 2;
  883. while (tries--) {
  884. while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
  885. if (!usberr) break;
  886. ClearEpHalt(epDataInIndex);
  887. if (tries) ResetRecovery();
  888. }
  889. if (!ret) {
  890. Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
  891. Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
  892. }
  893. else {
  894. // Throw away csw, IT IS NOT OF ANY USE.
  895. ResetRecovery();
  896. return ret;
  897. }
  898. ret = HandleUsbError(usberr, epDataInIndex);
  899. if (ret) ErrorMessage<uint8_t> (PSTR("============================ CSW"), ret);
  900. if (usberr == hrSUCCESS) {
  901. if (IsValidCSW(&csw, pcbw)) {
  902. //ErrorMessage<uint32_t> (PSTR("CSW.dCBWTag"), csw.dCSWTag);
  903. //ErrorMessage<uint8_t> (PSTR("bCSWStatus"), csw.bCSWStatus);
  904. //ErrorMessage<uint32_t> (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
  905. Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
  906. return csw.bCSWStatus;
  907. }
  908. else {
  909. // NOTE! Sometimes this is caused by the reported residue being wrong.
  910. // Get a different device. It isn't compliant, and should have never passed Q&A.
  911. // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
  912. // Other devices that exhibit this behavior exist in the wild too.
  913. // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk
  914. Notify(PSTR("Invalid CSW\r\n"), 0x80);
  915. ResetRecovery();
  916. //return MASS_ERR_SUCCESS;
  917. return MASS_ERR_INVALID_CSW;
  918. }
  919. }
  920. return ret;
  921. }
  922. /**
  923. * For driver use only.
  924. *
  925. * @param lun Logical Unit Number
  926. * @return
  927. */
  928. uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
  929. if (lun > bMaxLUN) return MASS_ERR_INVALID_LUN;
  930. bTheLUN = lun;
  931. return MASS_ERR_SUCCESS;
  932. }
  933. /**
  934. * For driver use only.
  935. *
  936. * @param status
  937. * @return
  938. */
  939. uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
  940. uint8_t ret = 0;
  941. switch (status) {
  942. case 0: return MASS_ERR_SUCCESS;
  943. case 2:
  944. ErrorMessage<uint8_t> (PSTR("Phase Error"), status);
  945. ErrorMessage<uint8_t> (PSTR("LUN"), bTheLUN);
  946. ResetRecovery();
  947. return MASS_ERR_GENERAL_SCSI_ERROR;
  948. case 1:
  949. ErrorMessage<uint8_t> (PSTR("SCSI Error"), status);
  950. ErrorMessage<uint8_t> (PSTR("LUN"), bTheLUN);
  951. RequestSenseResponce rsp;
  952. ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
  953. if (ret) return MASS_ERR_GENERAL_SCSI_ERROR;
  954. ErrorMessage<uint8_t> (PSTR("Response Code"), rsp.bResponseCode);
  955. if (rsp.bResponseCode & 0x80) {
  956. Notify(PSTR("Information field: "), 0x80);
  957. for (int i = 0; i < 4; i++) {
  958. D_PrintHex<uint8_t> (rsp.CmdSpecificInformation[i], 0x80);
  959. Notify(PSTR(" "), 0x80);
  960. }
  961. Notify(PSTR("\r\n"), 0x80);
  962. }
  963. ErrorMessage<uint8_t> (PSTR("Sense Key"), rsp.bmSenseKey);
  964. ErrorMessage<uint8_t> (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
  965. ErrorMessage<uint8_t> (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
  966. // warning, this is not testing ASQ, only SK and ASC.
  967. switch (rsp.bmSenseKey) {
  968. case SCSI_S_UNIT_ATTENTION:
  969. switch (rsp.bAdditionalSenseCode) {
  970. case SCSI_ASC_MEDIA_CHANGED:
  971. return MASS_ERR_MEDIA_CHANGED;
  972. default:
  973. return MASS_ERR_UNIT_NOT_READY;
  974. }
  975. case SCSI_S_NOT_READY:
  976. switch (rsp.bAdditionalSenseCode) {
  977. case SCSI_ASC_MEDIUM_NOT_PRESENT:
  978. return MASS_ERR_NO_MEDIA;
  979. default:
  980. return MASS_ERR_UNIT_NOT_READY;
  981. }
  982. case SCSI_S_ILLEGAL_REQUEST:
  983. switch (rsp.bAdditionalSenseCode) {
  984. case SCSI_ASC_LBA_OUT_OF_RANGE:
  985. return MASS_ERR_BAD_LBA;
  986. default:
  987. return MASS_ERR_CMD_NOT_SUPPORTED;
  988. }
  989. default:
  990. return MASS_ERR_GENERAL_SCSI_ERROR;
  991. }
  992. // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
  993. // case 0x05/0x14: we stalled out
  994. // case 0x15/0x16: we naked out.
  995. default:
  996. ErrorMessage<uint8_t> (PSTR("Gen SCSI Err"), status);
  997. ErrorMessage<uint8_t> (PSTR("LUN"), bTheLUN);
  998. return status;
  999. } // switch
  1000. }
  1001. ////////////////////////////////////////////////////////////////////////////////
  1002. // Debugging code
  1003. ////////////////////////////////////////////////////////////////////////////////
  1004. /**
  1005. *
  1006. * @param ep_ptr
  1007. */
  1008. void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
  1009. Notify(PSTR("Endpoint descriptor:"), 0x80);
  1010. Notify(PSTR("\r\nLength:\t\t"), 0x80);
  1011. D_PrintHex<uint8_t> (ep_ptr->bLength, 0x80);
  1012. Notify(PSTR("\r\nType:\t\t"), 0x80);
  1013. D_PrintHex<uint8_t> (ep_ptr->bDescriptorType, 0x80);
  1014. Notify(PSTR("\r\nAddress:\t"), 0x80);
  1015. D_PrintHex<uint8_t> (ep_ptr->bEndpointAddress, 0x80);
  1016. Notify(PSTR("\r\nAttributes:\t"), 0x80);
  1017. D_PrintHex<uint8_t> (ep_ptr->bmAttributes, 0x80);
  1018. Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
  1019. D_PrintHex<uint16_t> (ep_ptr->wMaxPacketSize, 0x80);
  1020. Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
  1021. D_PrintHex<uint8_t> (ep_ptr->bInterval, 0x80);
  1022. Notify(PSTR("\r\n"), 0x80);
  1023. }
  1024. ////////////////////////////////////////////////////////////////////////////////
  1025. // misc/to kill/to-do
  1026. ////////////////////////////////////////////////////////////////////////////////
  1027. /* We won't be needing this... */
  1028. 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))) {
  1029. #if MS_WANT_PARSER
  1030. if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
  1031. Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
  1032. Notify(PSTR("---------\r\n"), 0x80);
  1033. CommandBlockWrapper cbw = CommandBlockWrapper();
  1034. cbw.dCBWSignature = MASS_CBW_SIGNATURE;
  1035. cbw.dCBWTag = ++dCBWTag;
  1036. cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
  1037. cbw.bmCBWFlags = MASS_CMD_DIR_IN,
  1038. cbw.bmCBWLUN = lun;
  1039. cbw.bmCBWCBLength = 10;
  1040. cbw.CBWCB[0] = SCSI_CMD_READ_10;
  1041. cbw.CBWCB[8] = blocks;
  1042. cbw.CBWCB[2] = ((addr >> 24) & 0xff);
  1043. cbw.CBWCB[3] = ((addr >> 16) & 0xff);
  1044. cbw.CBWCB[4] = ((addr >> 8) & 0xff);
  1045. cbw.CBWCB[5] = (addr & 0xff);
  1046. return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
  1047. #else
  1048. return MASS_ERR_NOT_IMPLEMENTED;
  1049. #endif
  1050. }
  1051. #endif // USB_FLASH_DRIVE_SUPPORT