app_usbd_msc.c 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "sdk_common.h"
  41. #if NRF_MODULE_ENABLED(APP_USBD_MSC)
  42. #include <string.h>
  43. #include <ctype.h>
  44. #include "app_usbd.h"
  45. #include "app_usbd_msc.h"
  46. #include "app_usbd_string_desc.h"
  47. /**
  48. * @defgroup app_usbd_msc_internal USBD MSC internals
  49. * @{
  50. * @ingroup app_usbd_msc
  51. * @internal
  52. */
  53. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_requestsense_t) == 6);
  54. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_requestsense_resp_t) == 18);
  55. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_inquiry_t) == 6);
  56. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_inquiry_resp_t) == 36);
  57. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_read6_t) == 6);
  58. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_write6_t) == 6);
  59. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_modesense6_t) == 6);
  60. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_modesense6_resp_t) == 4);
  61. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_readcapacity10_t) == 10);
  62. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_readcapacity10_resp_t) == 8);
  63. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_read10_t) == 10);
  64. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_write10_t) == 10);
  65. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_modesense10_t) == 10);
  66. STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_modesense10_resp_t) == 8);
  67. STATIC_ASSERT(sizeof(app_usbd_msc_cbw_t) == 31);
  68. STATIC_ASSERT(sizeof(app_usbd_msc_csw_t) == 13);
  69. #define NRF_LOG_MODULE_NAME usbd_msc
  70. #if APP_USBD_MSC_CONFIG_LOG_ENABLED
  71. #define NRF_LOG_LEVEL APP_USBD_MSC_CONFIG_LOG_LEVEL
  72. #define NRF_LOG_INFO_COLOR APP_USBD_MSC_CONFIG_INFO_COLOR
  73. #define NRF_LOG_DEBUG_COLOR APP_USBD_MSC_CONFIG_DEBUG_COLOR
  74. #else // APP_USBD_MSC_CONFIG_LOG_ENABLED
  75. #define NRF_LOG_LEVEL 0
  76. #endif // APP_USBD_MSC_CONFIG_LOG_ENABLED
  77. #include "nrf_log.h"
  78. NRF_LOG_MODULE_REGISTER();
  79. #define APP_USBD_MSC_IFACE_IDX 0 /**< Mass storage class interface index */
  80. #define APP_USBD_MSC_EPIN_IDX 0 /**< Mass storage class endpoint IN index */
  81. #define APP_USBD_MSC_EPOUT_IDX 1 /**< Mass storage class endpoint OUT index */
  82. /**
  83. * @brief Set request buffer busy flag.
  84. *
  85. * @param[in] val Bitmask to set.
  86. * @param[in] id Buffer id.
  87. * */
  88. #define APP_USBD_MSC_REQ_BUSY_SET(val, id) SET_BIT(val, id)
  89. /**
  90. * @brief Clear request buffer busy flag.
  91. *
  92. * @param[in] val Bitmask to set.
  93. * @param[in] id Buffer id.
  94. * */
  95. #define APP_USBD_MSC_REQ_BUSY_CLR(val, id) CLR_BIT(val, id)
  96. #define APP_USBD_MSC_REQ_BUSY_FULL_MASK (0x03) /**< Request busy mask */
  97. static void msc_blockdev_ev_handler(nrf_block_dev_t const * p_blk_dev,
  98. nrf_block_dev_event_t const * p_event);
  99. /** @brief Command Block Wrapper signature */
  100. static const uint8_t m_cbw_signature[] = APP_USBD_MSC_CBW_SIGNATURE;
  101. /** @brief Command Status Wrapper signature */
  102. static const uint8_t m_csw_signature[] = APP_USBD_MSC_CSW_SIGNATURE;
  103. STATIC_ASSERT(sizeof(m_cbw_signature) == sizeof(((app_usbd_msc_cbw_t*)0)->signature));
  104. STATIC_ASSERT(sizeof(m_csw_signature) == sizeof(((app_usbd_msc_csw_t*)0)->signature));
  105. /**
  106. * @brief Auxiliary function to access MSC instance data.
  107. *
  108. * @param[in] p_inst Class instance data.
  109. *
  110. * @return MSC instance data @ref app_usbd_msc_t
  111. */
  112. static inline app_usbd_msc_t const * msc_get(app_usbd_class_inst_t const * p_inst)
  113. {
  114. ASSERT(p_inst != NULL);
  115. return (app_usbd_msc_t const *)p_inst;
  116. }
  117. /**
  118. * @brief Auxiliary function to access MSC context data.
  119. *
  120. * @param[in] p_msc MSC instance data.
  121. * @return MSC context data @ref app_usbd_msc_ctx_t
  122. */
  123. static inline app_usbd_msc_ctx_t * msc_ctx_get(app_usbd_msc_t const * p_msc)
  124. {
  125. ASSERT(p_msc != NULL);
  126. ASSERT(p_msc->specific.p_data != NULL);
  127. return &p_msc->specific.p_data->ctx;
  128. }
  129. /**
  130. * @brief Auxiliary function to access MSC IN endpoint address.
  131. *
  132. * @param[in] p_inst Class instance data.
  133. *
  134. * @return IN endpoint address.
  135. */
  136. static inline nrf_drv_usbd_ep_t ep_in_addr_get(app_usbd_class_inst_t const * p_inst)
  137. {
  138. app_usbd_class_iface_conf_t const * class_iface;
  139. class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_MSC_IFACE_IDX);
  140. app_usbd_class_ep_conf_t const * ep_cfg;
  141. ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_MSC_EPIN_IDX);
  142. return app_usbd_class_ep_address_get(ep_cfg);
  143. }
  144. /**
  145. * @brief Auxiliary function to access MSC OUT endpoint address.
  146. *
  147. * @param[in] p_inst Class instance data.
  148. *
  149. * @return OUT endpoint address.
  150. */
  151. static inline nrf_drv_usbd_ep_t ep_out_addr_get(app_usbd_class_inst_t const * p_inst)
  152. {
  153. app_usbd_class_iface_conf_t const * class_iface;
  154. class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_MSC_IFACE_IDX);
  155. app_usbd_class_ep_conf_t const * ep_cfg;
  156. ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_MSC_EPOUT_IDX);
  157. return app_usbd_class_ep_address_get(ep_cfg);
  158. }
  159. /**
  160. * @brief Clear the data buffer.
  161. *
  162. * @param p_msc MSC instance data.
  163. */
  164. static inline void msc_buff_clear(app_usbd_msc_t const * p_msc)
  165. {
  166. app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
  167. p_ctx->current.buff.rd_idx = 0;
  168. p_ctx->current.buff.d_count = 0;
  169. p_ctx->current.buff.a_count = 0;
  170. }
  171. /**
  172. * @brief Check if there is any data block ready in the buffer.
  173. *
  174. * @param p_msc MSC instance data.
  175. *
  176. * @retval true There is data block ready.
  177. * @retval false There is no data ready for processing.
  178. */
  179. static inline bool msc_buff_data_check(app_usbd_msc_t const * p_msc)
  180. {
  181. app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
  182. return (p_ctx->current.buff.d_count > 0);
  183. }
  184. /**
  185. * @brief Check if there is any free space in the buffer.
  186. *
  187. * @param p_msc MSC instance data.
  188. *
  189. * @retval true There is free space.
  190. * @retval false There is no free space.
  191. */
  192. static inline bool msc_buff_space_check(app_usbd_msc_t const * p_msc)
  193. {
  194. app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
  195. return (p_ctx->current.buff.a_count < p_msc->specific.inst.block_buff_count);
  196. }
  197. /**
  198. * @brief Allocate buffer block.
  199. *
  200. * @param p_msc MSC instance data.
  201. *
  202. * @return Pointer to a data block or NULL if there is no free space available.
  203. */
  204. static inline void * msc_buff_alloc(app_usbd_msc_t const * p_msc)
  205. {
  206. app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
  207. void * p_buff = NULL;
  208. CRITICAL_REGION_ENTER();
  209. if (msc_buff_space_check(p_msc))
  210. {
  211. uint8_t idx = (p_ctx->current.buff.rd_idx + p_ctx->current.buff.a_count) %
  212. p_msc->specific.inst.block_buff_count;
  213. size_t offset = idx * p_msc->specific.inst.block_buff_size;
  214. p_buff = ((uint8_t*)(p_msc->specific.inst.p_block_buff)) + offset;
  215. ++(p_ctx->current.buff.a_count);
  216. }
  217. NRF_LOG_DEBUG("buff_alloc, idx: %u, dc: %u, ac: %u",
  218. p_ctx->current.buff.rd_idx,
  219. p_ctx->current.buff.d_count,
  220. p_ctx->current.buff.a_count);
  221. CRITICAL_REGION_EXIT();
  222. return p_buff;
  223. }
  224. /**
  225. * @brief Put the buffer block.
  226. *
  227. * Puts previously allocated buffer and marks it as ready to be processed.
  228. *
  229. * @param p_msc MSC instance data.
  230. *
  231. * @note This one may be called only if the previous call of
  232. * @ref msc_buff_alloc succeed.
  233. */
  234. static inline void msc_buff_put(app_usbd_msc_t const * p_msc)
  235. {
  236. app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
  237. CRITICAL_REGION_ENTER();
  238. /* Assert if there is any space - if it is not it means some coding error */
  239. ASSERT(p_ctx->current.buff.d_count < p_ctx->current.buff.a_count);
  240. ASSERT(p_ctx->current.buff.d_count < p_msc->specific.inst.block_buff_count);
  241. ++(p_ctx->current.buff.d_count);
  242. NRF_LOG_DEBUG("buff_put, idx: %u, dc: %u, ac: %u",
  243. p_ctx->current.buff.rd_idx,
  244. p_ctx->current.buff.d_count,
  245. p_ctx->current.buff.a_count);
  246. CRITICAL_REGION_EXIT();
  247. }
  248. /**
  249. * @brief Get the data block filled with data.
  250. *
  251. * @param p_msc MSC instance data.
  252. *
  253. * @return Pointer to the buffer or NULL if there is no data to be processed.
  254. */
  255. static inline void * msc_buff_get(app_usbd_msc_t const * p_msc)
  256. {
  257. app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
  258. void * p_buff = NULL;
  259. CRITICAL_REGION_ENTER();
  260. if (msc_buff_data_check(p_msc))
  261. {
  262. uint8_t idx = p_ctx->current.buff.rd_idx;
  263. size_t offset = idx * p_msc->specific.inst.block_buff_size;
  264. p_buff = ((uint8_t*)(p_msc->specific.inst.p_block_buff)) + offset;
  265. }
  266. NRF_LOG_DEBUG("buff_get, idx: %u, dc: %u, ac: %u",
  267. p_ctx->current.buff.rd_idx,
  268. p_ctx->current.buff.d_count,
  269. p_ctx->current.buff.a_count);
  270. CRITICAL_REGION_EXIT();
  271. return p_buff;
  272. }
  273. /**
  274. * @brief Free the last used data buffer block.
  275. *
  276. * Function frees the oldest data block.
  277. *
  278. * @param p_msc MSC instance data.
  279. *
  280. * @note This one may be called only if the previous call of
  281. * @ref msc_buff_get succeed.
  282. */
  283. static inline void msc_buff_free(app_usbd_msc_t const * p_msc)
  284. {
  285. app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
  286. CRITICAL_REGION_ENTER();
  287. /* Assert if there is any data - in case there is none, a coding error exists */
  288. ASSERT(p_ctx->current.buff.d_count > 0);
  289. ASSERT(p_ctx->current.buff.a_count > 0);
  290. --(p_ctx->current.buff.d_count);
  291. --(p_ctx->current.buff.a_count);
  292. p_ctx->current.buff.rd_idx = (p_ctx->current.buff.rd_idx + 1) %
  293. p_msc->specific.inst.block_buff_count;
  294. NRF_LOG_DEBUG("buff_free, idx: %u, dc: %u, ac: %u",
  295. p_ctx->current.buff.rd_idx,
  296. p_ctx->current.buff.d_count,
  297. p_ctx->current.buff.a_count);
  298. CRITICAL_REGION_EXIT();
  299. }
  300. /**
  301. * @brief Helpful macro to sub a value with zero saturation.
  302. *
  303. * @param[in] m The minuend.
  304. * @param[in] s The subtrahend.
  305. *
  306. * @return The difference saturated at 0.
  307. */
  308. #define SUB_SAT0(m, s) ((m) < (s)) ? 0 : ((m) - (s))
  309. /**
  310. * @brief Command Block Wrapper trigger.
  311. *
  312. * @param[in] p_inst Generic class instance.
  313. * @param[in] state Next state transition.
  314. *
  315. * @return Standard error code.
  316. * */
  317. static ret_code_t cbw_wait_start(app_usbd_class_inst_t const * p_inst)
  318. {
  319. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  320. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  321. nrf_drv_usbd_ep_t ep_addr_out = ep_out_addr_get(p_inst);
  322. NRF_LOG_DEBUG("cbw_wait_start");
  323. memset(&p_msc_ctx->cbw, 0, sizeof(app_usbd_msc_cbw_t));
  324. NRF_DRV_USBD_TRANSFER_OUT(cbw, &p_msc_ctx->cbw, sizeof(app_usbd_msc_cbw_t));
  325. ret_code_t ret = app_usbd_ep_transfer(ep_addr_out, &cbw);
  326. if (ret == NRF_SUCCESS)
  327. {
  328. p_msc_ctx->state = APP_USBD_MSC_STATE_CBW;
  329. }
  330. return ret;
  331. }
  332. /**
  333. * @brief Command Status Wrapper trigger.
  334. *
  335. * @param[in] p_inst Generic class instance.
  336. * @param[in] state Next state transition.
  337. *
  338. * @return Standard error code.
  339. * */
  340. static ret_code_t csw_wait_start(app_usbd_class_inst_t const * p_inst, uint8_t status)
  341. {
  342. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  343. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  344. nrf_drv_usbd_ep_t ep_addr_in = ep_in_addr_get(p_inst);
  345. NRF_LOG_DEBUG("csw_wait_start: %u", status);
  346. /* The maximum of this two is already the data that was not processed */
  347. size_t datalen_left = MAX(
  348. p_msc_ctx->current.process.datalen_left,
  349. p_msc_ctx->current.transfer.datalen_left);
  350. UNUSED_RETURN_VALUE(uint32_encode(datalen_left, p_msc_ctx->csw.residue));
  351. p_msc_ctx->csw.status = status;
  352. NRF_DRV_USBD_TRANSFER_IN(csw, &p_msc_ctx->csw, sizeof(app_usbd_msc_csw_t));
  353. ret_code_t ret = app_usbd_ep_transfer(ep_addr_in, &csw);
  354. if (ret == NRF_SUCCESS)
  355. {
  356. p_msc_ctx->state = APP_USBD_MSC_STATE_CSW;
  357. }
  358. return ret;
  359. }
  360. /**
  361. * @brief IN transfer trigger.
  362. *
  363. * @param[in] p_inst Generic class instance.
  364. * @param[in] p_buff IN transfer data buffer.
  365. * @param[in] size IN transfer size.
  366. * @param[in] state Next state transition.
  367. *
  368. * @return Standard error code.
  369. * */
  370. static ret_code_t transfer_in_start(app_usbd_class_inst_t const * p_inst,
  371. void const * p_buff,
  372. size_t size,
  373. app_usbd_msc_state_t state)
  374. {
  375. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  376. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  377. NRF_LOG_DEBUG("transfer_in_start: p_buff: %p, size: %u", (uint32_t)p_buff, size);
  378. nrf_drv_usbd_ep_t ep_addr_in = ep_in_addr_get(p_inst);
  379. NRF_DRV_USBD_TRANSFER_IN(resp, p_buff, size);
  380. ret_code_t ret = app_usbd_ep_transfer(ep_addr_in, &resp);
  381. if (ret == NRF_SUCCESS)
  382. {
  383. p_msc_ctx->state = state;
  384. }
  385. return ret;
  386. }
  387. /**
  388. * @brief MSC reset request handler @ref APP_USBD_MSC_REQ_BULK_RESET
  389. *
  390. * @param[in] p_inst Generic class instance.
  391. *
  392. * */
  393. static void bulk_ep_reset(app_usbd_class_inst_t const * p_inst)
  394. {
  395. nrf_drv_usbd_ep_t ep_addr_in = ep_in_addr_get(p_inst);
  396. nrf_drv_usbd_ep_t ep_addr_out = ep_out_addr_get(p_inst);
  397. nrf_drv_usbd_ep_abort(ep_addr_in);
  398. nrf_drv_usbd_ep_abort(ep_addr_out);
  399. }
  400. /**
  401. * @brief OUT transfer trigger.
  402. *
  403. * @param[in] p_inst Generic class instance.
  404. * @param[in] p_buff OUT transfer data buffer.
  405. * @param[in] size OUT transfer size.
  406. * @param[in] state Next state transition.
  407. *
  408. * @return Standard error code.
  409. * */
  410. static ret_code_t transfer_out_start(app_usbd_class_inst_t const * p_inst,
  411. void * p_buff,
  412. size_t size,
  413. app_usbd_msc_state_t state)
  414. {
  415. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  416. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  417. NRF_LOG_DEBUG("transfer_out_start: p_buff: %p, size: %u", (uint32_t)p_buff, size);
  418. nrf_drv_usbd_ep_t ep_addr_out = ep_out_addr_get(p_inst);
  419. NRF_DRV_USBD_TRANSFER_OUT(resp, p_buff, size);
  420. ret_code_t ret = app_usbd_ep_transfer(ep_addr_out, &resp);
  421. if (ret == NRF_SUCCESS)
  422. {
  423. p_msc_ctx->state = state;
  424. }
  425. return ret;
  426. }
  427. /**
  428. * @brief Generic function to stall communication endpoints and mark error state.
  429. *
  430. * Function used internally to stall all communication endpoints and mark current state.
  431. *
  432. * @param p_inst Generic class instance.
  433. * @param state State to set.
  434. */
  435. static void status_generic_error_stall(app_usbd_class_inst_t const * p_inst,
  436. app_usbd_msc_state_t state)
  437. {
  438. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  439. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  440. nrf_drv_usbd_ep_t ep_in = ep_in_addr_get(p_inst);
  441. nrf_drv_usbd_ep_t ep_out = ep_out_addr_get(p_inst);
  442. nrf_drv_usbd_ep_stall(ep_in);
  443. nrf_drv_usbd_ep_stall(ep_out);
  444. nrf_drv_usbd_ep_abort(ep_in);
  445. nrf_drv_usbd_ep_abort(ep_out);
  446. p_msc_ctx->state = state;
  447. }
  448. /**
  449. * @brief Start status stage of unsupported SCSI command.
  450. *
  451. * @param[in,out] p_inst Generic class instance.
  452. *
  453. * @return Standard error code.
  454. *
  455. * @sa status_generic_error_stall
  456. */
  457. static ret_code_t status_unsupported_start(app_usbd_class_inst_t const * p_inst)
  458. {
  459. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  460. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  461. bool data_stage = uint32_decode(p_msc_ctx->cbw.datlen) != 0;
  462. ret_code_t ret = NRF_SUCCESS;
  463. if (!data_stage)
  464. {
  465. /* Try to transfer the response now */
  466. ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
  467. }
  468. else
  469. {
  470. /* Cannot transfer failed response in current command - stall the endpoints and postpone the answer */
  471. status_generic_error_stall(p_inst, APP_USBD_MSC_STATE_UNSUPPORTED);
  472. }
  473. return ret;
  474. }
  475. /**
  476. * @brief Start status stage of CBW invalid.
  477. *
  478. * @param[in,out] p_inst Generic class instance.
  479. *
  480. * @sa status_generic_error_stall
  481. */
  482. static void status_cbwinvalid_start(app_usbd_class_inst_t const * p_inst)
  483. {
  484. status_generic_error_stall(p_inst, APP_USBD_MSC_STATE_CBW_INVALID);
  485. }
  486. /**
  487. * @brief Start status stage of internal device error.
  488. *
  489. * Kind of error that requires bulk reset but does not stall endpoint permanently - the correct
  490. * answer is possible.
  491. *
  492. * @param[in] p_inst Generic class instance.
  493. *
  494. * @sa status_generic_error_stall
  495. */
  496. static void status_deverror_start(app_usbd_class_inst_t const * p_inst)
  497. {
  498. status_generic_error_stall(p_inst, APP_USBD_MSC_STATE_DEVICE_ERROR);
  499. }
  500. /**
  501. * @brief Internal SETUP standard IN request handler.
  502. *
  503. * @param[in] p_inst Generic class instance.
  504. * @param[in] p_setup_ev Setup event.
  505. *
  506. * @return Standard error code.
  507. * @retval NRF_SUCCESS Request handled correctly.
  508. * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
  509. */
  510. static ret_code_t setup_req_std_in(app_usbd_class_inst_t const * p_inst,
  511. app_usbd_setup_evt_t const * p_setup_ev)
  512. {
  513. /* Only Get Descriptor standard IN request is supported by MSC class */
  514. if ((app_usbd_setup_req_rec(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQREC_INTERFACE)
  515. &&
  516. (p_setup_ev->setup.bRequest == APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR))
  517. {
  518. size_t dsc_len = 0;
  519. size_t max_size;
  520. uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size);
  521. /* Try to find descriptor in class internals*/
  522. ret_code_t ret = app_usbd_class_descriptor_find(
  523. p_inst,
  524. p_setup_ev->setup.wValue.hb,
  525. p_setup_ev->setup.wValue.lb,
  526. p_trans_buff,
  527. &dsc_len);
  528. if (ret != NRF_ERROR_NOT_FOUND)
  529. {
  530. ASSERT(dsc_len < NRF_DRV_USBD_EPSIZE);
  531. return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, dsc_len);
  532. }
  533. }
  534. return NRF_ERROR_NOT_SUPPORTED;
  535. }
  536. /**
  537. * @brief Internal SETUP standard OUT request handler.
  538. *
  539. * @param[in] p_inst Generic class instance.
  540. * @param[in] p_setup_ev Setup event.
  541. *
  542. * @return Standard error code.
  543. * @retval NRF_SUCCESS Request handled correctly.
  544. * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
  545. * @retval NRF_ERROR_FORBIDDEN Endpoint stall cannot be cleared because of internal state.
  546. */
  547. static ret_code_t setup_req_std_out(app_usbd_class_inst_t const * p_inst,
  548. app_usbd_setup_evt_t const * p_setup_ev)
  549. {
  550. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  551. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  552. app_usbd_setup_reqrec_t req_rec = app_usbd_setup_req_rec(p_setup_ev->setup.bmRequestType);
  553. if ((req_rec == APP_USBD_SETUP_REQREC_ENDPOINT) &&
  554. (p_setup_ev->setup.bRequest == APP_USBD_SETUP_STDREQ_CLEAR_FEATURE) &&
  555. (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT))
  556. {
  557. if (p_msc_ctx->state == APP_USBD_MSC_STATE_CBW_INVALID)
  558. {
  559. return NRF_ERROR_FORBIDDEN;
  560. }
  561. ret_code_t ret = NRF_SUCCESS;
  562. /* Clearing endpoint here. It is done normally inside app_usbd, but we are overwritting this functionality */
  563. nrf_drv_usbd_ep_t ep_addr = (nrf_drv_usbd_ep_t)(p_setup_ev->setup.wIndex.lb);
  564. nrf_drv_usbd_ep_dtoggle_clear(ep_addr);
  565. nrf_drv_usbd_ep_stall_clear(ep_addr);
  566. if (NRF_USBD_EPIN_CHECK(ep_addr))
  567. {
  568. switch (p_msc_ctx->state)
  569. {
  570. case APP_USBD_MSC_STATE_UNSUPPORTED:
  571. {
  572. nrf_drv_usbd_ep_stall_clear(ep_out_addr_get(p_inst));
  573. /*Unsupported command handle: status stage*/
  574. ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
  575. if (ret != NRF_SUCCESS)
  576. {
  577. NRF_LOG_ERROR("Unexpected csw_wait_start on ep clear: %d", ret);
  578. }
  579. break;
  580. }
  581. case APP_USBD_MSC_STATE_DEVICE_ERROR:
  582. {
  583. nrf_drv_usbd_ep_stall_clear(ep_out_addr_get(p_inst));
  584. /*Unsupported command handle: status stage*/
  585. ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PE);
  586. if (ret != NRF_SUCCESS)
  587. {
  588. NRF_LOG_ERROR("Unexpected csw_wait_start on ep clear: %d", ret);
  589. }
  590. break;
  591. }
  592. default:
  593. break;
  594. }
  595. }
  596. return ret;
  597. }
  598. return NRF_ERROR_NOT_SUPPORTED;
  599. }
  600. /**
  601. * @brief Internal SETUP class IN request handler.
  602. *
  603. * @param[in] p_inst Generic class instance.
  604. * @param[in] p_setup_ev Setup event.
  605. *
  606. * @return Standard error code.
  607. * @retval NRF_SUCCESS Request handled correctly.
  608. * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
  609. */
  610. static ret_code_t setup_req_class_in(app_usbd_class_inst_t const * p_inst,
  611. app_usbd_setup_evt_t const * p_setup_ev)
  612. {
  613. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  614. switch (p_setup_ev->setup.bRequest)
  615. {
  616. case APP_USBD_MSC_REQ_GET_MAX_LUN:
  617. {
  618. if (p_setup_ev->setup.wValue.w != 0)
  619. {
  620. break;
  621. }
  622. if (p_setup_ev->setup.wLength.w != 1)
  623. {
  624. break;
  625. }
  626. size_t tx_size;
  627. uint16_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size);
  628. ASSERT(p_msc->specific.inst.block_devs_count != 0);
  629. p_tx_buff[0] = p_msc->specific.inst.block_devs_count - 1;
  630. ret_code_t ret = cbw_wait_start(p_inst);
  631. UNUSED_VARIABLE(ret);
  632. return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint8_t));
  633. }
  634. default:
  635. break;
  636. }
  637. return NRF_ERROR_NOT_SUPPORTED;
  638. }
  639. /**
  640. * @brief Internal SETUP class OUT request handler.
  641. *
  642. * @param[in] p_inst Generic class instance.
  643. * @param[in] p_setup_ev Setup event.
  644. *
  645. * @return Standard error code.
  646. * @retval NRF_SUCCESS Request handled correctly.
  647. * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
  648. */
  649. static ret_code_t setup_req_class_out(app_usbd_class_inst_t const * p_inst,
  650. app_usbd_setup_evt_t const * p_setup_ev)
  651. {
  652. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  653. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  654. switch (p_setup_ev->setup.bRequest)
  655. {
  656. case APP_USBD_MSC_REQ_BULK_RESET:
  657. {
  658. if (p_setup_ev->setup.wValue.w != 0)
  659. {
  660. break;
  661. }
  662. if (p_setup_ev->setup.wLength.w != 0)
  663. {
  664. break;
  665. }
  666. /*
  667. * Reset internal state to be ready for next CBW
  668. */
  669. NRF_LOG_DEBUG("bulk ep reset");
  670. bulk_ep_reset(p_inst);
  671. if (p_msc_ctx->state != APP_USBD_MSC_STATE_CBW)
  672. {
  673. ret_code_t ret = cbw_wait_start(p_inst);
  674. UNUSED_VARIABLE(ret);
  675. }
  676. return NRF_SUCCESS;
  677. }
  678. default:
  679. break;
  680. }
  681. return NRF_ERROR_NOT_SUPPORTED;
  682. }
  683. /**
  684. * @brief Control endpoint handle.
  685. *
  686. * @param[in] p_inst Generic class instance.
  687. * @param[in] p_setup_ev Setup event.
  688. *
  689. * @return Standard error code.
  690. * @retval NRF_SUCCESS Request handled correctly.
  691. * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
  692. */
  693. static ret_code_t setup_event_handler(app_usbd_class_inst_t const * p_inst,
  694. app_usbd_setup_evt_t const * p_setup_ev)
  695. {
  696. ASSERT(p_inst != NULL);
  697. ASSERT(p_setup_ev != NULL);
  698. if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN)
  699. {
  700. switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType))
  701. {
  702. case APP_USBD_SETUP_REQTYPE_STD:
  703. return setup_req_std_in(p_inst, p_setup_ev);
  704. case APP_USBD_SETUP_REQTYPE_CLASS:
  705. return setup_req_class_in(p_inst, p_setup_ev);
  706. default:
  707. break;
  708. }
  709. }
  710. else /* APP_USBD_SETUP_REQDIR_OUT */
  711. {
  712. switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType))
  713. {
  714. case APP_USBD_SETUP_REQTYPE_STD:
  715. return setup_req_std_out(p_inst, p_setup_ev);
  716. case APP_USBD_SETUP_REQTYPE_CLASS:
  717. return setup_req_class_out(p_inst, p_setup_ev);
  718. default:
  719. break;
  720. }
  721. }
  722. return NRF_ERROR_NOT_SUPPORTED;
  723. }
  724. /**
  725. * @brief Get number of blocks that should be transfered into the selected LUN
  726. *
  727. * Function calculates number of blocks for the request.
  728. * The number of block is calculated based on the work buffer size and the size left to transfer.
  729. *
  730. * @param p_msc MSC instance.
  731. * @param size The size of the transfer left.
  732. *
  733. * @return Number of blocks required for the transfer.
  734. */
  735. static uint32_t current_blkcnt_calc(app_usbd_msc_t const * p_msc, size_t size)
  736. {
  737. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  738. if (size > p_msc->specific.inst.block_buff_size)
  739. {
  740. size = p_msc->specific.inst.block_buff_size;
  741. }
  742. return CEIL_DIV(size, p_msc_ctx->current.process.blk_size);
  743. }
  744. /**
  745. * @brief Helper function to calculate next transfer size.
  746. *
  747. * @param[in] p_msc MSC instance.
  748. * @param[in] size Total size of the transfer left.
  749. *
  750. * @return Blocks to transfer.
  751. * */
  752. static uint32_t current_size_calc(app_usbd_msc_t const * p_msc, size_t size)
  753. {
  754. return MIN(size, p_msc->specific.inst.block_buff_size);
  755. }
  756. static ret_code_t read_transfer_processor(app_usbd_class_inst_t const * p_inst)
  757. {
  758. ret_code_t ret = NRF_SUCCESS;
  759. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  760. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  761. if ((!p_msc_ctx->current.transfer.pending))
  762. {
  763. NRF_LOG_DEBUG("read_transfer_processor: left: %u, state: %u",
  764. p_msc_ctx->current.transfer.size_left,
  765. p_msc_ctx->state);
  766. if (p_msc_ctx->current.transfer.abort)
  767. {
  768. NRF_LOG_ERROR("read_transfer_processor: aborted");
  769. ret = NRF_ERROR_NOT_SUPPORTED;
  770. }
  771. else if (p_msc_ctx->current.transfer.size_left > 0)
  772. {
  773. if (msc_buff_data_check(p_msc))
  774. {
  775. void * p_buff = msc_buff_get(p_msc);
  776. size_t req_size = current_size_calc(p_msc, p_msc_ctx->current.transfer.size_left);
  777. ASSERT(p_buff != NULL);
  778. /*Trigger new transfer.*/
  779. p_msc_ctx->current.transfer.pending = true;
  780. ret = transfer_in_start(p_inst, p_buff, req_size, APP_USBD_MSC_STATE_DATA_IN);
  781. if (ret != NRF_SUCCESS)
  782. {
  783. p_msc_ctx->current.transfer.pending = false;
  784. }
  785. }
  786. }
  787. else
  788. {
  789. if (p_msc_ctx->state == APP_USBD_MSC_STATE_DATA_IN)
  790. {
  791. if (p_msc_ctx->current.transfer.datalen_left == 0)
  792. {
  793. ret = csw_wait_start(p_inst, p_msc_ctx->csw.status);
  794. ASSERT(ret == NRF_SUCCESS);
  795. }
  796. else
  797. {
  798. ret = NRF_ERROR_NOT_SUPPORTED;
  799. }
  800. }
  801. }
  802. }
  803. return ret;
  804. }
  805. static ret_code_t read_blockmem_processor(app_usbd_class_inst_t const * p_inst)
  806. {
  807. ret_code_t ret = NRF_SUCCESS;
  808. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  809. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  810. if (!(p_msc_ctx->current.process.pending))
  811. {
  812. NRF_LOG_DEBUG("read_blockmem_processor: left: %u", p_msc_ctx->current.process.size_left);
  813. if (p_msc_ctx->current.process.abort)
  814. {
  815. NRF_LOG_ERROR("read_blockmem_processor: aborted");
  816. ret = NRF_ERROR_NOT_SUPPORTED;
  817. }
  818. else if ((p_msc_ctx->current.process.size_left > 0) && msc_buff_space_check(p_msc))
  819. {
  820. nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
  821. uint32_t blk_cnt = current_blkcnt_calc(p_msc, p_msc_ctx->current.process.size_left);
  822. void * p_buff = msc_buff_alloc(p_msc);
  823. ASSERT(p_buff != NULL);
  824. NRF_BLOCK_DEV_REQUEST(
  825. req,
  826. p_msc_ctx->current.process.blk_idx,
  827. blk_cnt,
  828. p_buff);
  829. p_msc_ctx->current.process.pending = true;
  830. ret = nrf_blk_dev_read_req(p_blkd, &req);
  831. if (ret != NRF_SUCCESS)
  832. {
  833. /* Mark process pending and move all pionters */
  834. p_msc_ctx->current.process.pending = false;
  835. NRF_LOG_ERROR("read_blockmem_processor: block req failed: %u", ret);
  836. }
  837. }
  838. }
  839. return ret;
  840. }
  841. static ret_code_t write_transfer_processor(app_usbd_class_inst_t const * p_inst)
  842. {
  843. ret_code_t ret = NRF_SUCCESS;
  844. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  845. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  846. if (!(p_msc_ctx->current.transfer.pending))
  847. {
  848. NRF_LOG_DEBUG("write_transfer_processor: left: %u", p_msc_ctx->current.transfer.size_left);
  849. if ((p_msc_ctx->current.transfer.size_left > 0) && msc_buff_space_check(p_msc))
  850. {
  851. void * p_buff = msc_buff_alloc(p_msc);
  852. size_t req_size = current_size_calc(p_msc, p_msc_ctx->current.transfer.size_left);
  853. ASSERT(p_buff != NULL);
  854. /*Trigger new transfer.*/
  855. p_msc_ctx->current.transfer.pending = true;
  856. ret = transfer_out_start(p_inst, p_buff, req_size, APP_USBD_MSC_STATE_DATA_OUT);
  857. if (ret != NRF_SUCCESS)
  858. {
  859. p_msc_ctx->current.transfer.pending = false;
  860. }
  861. }
  862. }
  863. return ret;
  864. }
  865. static ret_code_t write_blockmem_processor(app_usbd_class_inst_t const * p_inst)
  866. {
  867. ret_code_t ret = NRF_SUCCESS;
  868. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  869. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  870. if (!(p_msc_ctx->current.process.pending))
  871. {
  872. NRF_LOG_DEBUG("write_blockmem_processor: left: %u, state: %u",
  873. p_msc_ctx->current.process.size_left,
  874. p_msc_ctx->state);
  875. if (p_msc_ctx->current.process.abort)
  876. {
  877. NRF_LOG_ERROR("write_blockmem_processor: aborted");
  878. ret = NRF_ERROR_NOT_SUPPORTED;
  879. }
  880. else if (p_msc_ctx->current.process.size_left > 0)
  881. {
  882. if (msc_buff_data_check(p_msc))
  883. {
  884. nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
  885. uint32_t blk_cnt = current_blkcnt_calc(p_msc, p_msc_ctx->current.process.size_left);
  886. void * p_buff = msc_buff_get(p_msc);
  887. ASSERT(p_buff != NULL);
  888. NRF_BLOCK_DEV_REQUEST(
  889. req,
  890. p_msc_ctx->current.process.blk_idx,
  891. blk_cnt,
  892. p_buff);
  893. p_msc_ctx->current.process.pending = true;
  894. ret = nrf_blk_dev_write_req(p_blkd, &req);
  895. if (ret != NRF_SUCCESS)
  896. {
  897. p_msc_ctx->current.process.pending = false;
  898. NRF_LOG_ERROR("write_blockmem_processor: block req failed: %u", ret);
  899. }
  900. }
  901. }
  902. else
  903. {
  904. if (p_msc_ctx->state == APP_USBD_MSC_STATE_DATA_OUT)
  905. {
  906. if (p_msc_ctx->current.process.datalen_left == 0)
  907. {
  908. ret = csw_wait_start(p_inst, p_msc_ctx->csw.status);
  909. ASSERT(ret == NRF_SUCCESS);
  910. }
  911. else
  912. {
  913. ret = NRF_ERROR_NOT_SUPPORTED;
  914. }
  915. }
  916. }
  917. }
  918. return ret;
  919. }
  920. /**
  921. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_TESTUNITREADY handle.
  922. *
  923. * @param[in] p_inst Generic class instance.
  924. * @param[in] p_msc MSC instance.
  925. * @param[in] p_msc_ctx MSC context.
  926. * @return Standard error code.
  927. * */
  928. static ret_code_t cmd_testunitready(app_usbd_class_inst_t const * p_inst,
  929. app_usbd_msc_t const * p_msc,
  930. app_usbd_msc_ctx_t * p_msc_ctx)
  931. {
  932. NRF_LOG_DEBUG("CMD: TESTUNITREADY");
  933. if (uint32_decode(p_msc_ctx->cbw.datlen) != 0)
  934. {
  935. return status_unsupported_start(p_inst);
  936. }
  937. if (p_msc_ctx->cbw.cdb_length != APP_USBD_SCSI_CMD_TESTUNITREADY_LEN)
  938. {
  939. return status_unsupported_start(p_inst);
  940. }
  941. if (p_msc_ctx->cbw.lun >= p_msc->specific.inst.block_devs_count)
  942. {
  943. return status_unsupported_start(p_inst);
  944. }
  945. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  946. }
  947. /**
  948. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_REQUESTSENSE handle.
  949. *
  950. * @param[in] p_inst Generic class instance.
  951. * @param[in] p_msc MSC instance.
  952. * @param[in] p_msc_ctx MSC context.
  953. * @return Standard error code.
  954. * */
  955. static ret_code_t cmd_requestsense(app_usbd_class_inst_t const * p_inst,
  956. app_usbd_msc_t const * p_msc,
  957. app_usbd_msc_ctx_t * p_msc_ctx)
  958. {
  959. NRF_LOG_DEBUG("CMD: REQUESTSENSE");
  960. app_usbd_scsi_cmd_requestsense_t const * p_reqs = (const void *)p_msc_ctx->cbw.cdb;
  961. UNUSED_VARIABLE(p_reqs);
  962. if ((p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_requestsense_t)))
  963. {
  964. return status_unsupported_start(p_inst);
  965. }
  966. if (p_msc_ctx->cbw.lun >= p_msc->specific.inst.block_devs_count)
  967. {
  968. return status_unsupported_start(p_inst);
  969. }
  970. if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_requestsense_resp_t))
  971. {
  972. return status_unsupported_start(p_inst);
  973. }
  974. uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
  975. if (resp_len == 0)
  976. {
  977. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  978. }
  979. memset(&p_msc_ctx->scsi_resp, 0, sizeof(app_usbd_scsi_cmd_requestsense_resp_t));
  980. p_msc_ctx->scsi_resp.requestsense.code = APP_USBD_SCSI_CMD_REQSENSE_CODE_VALID |
  981. APP_USBD_SCSI_CMD_REQSENSE_CODE_CURRENT;
  982. p_msc_ctx->scsi_resp.requestsense.len = sizeof(app_usbd_scsi_cmd_requestsense_resp_t) -
  983. offsetof(app_usbd_scsi_cmd_requestsense_resp_t, len);
  984. return transfer_in_start(p_inst,
  985. &p_msc_ctx->scsi_resp,
  986. resp_len,
  987. APP_USBD_MSC_STATE_CMD_IN);
  988. }
  989. /**
  990. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_FORMAT_UNIT handle.
  991. *
  992. * @param[in] p_inst Generic class instance.
  993. * @param[in] p_msc MSC instance.
  994. * @param[in] p_msc_ctx MSC context.
  995. * @return Standard error code.
  996. * */
  997. static ret_code_t cmd_formatunit(app_usbd_class_inst_t const * p_inst,
  998. app_usbd_msc_t const * p_msc,
  999. app_usbd_msc_ctx_t * p_msc_ctx)
  1000. {
  1001. NRF_LOG_DEBUG("CMD: FORMAT_UNIT");
  1002. return status_unsupported_start(p_inst);
  1003. }
  1004. static ret_code_t cmd_read_start(app_usbd_class_inst_t const * p_inst,
  1005. app_usbd_msc_t const * p_msc,
  1006. app_usbd_msc_ctx_t * p_msc_ctx)
  1007. {
  1008. NRF_LOG_DEBUG("cmd_read_start");
  1009. ret_code_t ret;
  1010. if (p_msc_ctx->current.process.datalen_left == 0)
  1011. {
  1012. NRF_LOG_WARNING("Transfer size 0 detected");
  1013. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
  1014. }
  1015. if (p_msc_ctx->current.process.size_left == 0)
  1016. {
  1017. NRF_LOG_WARNING("Read size 0 detected");
  1018. return status_unsupported_start(p_inst);
  1019. }
  1020. if ((p_msc_ctx->cbw.flags & APP_USBD_MSC_CBW_DIRECTION_IN) == 0)
  1021. {
  1022. NRF_LOG_WARNING("Wrong transfer direction");
  1023. return status_unsupported_start(p_inst);
  1024. }
  1025. msc_buff_clear(p_msc);
  1026. if (p_msc_ctx->current.process.size_left > p_msc_ctx->current.process.datalen_left)
  1027. {
  1028. p_msc_ctx->current.process.size_left = p_msc_ctx->current.process.datalen_left;
  1029. /* After transmitting required number of bytes - set error information */
  1030. p_msc_ctx->csw.status = APP_USBD_MSC_CSW_STATUS_PE;
  1031. }
  1032. p_msc_ctx->current.transfer.datalen_left = p_msc_ctx->current.process.datalen_left;
  1033. p_msc_ctx->current.transfer.size_left = p_msc_ctx->current.process.size_left;
  1034. p_msc_ctx->current.transfer.pending = false;
  1035. p_msc_ctx->current.process. pending = false;
  1036. ret = read_blockmem_processor(p_inst);
  1037. NRF_LOG_DEBUG("read_blockmem: id: %u, left: %u, datalen: %u, ret: %u",
  1038. p_msc_ctx->current.process.blk_idx,
  1039. p_msc_ctx->current.process.size_left,
  1040. p_msc_ctx->current.process.datalen_left,
  1041. ret);
  1042. if (ret != NRF_SUCCESS)
  1043. {
  1044. UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
  1045. }
  1046. return ret;
  1047. }
  1048. /**
  1049. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_READ6 handle.
  1050. *
  1051. * @param[in] p_inst Generic class instance.
  1052. * @param[in] p_msc MSC instance.
  1053. * @param[in] p_msc_ctx MSC context.
  1054. * @return Standard error code.
  1055. * */
  1056. static ret_code_t cmd_read6(app_usbd_class_inst_t const * p_inst,
  1057. app_usbd_msc_t const * p_msc,
  1058. app_usbd_msc_ctx_t * p_msc_ctx)
  1059. {
  1060. NRF_LOG_DEBUG("CMD: READ6");
  1061. app_usbd_scsi_cmd_read6_t const * p_read6 = (const void *)p_msc_ctx->cbw.cdb;
  1062. if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_read6_t))
  1063. {
  1064. return status_unsupported_start(p_inst);
  1065. }
  1066. nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
  1067. uint32_t blk_size = nrf_blk_dev_geometry(p_blkd)->blk_size;
  1068. uint8_t blocks = p_read6->xfrlen;
  1069. p_msc_ctx->current.process.blk_idx =
  1070. ((p_read6->mslba & 0x1F) << 16) | uint16_big_decode(p_read6->lslba);
  1071. p_msc_ctx->current.process.blk_size = blk_size;
  1072. p_msc_ctx->current.process.size_left = blocks * blk_size;
  1073. return cmd_read_start(p_inst, p_msc, p_msc_ctx);
  1074. }
  1075. static ret_code_t cmd_write_start(app_usbd_class_inst_t const * p_inst,
  1076. app_usbd_msc_t const * p_msc,
  1077. app_usbd_msc_ctx_t * p_msc_ctx)
  1078. {
  1079. NRF_LOG_DEBUG("cmd_write_start");
  1080. ret_code_t ret;
  1081. if (p_msc_ctx->current.process.datalen_left == 0)
  1082. {
  1083. NRF_LOG_WARNING("Transfer size 0 detected");
  1084. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
  1085. }
  1086. if (p_msc_ctx->current.process.size_left == 0)
  1087. {
  1088. NRF_LOG_WARNING("Write size 0 detected");
  1089. return status_unsupported_start(p_inst);
  1090. }
  1091. if ((p_msc_ctx->cbw.flags & APP_USBD_MSC_CBW_DIRECTION_IN) != 0)
  1092. {
  1093. NRF_LOG_WARNING("Wrong transfer direction");
  1094. return status_unsupported_start(p_inst);
  1095. }
  1096. msc_buff_clear(p_msc);
  1097. if (p_msc_ctx->current.process.size_left > p_msc_ctx->current.process.datalen_left)
  1098. {
  1099. p_msc_ctx->current.process.size_left = p_msc_ctx->current.process.datalen_left;
  1100. /* After transmitting required number of bytes - set error information */
  1101. p_msc_ctx->csw.status = APP_USBD_MSC_CSW_STATUS_PE;
  1102. }
  1103. p_msc_ctx->current.transfer.datalen_left = p_msc_ctx->current.process.datalen_left;
  1104. p_msc_ctx->current.transfer.size_left = p_msc_ctx->current.process.size_left;
  1105. p_msc_ctx->current.transfer.pending = false;
  1106. p_msc_ctx->current.process. pending = false;
  1107. ret = write_transfer_processor(p_inst);
  1108. NRF_LOG_DEBUG("write_blockrx: id: %u, left: %u, datalen: %u, ret: %u",
  1109. p_msc_ctx->current.process.blk_idx,
  1110. p_msc_ctx->current.process.size_left,
  1111. p_msc_ctx->current.process.datalen_left,
  1112. ret);
  1113. if (ret != NRF_SUCCESS)
  1114. {
  1115. UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
  1116. }
  1117. return ret;
  1118. }
  1119. /**
  1120. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_WRITE6 handle.
  1121. *
  1122. * @param[in] p_inst Generic class instance.
  1123. * @param[in] p_msc MSC instance.
  1124. * @param[in] p_msc_ctx MSC context.
  1125. * @return Standard error code.
  1126. * */
  1127. static ret_code_t cmd_write6(app_usbd_class_inst_t const * p_inst,
  1128. app_usbd_msc_t const * p_msc,
  1129. app_usbd_msc_ctx_t * p_msc_ctx)
  1130. {
  1131. NRF_LOG_DEBUG("CMD: WRITE6");
  1132. app_usbd_scsi_cmd_write6_t const * p_write6 = (const void *)p_msc_ctx->cbw.cdb;
  1133. if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_write6_t))
  1134. {
  1135. return status_unsupported_start(p_inst);
  1136. }
  1137. nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
  1138. uint32_t blk_size = nrf_blk_dev_geometry(p_blkd)->blk_size;
  1139. uint8_t blocks = p_write6->xfrlen;
  1140. p_msc_ctx->current.process.blk_idx =
  1141. ((p_write6->mslba & 0x1F) << 16) | uint16_big_decode(p_write6->lslba);
  1142. p_msc_ctx->current.process.blk_size = blk_size;
  1143. p_msc_ctx->current.process.size_left = blocks * blk_size;
  1144. return cmd_write_start(p_inst, p_msc, p_msc_ctx);
  1145. }
  1146. /**
  1147. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_INQUIRY handle.
  1148. *
  1149. * @param[in] p_inst Generic class instance.
  1150. * @param[in] p_msc MSC instance.
  1151. * @param[in] p_msc_ctx MSC context.
  1152. * @return Standard error code.
  1153. * */
  1154. static ret_code_t cmd_inquiry(app_usbd_class_inst_t const * p_inst,
  1155. app_usbd_msc_t const * p_msc,
  1156. app_usbd_msc_ctx_t * p_msc_ctx)
  1157. {
  1158. NRF_LOG_DEBUG("CMD: INQUIRY");
  1159. app_usbd_scsi_cmd_inquiry_t const * p_inq = (const void *)p_msc_ctx->cbw.cdb;
  1160. if (p_inq->pagecode != 0)
  1161. {
  1162. NRF_LOG_WARNING("unsupported pagecode");
  1163. return status_unsupported_start(p_inst);
  1164. }
  1165. if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_inquiry_resp_t))
  1166. {
  1167. return status_unsupported_start(p_inst);
  1168. }
  1169. uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
  1170. if (resp_len == 0)
  1171. {
  1172. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  1173. }
  1174. p_msc_ctx->scsi_resp.inquiry.qualtype = APP_USBD_MSC_SCSI_INQ_QUAL_CONNECTED |
  1175. APP_USBD_MSC_SCSI_INQ_TYPE_DIR_ACCESS;
  1176. p_msc_ctx->scsi_resp.inquiry.flags1 = APP_USBD_MSC_SCSI_INQ_FLAG1_RMB;
  1177. p_msc_ctx->scsi_resp.inquiry.version = APP_USBD_SCSI_INQ_VER_SPC4;
  1178. p_msc_ctx->scsi_resp.inquiry.flags2 = APP_USBD_MSC_SCSI_INQ_FLAG2_RSP_SPC2 |
  1179. APP_USBD_MSC_SCSI_INQ_FLAG2_HISUP;
  1180. p_msc_ctx->scsi_resp.inquiry.len = sizeof(app_usbd_scsi_cmd_inquiry_resp_t) -
  1181. offsetof(app_usbd_scsi_cmd_inquiry_resp_t, len);
  1182. nrf_block_dev_t const * p_blkd =
  1183. p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
  1184. nrf_block_dev_info_strings_t * p_strings = NULL;
  1185. UNUSED_RETURN_VALUE(nrf_blk_dev_ioctl(p_blkd,
  1186. NRF_BLOCK_DEV_IOCTL_REQ_INFO_STRINGS,
  1187. &p_strings));
  1188. if (p_strings)
  1189. {
  1190. UNUSED_RETURN_VALUE(strncpy((char *)p_msc_ctx->scsi_resp.inquiry.vendorid,
  1191. p_strings->p_vendor,
  1192. sizeof(p_msc_ctx->scsi_resp.inquiry.vendorid)));
  1193. UNUSED_RETURN_VALUE(strncpy((char *)p_msc_ctx->scsi_resp.inquiry.productid,
  1194. p_strings->p_product,
  1195. sizeof(p_msc_ctx->scsi_resp.inquiry.productid)));
  1196. UNUSED_RETURN_VALUE(strncpy((char *)p_msc_ctx->scsi_resp.inquiry.revision,
  1197. p_strings->p_revision,
  1198. sizeof(p_msc_ctx->scsi_resp.inquiry.revision)));
  1199. }
  1200. else
  1201. {
  1202. memset(p_msc_ctx->scsi_resp.inquiry.vendorid,
  1203. 0,
  1204. sizeof(p_msc_ctx->scsi_resp.inquiry.vendorid));
  1205. memset(p_msc_ctx->scsi_resp.inquiry.productid,
  1206. 0,
  1207. sizeof(p_msc_ctx->scsi_resp.inquiry.productid));
  1208. memset(p_msc_ctx->scsi_resp.inquiry.revision,
  1209. 0,
  1210. sizeof(p_msc_ctx->scsi_resp.inquiry.revision));
  1211. }
  1212. return transfer_in_start(p_inst,
  1213. &p_msc_ctx->scsi_resp,
  1214. resp_len,
  1215. APP_USBD_MSC_STATE_CMD_IN);
  1216. }
  1217. /**
  1218. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_MODESELECT6 handle.
  1219. *
  1220. * @param[in] p_inst Generic class instance.
  1221. * @param[in] p_msc MSC instance.
  1222. * @param[in] p_msc_ctx MSC context.
  1223. * @return Standard error code.
  1224. * */
  1225. static ret_code_t cmd_modeselect6(app_usbd_class_inst_t const * p_inst,
  1226. app_usbd_msc_t const * p_msc,
  1227. app_usbd_msc_ctx_t * p_msc_ctx)
  1228. {
  1229. NRF_LOG_DEBUG("CMD: MODESELECT6");
  1230. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  1231. }
  1232. /**
  1233. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_MODESENSE6 handle.
  1234. *
  1235. * @param[in] p_inst Generic class instance.
  1236. * @param[in] p_msc MSC instance.
  1237. * @param[in] p_msc_ctx MSC context.
  1238. * @return Standard error code.
  1239. * */
  1240. static ret_code_t cmd_modesense6(app_usbd_class_inst_t const * p_inst,
  1241. app_usbd_msc_t const * p_msc,
  1242. app_usbd_msc_ctx_t * p_msc_ctx)
  1243. {
  1244. NRF_LOG_DEBUG("CMD: MODESENSE6");
  1245. app_usbd_scsi_cmd_modesense6_t const * p_sense6 = (const void *)p_msc_ctx->cbw.cdb;
  1246. UNUSED_VARIABLE(p_sense6);
  1247. if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_modesense6_t))
  1248. {
  1249. return status_unsupported_start(p_inst);
  1250. }
  1251. if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_modesense6_resp_t))
  1252. {
  1253. return status_unsupported_start(p_inst);
  1254. }
  1255. uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
  1256. app_usbd_scsi_cmd_modesense6_resp_t * p_resp = &p_msc_ctx->scsi_resp.modesense6;
  1257. p_resp->mdlen = sizeof(app_usbd_scsi_cmd_modesense6_resp_t) - 1;
  1258. p_resp->type = 0;
  1259. p_resp->param = 0;
  1260. p_resp->bdlen = 0;
  1261. return transfer_in_start(p_inst,
  1262. &p_msc_ctx->scsi_resp,
  1263. resp_len,
  1264. APP_USBD_MSC_STATE_CMD_IN);
  1265. }
  1266. /**
  1267. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_STARTSTOPUNIT handle.
  1268. *
  1269. * @param[in] p_inst Generic class instance.
  1270. * @param[in] p_msc MSC instance.
  1271. * @param[in] p_msc_ctx MSC context.
  1272. * @return Standard error code.
  1273. * */
  1274. static ret_code_t cmd_startstopunit(app_usbd_class_inst_t const * p_inst,
  1275. app_usbd_msc_t const * p_msc,
  1276. app_usbd_msc_ctx_t * p_msc_ctx)
  1277. {
  1278. NRF_LOG_DEBUG("CMD: STARTSTOPUNIT");
  1279. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  1280. }
  1281. /**
  1282. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_SENDDIAGNOSTIC handle.
  1283. *
  1284. * @param[in] p_inst Generic class instance.
  1285. * @param[in] p_msc MSC instance.
  1286. * @param[in] p_msc_ctx MSC context.
  1287. * @return Standard error code.
  1288. * */
  1289. static ret_code_t cmd_senddiagnostic(app_usbd_class_inst_t const * p_inst,
  1290. app_usbd_msc_t const * p_msc,
  1291. app_usbd_msc_ctx_t * p_msc_ctx)
  1292. {
  1293. NRF_LOG_DEBUG("CMD: SENDDIAGNOSTIC");
  1294. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  1295. }
  1296. /**
  1297. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_PREVENTMEDIAREMOVAL handle.
  1298. *
  1299. * @param[in] p_inst Generic class instance.
  1300. * @param[in] p_msc MSC instance.
  1301. * @param[in] p_msc_ctx MSC context.
  1302. * @return Standard error code.
  1303. * */
  1304. static ret_code_t cmd_preventremoval(app_usbd_class_inst_t const * p_inst,
  1305. app_usbd_msc_t const * p_msc,
  1306. app_usbd_msc_ctx_t * p_msc_ctx)
  1307. {
  1308. NRF_LOG_DEBUG("CMD: PREVENTMEDIAREMOVAL");
  1309. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  1310. }
  1311. /**
  1312. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_READCAPACITY10 handle.
  1313. *
  1314. * @param[in] p_inst Generic class instance.
  1315. * @param[in] p_msc MSC instance.
  1316. * @param[in] p_msc_ctx MSC context.
  1317. * @return Standard error code.
  1318. * */
  1319. static ret_code_t cmd_readcapacity10(app_usbd_class_inst_t const * p_inst,
  1320. app_usbd_msc_t const * p_msc,
  1321. app_usbd_msc_ctx_t * p_msc_ctx)
  1322. {
  1323. NRF_LOG_DEBUG("CMD: READCAPACITY10");
  1324. app_usbd_scsi_cmd_readcapacity10_t const * p_cap10 = (const void *)p_msc_ctx->cbw.cdb;
  1325. UNUSED_VARIABLE(p_cap10);
  1326. if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_readcapacity10_t))
  1327. {
  1328. return status_unsupported_start(p_inst);
  1329. }
  1330. if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_readcapacity10_resp_t))
  1331. {
  1332. return status_unsupported_start(p_inst);
  1333. }
  1334. uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
  1335. if (resp_len == 0)
  1336. {
  1337. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  1338. }
  1339. nrf_block_dev_t const * p_blkd =
  1340. p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
  1341. nrf_block_dev_geometry_t const * p_geometry = nrf_blk_dev_geometry(p_blkd);
  1342. UNUSED_RETURN_VALUE(
  1343. uint32_big_encode(p_geometry->blk_count - 1, p_msc_ctx->scsi_resp.readcapacity10.lba));
  1344. UNUSED_RETURN_VALUE(
  1345. uint32_big_encode(p_geometry->blk_size, p_msc_ctx->scsi_resp.readcapacity10.blklen));
  1346. return transfer_in_start(p_inst,
  1347. &p_msc_ctx->scsi_resp,
  1348. resp_len,
  1349. APP_USBD_MSC_STATE_CMD_IN);
  1350. }
  1351. /**
  1352. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_READ10 handle.
  1353. *
  1354. * @param[in] p_inst Generic class instance.
  1355. * @param[in] p_msc MSC instance.
  1356. * @param[in] p_msc_ctx MSC context.
  1357. * @return Standard error code.
  1358. * */
  1359. static ret_code_t cmd_read10(app_usbd_class_inst_t const * p_inst,
  1360. app_usbd_msc_t const * p_msc,
  1361. app_usbd_msc_ctx_t * p_msc_ctx)
  1362. {
  1363. NRF_LOG_DEBUG("CMD: READ10");
  1364. app_usbd_scsi_cmd_read10_t const * p_read10 = (const void *)p_msc_ctx->cbw.cdb;
  1365. if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_read10_t))
  1366. {
  1367. return status_unsupported_start(p_inst);
  1368. }
  1369. nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
  1370. uint32_t blk_size = nrf_blk_dev_geometry(p_blkd)->blk_size;
  1371. uint16_t blocks = uint16_big_decode(p_read10->xfrlen);
  1372. p_msc_ctx->current.process.blk_idx = uint32_big_decode(p_read10->lba);
  1373. p_msc_ctx->current.process.blk_size = blk_size;
  1374. p_msc_ctx->current.process.size_left = blocks * blk_size;
  1375. return cmd_read_start(p_inst, p_msc, p_msc_ctx);
  1376. }
  1377. /**
  1378. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_WRITE10 handle.
  1379. *
  1380. * @param[in] p_inst Generic class instance.
  1381. * @param[in] p_msc MSC instance.
  1382. * @param[in] p_msc_ctx MSC context.
  1383. * @return Standard error code.
  1384. * */
  1385. static ret_code_t cmd_write10(app_usbd_class_inst_t const * p_inst,
  1386. app_usbd_msc_t const * p_msc,
  1387. app_usbd_msc_ctx_t * p_msc_ctx)
  1388. {
  1389. NRF_LOG_DEBUG("CMD: WRITE10");
  1390. app_usbd_scsi_cmd_write10_t const * p_write10 = (const void *)p_msc_ctx->cbw.cdb;
  1391. if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_write10_t))
  1392. {
  1393. return status_unsupported_start(p_inst);
  1394. }
  1395. nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
  1396. uint32_t blk_size = nrf_blk_dev_geometry(p_blkd)->blk_size;
  1397. uint16_t blocks = uint16_big_decode(p_write10->xfrlen);
  1398. p_msc_ctx->current.process.blk_idx = uint32_big_decode(p_write10->lba);
  1399. p_msc_ctx->current.process.blk_size = blk_size;
  1400. p_msc_ctx->current.process.size_left = blocks * blk_size;
  1401. return cmd_write_start(p_inst, p_msc, p_msc_ctx);
  1402. }
  1403. /**
  1404. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_MODESELECT10 handle.
  1405. *
  1406. * @param[in] p_inst Generic class instance.
  1407. * @param[in] p_msc MSC instance.
  1408. * @param[in] p_msc_ctx MSC context.
  1409. * @return Standard error code.
  1410. * */
  1411. static ret_code_t cmd_modeselect10(app_usbd_class_inst_t const * p_inst,
  1412. app_usbd_msc_t const * p_msc,
  1413. app_usbd_msc_ctx_t * p_msc_ctx)
  1414. {
  1415. NRF_LOG_DEBUG("CMD: MODESELECT10");
  1416. return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  1417. }
  1418. /**
  1419. * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_MODESENSE10 handle.
  1420. *
  1421. * @param[in] p_inst Generic class instance.
  1422. * @param[in] p_msc MSC instance.
  1423. * @param[in] p_msc_ctx MSC context.
  1424. * @return Standard error code.
  1425. * */
  1426. static ret_code_t cmd_modesense10(app_usbd_class_inst_t const * p_inst,
  1427. app_usbd_msc_t const * p_msc,
  1428. app_usbd_msc_ctx_t * p_msc_ctx)
  1429. {
  1430. NRF_LOG_DEBUG("CMD: MODESENSE10");
  1431. app_usbd_scsi_cmd_modesense10_t const * p_sense10 = (const void *)p_msc_ctx->cbw.cdb;
  1432. UNUSED_VARIABLE(p_sense10);
  1433. if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_modesense10_t))
  1434. {
  1435. return status_unsupported_start(p_inst);
  1436. }
  1437. if (p_msc_ctx->cbw.lun >= p_msc->specific.inst.block_devs_count)
  1438. {
  1439. return status_unsupported_start(p_inst);
  1440. }
  1441. if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_modesense6_resp_t))
  1442. {
  1443. return status_unsupported_start(p_inst);
  1444. }
  1445. uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
  1446. app_usbd_scsi_cmd_modesense10_resp_t * p_resp = &p_msc_ctx->scsi_resp.modesense10;
  1447. memset(p_resp, 0, sizeof(app_usbd_scsi_cmd_modesense10_resp_t));
  1448. uint16_t len = sizeof(app_usbd_scsi_cmd_modesense10_resp_t) - sizeof(p_resp->mdlen);
  1449. p_resp->mdlen[1] = len & 0xff;
  1450. p_resp->mdlen[0] = (len >> 8) & 0xff;
  1451. return transfer_in_start(p_inst,
  1452. &p_msc_ctx->scsi_resp,
  1453. resp_len,
  1454. APP_USBD_MSC_STATE_CMD_IN);
  1455. }
  1456. /**
  1457. * @brief Get the size of the last OUT transfer.
  1458. *
  1459. * @param p_inst Generic class instance.
  1460. *
  1461. * @return Number of received bytes or 0 if none.
  1462. */
  1463. static size_t get_last_out_size(app_usbd_class_inst_t const * p_inst)
  1464. {
  1465. nrf_drv_usbd_ep_t ep = ep_out_addr_get(p_inst);
  1466. size_t size;
  1467. ret_code_t ret = nrf_drv_usbd_ep_status_get(ep, &size);
  1468. if (ret != NRF_SUCCESS)
  1469. {
  1470. size = 0;
  1471. }
  1472. return size;
  1473. }
  1474. /**
  1475. * @brief SCSI Command Block Wrapper handler.
  1476. *
  1477. * @param[in] p_inst Generic class instance.
  1478. * @return Standard error code.
  1479. * */
  1480. static ret_code_t state_cbw(app_usbd_class_inst_t const * p_inst)
  1481. {
  1482. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  1483. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  1484. memset(&p_msc_ctx->current, 0, sizeof(p_msc_ctx->current));
  1485. memset( p_msc_ctx->csw.tag, 0, sizeof(p_msc_ctx->csw.tag));
  1486. /*Verify the transfer size*/
  1487. if (get_last_out_size(p_inst) != sizeof(app_usbd_msc_cbw_t))
  1488. {
  1489. NRF_LOG_DEBUG("CMD: size error: %u", get_last_out_size(p_inst));
  1490. status_cbwinvalid_start(p_inst);
  1491. return NRF_SUCCESS;
  1492. }
  1493. /*Verify CBW signature*/
  1494. if (memcmp(p_msc_ctx->cbw.signature,
  1495. m_cbw_signature,
  1496. sizeof(m_cbw_signature)) != 0)
  1497. {
  1498. NRF_LOG_DEBUG("CMD: header error: 0x%02x%02x%02x%02x",
  1499. p_msc_ctx->cbw.signature[0], p_msc_ctx->cbw.signature[1],
  1500. p_msc_ctx->cbw.signature[2], p_msc_ctx->cbw.signature[3]);
  1501. status_cbwinvalid_start(p_inst);
  1502. return NRF_SUCCESS;
  1503. }
  1504. /*Prepare the response*/
  1505. memcpy(p_msc_ctx->csw.tag, p_msc_ctx->cbw.tag, sizeof(p_msc_ctx->csw.tag));
  1506. p_msc_ctx->csw.status = APP_USBD_MSC_CSW_STATUS_PASS;
  1507. p_msc_ctx->current.process.lun = p_msc_ctx->cbw.lun;
  1508. p_msc_ctx->current.process.datalen_left = uint32_decode(p_msc_ctx->cbw.datlen);
  1509. if (p_msc_ctx->current.process.lun >= p_msc->specific.inst.block_devs_count)
  1510. {
  1511. NRF_LOG_WARNING("Unsupported LUN");
  1512. return status_unsupported_start(p_inst);
  1513. }
  1514. ret_code_t ret = NRF_SUCCESS;
  1515. switch (p_msc_ctx->cbw.cdb[0])
  1516. {
  1517. case APP_USBD_SCSI_CMD_TESTUNITREADY:
  1518. ret = cmd_testunitready(p_inst, p_msc, p_msc_ctx);
  1519. break;
  1520. case APP_USBD_SCSI_CMD_REQUESTSENSE:
  1521. ret = cmd_requestsense(p_inst, p_msc, p_msc_ctx);
  1522. break;
  1523. case APP_USBD_SCSI_CMD_FORMAT_UNIT:
  1524. ret = cmd_formatunit(p_inst, p_msc, p_msc_ctx);
  1525. break;
  1526. case APP_USBD_SCSI_CMD_READ6:
  1527. ret = cmd_read6(p_inst, p_msc, p_msc_ctx);
  1528. break;
  1529. case APP_USBD_SCSI_CMD_WRITE6:
  1530. ret = cmd_write6(p_inst, p_msc, p_msc_ctx);
  1531. break;
  1532. case APP_USBD_SCSI_CMD_INQUIRY:
  1533. ret = cmd_inquiry(p_inst, p_msc, p_msc_ctx);
  1534. break;
  1535. case APP_USBD_SCSI_CMD_MODESELECT6:
  1536. ret = cmd_modeselect6(p_inst, p_msc, p_msc_ctx);
  1537. break;
  1538. case APP_USBD_SCSI_CMD_MODESENSE6:
  1539. ret = cmd_modesense6(p_inst, p_msc, p_msc_ctx);
  1540. break;
  1541. case APP_USBD_SCSI_CMD_STARTSTOPUNIT:
  1542. ret = cmd_startstopunit(p_inst, p_msc, p_msc_ctx);
  1543. break;
  1544. case APP_USBD_SCSI_CMD_SENDDIAGNOSTIC:
  1545. ret = cmd_senddiagnostic(p_inst, p_msc, p_msc_ctx);
  1546. break;
  1547. case APP_USBD_SCSI_CMD_PREVENTMEDIAREMOVAL:
  1548. ret = cmd_preventremoval(p_inst, p_msc, p_msc_ctx);
  1549. break;
  1550. case APP_USBD_SCSI_CMD_READCAPACITY10:
  1551. ret = cmd_readcapacity10(p_inst, p_msc, p_msc_ctx);
  1552. break;
  1553. case APP_USBD_SCSI_CMD_READ10:
  1554. ret = cmd_read10(p_inst, p_msc, p_msc_ctx);
  1555. break;
  1556. case APP_USBD_SCSI_CMD_WRITE10:
  1557. ret = cmd_write10(p_inst, p_msc, p_msc_ctx);
  1558. break;
  1559. case APP_USBD_SCSI_CMD_MODESELECT10:
  1560. ret = cmd_modeselect10(p_inst, p_msc, p_msc_ctx);
  1561. break;
  1562. case APP_USBD_SCSI_CMD_MODESENSE10:
  1563. ret = cmd_modesense10(p_inst, p_msc, p_msc_ctx);
  1564. break;
  1565. default:
  1566. NRF_LOG_DEBUG("CMD: UNSUPPORTED");
  1567. NRF_LOG_HEXDUMP_DEBUG(&(p_msc_ctx->cbw), sizeof(p_msc_ctx->cbw));
  1568. if (uint32_decode(p_msc_ctx->cbw.datlen) != 0)
  1569. {
  1570. ret = status_unsupported_start(p_inst);
  1571. }
  1572. else
  1573. {
  1574. ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
  1575. }
  1576. break;
  1577. }
  1578. return ret;
  1579. }
  1580. /**
  1581. * @brief Mark transfer block process.
  1582. *
  1583. * Common part of the @ref state_data_in_handle and @ref state_data_out_handle
  1584. * that marks the current transfer state.
  1585. *
  1586. * @param p_msc_ctx MSC context.
  1587. * @param size Number of bytes transfered.
  1588. */
  1589. static void state_data_in_out_process(app_usbd_msc_ctx_t * p_msc_ctx, size_t size)
  1590. {
  1591. p_msc_ctx->current.transfer.pending = false;
  1592. p_msc_ctx->current.transfer.size_left =
  1593. SUB_SAT0(p_msc_ctx->current.transfer.size_left, size);
  1594. p_msc_ctx->current.transfer.datalen_left =
  1595. SUB_SAT0(p_msc_ctx->current.transfer.datalen_left, size);
  1596. }
  1597. /**
  1598. * @brief Handle read6/read10 command data stage.
  1599. *
  1600. * @param[in] p_inst Generic class instance.
  1601. * @param[in] size Number of bytes sent.
  1602. *
  1603. * @return Standard error code.
  1604. */
  1605. static ret_code_t state_data_in_handle(app_usbd_class_inst_t const * p_inst, size_t size)
  1606. {
  1607. ret_code_t ret;
  1608. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  1609. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  1610. NRF_LOG_DEBUG("APP_USBD_MSC_STATE_DATA_IN");
  1611. /* For the in transfer direction, correctly transfered block have to match */
  1612. ASSERT(current_size_calc(p_msc, p_msc_ctx->current.transfer.size_left) == size);
  1613. /* Mark the fact the transfer block has been transfered */
  1614. state_data_in_out_process(p_msc_ctx, size);
  1615. msc_buff_free(p_msc);
  1616. ret = read_transfer_processor(p_inst);
  1617. if(ret == NRF_SUCCESS)
  1618. {
  1619. ret = read_blockmem_processor(p_inst);
  1620. }
  1621. if (ret != NRF_SUCCESS)
  1622. {
  1623. UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
  1624. }
  1625. return ret;
  1626. }
  1627. /**
  1628. * @brief Endpoint IN event handler.
  1629. *
  1630. * @param[in] p_inst Generic class instance.
  1631. * @param[in] p_setup_ev Setup event.
  1632. *
  1633. * @return Standard error code.
  1634. */
  1635. static ret_code_t endpoint_in_event_handler(app_usbd_class_inst_t const * p_inst,
  1636. app_usbd_complex_evt_t const * p_event)
  1637. {
  1638. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  1639. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  1640. size_t size;
  1641. NRF_LOG_DEBUG("state: %d, ep in event, status: %d",
  1642. p_msc_ctx->state,
  1643. p_event->drv_evt.data.eptransfer.status);
  1644. if (NRF_SUCCESS != nrf_drv_usbd_ep_status_get(p_event->drv_evt.data.eptransfer.ep, &size))
  1645. {
  1646. size = 0;
  1647. }
  1648. if (p_event->drv_evt.data.eptransfer.status != NRF_USBD_EP_OK)
  1649. {
  1650. return NRF_SUCCESS;
  1651. }
  1652. ret_code_t ret = NRF_SUCCESS;
  1653. switch (p_msc_ctx->state)
  1654. {
  1655. case APP_USBD_MSC_STATE_CMD_IN:
  1656. {
  1657. p_msc_ctx->current.process.datalen_left -= size;
  1658. ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
  1659. break;
  1660. }
  1661. case APP_USBD_MSC_STATE_DATA_IN:
  1662. {
  1663. ret = state_data_in_handle(p_inst, size);
  1664. break;
  1665. }
  1666. case APP_USBD_MSC_STATE_CSW:
  1667. {
  1668. break;
  1669. }
  1670. case APP_USBD_MSC_STATE_DATA_OUT:
  1671. {
  1672. break;
  1673. }
  1674. case APP_USBD_MSC_STATE_UNSUPPORTED:
  1675. {
  1676. ret = NRF_ERROR_NOT_SUPPORTED;
  1677. break;
  1678. }
  1679. default:
  1680. {
  1681. ret = NRF_ERROR_INTERNAL;
  1682. break;
  1683. }
  1684. }
  1685. return ret;
  1686. }
  1687. /**
  1688. * @brief Handle write6/write10 command data stage.
  1689. *
  1690. * @param[in] p_inst Generic class instance.
  1691. * @param[in] size Number of bytes received.
  1692. *
  1693. * @return Standard error code.
  1694. * @retval NRF_SUCCESS Request handled correctly.
  1695. * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
  1696. */
  1697. static ret_code_t state_data_out_handle(app_usbd_class_inst_t const * p_inst, size_t size)
  1698. {
  1699. ret_code_t ret = NRF_SUCCESS;
  1700. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  1701. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  1702. NRF_LOG_DEBUG("APP_USBD_MSC_STATE_DATA_OUT");
  1703. /* For the OUT transfer direction we may get less than we expected */
  1704. if (current_size_calc(p_msc, p_msc_ctx->current.transfer.size_left) != size)
  1705. {
  1706. p_msc_ctx->current.process.abort = true;
  1707. }
  1708. /* Mark the fact the transfer block has been transfered */
  1709. state_data_in_out_process(p_msc_ctx, size);
  1710. msc_buff_put(p_msc);
  1711. ret = write_transfer_processor(p_inst);
  1712. if(ret == NRF_SUCCESS)
  1713. {
  1714. ret = write_blockmem_processor(p_inst);
  1715. }
  1716. if (ret != NRF_SUCCESS)
  1717. {
  1718. UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
  1719. }
  1720. return ret;
  1721. }
  1722. /**
  1723. * @brief Endpoint OUT event handler.
  1724. *
  1725. * @param[in] p_inst Generic class instance.
  1726. * @param[in] p_setup_ev Setup event.
  1727. *
  1728. * @return Standard error code.
  1729. * @retval NRF_SUCCESS Request handled correctly.
  1730. * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
  1731. */
  1732. static ret_code_t endpoint_out_event_handler(app_usbd_class_inst_t const * p_inst,
  1733. app_usbd_complex_evt_t const * p_event)
  1734. {
  1735. ret_code_t ret = NRF_SUCCESS;
  1736. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  1737. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  1738. size_t size;
  1739. NRF_LOG_DEBUG("state: %d, ep out event, status: %d",
  1740. p_msc_ctx->state,
  1741. p_event->drv_evt.data.eptransfer.status);
  1742. if (NRF_SUCCESS != nrf_drv_usbd_ep_status_get(p_event->drv_evt.data.eptransfer.ep, &size))
  1743. {
  1744. size = 0;
  1745. }
  1746. if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_WAITING)
  1747. {
  1748. if (p_msc_ctx->state == APP_USBD_MSC_STATE_DATA_OUT)
  1749. {
  1750. NRF_LOG_DEBUG("NRF_USBD_EP_WAITING");
  1751. }
  1752. else if (p_msc_ctx->state == APP_USBD_MSC_STATE_CSW ||
  1753. p_msc_ctx->state == APP_USBD_MSC_STATE_IDLE)
  1754. {
  1755. ret = cbw_wait_start(p_inst);
  1756. }
  1757. return ret;
  1758. }
  1759. else if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_ABORTED)
  1760. {
  1761. p_msc_ctx->state = APP_USBD_MSC_STATE_IDLE;
  1762. return NRF_SUCCESS;
  1763. }
  1764. else if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_OVERLOAD)
  1765. {
  1766. NRF_LOG_ERROR("Data overload");
  1767. switch (p_msc_ctx->state)
  1768. {
  1769. case APP_USBD_MSC_STATE_DATA_OUT:
  1770. {
  1771. status_deverror_start(p_inst);
  1772. break;
  1773. }
  1774. /* Default action is the same like CBW - stall totally until bulk reset */
  1775. case APP_USBD_MSC_STATE_CBW:
  1776. default:
  1777. {
  1778. status_cbwinvalid_start(p_inst);
  1779. break;
  1780. }
  1781. }
  1782. return NRF_SUCCESS;
  1783. }
  1784. else /*NRF_USBD_EP_OK*/
  1785. {
  1786. switch (p_msc_ctx->state)
  1787. {
  1788. case APP_USBD_MSC_STATE_CBW:
  1789. {
  1790. ret = state_cbw(p_inst);
  1791. break;
  1792. }
  1793. case APP_USBD_MSC_STATE_DATA_OUT:
  1794. {
  1795. CRITICAL_REGION_ENTER();
  1796. ret = state_data_out_handle(p_inst, size);
  1797. CRITICAL_REGION_EXIT();
  1798. break;
  1799. }
  1800. case APP_USBD_MSC_STATE_UNSUPPORTED:
  1801. {
  1802. ret = NRF_ERROR_NOT_SUPPORTED;
  1803. break;
  1804. }
  1805. case APP_USBD_MSC_STATE_CSW:
  1806. break;
  1807. default:
  1808. {
  1809. ASSERT(0);
  1810. ret = NRF_ERROR_NOT_SUPPORTED;
  1811. break;
  1812. }
  1813. }
  1814. }
  1815. NRF_LOG_DEBUG("Ep proc status: %d", ret);
  1816. return ret;
  1817. }
  1818. /**
  1819. * @brief @ref app_usbd_class_methods_t::event_handler
  1820. */
  1821. static ret_code_t msc_event_handler(app_usbd_class_inst_t const * p_inst,
  1822. app_usbd_complex_evt_t const * p_event)
  1823. {
  1824. ASSERT(p_inst != NULL);
  1825. ASSERT(p_event != NULL);
  1826. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  1827. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  1828. UNUSED_VARIABLE(p_msc);
  1829. UNUSED_VARIABLE(p_msc_ctx);
  1830. ret_code_t ret = NRF_SUCCESS;
  1831. switch (p_event->app_evt.type)
  1832. {
  1833. case APP_USBD_EVT_DRV_SOF:
  1834. break;
  1835. case APP_USBD_EVT_DRV_RESET:
  1836. /* Initialize */
  1837. memset(p_msc_ctx, 0, sizeof(app_usbd_msc_csw_t));
  1838. /* Configure the CSW signature as it should never be changed when software works */
  1839. memcpy(p_msc_ctx->csw.signature, m_csw_signature, sizeof(m_csw_signature));
  1840. break;
  1841. case APP_USBD_EVT_DRV_SETUP:
  1842. ret = setup_event_handler(p_inst, (app_usbd_setup_evt_t const *)p_event);
  1843. break;
  1844. case APP_USBD_EVT_DRV_EPTRANSFER:
  1845. if (NRF_USBD_EPIN_CHECK(p_event->drv_evt.data.eptransfer.ep))
  1846. {
  1847. ret = endpoint_in_event_handler(p_inst, p_event);
  1848. }
  1849. else
  1850. {
  1851. ret = endpoint_out_event_handler(p_inst, p_event);
  1852. }
  1853. break;
  1854. case APP_USBD_EVT_DRV_SUSPEND:
  1855. {
  1856. /*Flush all block devices cache on suspend*/
  1857. for (size_t i = 0; i < p_msc->specific.inst.block_devs_count; ++i)
  1858. {
  1859. nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[i];
  1860. (void)nrf_blk_dev_ioctl(p_blkd, NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH, NULL);
  1861. }
  1862. break;
  1863. }
  1864. case APP_USBD_EVT_DRV_RESUME:
  1865. break;
  1866. case APP_USBD_EVT_INST_APPEND:
  1867. {
  1868. /*Verify serial number string*/
  1869. uint16_t const * p_serial_str = app_usbd_string_desc_get(APP_USBD_STRING_ID_SERIAL, 0);
  1870. if (p_serial_str == NULL)
  1871. {
  1872. return NRF_ERROR_NOT_SUPPORTED;
  1873. }
  1874. size_t len = app_usbd_string_desc_length(p_serial_str) / sizeof(uint16_t);
  1875. if (len < APP_USBD_MSC_MINIMAL_SERIAL_STRING_SIZE)
  1876. {
  1877. return NRF_ERROR_NOT_SUPPORTED;
  1878. }
  1879. for (size_t i = 1; i < len; ++i)
  1880. {
  1881. if (isxdigit(p_serial_str[i]) == 0)
  1882. {
  1883. return NRF_ERROR_NOT_SUPPORTED;
  1884. }
  1885. }
  1886. break;
  1887. }
  1888. case APP_USBD_EVT_INST_REMOVE:
  1889. {
  1890. break;
  1891. }
  1892. case APP_USBD_EVT_STARTED:
  1893. {
  1894. /*Initialize all block devices*/
  1895. ASSERT(p_msc->specific.inst.block_devs_count <= 16);
  1896. for (size_t i = 0; i < p_msc->specific.inst.block_devs_count; ++i)
  1897. {
  1898. nrf_block_dev_t const * p_blk_dev = p_msc->specific.inst.pp_block_devs[i];
  1899. ret = nrf_blk_dev_init(p_blk_dev, msc_blockdev_ev_handler, p_msc);
  1900. if (ret != NRF_SUCCESS)
  1901. {
  1902. continue;
  1903. }
  1904. p_msc_ctx->blk_dev_init_mask |= 1u << i;
  1905. ASSERT(nrf_blk_dev_geometry(p_blk_dev)->blk_size <=
  1906. p_msc->specific.inst.block_buff_size);
  1907. }
  1908. break;
  1909. }
  1910. case APP_USBD_EVT_STOPPED:
  1911. {
  1912. /*Un-initialize all block devices*/
  1913. ASSERT(p_msc->specific.inst.block_devs_count <= 16);
  1914. size_t i;
  1915. for (i = 0; i < p_msc->specific.inst.block_devs_count; ++i)
  1916. {
  1917. nrf_block_dev_t const * p_blk_dev = p_msc->specific.inst.pp_block_devs[i];
  1918. ret = nrf_blk_dev_uninit(p_blk_dev);
  1919. if (ret != NRF_SUCCESS)
  1920. {
  1921. continue;
  1922. }
  1923. p_msc_ctx->blk_dev_init_mask &= ~(1u << i);
  1924. }
  1925. break;
  1926. }
  1927. default:
  1928. ret = NRF_ERROR_NOT_SUPPORTED;
  1929. break;
  1930. }
  1931. return ret;
  1932. }
  1933. /**
  1934. * @brief @ref app_usbd_class_methods_t::feed_descriptors
  1935. */
  1936. static bool msc_feed_descriptors(app_usbd_class_descriptor_ctx_t * p_ctx,
  1937. app_usbd_class_inst_t const * p_inst,
  1938. uint8_t * p_buff,
  1939. size_t max_size)
  1940. {
  1941. static uint8_t ifaces = 0;
  1942. ifaces = app_usbd_class_iface_count_get(p_inst);
  1943. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  1944. APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size);
  1945. static uint8_t i = 0;
  1946. for (i = 0; i < ifaces; i++)
  1947. {
  1948. /* INTERFACE DESCRIPTOR */
  1949. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength
  1950. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType = Interface
  1951. static app_usbd_class_iface_conf_t const * p_cur_iface = NULL;
  1952. p_cur_iface = app_usbd_class_iface_get(p_inst, i);
  1953. APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_number_get(p_cur_iface)); // bInterfaceNumber
  1954. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bAlternateSetting
  1955. APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_ep_count_get(p_cur_iface)); // bNumEndpoints
  1956. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_MSC_CLASS); // bInterfaceClass = MSC
  1957. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_msc->specific.inst.subclass); // bInterfaceSubclass (Industry Standard Command Block)
  1958. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_msc->specific.inst.protocol); // bInterfaceProtocol
  1959. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface
  1960. static uint8_t endpoints = 0;
  1961. endpoints = app_usbd_class_iface_ep_count_get(p_cur_iface);
  1962. static uint8_t j = 0;
  1963. for (j = 0; j < endpoints; j++)
  1964. {
  1965. // ENDPOINT DESCRIPTOR
  1966. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x07); // bLength
  1967. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_ENDPOINT); // bDescriptorType = Endpoint
  1968. static app_usbd_class_ep_conf_t const * p_cur_ep = NULL;
  1969. p_cur_ep = app_usbd_class_iface_ep_get(p_cur_iface, j);
  1970. APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_ep_address_get(p_cur_ep)); // bEndpointAddress
  1971. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK); // bmAttributes
  1972. APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize LSB
  1973. APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize MSB
  1974. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterval
  1975. }
  1976. }
  1977. APP_USBD_CLASS_DESCRIPTOR_END();
  1978. }
  1979. const app_usbd_class_methods_t app_usbd_msc_class_methods = {
  1980. .event_handler = msc_event_handler,
  1981. .feed_descriptors = msc_feed_descriptors,
  1982. };
  1983. /**
  1984. * @brief Mark block device process.
  1985. *
  1986. * Common part of the @ref msc_blockdev_read_done_handler and @ref msc_blockdev_write_done_handler
  1987. * that marks the current processing state.
  1988. *
  1989. * @param p_blk_dev Block device handle.
  1990. * @param p_event Block device event.
  1991. */
  1992. static void msc_blockdev_done_process(nrf_block_dev_t const * p_blk_dev,
  1993. nrf_block_dev_event_t const * p_event)
  1994. {
  1995. app_usbd_class_inst_t const * p_inst = p_event->p_context;
  1996. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  1997. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  1998. uint32_t blk_count = p_event->p_blk_req->blk_count;
  1999. uint32_t size = blk_count * p_msc_ctx->current.process.blk_size;
  2000. p_msc_ctx->current.process.blk_idx += blk_count;
  2001. p_msc_ctx->current.process.size_left =
  2002. SUB_SAT0(p_msc_ctx->current.process.size_left, size);
  2003. p_msc_ctx->current.process.datalen_left =
  2004. SUB_SAT0(p_msc_ctx->current.process.datalen_left, size);
  2005. p_msc_ctx->current.process.pending = false;
  2006. }
  2007. /**
  2008. * @brief Block device read done event handler.
  2009. *
  2010. * @ref NRF_BLOCK_DEV_EVT_BLK_READ_DONE
  2011. *
  2012. * @param p_blk_dev Block device handle.
  2013. * @param p_event Block device event.
  2014. *
  2015. * */
  2016. static void msc_blockdev_read_done_handler(nrf_block_dev_t const * p_blk_dev,
  2017. nrf_block_dev_event_t const * p_event)
  2018. {
  2019. ret_code_t ret;
  2020. app_usbd_class_inst_t const * p_inst = p_event->p_context;
  2021. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  2022. app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
  2023. NRF_LOG_DEBUG("read_done_handler: p_buff: %p, size: %u",
  2024. (uint32_t)p_event->p_blk_req->p_buff,
  2025. p_event->p_blk_req->blk_count);
  2026. msc_buff_put(p_msc);
  2027. if (p_event->result == NRF_BLOCK_DEV_RESULT_SUCCESS)
  2028. {
  2029. msc_blockdev_done_process(p_blk_dev, p_event);
  2030. }
  2031. else
  2032. {
  2033. p_msc_ctx->current.transfer.abort = true;
  2034. }
  2035. ret = read_transfer_processor(p_inst);
  2036. if(ret == NRF_SUCCESS)
  2037. {
  2038. ret = read_blockmem_processor(p_inst);
  2039. }
  2040. if (ret != NRF_SUCCESS)
  2041. {
  2042. UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
  2043. }
  2044. }
  2045. /**
  2046. * @brief Block device write done event handler.
  2047. *
  2048. * @ref NRF_BLOCK_DEV_EVT_BLK_WRITE_DONE
  2049. *
  2050. * @param p_blk_dev Block device handle.
  2051. * @param p_event Block device event.
  2052. *
  2053. * */
  2054. static void msc_blockdev_write_done_handler(nrf_block_dev_t const * p_blk_dev,
  2055. nrf_block_dev_event_t const * p_event)
  2056. {
  2057. ret_code_t ret;
  2058. app_usbd_class_inst_t const * p_inst = p_event->p_context;
  2059. app_usbd_msc_t const * p_msc = msc_get(p_inst);
  2060. NRF_LOG_DEBUG("write_done_handler: p_buff: %p, size: %u",
  2061. (uint32_t)p_event->p_blk_req->p_buff,
  2062. p_event->p_blk_req->blk_count);
  2063. msc_buff_free(p_msc);
  2064. if (p_event->result == NRF_BLOCK_DEV_RESULT_SUCCESS)
  2065. {
  2066. msc_blockdev_done_process(p_blk_dev, p_event);
  2067. }
  2068. else
  2069. {
  2070. UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
  2071. }
  2072. ret = write_transfer_processor(p_inst);
  2073. if(ret == NRF_SUCCESS)
  2074. {
  2075. ret = write_blockmem_processor(p_inst);
  2076. }
  2077. if (ret != NRF_SUCCESS)
  2078. {
  2079. UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
  2080. }
  2081. }
  2082. /**
  2083. * @brief Block device event handler.
  2084. *
  2085. * Mass storage block device event handler. Need to be pined to all block devices
  2086. * from initializer list.
  2087. *
  2088. * @param p_blk_dev Block device handle.
  2089. * @param p_event Block device event.
  2090. *
  2091. * */
  2092. static void msc_blockdev_ev_handler(nrf_block_dev_t const * p_blk_dev,
  2093. nrf_block_dev_event_t const * p_event)
  2094. {
  2095. switch (p_event->ev_type)
  2096. {
  2097. case NRF_BLOCK_DEV_EVT_INIT:
  2098. break;
  2099. case NRF_BLOCK_DEV_EVT_UNINIT:
  2100. break;
  2101. case NRF_BLOCK_DEV_EVT_BLK_READ_DONE:
  2102. CRITICAL_REGION_ENTER();
  2103. msc_blockdev_read_done_handler(p_blk_dev, p_event);
  2104. CRITICAL_REGION_EXIT();
  2105. break;
  2106. case NRF_BLOCK_DEV_EVT_BLK_WRITE_DONE:
  2107. CRITICAL_REGION_ENTER();
  2108. msc_blockdev_write_done_handler(p_blk_dev, p_event);
  2109. CRITICAL_REGION_EXIT();
  2110. break;
  2111. default:
  2112. break;
  2113. }
  2114. }
  2115. /** @} */
  2116. bool app_usbd_msc_sync(app_usbd_msc_t const * p_msc)
  2117. {
  2118. bool rc = true;
  2119. ret_code_t ret = NRF_SUCCESS;
  2120. for (size_t i = 0; i < p_msc->specific.inst.block_devs_count; ++i)
  2121. {
  2122. nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[i];
  2123. bool flush_in_progress = true;
  2124. ret = nrf_blk_dev_ioctl(p_blkd,
  2125. NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH,
  2126. &flush_in_progress);
  2127. if ((ret != NRF_SUCCESS) || flush_in_progress)
  2128. {
  2129. rc = false;
  2130. }
  2131. }
  2132. return rc;
  2133. }
  2134. #endif //NRF_MODULE_ENABLED(APP_USBD_MSC)