usbd_msc_scsi.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. /**
  2. ******************************************************************************
  3. * @file usbd_msc_scsi.c
  4. * @author MCD Application Team
  5. * @version V2.4.1
  6. * @date 19-June-2015
  7. * @brief This file provides all the USBD SCSI layer functions.
  8. ******************************************************************************
  9. * @attention
  10. *
  11. * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
  12. *
  13. * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  14. * You may not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at:
  16. *
  17. * http://www.st.com/software_license_agreement_liberty_v2
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS,
  21. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. *
  25. ******************************************************************************
  26. */
  27. /* Includes ------------------------------------------------------------------*/
  28. #include "usbd_composite.h"
  29. #include "usbd_msc_bot.h"
  30. #include "usbd_msc_scsi.h"
  31. #include "usbd_msc.h"
  32. #include "usbd_msc_data.h"
  33. /** @addtogroup STM32_USB_DEVICE_LIBRARY
  34. * @{
  35. */
  36. /** @defgroup MSC_SCSI
  37. * @brief Mass storage SCSI layer module
  38. * @{
  39. */
  40. /** @defgroup MSC_SCSI_Private_TypesDefinitions
  41. * @{
  42. */
  43. /**
  44. * @}
  45. */
  46. /** @defgroup MSC_SCSI_Private_Defines
  47. * @{
  48. */
  49. /**
  50. * @}
  51. */
  52. /** @defgroup MSC_SCSI_Private_Macros
  53. * @{
  54. */
  55. /**
  56. * @}
  57. */
  58. /** @defgroup MSC_SCSI_Private_Variables
  59. * @{
  60. */
  61. /**
  62. * @}
  63. */
  64. /** @defgroup MSC_SCSI_Private_FunctionPrototypes
  65. * @{
  66. */
  67. static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  68. static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  69. static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  70. static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  71. static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  72. static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  73. static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  74. static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  75. static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
  76. static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
  77. static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
  78. static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev,
  79. uint8_t lun ,
  80. uint32_t blk_offset ,
  81. uint16_t blk_nbr);
  82. static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev,
  83. uint8_t lun);
  84. static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev,
  85. uint8_t lun);
  86. /**
  87. * @}
  88. */
  89. /** @defgroup MSC_SCSI_Private_Functions
  90. * @{
  91. */
  92. /**
  93. * @brief SCSI_ProcessCmd
  94. * Process SCSI commands
  95. * @param pdev: device instance
  96. * @param lun: Logical unit number
  97. * @param params: Command parameters
  98. * @retval status
  99. */
  100. int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
  101. uint8_t lun,
  102. uint8_t *params)
  103. {
  104. switch (params[0])
  105. {
  106. case SCSI_TEST_UNIT_READY:
  107. return SCSI_TestUnitReady(pdev, lun, params);
  108. case SCSI_REQUEST_SENSE:
  109. return SCSI_RequestSense (pdev, lun, params);
  110. case SCSI_INQUIRY:
  111. return SCSI_Inquiry(pdev, lun, params);
  112. case SCSI_START_STOP_UNIT:
  113. return SCSI_StartStopUnit(pdev, lun, params);
  114. case SCSI_ALLOW_MEDIUM_REMOVAL:
  115. return SCSI_StartStopUnit(pdev, lun, params);
  116. case SCSI_MODE_SENSE6:
  117. return SCSI_ModeSense6 (pdev, lun, params);
  118. case SCSI_MODE_SENSE10:
  119. return SCSI_ModeSense10 (pdev, lun, params);
  120. case SCSI_READ_FORMAT_CAPACITIES:
  121. return SCSI_ReadFormatCapacity(pdev, lun, params);
  122. case SCSI_READ_CAPACITY10:
  123. return SCSI_ReadCapacity10(pdev, lun, params);
  124. case SCSI_READ10:
  125. return SCSI_Read10(pdev, lun, params);
  126. case SCSI_WRITE10:
  127. return SCSI_Write10(pdev, lun, params);
  128. case SCSI_VERIFY10:
  129. return SCSI_Verify10(pdev, lun, params);
  130. default:
  131. SCSI_SenseCode(pdev,
  132. lun,
  133. ILLEGAL_REQUEST,
  134. INVALID_CDB);
  135. return -1;
  136. }
  137. }
  138. /**
  139. * @brief SCSI_TestUnitReady
  140. * Process SCSI Test Unit Ready Command
  141. * @param lun: Logical unit number
  142. * @param params: Command parameters
  143. * @retval status
  144. */
  145. static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
  146. {
  147. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  148. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  149. /* case 9 : Hi > D0 */
  150. if (hmsc->cbw.dDataLength != 0)
  151. {
  152. SCSI_SenseCode(pdev,
  153. hmsc->cbw.bLUN,
  154. ILLEGAL_REQUEST,
  155. INVALID_CDB);
  156. return -1;
  157. }
  158. if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
  159. {
  160. SCSI_SenseCode(pdev,
  161. lun,
  162. NOT_READY,
  163. MEDIUM_NOT_PRESENT);
  164. hmsc->bot_state = USBD_BOT_NO_DATA;
  165. return -1;
  166. }
  167. hmsc->bot_data_length = 0;
  168. return 0;
  169. }
  170. /**
  171. * @brief SCSI_Inquiry
  172. * Process Inquiry command
  173. * @param lun: Logical unit number
  174. * @param params: Command parameters
  175. * @retval status
  176. */
  177. static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
  178. {
  179. uint8_t* pPage;
  180. uint16_t len;
  181. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  182. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  183. if (params[1] & 0x01)/*Evpd is set*/
  184. {
  185. pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
  186. len = LENGTH_INQUIRY_PAGE00;
  187. if (params[4] <= len)
  188. {
  189. len = params[4];
  190. }
  191. memcpy(hmsc->bot_data, pPage, len);
  192. }
  193. else
  194. {
  195. len = ((USBD_StorageTypeDef *)pdev->pUserData)->Inquiry(lun, hmsc->bot_data, params[4]);
  196. if (params[4] <= len)
  197. {
  198. len = params[4];
  199. }
  200. }
  201. hmsc->bot_data_length = len;
  202. return 0;
  203. }
  204. /**
  205. * @brief SCSI_ReadCapacity10
  206. * Process Read Capacity 10 command
  207. * @param lun: Logical unit number
  208. * @param params: Command parameters
  209. * @retval status
  210. */
  211. static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
  212. {
  213. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  214. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  215. if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0)
  216. {
  217. SCSI_SenseCode(pdev,
  218. lun,
  219. NOT_READY,
  220. MEDIUM_NOT_PRESENT);
  221. return -1;
  222. }
  223. else
  224. {
  225. hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 24);
  226. hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 16);
  227. hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 8);
  228. hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1);
  229. hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >> 24);
  230. hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >> 16);
  231. hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >> 8);
  232. hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size);
  233. hmsc->bot_data_length = 8;
  234. return 0;
  235. }
  236. }
  237. /**
  238. * @brief SCSI_ReadFormatCapacity
  239. * Process Read Format Capacity command
  240. * @param lun: Logical unit number
  241. * @param params: Command parameters
  242. * @retval status
  243. */
  244. static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
  245. {
  246. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  247. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  248. uint16_t blk_size;
  249. uint32_t blk_nbr;
  250. uint16_t i;
  251. for(i=0 ; i < 12 ; i++)
  252. {
  253. hmsc->bot_data[i] = 0;
  254. }
  255. if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blk_nbr, &blk_size) != 0)
  256. {
  257. SCSI_SenseCode(pdev,
  258. lun,
  259. NOT_READY,
  260. MEDIUM_NOT_PRESENT);
  261. return -1;
  262. }
  263. else
  264. {
  265. hmsc->bot_data[3] = 0x08;
  266. hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1) >> 24);
  267. hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1) >> 16);
  268. hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1) >> 8);
  269. hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1);
  270. hmsc->bot_data[8] = 0x02;
  271. hmsc->bot_data[9] = (uint8_t)(blk_size >> 16);
  272. hmsc->bot_data[10] = (uint8_t)(blk_size >> 8);
  273. hmsc->bot_data[11] = (uint8_t)(blk_size);
  274. hmsc->bot_data_length = 12;
  275. return 0;
  276. }
  277. }
  278. /**
  279. * @brief SCSI_ModeSense6
  280. * Process Mode Sense6 command
  281. * @param lun: Logical unit number
  282. * @param params: Command parameters
  283. * @retval status
  284. */
  285. static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
  286. {
  287. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  288. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  289. uint16_t len = 8 ;
  290. hmsc->bot_data_length = len;
  291. while (len)
  292. {
  293. len--;
  294. hmsc->bot_data[len] = MSC_Mode_Sense6_data[len];
  295. }
  296. return 0;
  297. }
  298. /**
  299. * @brief SCSI_ModeSense10
  300. * Process Mode Sense10 command
  301. * @param lun: Logical unit number
  302. * @param params: Command parameters
  303. * @retval status
  304. */
  305. static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
  306. {
  307. uint16_t len = 8;
  308. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  309. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  310. hmsc->bot_data_length = len;
  311. while (len)
  312. {
  313. len--;
  314. hmsc->bot_data[len] = MSC_Mode_Sense10_data[len];
  315. }
  316. return 0;
  317. }
  318. /**
  319. * @brief SCSI_RequestSense
  320. * Process Request Sense command
  321. * @param lun: Logical unit number
  322. * @param params: Command parameters
  323. * @retval status
  324. */
  325. static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
  326. {
  327. uint8_t i;
  328. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  329. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  330. for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++)
  331. {
  332. hmsc->bot_data[i] = 0;
  333. }
  334. hmsc->bot_data[0] = 0x70;
  335. hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6;
  336. if((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) {
  337. hmsc->bot_data[2] = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey;
  338. hmsc->bot_data[12] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ;
  339. hmsc->bot_data[13] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC;
  340. hmsc->scsi_sense_head++;
  341. if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH)
  342. {
  343. hmsc->scsi_sense_head = 0;
  344. }
  345. }
  346. hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN;
  347. if (params[4] <= REQUEST_SENSE_DATA_LEN)
  348. {
  349. hmsc->bot_data_length = params[4];
  350. }
  351. return 0;
  352. }
  353. /**
  354. * @brief SCSI_SenseCode
  355. * Load the last error code in the error list
  356. * @param lun: Logical unit number
  357. * @param sKey: Sense Key
  358. * @param ASC: Additional Sense Key
  359. * @retval none
  360. */
  361. void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
  362. {
  363. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  364. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  365. hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey;
  366. hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8;
  367. hmsc->scsi_sense_tail++;
  368. if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH)
  369. {
  370. hmsc->scsi_sense_tail = 0;
  371. }
  372. }
  373. /**
  374. * @brief SCSI_StartStopUnit
  375. * Process Start Stop Unit command
  376. * @param lun: Logical unit number
  377. * @param params: Command parameters
  378. * @retval status
  379. */
  380. static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
  381. {
  382. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  383. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  384. hmsc->bot_data_length = 0;
  385. return 0;
  386. }
  387. /**
  388. * @brief SCSI_Read10
  389. * Process Read10 command
  390. * @param lun: Logical unit number
  391. * @param params: Command parameters
  392. * @retval status
  393. */
  394. static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
  395. {
  396. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  397. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  398. if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
  399. {
  400. /* case 10 : Ho <> Di */
  401. if ((hmsc->cbw.bmFlags & 0x80) != 0x80)
  402. {
  403. SCSI_SenseCode(pdev,
  404. hmsc->cbw.bLUN,
  405. ILLEGAL_REQUEST,
  406. INVALID_CDB);
  407. return -1;
  408. }
  409. if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
  410. {
  411. SCSI_SenseCode(pdev,
  412. lun,
  413. NOT_READY,
  414. MEDIUM_NOT_PRESENT);
  415. return -1;
  416. }
  417. hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | \
  418. ((uint32_t)params[3] << 16) | \
  419. ((uint32_t)params[4] << 8) | \
  420. (uint32_t)params[5];
  421. hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) | \
  422. (uint32_t)params[8];
  423. if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)
  424. {
  425. return -1; /* error */
  426. }
  427. hmsc->bot_state = USBD_BOT_DATA_IN;
  428. hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
  429. hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
  430. /* cases 4,5 : Hi <> Dn */
  431. if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
  432. {
  433. SCSI_SenseCode(pdev,
  434. hmsc->cbw.bLUN,
  435. ILLEGAL_REQUEST,
  436. INVALID_CDB);
  437. return -1;
  438. }
  439. }
  440. hmsc->bot_data_length = S2S_MSC_MEDIA_PACKET;
  441. return SCSI_ProcessRead(pdev, lun);
  442. }
  443. /**
  444. * @brief SCSI_Write10
  445. * Process Write10 command
  446. * @param lun: Logical unit number
  447. * @param params: Command parameters
  448. * @retval status
  449. */
  450. static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
  451. {
  452. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  453. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  454. if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
  455. {
  456. /* case 8 : Hi <> Do */
  457. if ((hmsc->cbw.bmFlags & 0x80) == 0x80)
  458. {
  459. SCSI_SenseCode(pdev,
  460. hmsc->cbw.bLUN,
  461. ILLEGAL_REQUEST,
  462. INVALID_CDB);
  463. return -1;
  464. }
  465. /* Check whether Media is ready */
  466. if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
  467. {
  468. SCSI_SenseCode(pdev,
  469. lun,
  470. NOT_READY,
  471. MEDIUM_NOT_PRESENT);
  472. return -1;
  473. }
  474. /* Check If media is write-protected */
  475. if(((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 )
  476. {
  477. SCSI_SenseCode(pdev,
  478. lun,
  479. NOT_READY,
  480. WRITE_PROTECTED);
  481. return -1;
  482. }
  483. hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | \
  484. ((uint32_t)params[3] << 16) | \
  485. ((uint32_t)params[4] << 8) | \
  486. (uint32_t)params[5];
  487. hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) | \
  488. (uint32_t)params[8];
  489. /* check if LBA address is in the right range */
  490. if(SCSI_CheckAddressRange(pdev,
  491. lun,
  492. hmsc->scsi_blk_addr,
  493. hmsc->scsi_blk_len) < 0)
  494. {
  495. return -1; /* error */
  496. }
  497. hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
  498. hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
  499. /* cases 3,11,13 : Hn,Ho <> D0 */
  500. if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
  501. {
  502. SCSI_SenseCode(pdev,
  503. hmsc->cbw.bLUN,
  504. ILLEGAL_REQUEST,
  505. INVALID_CDB);
  506. return -1;
  507. }
  508. /* Prepare EP to receive first data packet */
  509. hmsc->bot_state = USBD_BOT_DATA_OUT;
  510. USBD_LL_PrepareReceive (pdev,
  511. MSC_EPOUT_ADDR,
  512. hmsc->bot_data,
  513. MIN (hmsc->scsi_blk_len, S2S_MSC_MEDIA_PACKET));
  514. }
  515. else /* Write Process ongoing */
  516. {
  517. return SCSI_ProcessWrite(pdev, lun);
  518. }
  519. return 0;
  520. }
  521. /**
  522. * @brief SCSI_Verify10
  523. * Process Verify10 command
  524. * @param lun: Logical unit number
  525. * @param params: Command parameters
  526. * @retval status
  527. */
  528. static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
  529. {
  530. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  531. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  532. if ((params[1]& 0x02) == 0x02)
  533. {
  534. SCSI_SenseCode (pdev,
  535. lun,
  536. ILLEGAL_REQUEST,
  537. INVALID_FIELED_IN_COMMAND);
  538. return -1; /* Error, Verify Mode Not supported*/
  539. }
  540. if(SCSI_CheckAddressRange(pdev,
  541. lun,
  542. hmsc->scsi_blk_addr,
  543. hmsc->scsi_blk_len) < 0)
  544. {
  545. return -1; /* error */
  546. }
  547. hmsc->bot_data_length = 0;
  548. return 0;
  549. }
  550. /**
  551. * @brief SCSI_CheckAddressRange
  552. * Check address range
  553. * @param lun: Logical unit number
  554. * @param blk_offset: first block address
  555. * @param blk_nbr: number of block to be processed
  556. * @retval status
  557. */
  558. static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr)
  559. {
  560. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  561. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  562. // michael@codesrc.com: Re-check block limits in cause we have different values
  563. // for different LUN's.
  564. uint32_t blkNbr;
  565. uint16_t blkSize;
  566. if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blkNbr, &blkSize) != 0)
  567. {
  568. SCSI_SenseCode(pdev,
  569. lun,
  570. NOT_READY,
  571. MEDIUM_NOT_PRESENT);
  572. return -1;
  573. }
  574. // global variables. wooo
  575. hmsc->scsi_blk_size = blkSize;
  576. hmsc->scsi_blk_nbr = blkNbr;
  577. if ((blk_offset + blk_nbr) > blkNbr )
  578. {
  579. SCSI_SenseCode(pdev,
  580. lun,
  581. ILLEGAL_REQUEST,
  582. ADDRESS_OUT_OF_RANGE);
  583. return -1;
  584. }
  585. return 0;
  586. }
  587. /**
  588. * @brief SCSI_ProcessRead
  589. * Handle Read Process
  590. * @param lun: Logical unit number
  591. * @retval status
  592. */
  593. static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
  594. {
  595. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  596. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  597. uint32_t len;
  598. len = MIN(hmsc->scsi_blk_len , S2S_MSC_MEDIA_PACKET);
  599. if( ((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun ,
  600. hmsc->bot_data,
  601. hmsc->scsi_blk_addr / hmsc->scsi_blk_size,
  602. len / hmsc->scsi_blk_size) < 0)
  603. {
  604. SCSI_SenseCode(pdev,
  605. lun,
  606. HARDWARE_ERROR,
  607. UNRECOVERED_READ_ERROR);
  608. return -1;
  609. }
  610. USBD_LL_Transmit (pdev,
  611. MSC_EPIN_ADDR,
  612. hmsc->bot_data,
  613. len);
  614. hmsc->scsi_blk_addr += len;
  615. hmsc->scsi_blk_len -= len;
  616. /* case 6 : Hi = Di */
  617. hmsc->csw.dDataResidue -= len;
  618. if (hmsc->scsi_blk_len == 0)
  619. {
  620. hmsc->bot_state = USBD_BOT_LAST_DATA_IN;
  621. }
  622. return 0;
  623. }
  624. /**
  625. * @brief SCSI_ProcessWrite
  626. * Handle Write Process
  627. * @param lun: Logical unit number
  628. * @retval status
  629. */
  630. static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun)
  631. {
  632. uint32_t len;
  633. USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
  634. USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
  635. len = MIN(hmsc->scsi_blk_len , S2S_MSC_MEDIA_PACKET);
  636. if(((USBD_StorageTypeDef *)pdev->pUserData)->Write(lun ,
  637. hmsc->bot_data,
  638. hmsc->scsi_blk_addr / hmsc->scsi_blk_size,
  639. len / hmsc->scsi_blk_size) < 0)
  640. {
  641. SCSI_SenseCode(pdev,
  642. lun,
  643. HARDWARE_ERROR,
  644. WRITE_FAULT);
  645. return -1;
  646. }
  647. hmsc->scsi_blk_addr += len;
  648. hmsc->scsi_blk_len -= len;
  649. /* case 12 : Ho = Do */
  650. hmsc->csw.dDataResidue -= len;
  651. if (hmsc->scsi_blk_len == 0)
  652. {
  653. MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
  654. }
  655. else
  656. {
  657. /* Prepare EP to Receive next packet */
  658. USBD_LL_PrepareReceive (pdev,
  659. MSC_EPOUT_ADDR,
  660. hmsc->bot_data,
  661. MIN (hmsc->scsi_blk_len, S2S_MSC_MEDIA_PACKET));
  662. }
  663. return 0;
  664. }
  665. /**
  666. * @}
  667. */
  668. /**
  669. * @}
  670. */
  671. /**
  672. * @}
  673. */
  674. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/