Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

před 1 rokem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. /*
  2. * This file is part of the libopencm3 project.
  3. *
  4. * Copyright (C) 2013 Weston Schmidt <weston_schmidt@alumni.purdue.edu>
  5. * Copyright (C) 2013 Pavol Rusnak <stick@gk2.sk>
  6. *
  7. * This library is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with this library. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <stdint.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <libopencm3/cm3/common.h>
  24. #include <libopencm3/usb/usbd.h>
  25. #include <libopencm3/usb/msc.h>
  26. #include "usb_private.h"
  27. /* Definitions of Mass Storage Class from:
  28. *
  29. * (A) "Universal Serial Bus Mass Storage Class Bulk-Only Transport
  30. * Revision 1.0"
  31. *
  32. * (B) "Universal Serial Bus Mass Storage Class Specification Overview
  33. * Revision 1.0"
  34. */
  35. /* Command Block Wrapper */
  36. #define CBW_SIGNATURE 0x43425355
  37. #define CBW_STATUS_SUCCESS 0
  38. #define CBW_STATUS_FAILED 1
  39. #define CBW_STATUS_PHASE_ERROR 2
  40. /* Command Status Wrapper */
  41. #define CSW_SIGNATURE 0x53425355
  42. #define CSW_STATUS_SUCCESS 0
  43. #define CSW_STATUS_FAILED 1
  44. #define CSW_STATUS_PHASE_ERROR 2
  45. /* Implemented SCSI Commands */
  46. #define SCSI_TEST_UNIT_READY 0x00
  47. #define SCSI_REQUEST_SENSE 0x03
  48. #define SCSI_FORMAT_UNIT 0x04
  49. #define SCSI_READ_6 0x08
  50. #define SCSI_WRITE_6 0x0A
  51. #define SCSI_INQUIRY 0x12
  52. #define SCSI_MODE_SENSE_6 0x1A
  53. #define SCSI_SEND_DIAGNOSTIC 0x1D
  54. #define SCSI_READ_CAPACITY 0x25
  55. #define SCSI_READ_10 0x28
  56. /* Required SCSI Commands */
  57. /* Optional SCSI Commands */
  58. #define SCSI_REPORT_LUNS 0xA0
  59. #define SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
  60. #define SCSI_MODE_SELECT_6 0x15
  61. #define SCSI_MODE_SELECT_10 0x55
  62. #define SCSI_MODE_SENSE_10 0x5A
  63. #define SCSI_READ_12 0xA8
  64. #define SCSI_READ_FORMAT_CAPACITIES 0x23
  65. #define SCSI_READ_TOC_PMA_ATIP 0x43
  66. #define SCSI_START_STOP_UNIT 0x1B
  67. #define SCSI_SYNCHRONIZE_CACHE 0x35
  68. #define SCSI_VERIFY 0x2F
  69. #define SCSI_WRITE_10 0x2A
  70. #define SCSI_WRITE_12 0xAA
  71. /* The sense codes */
  72. enum sbc_sense_key {
  73. SBC_SENSE_KEY_NO_SENSE = 0x00,
  74. SBC_SENSE_KEY_RECOVERED_ERROR = 0x01,
  75. SBC_SENSE_KEY_NOT_READY = 0x02,
  76. SBC_SENSE_KEY_MEDIUM_ERROR = 0x03,
  77. SBC_SENSE_KEY_HARDWARE_ERROR = 0x04,
  78. SBC_SENSE_KEY_ILLEGAL_REQUEST = 0x05,
  79. SBC_SENSE_KEY_UNIT_ATTENTION = 0x06,
  80. SBC_SENSE_KEY_DATA_PROTECT = 0x07,
  81. SBC_SENSE_KEY_BLANK_CHECK = 0x08,
  82. SBC_SENSE_KEY_VENDOR_SPECIFIC = 0x09,
  83. SBC_SENSE_KEY_COPY_ABORTED = 0x0A,
  84. SBC_SENSE_KEY_ABORTED_COMMAND = 0x0B,
  85. SBC_SENSE_KEY_VOLUME_OVERFLOW = 0x0D,
  86. SBC_SENSE_KEY_MISCOMPARE = 0x0E
  87. };
  88. enum sbc_asc {
  89. SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION = 0x00,
  90. SBC_ASC_PERIPHERAL_DEVICE_WRITE_FAULT = 0x03,
  91. SBC_ASC_LOGICAL_UNIT_NOT_READY = 0x04,
  92. SBC_ASC_UNRECOVERED_READ_ERROR = 0x11,
  93. SBC_ASC_INVALID_COMMAND_OPERATION_CODE = 0x20,
  94. SBC_ASC_LBA_OUT_OF_RANGE = 0x21,
  95. SBC_ASC_INVALID_FIELD_IN_CDB = 0x24,
  96. SBC_ASC_WRITE_PROTECTED = 0x27,
  97. SBC_ASC_NOT_READY_TO_READY_CHANGE = 0x28,
  98. SBC_ASC_FORMAT_ERROR = 0x31,
  99. SBC_ASC_MEDIUM_NOT_PRESENT = 0x3A
  100. };
  101. enum sbc_ascq {
  102. SBC_ASCQ_NA = 0x00,
  103. SBC_ASCQ_FORMAT_COMMAND_FAILED = 0x01,
  104. SBC_ASCQ_INITIALIZING_COMMAND_REQUIRED = 0x02,
  105. SBC_ASCQ_OPERATION_IN_PROGRESS = 0x07
  106. };
  107. enum trans_event {
  108. EVENT_CBW_VALID,
  109. EVENT_NEED_STATUS
  110. };
  111. struct usb_msc_cbw {
  112. uint32_t dCBWSignature;
  113. uint32_t dCBWTag;
  114. uint32_t dCBWDataTransferLength;
  115. uint8_t bmCBWFlags;
  116. uint8_t bCBWLUN;
  117. uint8_t bCBWCBLength;
  118. uint8_t CBWCB[16];
  119. } __attribute__((packed));
  120. struct usb_msc_csw {
  121. uint32_t dCSWSignature;
  122. uint32_t dCSWTag;
  123. uint32_t dCSWDataResidue;
  124. uint8_t bCSWStatus;
  125. } __attribute__((packed));
  126. struct sbc_sense_info {
  127. uint8_t key;
  128. uint8_t asc;
  129. uint8_t ascq;
  130. };
  131. struct usb_msc_trans {
  132. uint8_t cbw_cnt; /* Read until 31 bytes */
  133. union {
  134. struct usb_msc_cbw cbw;
  135. uint8_t buf[1];
  136. } cbw;
  137. uint32_t bytes_to_read;
  138. uint32_t bytes_to_write;
  139. uint32_t byte_count; /* Either read until equal to
  140. bytes_to_read or write until equal
  141. to bytes_to_write. */
  142. uint32_t lba_start;
  143. uint32_t block_count;
  144. uint32_t current_block;
  145. uint8_t msd_buf[512];
  146. bool csw_valid;
  147. uint8_t csw_sent; /* Write until 13 bytes */
  148. union {
  149. struct usb_msc_csw csw;
  150. uint8_t buf[1];
  151. } csw;
  152. };
  153. struct _usbd_mass_storage {
  154. usbd_device *usbd_dev;
  155. uint8_t ep_in;
  156. uint8_t ep_in_size;
  157. uint8_t ep_out;
  158. uint8_t ep_out_size;
  159. const char *vendor_id;
  160. const char *product_id;
  161. const char *product_revision_level;
  162. uint32_t block_count;
  163. int (*read_block)(uint32_t lba, uint8_t *copy_to);
  164. int (*write_block)(uint32_t lba, const uint8_t *copy_from);
  165. void (*lock)(void);
  166. void (*unlock)(void);
  167. struct usb_msc_trans trans;
  168. struct sbc_sense_info sense;
  169. };
  170. static usbd_mass_storage _mass_storage;
  171. /*-- SCSI Base Responses -----------------------------------------------------*/
  172. static const uint8_t _spc3_inquiry_response[36] = {
  173. 0x00, /* Byte 0: Peripheral Qualifier = 0, Peripheral Device Type = 0 */
  174. 0x80, /* Byte 1: RMB = 1, Reserved = 0 */
  175. 0x04, /* Byte 2: Version = 0 */
  176. 0x02, /* Byte 3: Obsolete = 0, NormACA = 0, HiSup = 0, Response Data Format = 2 */
  177. 0x20, /* Byte 4: Additional Length (n-4) = 31 + 4 */
  178. 0x00, /* Byte 5: SCCS = 0, ACC = 0, TPGS = 0, 3PC = 0, Reserved = 0, Protect = 0 */
  179. 0x00, /* Byte 6: BQue = 0, EncServ = 0, VS = 0, MultiP = 0, MChngr = 0, Obsolete = 0, Addr16 = 0 */
  180. 0x00, /* Byte 7: Obsolete = 0, Wbus16 = 0, Sync = 0, Linked = 0, CmdQue = 0, VS = 0 */
  181. /* Byte 8 - Byte 15: Vendor Identification */
  182. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  183. /* Byte 16 - Byte 31: Product Identification */
  184. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  185. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  186. /* Byte 32 - Byte 35: Product Revision Level */
  187. 0x20, 0x20, 0x20, 0x20
  188. };
  189. static const uint8_t _spc3_request_sense[18] = {
  190. 0x70, /* Byte 0: VALID = 0, Response Code = 112 */
  191. 0x00, /* Byte 1: Obsolete = 0 */
  192. 0x00, /* Byte 2: Filemark = 0, EOM = 0, ILI = 0, Reserved = 0, Sense Key = 0 */
  193. /* Byte 3 - Byte 6: Information = 0 */
  194. 0, 0, 0, 0,
  195. 0x0a, /* Byte 7: Additional Sense Length = 10 */
  196. /* Byte 8 - Byte 11: Command Specific Info = 0 */
  197. 0, 0, 0, 0,
  198. 0x00, /* Byte 12: Additional Sense Code (ASC) = 0 */
  199. 0x00, /* Byte 13: Additional Sense Code Qualifier (ASCQ) = 0 */
  200. 0x00, /* Byte 14: Field Replaceable Unit Code (FRUC) = 0 */
  201. 0x00, /* Byte 15: SKSV = 0, SenseKeySpecific[0] = 0 */
  202. 0x00, /* Byte 16: SenseKeySpecific[0] = 0 */
  203. 0x00 /* Byte 17: SenseKeySpecific[0] = 0 */
  204. };
  205. /*-- SCSI Layer --------------------------------------------------------------*/
  206. static void set_sbc_status(usbd_mass_storage *ms,
  207. enum sbc_sense_key key,
  208. enum sbc_asc asc,
  209. enum sbc_ascq ascq)
  210. {
  211. ms->sense.key = (uint8_t) key;
  212. ms->sense.asc = (uint8_t) asc;
  213. ms->sense.ascq = (uint8_t) ascq;
  214. }
  215. static void set_sbc_status_good(usbd_mass_storage *ms)
  216. {
  217. set_sbc_status(ms,
  218. SBC_SENSE_KEY_NO_SENSE,
  219. SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION,
  220. SBC_ASCQ_NA);
  221. }
  222. static uint8_t *get_cbw_buf(struct usb_msc_trans *trans)
  223. {
  224. return &trans->cbw.cbw.CBWCB[0];
  225. }
  226. static void scsi_read_6(usbd_mass_storage *ms,
  227. struct usb_msc_trans *trans,
  228. enum trans_event event)
  229. {
  230. if (EVENT_CBW_VALID == event) {
  231. uint8_t *buf;
  232. buf = get_cbw_buf(trans);
  233. trans->lba_start = (buf[2] << 8) | buf[3];
  234. trans->block_count = buf[4];
  235. trans->current_block = 0;
  236. /* TODO: Check the lba & block_count for range. */
  237. /* both are in terms of 512 byte blocks, so shift by 9 */
  238. trans->bytes_to_write = trans->block_count << 9;
  239. set_sbc_status_good(ms);
  240. }
  241. }
  242. static void scsi_write_6(usbd_mass_storage *ms,
  243. struct usb_msc_trans *trans,
  244. enum trans_event event)
  245. {
  246. (void) ms;
  247. if (EVENT_CBW_VALID == event) {
  248. uint8_t *buf;
  249. buf = get_cbw_buf(trans);
  250. trans->lba_start = ((0x1f & buf[1]) << 16)
  251. | (buf[2] << 8) | buf[3];
  252. trans->block_count = buf[4];
  253. trans->current_block = 0;
  254. trans->bytes_to_read = trans->block_count << 9;
  255. }
  256. }
  257. static void scsi_write_10(usbd_mass_storage *ms,
  258. struct usb_msc_trans *trans,
  259. enum trans_event event)
  260. {
  261. (void) ms;
  262. if (EVENT_CBW_VALID == event) {
  263. uint8_t *buf;
  264. buf = get_cbw_buf(trans);
  265. trans->lba_start = (buf[2] << 24) | (buf[3] << 16) |
  266. (buf[4] << 8) | buf[5];
  267. trans->block_count = (buf[7] << 8) | buf[8];
  268. trans->current_block = 0;
  269. trans->bytes_to_read = trans->block_count << 9;
  270. }
  271. }
  272. static void scsi_read_10(usbd_mass_storage *ms,
  273. struct usb_msc_trans *trans,
  274. enum trans_event event)
  275. {
  276. if (EVENT_CBW_VALID == event) {
  277. uint8_t *buf;
  278. buf = get_cbw_buf(trans);
  279. trans->lba_start = (buf[2] << 24) | (buf[3] << 16)
  280. | (buf[4] << 8) | buf[5];
  281. trans->block_count = (buf[7] << 8) | buf[8];
  282. /* TODO: Check the lba & block_count for range. */
  283. /* both are in terms of 512 byte blocks, so shift by 9 */
  284. trans->bytes_to_write = trans->block_count << 9;
  285. set_sbc_status_good(ms);
  286. }
  287. }
  288. static void scsi_read_capacity(usbd_mass_storage *ms,
  289. struct usb_msc_trans *trans,
  290. enum trans_event event)
  291. {
  292. if (EVENT_CBW_VALID == event) {
  293. trans->msd_buf[0] = ms->block_count >> 24;
  294. trans->msd_buf[1] = 0xff & (ms->block_count >> 16);
  295. trans->msd_buf[2] = 0xff & (ms->block_count >> 8);
  296. trans->msd_buf[3] = 0xff & ms->block_count;
  297. /* Block size: 512 */
  298. trans->msd_buf[4] = 0;
  299. trans->msd_buf[5] = 0;
  300. trans->msd_buf[6] = 2;
  301. trans->msd_buf[7] = 0;
  302. trans->bytes_to_write = 8;
  303. set_sbc_status_good(ms);
  304. }
  305. }
  306. static void scsi_format_unit(usbd_mass_storage *ms,
  307. struct usb_msc_trans *trans,
  308. enum trans_event event)
  309. {
  310. if (EVENT_CBW_VALID == event) {
  311. uint32_t i;
  312. memset(trans->msd_buf, 0, 512);
  313. for (i = 0; i < ms->block_count; i++) {
  314. (*ms->write_block)(i, trans->msd_buf);
  315. }
  316. set_sbc_status_good(ms);
  317. }
  318. }
  319. static void scsi_request_sense(usbd_mass_storage *ms,
  320. struct usb_msc_trans *trans,
  321. enum trans_event event)
  322. {
  323. if (EVENT_CBW_VALID == event) {
  324. uint8_t *buf;
  325. buf = &trans->cbw.cbw.CBWCB[0];
  326. trans->bytes_to_write = buf[4]; /* allocation length */
  327. memcpy(trans->msd_buf, _spc3_request_sense,
  328. sizeof(_spc3_request_sense));
  329. trans->msd_buf[2] = ms->sense.key;
  330. trans->msd_buf[12] = ms->sense.asc;
  331. trans->msd_buf[13] = ms->sense.ascq;
  332. }
  333. }
  334. static void scsi_mode_sense_6(usbd_mass_storage *ms,
  335. struct usb_msc_trans *trans,
  336. enum trans_event event)
  337. {
  338. (void) ms;
  339. if (EVENT_CBW_VALID == event) {
  340. #if 0
  341. uint8_t *buf;
  342. uint8_t page_code;
  343. uint8_t allocation_length;
  344. buf = &trans->cbw.cbw.CBWCB[0];
  345. page_code = buf[2];
  346. allocation_length = buf[4];
  347. if (0x1C == page_code) { /* Informational Exceptions */
  348. #endif
  349. trans->bytes_to_write = 4;
  350. trans->msd_buf[0] = 3; /* Num bytes that follow */
  351. trans->msd_buf[1] = 0; /* Medium Type */
  352. trans->msd_buf[2] = 0; /* Device specific param */
  353. trans->csw.csw.dCSWDataResidue = 4;
  354. #if 0
  355. } else if (0x01 == page_code) { /* Error recovery */
  356. } else if (0x3F == page_code) { /* All */
  357. } else {
  358. /* Error */
  359. trans->csw.csw.bCSWStatus = CSW_STATUS_FAILED;
  360. set_sbc_status(ms,
  361. SBC_SENSE_KEY_ILLEGAL_REQUEST,
  362. SBC_ASC_INVALID_FIELD_IN_CDB,
  363. SBC_ASCQ_NA);
  364. }
  365. #endif
  366. }
  367. }
  368. static void scsi_inquiry(usbd_mass_storage *ms,
  369. struct usb_msc_trans *trans,
  370. enum trans_event event)
  371. {
  372. if (EVENT_CBW_VALID == event) {
  373. uint8_t evpd;
  374. uint8_t *buf;
  375. buf = get_cbw_buf(trans);
  376. evpd = 1 & buf[1];
  377. if (0 == evpd) {
  378. size_t len;
  379. trans->bytes_to_write = sizeof(_spc3_inquiry_response);
  380. memcpy(trans->msd_buf, _spc3_inquiry_response,
  381. sizeof(_spc3_inquiry_response));
  382. len = strlen(ms->vendor_id);
  383. len = MIN(len, 8);
  384. memcpy(&trans->msd_buf[8], ms->vendor_id, len);
  385. len = strlen(ms->product_id);
  386. len = MIN(len, 16);
  387. memcpy(&trans->msd_buf[16], ms->product_id, len);
  388. len = strlen(ms->product_revision_level);
  389. len = MIN(len, 4);
  390. memcpy(&trans->msd_buf[32], ms->product_revision_level,
  391. len);
  392. trans->csw.csw.dCSWDataResidue =
  393. sizeof(_spc3_inquiry_response);
  394. set_sbc_status_good(ms);
  395. } else {
  396. /* TODO: Add VPD 0x83 support */
  397. /* TODO: Add VPD 0x00 support */
  398. }
  399. }
  400. }
  401. static void scsi_command(usbd_mass_storage *ms,
  402. struct usb_msc_trans *trans,
  403. enum trans_event event)
  404. {
  405. if (EVENT_CBW_VALID == event) {
  406. /* Setup the default success */
  407. trans->csw_sent = 0;
  408. trans->csw.csw.dCSWSignature = CSW_SIGNATURE;
  409. trans->csw.csw.dCSWTag = trans->cbw.cbw.dCBWTag;
  410. trans->csw.csw.dCSWDataResidue = 0;
  411. trans->csw.csw.bCSWStatus = CSW_STATUS_SUCCESS;
  412. trans->bytes_to_write = 0;
  413. trans->bytes_to_read = 0;
  414. trans->byte_count = 0;
  415. }
  416. switch (trans->cbw.cbw.CBWCB[0]) {
  417. case SCSI_TEST_UNIT_READY:
  418. case SCSI_SEND_DIAGNOSTIC:
  419. /* Do nothing, just send the success. */
  420. set_sbc_status_good(ms);
  421. break;
  422. case SCSI_FORMAT_UNIT:
  423. scsi_format_unit(ms, trans, event);
  424. break;
  425. case SCSI_REQUEST_SENSE:
  426. scsi_request_sense(ms, trans, event);
  427. break;
  428. case SCSI_MODE_SENSE_6:
  429. scsi_mode_sense_6(ms, trans, event);
  430. break;
  431. case SCSI_READ_6:
  432. scsi_read_6(ms, trans, event);
  433. break;
  434. case SCSI_INQUIRY:
  435. scsi_inquiry(ms, trans, event);
  436. break;
  437. case SCSI_READ_CAPACITY:
  438. scsi_read_capacity(ms, trans, event);
  439. break;
  440. case SCSI_READ_10:
  441. scsi_read_10(ms, trans, event);
  442. break;
  443. case SCSI_WRITE_6:
  444. scsi_write_6(ms, trans, event);
  445. break;
  446. case SCSI_WRITE_10:
  447. scsi_write_10(ms, trans, event);
  448. break;
  449. default:
  450. set_sbc_status(ms, SBC_SENSE_KEY_ILLEGAL_REQUEST,
  451. SBC_ASC_INVALID_COMMAND_OPERATION_CODE,
  452. SBC_ASCQ_NA);
  453. trans->bytes_to_write = 0;
  454. trans->bytes_to_read = 0;
  455. trans->csw.csw.bCSWStatus = CSW_STATUS_FAILED;
  456. break;
  457. }
  458. }
  459. /*-- USB Mass Storage Layer --------------------------------------------------*/
  460. /** @brief Handle the USB 'OUT' requests. */
  461. static void msc_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
  462. {
  463. usbd_mass_storage *ms;
  464. struct usb_msc_trans *trans;
  465. int len, max_len, left;
  466. void *p;
  467. ms = &_mass_storage;
  468. trans = &ms->trans;
  469. /* RX only */
  470. left = sizeof(struct usb_msc_cbw) - trans->cbw_cnt;
  471. if (0 < left) {
  472. max_len = MIN(ms->ep_out_size, left);
  473. p = &trans->cbw.buf[0x1ff & trans->cbw_cnt];
  474. len = usbd_ep_read_packet(usbd_dev, ep, p, max_len);
  475. trans->cbw_cnt += len;
  476. if (sizeof(struct usb_msc_cbw) == trans->cbw_cnt) {
  477. scsi_command(ms, trans, EVENT_CBW_VALID);
  478. if (trans->byte_count < trans->bytes_to_read) {
  479. /* We must wait until there is something to
  480. * read again. */
  481. return;
  482. }
  483. }
  484. }
  485. if (trans->byte_count < trans->bytes_to_read) {
  486. if (0 < trans->block_count) {
  487. if ((0 == trans->byte_count) && (NULL != ms->lock)) {
  488. (*ms->lock)();
  489. }
  490. }
  491. left = trans->bytes_to_read - trans->byte_count;
  492. max_len = MIN(ms->ep_out_size, left);
  493. p = &trans->msd_buf[0x1ff & trans->byte_count];
  494. len = usbd_ep_read_packet(usbd_dev, ep, p, max_len);
  495. trans->byte_count += len;
  496. if (0 < trans->block_count) {
  497. if (0 == (0x1ff & trans->byte_count)) {
  498. uint32_t lba;
  499. lba = trans->lba_start + trans->current_block;
  500. if (0 != (*ms->write_block)(lba,
  501. trans->msd_buf)) {
  502. /* Error */
  503. }
  504. trans->current_block++;
  505. }
  506. }
  507. /* Fix "writes aren't acknowledged" bug on Linux (PR #409) */
  508. if (false == trans->csw_valid) {
  509. scsi_command(ms, trans, EVENT_NEED_STATUS);
  510. trans->csw_valid = true;
  511. }
  512. left = sizeof(struct usb_msc_csw) - trans->csw_sent;
  513. if (0 < left) {
  514. max_len = MIN(ms->ep_out_size, left);
  515. p = &trans->csw.buf[trans->csw_sent];
  516. len = usbd_ep_write_packet(usbd_dev, ms->ep_in, p,
  517. max_len);
  518. trans->csw_sent += len;
  519. }
  520. } else if (trans->byte_count < trans->bytes_to_write) {
  521. if (0 < trans->block_count) {
  522. if ((0 == trans->byte_count) && (NULL != ms->lock)) {
  523. (*ms->lock)();
  524. }
  525. if (0 == (0x1ff & trans->byte_count)) {
  526. uint32_t lba;
  527. lba = trans->lba_start + trans->current_block;
  528. if (0 != (*ms->read_block)(lba,
  529. trans->msd_buf)) {
  530. /* Error */
  531. }
  532. trans->current_block++;
  533. }
  534. }
  535. left = trans->bytes_to_write - trans->byte_count;
  536. max_len = MIN(ms->ep_out_size, left);
  537. p = &trans->msd_buf[0x1ff & trans->byte_count];
  538. len = usbd_ep_write_packet(usbd_dev, ms->ep_in, p, max_len);
  539. trans->byte_count += len;
  540. } else {
  541. if (0 < trans->block_count) {
  542. if (trans->current_block == trans->block_count) {
  543. uint32_t lba;
  544. lba = trans->lba_start + trans->current_block;
  545. if (0 != (*ms->write_block)(lba,
  546. trans->msd_buf)) {
  547. /* Error */
  548. }
  549. trans->current_block = 0;
  550. if (NULL != ms->unlock) {
  551. (*ms->unlock)();
  552. }
  553. }
  554. }
  555. if (false == trans->csw_valid) {
  556. scsi_command(ms, trans, EVENT_NEED_STATUS);
  557. trans->csw_valid = true;
  558. }
  559. left = sizeof(struct usb_msc_csw) - trans->csw_sent;
  560. if (0 < left) {
  561. max_len = MIN(ms->ep_out_size, left);
  562. p = &trans->csw.buf[trans->csw_sent];
  563. len = usbd_ep_write_packet(usbd_dev, ms->ep_in, p,
  564. max_len);
  565. trans->csw_sent += len;
  566. }
  567. }
  568. }
  569. /** @brief Handle the USB 'IN' requests. */
  570. static void msc_data_tx_cb(usbd_device *usbd_dev, uint8_t ep)
  571. {
  572. usbd_mass_storage *ms;
  573. struct usb_msc_trans *trans;
  574. int len, max_len, left;
  575. void *p;
  576. ms = &_mass_storage;
  577. trans = &ms->trans;
  578. if (trans->byte_count < trans->bytes_to_write) {
  579. if (0 < trans->block_count) {
  580. if (0 == (0x1ff & trans->byte_count)) {
  581. uint32_t lba;
  582. lba = trans->lba_start + trans->current_block;
  583. if (0 != (*ms->read_block)(lba,
  584. trans->msd_buf)) {
  585. /* Error */
  586. }
  587. trans->current_block++;
  588. }
  589. }
  590. left = trans->bytes_to_write - trans->byte_count;
  591. max_len = MIN(ms->ep_out_size, left);
  592. p = &trans->msd_buf[0x1ff & trans->byte_count];
  593. len = usbd_ep_write_packet(usbd_dev, ep, p, max_len);
  594. trans->byte_count += len;
  595. } else {
  596. if (0 < trans->block_count) {
  597. if (trans->current_block == trans->block_count) {
  598. trans->current_block = 0;
  599. if (NULL != ms->unlock) {
  600. (*ms->unlock)();
  601. }
  602. }
  603. }
  604. if (false == trans->csw_valid) {
  605. scsi_command(ms, trans, EVENT_NEED_STATUS);
  606. trans->csw_valid = true;
  607. }
  608. left = sizeof(struct usb_msc_csw) - trans->csw_sent;
  609. if (0 < left) {
  610. max_len = MIN(ms->ep_out_size, left);
  611. p = &trans->csw.buf[trans->csw_sent];
  612. len = usbd_ep_write_packet(usbd_dev, ep, p, max_len);
  613. trans->csw_sent += len;
  614. } else if (sizeof(struct usb_msc_csw) == trans->csw_sent) {
  615. /* End of transaction */
  616. trans->lba_start = 0xffffffff;
  617. trans->block_count = 0;
  618. trans->current_block = 0;
  619. trans->cbw_cnt = 0;
  620. trans->bytes_to_read = 0;
  621. trans->bytes_to_write = 0;
  622. trans->byte_count = 0;
  623. trans->csw_sent = 0;
  624. trans->csw_valid = false;
  625. }
  626. }
  627. }
  628. /** @brief Handle various control requests related to the msc storage
  629. * interface.
  630. */
  631. static enum usbd_request_return_codes
  632. msc_control_request(usbd_device *usbd_dev,
  633. struct usb_setup_data *req, uint8_t **buf, uint16_t *len,
  634. usbd_control_complete_callback *complete)
  635. {
  636. (void)complete;
  637. (void)usbd_dev;
  638. switch (req->bRequest) {
  639. case USB_MSC_REQ_BULK_ONLY_RESET:
  640. /* Do any special reset code here. */
  641. return USBD_REQ_HANDLED;
  642. case USB_MSC_REQ_GET_MAX_LUN:
  643. /* Return the number of LUNs. We use 0. */
  644. *buf[0] = 0;
  645. *len = 1;
  646. return USBD_REQ_HANDLED;
  647. }
  648. return USBD_REQ_NOTSUPP;
  649. }
  650. /** @brief Setup the endpoints to be bulk & register the callbacks. */
  651. static void msc_set_config(usbd_device *usbd_dev, uint16_t wValue)
  652. {
  653. usbd_mass_storage *ms = &_mass_storage;
  654. (void)wValue;
  655. usbd_ep_setup(usbd_dev, ms->ep_in, USB_ENDPOINT_ATTR_BULK,
  656. ms->ep_in_size, msc_data_tx_cb);
  657. usbd_ep_setup(usbd_dev, ms->ep_out, USB_ENDPOINT_ATTR_BULK,
  658. ms->ep_out_size, msc_data_rx_cb);
  659. usbd_register_control_callback(
  660. usbd_dev,
  661. USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
  662. USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
  663. msc_control_request);
  664. }
  665. /** @addtogroup usb_msc */
  666. /** @{ */
  667. /** @brief Initializes the USB Mass Storage subsystem.
  668. @note Currently you can only have this profile active.
  669. @param[in] usbd_dev The USB device to associate the Mass Storage with.
  670. @param[in] ep_in The USB 'IN' endpoint.
  671. @param[in] ep_in_size The maximum endpoint size. Valid values: 8, 16, 32 or 64
  672. @param[in] ep_out The USB 'OUT' endpoint.
  673. @param[in] ep_out_size The maximum endpoint size. Valid values: 8, 16, 32 or 64
  674. @param[in] vendor_id The SCSI vendor ID to return. Maximum used length is 8.
  675. @param[in] product_id The SCSI product ID to return. Maximum used length is 16.
  676. @param[in] product_revision_level The SCSI product revision level to return.
  677. Maximum used length is 4.
  678. @param[in] block_count The number of 512-byte blocks available.
  679. @param[in] read_block The function called when the host requests to read a LBA
  680. block. Must _NOT_ be NULL.
  681. @param[in] write_block The function called when the host requests to write a
  682. LBA block. Must _NOT_ be NULL.
  683. @return Pointer to the usbd_mass_storage struct.
  684. */
  685. usbd_mass_storage *usb_msc_init(usbd_device *usbd_dev,
  686. uint8_t ep_in, uint8_t ep_in_size,
  687. uint8_t ep_out, uint8_t ep_out_size,
  688. const char *vendor_id,
  689. const char *product_id,
  690. const char *product_revision_level,
  691. const uint32_t block_count,
  692. int (*read_block)(uint32_t lba,
  693. uint8_t *copy_to),
  694. int (*write_block)(uint32_t lba,
  695. const uint8_t *copy_from))
  696. {
  697. _mass_storage.usbd_dev = usbd_dev;
  698. _mass_storage.ep_in = ep_in;
  699. _mass_storage.ep_in_size = ep_in_size;
  700. _mass_storage.ep_out = ep_out;
  701. _mass_storage.ep_out_size = ep_out_size;
  702. _mass_storage.vendor_id = vendor_id;
  703. _mass_storage.product_id = product_id;
  704. _mass_storage.product_revision_level = product_revision_level;
  705. _mass_storage.block_count = block_count - 1;
  706. _mass_storage.read_block = read_block;
  707. _mass_storage.write_block = write_block;
  708. _mass_storage.lock = NULL;
  709. _mass_storage.unlock = NULL;
  710. _mass_storage.trans.lba_start = 0xffffffff;
  711. _mass_storage.trans.block_count = 0;
  712. _mass_storage.trans.current_block = 0;
  713. _mass_storage.trans.cbw_cnt = 0;
  714. _mass_storage.trans.bytes_to_read = 0;
  715. _mass_storage.trans.bytes_to_write = 0;
  716. _mass_storage.trans.byte_count = 0;
  717. _mass_storage.trans.csw_valid = false;
  718. _mass_storage.trans.csw_sent = 0;
  719. set_sbc_status_good(&_mass_storage);
  720. usbd_register_set_config_callback(usbd_dev, msc_set_config);
  721. return &_mass_storage;
  722. }
  723. /** @} */