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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

masstorage.cpp 41KB

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