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.

mscuser.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /*----------------------------------------------------------------------------
  2. * U S B - K e r n e l
  3. *----------------------------------------------------------------------------
  4. * Name: MSCUSER.C
  5. * Purpose: Mass Storage Class Custom User Module
  6. * Version: V1.10
  7. *----------------------------------------------------------------------------
  8. * This software is supplied "AS IS" without any warranties, express,
  9. * implied or statutory, including but not limited to the implied
  10. * warranties of fitness for purpose, satisfactory quality and
  11. * noninfringement. Keil extends you a royalty-free right to reproduce
  12. * and distribute executable files created using this software for use
  13. * on NXP Semiconductors LPC family microcontroller devices only. Nothing
  14. * else gives you the right to use this software.
  15. *
  16. * Copyright (c) 2005-2009 Keil Software.
  17. *---------------------------------------------------------------------------*/
  18. extern "C" {
  19. #include "LPC17xx.h"
  20. #include "lpc_types.h"
  21. }
  22. #include "usb.h"
  23. #include "msc.h"
  24. #include "usbcfg.h"
  25. #include "usbhw.h"
  26. #include "usbcore.h"
  27. #include "mscuser.h"
  28. #include "../chanfs/diskio.h"
  29. #include <debug_frmwrk.h>
  30. DWORD MSC_BlockCount = 0;
  31. uint32_t MemOK; /* Memory OK */
  32. DWORD lba; /* start block */
  33. DWORD transfer_count; /* blocks to transfer */
  34. DWORD length;
  35. uint32_t block_offset; /* current block offset*/
  36. uint8_t BulkStage; /* Bulk Stage */
  37. uint8_t BulkBuf[MSC_MAX_PACKET]; /* Bulk In/Out Buffer */
  38. uint8_t block_cache[MSC_BLOCK_SIZE];
  39. uint8_t BulkLen; /* Bulk In/Out Length */
  40. MSC_CBW CBW; /* Command Block Wrapper */
  41. MSC_CSW CSW; /* Command Status Wrapper */
  42. uint8_t media_lock = 0;
  43. uint32_t MSC_SD_Lock() {
  44. media_lock = CBW.CB[4]; //0x1 - lock, 0x0 - unlock
  45. // logical_unit = CBW.CB[1] & 0xE0;
  46. CSW.bStatus = CSW_CMD_PASSED;
  47. MSC_SetCSW();
  48. return 0;
  49. }
  50. uint32_t MSC_SD_Release(uint8_t pdrv) {
  51. MSC_BlockCount = 0;
  52. return 0;
  53. }
  54. uint32_t MSC_SD_Init(uint8_t pdrv) {
  55. DSTATUS ret = disk_initialize(pdrv);
  56. if(ret) return ret;
  57. if(disk_ioctl (pdrv, GET_SECTOR_COUNT, (void *)(&MSC_BlockCount))) return 1;
  58. return 0;
  59. }
  60. #define STARTSTOP_STOPMOTOR 0x0
  61. #define STARTSTOP_STARTMOTOR 0x1
  62. #define STARTSTOP_EJECT 0x2
  63. #define STARTSTOP_LOAD 0x3
  64. void MSC_StartStopUnit() {
  65. switch (CBW.CB[4] & 0x03) {
  66. case STARTSTOP_EJECT:
  67. MSC_SD_Release(0);
  68. break;
  69. case STARTSTOP_LOAD:
  70. if(MSC_BlockCount == 0) {
  71. if(MSC_SD_Init(0) != 0) {
  72. CSW.bStatus = CSW_CMD_FAILED;
  73. MSC_SetCSW();
  74. return;
  75. }
  76. }
  77. break;
  78. default:
  79. _DBG("MSC_StartStopUnit unknown startstopunit sub command\n");
  80. }
  81. CSW.bStatus = CSW_CMD_PASSED;
  82. MSC_SetCSW();
  83. }
  84. /*
  85. * MSC Mass Storage Reset Request Callback
  86. * Called automatically on Mass Storage Reset Request
  87. * Parameters: None (global SetupPacket and EP0Buf)
  88. * Return Value: TRUE - Success, FALSE - Error
  89. */
  90. uint32_t MSC_Reset (void) {
  91. BulkStage = MSC_BS_CBW;
  92. return (TRUE);
  93. }
  94. /*
  95. * MSC Get Max LUN Request Callback
  96. * Called automatically on Get Max LUN Request
  97. * Parameters: None (global SetupPacket and EP0Buf)
  98. * Return Value: TRUE - Success, FALSE - Error
  99. */
  100. uint32_t MSC_GetMaxLUN (void) {
  101. EP0Buf[0] = 0; /* No LUN associated with this device */
  102. return (TRUE);
  103. }
  104. /*
  105. * MSC Memory Read Callback
  106. * Called automatically on Memory Read Event
  107. * Parameters: None (global variables)
  108. * Return Value: None
  109. */
  110. void MSC_MemoryRead (void) {
  111. uint32_t n = (length > MSC_MAX_PACKET) ? MSC_MAX_PACKET : length;
  112. if (lba > MSC_BlockCount) {
  113. n = (MSC_BlockCount - lba) * MSC_BLOCK_SIZE + block_offset;
  114. BulkStage = MSC_BS_ERROR;
  115. }
  116. if(block_offset == 0) {
  117. disk_read (0, block_cache, lba, 1);
  118. }
  119. USB_WriteEP(MSC_EP_IN, &block_cache[block_offset], n);
  120. block_offset += n;
  121. length -= n;
  122. CSW.dDataResidue -= n;
  123. if(block_offset >= MSC_BLOCK_SIZE) {
  124. block_offset = 0;
  125. ++lba;
  126. }
  127. if (length == 0) {
  128. BulkStage = MSC_BS_DATA_IN_LAST;
  129. }
  130. if (BulkStage != MSC_BS_DATA_IN) {
  131. CSW.bStatus = CSW_CMD_PASSED;
  132. }
  133. }
  134. /*
  135. * MSC Memory Write Callback
  136. * Called automatically on Memory Write Event
  137. * Parameters: None (global variables)
  138. * Return Value: None
  139. */
  140. void MSC_MemoryWrite (void) {
  141. for (uint32_t n = 0; n < BulkLen; n++) {
  142. block_cache[block_offset + n] = BulkBuf[n];
  143. }
  144. if(block_offset + BulkLen >= MSC_BLOCK_SIZE) {
  145. if(!(disk_status(0) & STA_PROTECT)){
  146. disk_write(0, block_cache, lba, 1);
  147. }
  148. }
  149. block_offset += BulkLen;
  150. length -= BulkLen;
  151. CSW.dDataResidue -= BulkLen;
  152. if(block_offset >= MSC_BLOCK_SIZE) {
  153. block_offset = 0;
  154. ++lba;
  155. }
  156. if ((length == 0) || (BulkStage == MSC_BS_CSW)) {
  157. CSW.bStatus = CSW_CMD_PASSED;
  158. MSC_SetCSW();
  159. }
  160. }
  161. /*
  162. * MSC Memory Verify Callback
  163. * Called automatically on Memory Verify Event
  164. * Parameters: None (global variables)
  165. * Return Value: None
  166. */
  167. void MSC_MemoryVerify (void) {
  168. if(!block_offset) {
  169. disk_read(0, block_cache, lba, 1);
  170. }
  171. for (uint32_t n = 0; n < BulkLen; n++) {
  172. if (block_cache[block_offset + n] != BulkBuf[n]) {
  173. MemOK = FALSE;
  174. break;
  175. }
  176. }
  177. block_offset += BulkLen;
  178. length -= BulkLen;
  179. CSW.dDataResidue -= BulkLen;
  180. if ((length == 0) || (BulkStage == MSC_BS_CSW)) {
  181. CSW.bStatus = (MemOK) ? CSW_CMD_PASSED : CSW_CMD_FAILED;
  182. MSC_SetCSW();
  183. }
  184. }
  185. /*
  186. * MSC SCSI Read/Write Setup Callback
  187. * Parameters: None (global variables)
  188. * Return Value: TRUE - Success, FALSE - Error
  189. */
  190. uint32_t MSC_RWSetup (void) {
  191. uint32_t n;
  192. /* Logical Block Address of First Block */
  193. lba = (CBW.CB[2] << 24) |
  194. (CBW.CB[3] << 16) |
  195. (CBW.CB[4] << 8) |
  196. (CBW.CB[5] << 0);
  197. /* Number of Blocks to transfer */
  198. transfer_count = (CBW.CB[7] << 8) |
  199. (CBW.CB[8] << 0);
  200. block_offset = 0;
  201. length = transfer_count * MSC_BLOCK_SIZE;
  202. if (CBW.dDataLength != (transfer_count * MSC_BLOCK_SIZE)) {
  203. USB_SetStallEP(MSC_EP_IN);
  204. USB_SetStallEP(MSC_EP_OUT);
  205. CSW.bStatus = CSW_PHASE_ERROR;
  206. MSC_SetCSW();
  207. return (FALSE);
  208. }
  209. return (TRUE);
  210. }
  211. /*
  212. * Check Data IN Format
  213. * Parameters: None (global variables)
  214. * Return Value: TRUE - Success, FALSE - Error
  215. */
  216. uint32_t DataInFormat (void) {
  217. if (CBW.dDataLength == 0) {
  218. CSW.bStatus = CSW_PHASE_ERROR;
  219. MSC_SetCSW();
  220. return (FALSE);
  221. }
  222. if ((CBW.bmFlags & 0x80) == 0) {
  223. USB_SetStallEP(MSC_EP_OUT);
  224. CSW.bStatus = CSW_PHASE_ERROR;
  225. MSC_SetCSW();
  226. return (FALSE);
  227. }
  228. return (TRUE);
  229. }
  230. /*
  231. * Perform Data IN Transfer
  232. * Parameters: None (global variables)
  233. * Return Value: TRUE - Success, FALSE - Error
  234. */
  235. void DataInTransfer (void) {
  236. if (BulkLen > CBW.dDataLength) {
  237. BulkLen = CBW.dDataLength;
  238. }
  239. USB_WriteEP(MSC_EP_IN, BulkBuf, BulkLen);
  240. BulkStage = MSC_BS_DATA_IN_LAST;
  241. CSW.dDataResidue -= BulkLen;
  242. CSW.bStatus = CSW_CMD_PASSED;
  243. }
  244. /*
  245. * MSC SCSI Test Unit Ready Callback
  246. * Parameters: None (global variables)
  247. * Return Value: None
  248. */
  249. void MSC_TestUnitReady (void) {
  250. if (CBW.dDataLength != 0) {
  251. if ((CBW.bmFlags & 0x80) != 0) {
  252. USB_SetStallEP(MSC_EP_IN);
  253. } else {
  254. USB_SetStallEP(MSC_EP_OUT);
  255. }
  256. }
  257. if(MSC_BlockCount > 0) {
  258. CSW.bStatus = CSW_CMD_PASSED;
  259. } else {
  260. CSW.bStatus = CSW_CMD_FAILED;
  261. }
  262. MSC_SetCSW();
  263. }
  264. /*
  265. * MSC SCSI Request Sense Callback
  266. * Parameters: None (global variables)
  267. * Return Value: None
  268. */
  269. void MSC_RequestSense (void) {
  270. if (!DataInFormat()) return;
  271. BulkBuf[ 0] = 0x70; /* Response Code */
  272. BulkBuf[ 1] = 0x00;
  273. BulkBuf[ 2] = static_cast<uint8_t>(Sense_KEY::ILLEGAL_REQUEST);
  274. BulkBuf[ 3] = 0x00;
  275. BulkBuf[ 4] = 0x00;
  276. BulkBuf[ 5] = 0x00;
  277. BulkBuf[ 6] = 0x00;
  278. BulkBuf[ 7] = 0x0A; /* Additional Length */
  279. BulkBuf[ 8] = 0x00;
  280. BulkBuf[ 9] = 0x00;
  281. BulkBuf[10] = 0x00;
  282. BulkBuf[11] = 0x00;
  283. BulkBuf[12] = static_cast<uint8_t>(Sense_ASC::CANNOT_READ_MEDIUM);
  284. BulkBuf[13] = static_cast<uint8_t>(Sense_ASCQ::UNKNOWN_FORMAT);
  285. BulkBuf[14] = 0x00;
  286. BulkBuf[15] = 0x00;
  287. BulkBuf[16] = 0x00;
  288. BulkBuf[17] = 0x00;
  289. if (MSC_BlockCount == 0) {
  290. BulkBuf[ 2] = static_cast<uint8_t>(Sense_KEY::NOT_READY);
  291. BulkBuf[12] = static_cast<uint8_t>(Sense_ASC::MEDIUM_NOT_PRESENT);
  292. BulkBuf[13] = static_cast<uint8_t>(Sense_ASCQ::LOADABLE);
  293. }
  294. BulkLen = 18;
  295. DataInTransfer();
  296. }
  297. /*
  298. * MSC SCSI Inquiry Callback
  299. * Parameters: None (global variables)
  300. * Return Value: None
  301. */
  302. void MSC_Inquiry (void) {
  303. if (!DataInFormat()) return;
  304. BulkBuf[ 0] = 0x00; /* Direct Access Device */
  305. BulkBuf[ 1] = 0x80; /* RMB = 1: Removable Medium */
  306. BulkBuf[ 2] = 0x00; /* Version: No conformance claim to standard */
  307. BulkBuf[ 3] = 0x01;
  308. BulkBuf[ 4] = 36-4; /* Additional Length */
  309. BulkBuf[ 5] = 0x80; /* SCCS = 1: Storage Controller Component */
  310. BulkBuf[ 6] = 0x00;
  311. BulkBuf[ 7] = 0x00;
  312. BulkBuf[ 8] = 'M'; /* Vendor Identification */
  313. BulkBuf[ 9] = 'a';
  314. BulkBuf[10] = 'r';
  315. BulkBuf[11] = 'l';
  316. BulkBuf[12] = 'i';
  317. BulkBuf[13] = 'n';
  318. BulkBuf[14] = ' ';
  319. BulkBuf[15] = ' ';
  320. BulkBuf[16] = 'R'; /* Product Identification */
  321. BulkBuf[17] = 'e';
  322. BulkBuf[18] = '-';
  323. BulkBuf[19] = 'A';
  324. BulkBuf[20] = 'R';
  325. BulkBuf[21] = 'M';
  326. BulkBuf[22] = ' ';
  327. BulkBuf[23] = 'S';
  328. BulkBuf[24] = 'D';
  329. BulkBuf[25] = 'C';
  330. BulkBuf[26] = 'a';
  331. BulkBuf[27] = 'r';
  332. BulkBuf[28] = 'd';
  333. BulkBuf[29] = ' ';
  334. BulkBuf[30] = '0';
  335. BulkBuf[31] = '1';
  336. BulkBuf[32] = '1'; /* Product Revision Level */
  337. BulkBuf[33] = '.';
  338. BulkBuf[34] = '0';
  339. BulkBuf[35] = ' ';
  340. if(MSC_BlockCount == 0) {
  341. BulkBuf[0] = 0x20; // Direct Access Device usually available but not currently
  342. }
  343. BulkLen = 36;
  344. DataInTransfer();
  345. }
  346. /*
  347. * MSC SCSI Mode Sense (6-Byte) Callback
  348. * Parameters: None (global variables)
  349. * Return Value: None
  350. */
  351. void MSC_ModeSense6 (void) {
  352. if (!DataInFormat()) return;
  353. BulkBuf[ 0] = 0x03;
  354. BulkBuf[ 1] = 0x00;
  355. BulkBuf[ 2] = 0x00;
  356. BulkBuf[ 3] = 0x00;
  357. BulkLen = 4;
  358. DataInTransfer();
  359. }
  360. /*
  361. * MSC SCSI Mode Sense (10-Byte) Callback
  362. * Parameters: None (global variables)
  363. * Return Value: None
  364. */
  365. void MSC_ModeSense10 (void) {
  366. if (!DataInFormat()) return;
  367. BulkBuf[ 0] = 0x00;
  368. BulkBuf[ 1] = 0x06;
  369. BulkBuf[ 2] = 0x00;
  370. BulkBuf[ 3] = 0x00;
  371. BulkBuf[ 4] = 0x00;
  372. BulkBuf[ 5] = 0x00;
  373. BulkBuf[ 6] = 0x00;
  374. BulkBuf[ 7] = 0x00;
  375. BulkLen = 8;
  376. DataInTransfer();
  377. }
  378. /*
  379. * MSC SCSI Read Capacity Callback
  380. * Parameters: None (global variables)
  381. * Return Value: None
  382. */
  383. void MSC_ReadCapacity (void) {
  384. if (!DataInFormat()) return;
  385. /* Last Logical Block */
  386. BulkBuf[ 0] = ((MSC_BlockCount - 1) >> 24) & 0xFF;
  387. BulkBuf[ 1] = ((MSC_BlockCount - 1) >> 16) & 0xFF;
  388. BulkBuf[ 2] = ((MSC_BlockCount - 1) >> 8) & 0xFF;
  389. BulkBuf[ 3] = ((MSC_BlockCount - 1) >> 0) & 0xFF;
  390. /* Block Length */
  391. BulkBuf[ 4] = (MSC_BLOCK_SIZE >> 24) & 0xFF;
  392. BulkBuf[ 5] = (MSC_BLOCK_SIZE >> 16) & 0xFF;
  393. BulkBuf[ 6] = (MSC_BLOCK_SIZE >> 8) & 0xFF;
  394. BulkBuf[ 7] = (MSC_BLOCK_SIZE >> 0) & 0xFF;
  395. BulkLen = 8;
  396. DataInTransfer();
  397. }
  398. /*
  399. * MSC SCSI Read Format Capacity Callback
  400. * Parameters: None (global variables)
  401. * Return Value: None
  402. */
  403. void MSC_ReadFormatCapacity (void) {
  404. if (!DataInFormat()) return;
  405. BulkBuf[ 0] = 0x00;
  406. BulkBuf[ 1] = 0x00;
  407. BulkBuf[ 2] = 0x00;
  408. BulkBuf[ 3] = 0x08; /* Capacity List Length */
  409. /* Block Count */
  410. BulkBuf[ 4] = (MSC_BlockCount >> 24) & 0xFF;
  411. BulkBuf[ 5] = (MSC_BlockCount >> 16) & 0xFF;
  412. BulkBuf[ 6] = (MSC_BlockCount >> 8) & 0xFF;
  413. BulkBuf[ 7] = (MSC_BlockCount >> 0) & 0xFF;
  414. /* Block Length */
  415. BulkBuf[ 8] = 0x02; /* Descriptor Code: Formatted Media */
  416. BulkBuf[ 9] = (MSC_BLOCK_SIZE >> 16) & 0xFF;
  417. BulkBuf[10] = (MSC_BLOCK_SIZE >> 8) & 0xFF;
  418. BulkBuf[11] = (MSC_BLOCK_SIZE >> 0) & 0xFF;
  419. BulkLen = 12;
  420. DataInTransfer();
  421. }
  422. /*
  423. * MSC Get Command Block Wrapper Callback
  424. * Parameters: None (global variables)
  425. * Return Value: None
  426. */
  427. void MSC_GetCBW (void) {
  428. uint32_t n;
  429. for (n = 0; n < BulkLen; n++) {
  430. *((uint8_t *)&CBW + n) = BulkBuf[n];
  431. }
  432. if ((BulkLen == sizeof(CBW)) && (CBW.dSignature == MSC_CBW_Signature)) {
  433. /* Valid CBW */
  434. CSW.dTag = CBW.dTag;
  435. CSW.dDataResidue = CBW.dDataLength;
  436. if ((CBW.bLUN != 0) || (CBW.bCBLength < 1) || CBW.bCBLength > 16) {
  437. fail: CSW.bStatus = CSW_CMD_FAILED;
  438. MSC_SetCSW();
  439. _DBG("Failed SCSI OP code ");
  440. _DBH(CBW.CB[0]);
  441. _DBG("\n");
  442. } else {
  443. switch (CBW.CB[0]) {
  444. case SCSI_TEST_UNIT_READY:
  445. MSC_TestUnitReady();
  446. break;
  447. case SCSI_REQUEST_SENSE:
  448. MSC_RequestSense();
  449. break;
  450. case SCSI_FORMAT_UNIT:
  451. goto fail;
  452. case SCSI_INQUIRY:
  453. MSC_Inquiry();
  454. break;
  455. case SCSI_START_STOP_UNIT:
  456. MSC_StartStopUnit();
  457. break;
  458. case SCSI_MEDIA_REMOVAL:
  459. MSC_SD_Lock();
  460. break;
  461. case SCSI_MODE_SELECT6:
  462. goto fail;
  463. case SCSI_MODE_SENSE6:
  464. MSC_ModeSense6();
  465. break;
  466. case SCSI_MODE_SELECT10:
  467. goto fail;
  468. case SCSI_MODE_SENSE10:
  469. MSC_ModeSense10();
  470. break;
  471. case SCSI_READ_FORMAT_CAPACITIES:
  472. MSC_ReadFormatCapacity();
  473. break;
  474. case SCSI_READ_CAPACITY:
  475. MSC_ReadCapacity();
  476. break;
  477. case SCSI_READ10:
  478. if (MSC_RWSetup()) {
  479. if ((CBW.bmFlags & 0x80) != 0) {
  480. BulkStage = MSC_BS_DATA_IN;
  481. MSC_MemoryRead();
  482. } else {
  483. USB_SetStallEP(MSC_EP_OUT);
  484. CSW.bStatus = CSW_PHASE_ERROR;
  485. MSC_SetCSW();
  486. }
  487. }
  488. break;
  489. case SCSI_WRITE10:
  490. if (MSC_RWSetup()) {
  491. if ((CBW.bmFlags & 0x80) == 0) {
  492. BulkStage = MSC_BS_DATA_OUT;
  493. } else {
  494. USB_SetStallEP(MSC_EP_IN);
  495. CSW.bStatus = CSW_PHASE_ERROR;
  496. MSC_SetCSW();
  497. }
  498. }
  499. break;
  500. case SCSI_VERIFY10:
  501. if (MSC_RWSetup()) {
  502. if ((CBW.bmFlags & 0x80) == 0) {
  503. BulkStage = MSC_BS_DATA_OUT;
  504. MemOK = TRUE;
  505. } else {
  506. USB_SetStallEP(MSC_EP_IN);
  507. CSW.bStatus = CSW_PHASE_ERROR;
  508. MSC_SetCSW();
  509. }
  510. }
  511. break;
  512. default:
  513. goto fail;
  514. }
  515. }
  516. } else {
  517. /* Invalid CBW */
  518. USB_SetStallEP(MSC_EP_IN);
  519. USB_SetStallEP(MSC_EP_OUT);
  520. BulkStage = MSC_BS_ERROR;
  521. }
  522. }
  523. /*
  524. * MSC Set Command Status Wrapper Callback
  525. * Parameters: None (global variables)
  526. * Return Value: None
  527. */
  528. void MSC_SetCSW (void) {
  529. CSW.dSignature = MSC_CSW_Signature;
  530. USB_WriteEP(MSC_EP_IN, (uint8_t *)&CSW, sizeof(CSW));
  531. BulkStage = MSC_BS_CSW;
  532. }
  533. /*
  534. * MSC Bulk In Callback
  535. * Parameters: None (global variables)
  536. * Return Value: None
  537. */
  538. void MSC_BulkIn (void) {
  539. switch (BulkStage) {
  540. case MSC_BS_DATA_IN:
  541. switch (CBW.CB[0]) {
  542. case SCSI_READ10:
  543. MSC_MemoryRead();
  544. break;
  545. }
  546. break;
  547. case MSC_BS_DATA_IN_LAST:
  548. MSC_SetCSW();
  549. break;
  550. case MSC_BS_DATA_IN_LAST_STALL:
  551. USB_SetStallEP(MSC_EP_IN);
  552. MSC_SetCSW();
  553. break;
  554. case MSC_BS_CSW:
  555. BulkStage = MSC_BS_CBW;
  556. break;
  557. }
  558. }
  559. /*
  560. * MSC Bulk Out Callback
  561. * Parameters: None (global variables)
  562. * Return Value: None
  563. */
  564. void MSC_BulkOut (void) {
  565. BulkLen = (uint8_t)USB_ReadEP(MSC_EP_OUT, BulkBuf);
  566. switch (BulkStage) {
  567. case MSC_BS_CBW:
  568. MSC_GetCBW();
  569. break;
  570. case MSC_BS_DATA_OUT:
  571. switch (CBW.CB[0]) {
  572. case SCSI_WRITE10:
  573. MSC_MemoryWrite();
  574. break;
  575. case SCSI_VERIFY10:
  576. MSC_MemoryVerify();
  577. break;
  578. }
  579. break;
  580. default:
  581. USB_SetStallEP(MSC_EP_OUT);
  582. CSW.bStatus = CSW_PHASE_ERROR;
  583. MSC_SetCSW();
  584. break;
  585. }
  586. }