12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492 |
- /**
- * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Nordic
- * Semiconductor ASA integrated circuit in a product or a software update for
- * such product, must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 4. This software, with or without modification, must only be used with a
- * Nordic Semiconductor ASA integrated circuit.
- *
- * 5. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include "sdk_common.h"
- #if NRF_MODULE_ENABLED(APP_USBD_MSC)
- #include <string.h>
- #include <ctype.h>
- #include "app_usbd.h"
- #include "app_usbd_msc.h"
- #include "app_usbd_string_desc.h"
- /**
- * @defgroup app_usbd_msc_internal USBD MSC internals
- * @{
- * @ingroup app_usbd_msc
- * @internal
- */
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_requestsense_t) == 6);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_requestsense_resp_t) == 18);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_inquiry_t) == 6);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_inquiry_resp_t) == 36);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_read6_t) == 6);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_write6_t) == 6);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_modesense6_t) == 6);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_modesense6_resp_t) == 4);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_readcapacity10_t) == 10);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_readcapacity10_resp_t) == 8);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_read10_t) == 10);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_write10_t) == 10);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_modesense10_t) == 10);
- STATIC_ASSERT(sizeof(app_usbd_scsi_cmd_modesense10_resp_t) == 8);
- STATIC_ASSERT(sizeof(app_usbd_msc_cbw_t) == 31);
- STATIC_ASSERT(sizeof(app_usbd_msc_csw_t) == 13);
- #define NRF_LOG_MODULE_NAME usbd_msc
- #if APP_USBD_MSC_CONFIG_LOG_ENABLED
- #define NRF_LOG_LEVEL APP_USBD_MSC_CONFIG_LOG_LEVEL
- #define NRF_LOG_INFO_COLOR APP_USBD_MSC_CONFIG_INFO_COLOR
- #define NRF_LOG_DEBUG_COLOR APP_USBD_MSC_CONFIG_DEBUG_COLOR
- #else // APP_USBD_MSC_CONFIG_LOG_ENABLED
- #define NRF_LOG_LEVEL 0
- #endif // APP_USBD_MSC_CONFIG_LOG_ENABLED
- #include "nrf_log.h"
- NRF_LOG_MODULE_REGISTER();
- #define APP_USBD_MSC_IFACE_IDX 0 /**< Mass storage class interface index */
- #define APP_USBD_MSC_EPIN_IDX 0 /**< Mass storage class endpoint IN index */
- #define APP_USBD_MSC_EPOUT_IDX 1 /**< Mass storage class endpoint OUT index */
- /**
- * @brief Set request buffer busy flag.
- *
- * @param[in] val Bitmask to set.
- * @param[in] id Buffer id.
- * */
- #define APP_USBD_MSC_REQ_BUSY_SET(val, id) SET_BIT(val, id)
- /**
- * @brief Clear request buffer busy flag.
- *
- * @param[in] val Bitmask to set.
- * @param[in] id Buffer id.
- * */
- #define APP_USBD_MSC_REQ_BUSY_CLR(val, id) CLR_BIT(val, id)
- #define APP_USBD_MSC_REQ_BUSY_FULL_MASK (0x03) /**< Request busy mask */
- static void msc_blockdev_ev_handler(nrf_block_dev_t const * p_blk_dev,
- nrf_block_dev_event_t const * p_event);
- /** @brief Command Block Wrapper signature */
- static const uint8_t m_cbw_signature[] = APP_USBD_MSC_CBW_SIGNATURE;
- /** @brief Command Status Wrapper signature */
- static const uint8_t m_csw_signature[] = APP_USBD_MSC_CSW_SIGNATURE;
- STATIC_ASSERT(sizeof(m_cbw_signature) == sizeof(((app_usbd_msc_cbw_t*)0)->signature));
- STATIC_ASSERT(sizeof(m_csw_signature) == sizeof(((app_usbd_msc_csw_t*)0)->signature));
- /**
- * @brief Auxiliary function to access MSC instance data.
- *
- * @param[in] p_inst Class instance data.
- *
- * @return MSC instance data @ref app_usbd_msc_t
- */
- static inline app_usbd_msc_t const * msc_get(app_usbd_class_inst_t const * p_inst)
- {
- ASSERT(p_inst != NULL);
- return (app_usbd_msc_t const *)p_inst;
- }
- /**
- * @brief Auxiliary function to access MSC context data.
- *
- * @param[in] p_msc MSC instance data.
- * @return MSC context data @ref app_usbd_msc_ctx_t
- */
- static inline app_usbd_msc_ctx_t * msc_ctx_get(app_usbd_msc_t const * p_msc)
- {
- ASSERT(p_msc != NULL);
- ASSERT(p_msc->specific.p_data != NULL);
- return &p_msc->specific.p_data->ctx;
- }
- /**
- * @brief Auxiliary function to access MSC IN endpoint address.
- *
- * @param[in] p_inst Class instance data.
- *
- * @return IN endpoint address.
- */
- static inline nrf_drv_usbd_ep_t ep_in_addr_get(app_usbd_class_inst_t const * p_inst)
- {
- app_usbd_class_iface_conf_t const * class_iface;
- class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_MSC_IFACE_IDX);
- app_usbd_class_ep_conf_t const * ep_cfg;
- ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_MSC_EPIN_IDX);
- return app_usbd_class_ep_address_get(ep_cfg);
- }
- /**
- * @brief Auxiliary function to access MSC OUT endpoint address.
- *
- * @param[in] p_inst Class instance data.
- *
- * @return OUT endpoint address.
- */
- static inline nrf_drv_usbd_ep_t ep_out_addr_get(app_usbd_class_inst_t const * p_inst)
- {
- app_usbd_class_iface_conf_t const * class_iface;
- class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_MSC_IFACE_IDX);
- app_usbd_class_ep_conf_t const * ep_cfg;
- ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_MSC_EPOUT_IDX);
- return app_usbd_class_ep_address_get(ep_cfg);
- }
- /**
- * @brief Clear the data buffer.
- *
- * @param p_msc MSC instance data.
- */
- static inline void msc_buff_clear(app_usbd_msc_t const * p_msc)
- {
- app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
- p_ctx->current.buff.rd_idx = 0;
- p_ctx->current.buff.d_count = 0;
- p_ctx->current.buff.a_count = 0;
- }
- /**
- * @brief Check if there is any data block ready in the buffer.
- *
- * @param p_msc MSC instance data.
- *
- * @retval true There is data block ready.
- * @retval false There is no data ready for processing.
- */
- static inline bool msc_buff_data_check(app_usbd_msc_t const * p_msc)
- {
- app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
- return (p_ctx->current.buff.d_count > 0);
- }
- /**
- * @brief Check if there is any free space in the buffer.
- *
- * @param p_msc MSC instance data.
- *
- * @retval true There is free space.
- * @retval false There is no free space.
- */
- static inline bool msc_buff_space_check(app_usbd_msc_t const * p_msc)
- {
- app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
- return (p_ctx->current.buff.a_count < p_msc->specific.inst.block_buff_count);
- }
- /**
- * @brief Allocate buffer block.
- *
- * @param p_msc MSC instance data.
- *
- * @return Pointer to a data block or NULL if there is no free space available.
- */
- static inline void * msc_buff_alloc(app_usbd_msc_t const * p_msc)
- {
- app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
- void * p_buff = NULL;
- CRITICAL_REGION_ENTER();
- if (msc_buff_space_check(p_msc))
- {
- uint8_t idx = (p_ctx->current.buff.rd_idx + p_ctx->current.buff.a_count) %
- p_msc->specific.inst.block_buff_count;
- size_t offset = idx * p_msc->specific.inst.block_buff_size;
- p_buff = ((uint8_t*)(p_msc->specific.inst.p_block_buff)) + offset;
- ++(p_ctx->current.buff.a_count);
- }
- NRF_LOG_DEBUG("buff_alloc, idx: %u, dc: %u, ac: %u",
- p_ctx->current.buff.rd_idx,
- p_ctx->current.buff.d_count,
- p_ctx->current.buff.a_count);
- CRITICAL_REGION_EXIT();
- return p_buff;
- }
- /**
- * @brief Put the buffer block.
- *
- * Puts previously allocated buffer and marks it as ready to be processed.
- *
- * @param p_msc MSC instance data.
- *
- * @note This one may be called only if the previous call of
- * @ref msc_buff_alloc succeed.
- */
- static inline void msc_buff_put(app_usbd_msc_t const * p_msc)
- {
- app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
- CRITICAL_REGION_ENTER();
- /* Assert if there is any space - if it is not it means some coding error */
- ASSERT(p_ctx->current.buff.d_count < p_ctx->current.buff.a_count);
- ASSERT(p_ctx->current.buff.d_count < p_msc->specific.inst.block_buff_count);
- ++(p_ctx->current.buff.d_count);
- NRF_LOG_DEBUG("buff_put, idx: %u, dc: %u, ac: %u",
- p_ctx->current.buff.rd_idx,
- p_ctx->current.buff.d_count,
- p_ctx->current.buff.a_count);
- CRITICAL_REGION_EXIT();
- }
- /**
- * @brief Get the data block filled with data.
- *
- * @param p_msc MSC instance data.
- *
- * @return Pointer to the buffer or NULL if there is no data to be processed.
- */
- static inline void * msc_buff_get(app_usbd_msc_t const * p_msc)
- {
- app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
- void * p_buff = NULL;
- CRITICAL_REGION_ENTER();
- if (msc_buff_data_check(p_msc))
- {
- uint8_t idx = p_ctx->current.buff.rd_idx;
- size_t offset = idx * p_msc->specific.inst.block_buff_size;
- p_buff = ((uint8_t*)(p_msc->specific.inst.p_block_buff)) + offset;
- }
- NRF_LOG_DEBUG("buff_get, idx: %u, dc: %u, ac: %u",
- p_ctx->current.buff.rd_idx,
- p_ctx->current.buff.d_count,
- p_ctx->current.buff.a_count);
- CRITICAL_REGION_EXIT();
- return p_buff;
- }
- /**
- * @brief Free the last used data buffer block.
- *
- * Function frees the oldest data block.
- *
- * @param p_msc MSC instance data.
- *
- * @note This one may be called only if the previous call of
- * @ref msc_buff_get succeed.
- */
- static inline void msc_buff_free(app_usbd_msc_t const * p_msc)
- {
- app_usbd_msc_ctx_t * p_ctx = msc_ctx_get(p_msc);
- CRITICAL_REGION_ENTER();
- /* Assert if there is any data - in case there is none, a coding error exists */
- ASSERT(p_ctx->current.buff.d_count > 0);
- ASSERT(p_ctx->current.buff.a_count > 0);
- --(p_ctx->current.buff.d_count);
- --(p_ctx->current.buff.a_count);
- p_ctx->current.buff.rd_idx = (p_ctx->current.buff.rd_idx + 1) %
- p_msc->specific.inst.block_buff_count;
- NRF_LOG_DEBUG("buff_free, idx: %u, dc: %u, ac: %u",
- p_ctx->current.buff.rd_idx,
- p_ctx->current.buff.d_count,
- p_ctx->current.buff.a_count);
- CRITICAL_REGION_EXIT();
- }
- /**
- * @brief Helpful macro to sub a value with zero saturation.
- *
- * @param[in] m The minuend.
- * @param[in] s The subtrahend.
- *
- * @return The difference saturated at 0.
- */
- #define SUB_SAT0(m, s) ((m) < (s)) ? 0 : ((m) - (s))
- /**
- * @brief Command Block Wrapper trigger.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] state Next state transition.
- *
- * @return Standard error code.
- * */
- static ret_code_t cbw_wait_start(app_usbd_class_inst_t const * p_inst)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- nrf_drv_usbd_ep_t ep_addr_out = ep_out_addr_get(p_inst);
- NRF_LOG_DEBUG("cbw_wait_start");
- memset(&p_msc_ctx->cbw, 0, sizeof(app_usbd_msc_cbw_t));
- NRF_DRV_USBD_TRANSFER_OUT(cbw, &p_msc_ctx->cbw, sizeof(app_usbd_msc_cbw_t));
- ret_code_t ret = app_usbd_ep_transfer(ep_addr_out, &cbw);
- if (ret == NRF_SUCCESS)
- {
- p_msc_ctx->state = APP_USBD_MSC_STATE_CBW;
- }
- return ret;
- }
- /**
- * @brief Command Status Wrapper trigger.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] state Next state transition.
- *
- * @return Standard error code.
- * */
- static ret_code_t csw_wait_start(app_usbd_class_inst_t const * p_inst, uint8_t status)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- nrf_drv_usbd_ep_t ep_addr_in = ep_in_addr_get(p_inst);
- NRF_LOG_DEBUG("csw_wait_start: %u", status);
- /* The maximum of this two is already the data that was not processed */
- size_t datalen_left = MAX(
- p_msc_ctx->current.process.datalen_left,
- p_msc_ctx->current.transfer.datalen_left);
- UNUSED_RETURN_VALUE(uint32_encode(datalen_left, p_msc_ctx->csw.residue));
- p_msc_ctx->csw.status = status;
- NRF_DRV_USBD_TRANSFER_IN(csw, &p_msc_ctx->csw, sizeof(app_usbd_msc_csw_t));
- ret_code_t ret = app_usbd_ep_transfer(ep_addr_in, &csw);
- if (ret == NRF_SUCCESS)
- {
- p_msc_ctx->state = APP_USBD_MSC_STATE_CSW;
- }
- return ret;
- }
- /**
- * @brief IN transfer trigger.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_buff IN transfer data buffer.
- * @param[in] size IN transfer size.
- * @param[in] state Next state transition.
- *
- * @return Standard error code.
- * */
- static ret_code_t transfer_in_start(app_usbd_class_inst_t const * p_inst,
- void const * p_buff,
- size_t size,
- app_usbd_msc_state_t state)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- NRF_LOG_DEBUG("transfer_in_start: p_buff: %p, size: %u", (uint32_t)p_buff, size);
- nrf_drv_usbd_ep_t ep_addr_in = ep_in_addr_get(p_inst);
- NRF_DRV_USBD_TRANSFER_IN(resp, p_buff, size);
- ret_code_t ret = app_usbd_ep_transfer(ep_addr_in, &resp);
- if (ret == NRF_SUCCESS)
- {
- p_msc_ctx->state = state;
- }
- return ret;
- }
- /**
- * @brief MSC reset request handler @ref APP_USBD_MSC_REQ_BULK_RESET
- *
- * @param[in] p_inst Generic class instance.
- *
- * */
- static void bulk_ep_reset(app_usbd_class_inst_t const * p_inst)
- {
- nrf_drv_usbd_ep_t ep_addr_in = ep_in_addr_get(p_inst);
- nrf_drv_usbd_ep_t ep_addr_out = ep_out_addr_get(p_inst);
- nrf_drv_usbd_ep_abort(ep_addr_in);
- nrf_drv_usbd_ep_abort(ep_addr_out);
- }
- /**
- * @brief OUT transfer trigger.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_buff OUT transfer data buffer.
- * @param[in] size OUT transfer size.
- * @param[in] state Next state transition.
- *
- * @return Standard error code.
- * */
- static ret_code_t transfer_out_start(app_usbd_class_inst_t const * p_inst,
- void * p_buff,
- size_t size,
- app_usbd_msc_state_t state)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- NRF_LOG_DEBUG("transfer_out_start: p_buff: %p, size: %u", (uint32_t)p_buff, size);
- nrf_drv_usbd_ep_t ep_addr_out = ep_out_addr_get(p_inst);
- NRF_DRV_USBD_TRANSFER_OUT(resp, p_buff, size);
- ret_code_t ret = app_usbd_ep_transfer(ep_addr_out, &resp);
- if (ret == NRF_SUCCESS)
- {
- p_msc_ctx->state = state;
- }
- return ret;
- }
- /**
- * @brief Generic function to stall communication endpoints and mark error state.
- *
- * Function used internally to stall all communication endpoints and mark current state.
- *
- * @param p_inst Generic class instance.
- * @param state State to set.
- */
- static void status_generic_error_stall(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_state_t state)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- nrf_drv_usbd_ep_t ep_in = ep_in_addr_get(p_inst);
- nrf_drv_usbd_ep_t ep_out = ep_out_addr_get(p_inst);
- nrf_drv_usbd_ep_stall(ep_in);
- nrf_drv_usbd_ep_stall(ep_out);
- nrf_drv_usbd_ep_abort(ep_in);
- nrf_drv_usbd_ep_abort(ep_out);
- p_msc_ctx->state = state;
- }
- /**
- * @brief Start status stage of unsupported SCSI command.
- *
- * @param[in,out] p_inst Generic class instance.
- *
- * @return Standard error code.
- *
- * @sa status_generic_error_stall
- */
- static ret_code_t status_unsupported_start(app_usbd_class_inst_t const * p_inst)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- bool data_stage = uint32_decode(p_msc_ctx->cbw.datlen) != 0;
- ret_code_t ret = NRF_SUCCESS;
- if (!data_stage)
- {
- /* Try to transfer the response now */
- ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
- }
- else
- {
- /* Cannot transfer failed response in current command - stall the endpoints and postpone the answer */
- status_generic_error_stall(p_inst, APP_USBD_MSC_STATE_UNSUPPORTED);
- }
- return ret;
- }
- /**
- * @brief Start status stage of CBW invalid.
- *
- * @param[in,out] p_inst Generic class instance.
- *
- * @sa status_generic_error_stall
- */
- static void status_cbwinvalid_start(app_usbd_class_inst_t const * p_inst)
- {
- status_generic_error_stall(p_inst, APP_USBD_MSC_STATE_CBW_INVALID);
- }
- /**
- * @brief Start status stage of internal device error.
- *
- * Kind of error that requires bulk reset but does not stall endpoint permanently - the correct
- * answer is possible.
- *
- * @param[in] p_inst Generic class instance.
- *
- * @sa status_generic_error_stall
- */
- static void status_deverror_start(app_usbd_class_inst_t const * p_inst)
- {
- status_generic_error_stall(p_inst, APP_USBD_MSC_STATE_DEVICE_ERROR);
- }
- /**
- * @brief Internal SETUP standard IN request handler.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_setup_ev Setup event.
- *
- * @return Standard error code.
- * @retval NRF_SUCCESS Request handled correctly.
- * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
- */
- static ret_code_t setup_req_std_in(app_usbd_class_inst_t const * p_inst,
- app_usbd_setup_evt_t const * p_setup_ev)
- {
- /* Only Get Descriptor standard IN request is supported by MSC class */
- if ((app_usbd_setup_req_rec(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQREC_INTERFACE)
- &&
- (p_setup_ev->setup.bRequest == APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR))
- {
- size_t dsc_len = 0;
- size_t max_size;
- uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size);
- /* Try to find descriptor in class internals*/
- ret_code_t ret = app_usbd_class_descriptor_find(
- p_inst,
- p_setup_ev->setup.wValue.hb,
- p_setup_ev->setup.wValue.lb,
- p_trans_buff,
- &dsc_len);
- if (ret != NRF_ERROR_NOT_FOUND)
- {
- ASSERT(dsc_len < NRF_DRV_USBD_EPSIZE);
- return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, dsc_len);
- }
- }
- return NRF_ERROR_NOT_SUPPORTED;
- }
- /**
- * @brief Internal SETUP standard OUT request handler.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_setup_ev Setup event.
- *
- * @return Standard error code.
- * @retval NRF_SUCCESS Request handled correctly.
- * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
- * @retval NRF_ERROR_FORBIDDEN Endpoint stall cannot be cleared because of internal state.
- */
- static ret_code_t setup_req_std_out(app_usbd_class_inst_t const * p_inst,
- app_usbd_setup_evt_t const * p_setup_ev)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- app_usbd_setup_reqrec_t req_rec = app_usbd_setup_req_rec(p_setup_ev->setup.bmRequestType);
- if ((req_rec == APP_USBD_SETUP_REQREC_ENDPOINT) &&
- (p_setup_ev->setup.bRequest == APP_USBD_SETUP_STDREQ_CLEAR_FEATURE) &&
- (p_setup_ev->setup.wValue.w == APP_USBD_SETUP_STDFEATURE_ENDPOINT_HALT))
- {
- if (p_msc_ctx->state == APP_USBD_MSC_STATE_CBW_INVALID)
- {
- return NRF_ERROR_FORBIDDEN;
- }
- ret_code_t ret = NRF_SUCCESS;
- /* Clearing endpoint here. It is done normally inside app_usbd, but we are overwritting this functionality */
- nrf_drv_usbd_ep_t ep_addr = (nrf_drv_usbd_ep_t)(p_setup_ev->setup.wIndex.lb);
- nrf_drv_usbd_ep_dtoggle_clear(ep_addr);
- nrf_drv_usbd_ep_stall_clear(ep_addr);
- if (NRF_USBD_EPIN_CHECK(ep_addr))
- {
- switch (p_msc_ctx->state)
- {
- case APP_USBD_MSC_STATE_UNSUPPORTED:
- {
- nrf_drv_usbd_ep_stall_clear(ep_out_addr_get(p_inst));
- /*Unsupported command handle: status stage*/
- ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
- if (ret != NRF_SUCCESS)
- {
- NRF_LOG_ERROR("Unexpected csw_wait_start on ep clear: %d", ret);
- }
- break;
- }
- case APP_USBD_MSC_STATE_DEVICE_ERROR:
- {
- nrf_drv_usbd_ep_stall_clear(ep_out_addr_get(p_inst));
- /*Unsupported command handle: status stage*/
- ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PE);
- if (ret != NRF_SUCCESS)
- {
- NRF_LOG_ERROR("Unexpected csw_wait_start on ep clear: %d", ret);
- }
- break;
- }
- default:
- break;
- }
- }
- return ret;
- }
- return NRF_ERROR_NOT_SUPPORTED;
- }
- /**
- * @brief Internal SETUP class IN request handler.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_setup_ev Setup event.
- *
- * @return Standard error code.
- * @retval NRF_SUCCESS Request handled correctly.
- * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
- */
- static ret_code_t setup_req_class_in(app_usbd_class_inst_t const * p_inst,
- app_usbd_setup_evt_t const * p_setup_ev)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- switch (p_setup_ev->setup.bRequest)
- {
- case APP_USBD_MSC_REQ_GET_MAX_LUN:
- {
- if (p_setup_ev->setup.wValue.w != 0)
- {
- break;
- }
- if (p_setup_ev->setup.wLength.w != 1)
- {
- break;
- }
- size_t tx_size;
- uint16_t * p_tx_buff = app_usbd_core_setup_transfer_buff_get(&tx_size);
- ASSERT(p_msc->specific.inst.block_devs_count != 0);
- p_tx_buff[0] = p_msc->specific.inst.block_devs_count - 1;
- ret_code_t ret = cbw_wait_start(p_inst);
- UNUSED_VARIABLE(ret);
- return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_tx_buff, sizeof(uint8_t));
- }
- default:
- break;
- }
- return NRF_ERROR_NOT_SUPPORTED;
- }
- /**
- * @brief Internal SETUP class OUT request handler.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_setup_ev Setup event.
- *
- * @return Standard error code.
- * @retval NRF_SUCCESS Request handled correctly.
- * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
- */
- static ret_code_t setup_req_class_out(app_usbd_class_inst_t const * p_inst,
- app_usbd_setup_evt_t const * p_setup_ev)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- switch (p_setup_ev->setup.bRequest)
- {
- case APP_USBD_MSC_REQ_BULK_RESET:
- {
- if (p_setup_ev->setup.wValue.w != 0)
- {
- break;
- }
- if (p_setup_ev->setup.wLength.w != 0)
- {
- break;
- }
- /*
- * Reset internal state to be ready for next CBW
- */
- NRF_LOG_DEBUG("bulk ep reset");
- bulk_ep_reset(p_inst);
- if (p_msc_ctx->state != APP_USBD_MSC_STATE_CBW)
- {
- ret_code_t ret = cbw_wait_start(p_inst);
- UNUSED_VARIABLE(ret);
- }
- return NRF_SUCCESS;
- }
- default:
- break;
- }
- return NRF_ERROR_NOT_SUPPORTED;
- }
- /**
- * @brief Control endpoint handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_setup_ev Setup event.
- *
- * @return Standard error code.
- * @retval NRF_SUCCESS Request handled correctly.
- * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
- */
- static ret_code_t setup_event_handler(app_usbd_class_inst_t const * p_inst,
- app_usbd_setup_evt_t const * p_setup_ev)
- {
- ASSERT(p_inst != NULL);
- ASSERT(p_setup_ev != NULL);
- if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN)
- {
- switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType))
- {
- case APP_USBD_SETUP_REQTYPE_STD:
- return setup_req_std_in(p_inst, p_setup_ev);
- case APP_USBD_SETUP_REQTYPE_CLASS:
- return setup_req_class_in(p_inst, p_setup_ev);
- default:
- break;
- }
- }
- else /* APP_USBD_SETUP_REQDIR_OUT */
- {
- switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType))
- {
- case APP_USBD_SETUP_REQTYPE_STD:
- return setup_req_std_out(p_inst, p_setup_ev);
- case APP_USBD_SETUP_REQTYPE_CLASS:
- return setup_req_class_out(p_inst, p_setup_ev);
- default:
- break;
- }
- }
- return NRF_ERROR_NOT_SUPPORTED;
- }
- /**
- * @brief Get number of blocks that should be transfered into the selected LUN
- *
- * Function calculates number of blocks for the request.
- * The number of block is calculated based on the work buffer size and the size left to transfer.
- *
- * @param p_msc MSC instance.
- * @param size The size of the transfer left.
- *
- * @return Number of blocks required for the transfer.
- */
- static uint32_t current_blkcnt_calc(app_usbd_msc_t const * p_msc, size_t size)
- {
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- if (size > p_msc->specific.inst.block_buff_size)
- {
- size = p_msc->specific.inst.block_buff_size;
- }
- return CEIL_DIV(size, p_msc_ctx->current.process.blk_size);
- }
- /**
- * @brief Helper function to calculate next transfer size.
- *
- * @param[in] p_msc MSC instance.
- * @param[in] size Total size of the transfer left.
- *
- * @return Blocks to transfer.
- * */
- static uint32_t current_size_calc(app_usbd_msc_t const * p_msc, size_t size)
- {
- return MIN(size, p_msc->specific.inst.block_buff_size);
- }
- static ret_code_t read_transfer_processor(app_usbd_class_inst_t const * p_inst)
- {
- ret_code_t ret = NRF_SUCCESS;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- if ((!p_msc_ctx->current.transfer.pending))
- {
- NRF_LOG_DEBUG("read_transfer_processor: left: %u, state: %u",
- p_msc_ctx->current.transfer.size_left,
- p_msc_ctx->state);
- if (p_msc_ctx->current.transfer.abort)
- {
- NRF_LOG_ERROR("read_transfer_processor: aborted");
- ret = NRF_ERROR_NOT_SUPPORTED;
- }
- else if (p_msc_ctx->current.transfer.size_left > 0)
- {
- if (msc_buff_data_check(p_msc))
- {
- void * p_buff = msc_buff_get(p_msc);
- size_t req_size = current_size_calc(p_msc, p_msc_ctx->current.transfer.size_left);
- ASSERT(p_buff != NULL);
- /*Trigger new transfer.*/
- p_msc_ctx->current.transfer.pending = true;
- ret = transfer_in_start(p_inst, p_buff, req_size, APP_USBD_MSC_STATE_DATA_IN);
- if (ret != NRF_SUCCESS)
- {
- p_msc_ctx->current.transfer.pending = false;
- }
- }
- }
- else
- {
- if (p_msc_ctx->state == APP_USBD_MSC_STATE_DATA_IN)
- {
- if (p_msc_ctx->current.transfer.datalen_left == 0)
- {
- ret = csw_wait_start(p_inst, p_msc_ctx->csw.status);
- ASSERT(ret == NRF_SUCCESS);
- }
- else
- {
- ret = NRF_ERROR_NOT_SUPPORTED;
- }
- }
- }
- }
- return ret;
- }
- static ret_code_t read_blockmem_processor(app_usbd_class_inst_t const * p_inst)
- {
- ret_code_t ret = NRF_SUCCESS;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- if (!(p_msc_ctx->current.process.pending))
- {
- NRF_LOG_DEBUG("read_blockmem_processor: left: %u", p_msc_ctx->current.process.size_left);
- if (p_msc_ctx->current.process.abort)
- {
- NRF_LOG_ERROR("read_blockmem_processor: aborted");
- ret = NRF_ERROR_NOT_SUPPORTED;
- }
- else if ((p_msc_ctx->current.process.size_left > 0) && msc_buff_space_check(p_msc))
- {
- nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
- uint32_t blk_cnt = current_blkcnt_calc(p_msc, p_msc_ctx->current.process.size_left);
- void * p_buff = msc_buff_alloc(p_msc);
- ASSERT(p_buff != NULL);
- NRF_BLOCK_DEV_REQUEST(
- req,
- p_msc_ctx->current.process.blk_idx,
- blk_cnt,
- p_buff);
- p_msc_ctx->current.process.pending = true;
- ret = nrf_blk_dev_read_req(p_blkd, &req);
- if (ret != NRF_SUCCESS)
- {
- /* Mark process pending and move all pionters */
- p_msc_ctx->current.process.pending = false;
- NRF_LOG_ERROR("read_blockmem_processor: block req failed: %u", ret);
- }
- }
- }
- return ret;
- }
- static ret_code_t write_transfer_processor(app_usbd_class_inst_t const * p_inst)
- {
- ret_code_t ret = NRF_SUCCESS;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- if (!(p_msc_ctx->current.transfer.pending))
- {
- NRF_LOG_DEBUG("write_transfer_processor: left: %u", p_msc_ctx->current.transfer.size_left);
- if ((p_msc_ctx->current.transfer.size_left > 0) && msc_buff_space_check(p_msc))
- {
- void * p_buff = msc_buff_alloc(p_msc);
- size_t req_size = current_size_calc(p_msc, p_msc_ctx->current.transfer.size_left);
- ASSERT(p_buff != NULL);
- /*Trigger new transfer.*/
- p_msc_ctx->current.transfer.pending = true;
- ret = transfer_out_start(p_inst, p_buff, req_size, APP_USBD_MSC_STATE_DATA_OUT);
- if (ret != NRF_SUCCESS)
- {
- p_msc_ctx->current.transfer.pending = false;
- }
- }
- }
- return ret;
- }
- static ret_code_t write_blockmem_processor(app_usbd_class_inst_t const * p_inst)
- {
- ret_code_t ret = NRF_SUCCESS;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- if (!(p_msc_ctx->current.process.pending))
- {
- NRF_LOG_DEBUG("write_blockmem_processor: left: %u, state: %u",
- p_msc_ctx->current.process.size_left,
- p_msc_ctx->state);
- if (p_msc_ctx->current.process.abort)
- {
- NRF_LOG_ERROR("write_blockmem_processor: aborted");
- ret = NRF_ERROR_NOT_SUPPORTED;
- }
- else if (p_msc_ctx->current.process.size_left > 0)
- {
- if (msc_buff_data_check(p_msc))
- {
- nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
- uint32_t blk_cnt = current_blkcnt_calc(p_msc, p_msc_ctx->current.process.size_left);
- void * p_buff = msc_buff_get(p_msc);
- ASSERT(p_buff != NULL);
- NRF_BLOCK_DEV_REQUEST(
- req,
- p_msc_ctx->current.process.blk_idx,
- blk_cnt,
- p_buff);
- p_msc_ctx->current.process.pending = true;
- ret = nrf_blk_dev_write_req(p_blkd, &req);
- if (ret != NRF_SUCCESS)
- {
- p_msc_ctx->current.process.pending = false;
- NRF_LOG_ERROR("write_blockmem_processor: block req failed: %u", ret);
- }
- }
- }
- else
- {
- if (p_msc_ctx->state == APP_USBD_MSC_STATE_DATA_OUT)
- {
- if (p_msc_ctx->current.process.datalen_left == 0)
- {
- ret = csw_wait_start(p_inst, p_msc_ctx->csw.status);
- ASSERT(ret == NRF_SUCCESS);
- }
- else
- {
- ret = NRF_ERROR_NOT_SUPPORTED;
- }
- }
- }
- }
- return ret;
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_TESTUNITREADY handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_testunitready(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: TESTUNITREADY");
- if (uint32_decode(p_msc_ctx->cbw.datlen) != 0)
- {
- return status_unsupported_start(p_inst);
- }
- if (p_msc_ctx->cbw.cdb_length != APP_USBD_SCSI_CMD_TESTUNITREADY_LEN)
- {
- return status_unsupported_start(p_inst);
- }
- if (p_msc_ctx->cbw.lun >= p_msc->specific.inst.block_devs_count)
- {
- return status_unsupported_start(p_inst);
- }
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_REQUESTSENSE handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_requestsense(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: REQUESTSENSE");
- app_usbd_scsi_cmd_requestsense_t const * p_reqs = (const void *)p_msc_ctx->cbw.cdb;
- UNUSED_VARIABLE(p_reqs);
- if ((p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_requestsense_t)))
- {
- return status_unsupported_start(p_inst);
- }
- if (p_msc_ctx->cbw.lun >= p_msc->specific.inst.block_devs_count)
- {
- return status_unsupported_start(p_inst);
- }
- if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_requestsense_resp_t))
- {
- return status_unsupported_start(p_inst);
- }
- uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
- if (resp_len == 0)
- {
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- memset(&p_msc_ctx->scsi_resp, 0, sizeof(app_usbd_scsi_cmd_requestsense_resp_t));
- p_msc_ctx->scsi_resp.requestsense.code = APP_USBD_SCSI_CMD_REQSENSE_CODE_VALID |
- APP_USBD_SCSI_CMD_REQSENSE_CODE_CURRENT;
- p_msc_ctx->scsi_resp.requestsense.len = sizeof(app_usbd_scsi_cmd_requestsense_resp_t) -
- offsetof(app_usbd_scsi_cmd_requestsense_resp_t, len);
- return transfer_in_start(p_inst,
- &p_msc_ctx->scsi_resp,
- resp_len,
- APP_USBD_MSC_STATE_CMD_IN);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_FORMAT_UNIT handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_formatunit(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: FORMAT_UNIT");
- return status_unsupported_start(p_inst);
- }
- static ret_code_t cmd_read_start(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("cmd_read_start");
- ret_code_t ret;
- if (p_msc_ctx->current.process.datalen_left == 0)
- {
- NRF_LOG_WARNING("Transfer size 0 detected");
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
- }
- if (p_msc_ctx->current.process.size_left == 0)
- {
- NRF_LOG_WARNING("Read size 0 detected");
- return status_unsupported_start(p_inst);
- }
- if ((p_msc_ctx->cbw.flags & APP_USBD_MSC_CBW_DIRECTION_IN) == 0)
- {
- NRF_LOG_WARNING("Wrong transfer direction");
- return status_unsupported_start(p_inst);
- }
- msc_buff_clear(p_msc);
- if (p_msc_ctx->current.process.size_left > p_msc_ctx->current.process.datalen_left)
- {
- p_msc_ctx->current.process.size_left = p_msc_ctx->current.process.datalen_left;
- /* After transmitting required number of bytes - set error information */
- p_msc_ctx->csw.status = APP_USBD_MSC_CSW_STATUS_PE;
- }
- p_msc_ctx->current.transfer.datalen_left = p_msc_ctx->current.process.datalen_left;
- p_msc_ctx->current.transfer.size_left = p_msc_ctx->current.process.size_left;
- p_msc_ctx->current.transfer.pending = false;
- p_msc_ctx->current.process. pending = false;
- ret = read_blockmem_processor(p_inst);
- NRF_LOG_DEBUG("read_blockmem: id: %u, left: %u, datalen: %u, ret: %u",
- p_msc_ctx->current.process.blk_idx,
- p_msc_ctx->current.process.size_left,
- p_msc_ctx->current.process.datalen_left,
- ret);
- if (ret != NRF_SUCCESS)
- {
- UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
- }
- return ret;
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_READ6 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_read6(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: READ6");
- app_usbd_scsi_cmd_read6_t const * p_read6 = (const void *)p_msc_ctx->cbw.cdb;
- if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_read6_t))
- {
- return status_unsupported_start(p_inst);
- }
- nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
- uint32_t blk_size = nrf_blk_dev_geometry(p_blkd)->blk_size;
- uint8_t blocks = p_read6->xfrlen;
- p_msc_ctx->current.process.blk_idx =
- ((p_read6->mslba & 0x1F) << 16) | uint16_big_decode(p_read6->lslba);
- p_msc_ctx->current.process.blk_size = blk_size;
- p_msc_ctx->current.process.size_left = blocks * blk_size;
- return cmd_read_start(p_inst, p_msc, p_msc_ctx);
- }
- static ret_code_t cmd_write_start(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("cmd_write_start");
- ret_code_t ret;
- if (p_msc_ctx->current.process.datalen_left == 0)
- {
- NRF_LOG_WARNING("Transfer size 0 detected");
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
- }
- if (p_msc_ctx->current.process.size_left == 0)
- {
- NRF_LOG_WARNING("Write size 0 detected");
- return status_unsupported_start(p_inst);
- }
- if ((p_msc_ctx->cbw.flags & APP_USBD_MSC_CBW_DIRECTION_IN) != 0)
- {
- NRF_LOG_WARNING("Wrong transfer direction");
- return status_unsupported_start(p_inst);
- }
- msc_buff_clear(p_msc);
- if (p_msc_ctx->current.process.size_left > p_msc_ctx->current.process.datalen_left)
- {
- p_msc_ctx->current.process.size_left = p_msc_ctx->current.process.datalen_left;
- /* After transmitting required number of bytes - set error information */
- p_msc_ctx->csw.status = APP_USBD_MSC_CSW_STATUS_PE;
- }
- p_msc_ctx->current.transfer.datalen_left = p_msc_ctx->current.process.datalen_left;
- p_msc_ctx->current.transfer.size_left = p_msc_ctx->current.process.size_left;
- p_msc_ctx->current.transfer.pending = false;
- p_msc_ctx->current.process. pending = false;
- ret = write_transfer_processor(p_inst);
- NRF_LOG_DEBUG("write_blockrx: id: %u, left: %u, datalen: %u, ret: %u",
- p_msc_ctx->current.process.blk_idx,
- p_msc_ctx->current.process.size_left,
- p_msc_ctx->current.process.datalen_left,
- ret);
- if (ret != NRF_SUCCESS)
- {
- UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
- }
- return ret;
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_WRITE6 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_write6(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: WRITE6");
- app_usbd_scsi_cmd_write6_t const * p_write6 = (const void *)p_msc_ctx->cbw.cdb;
- if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_write6_t))
- {
- return status_unsupported_start(p_inst);
- }
- nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
- uint32_t blk_size = nrf_blk_dev_geometry(p_blkd)->blk_size;
- uint8_t blocks = p_write6->xfrlen;
- p_msc_ctx->current.process.blk_idx =
- ((p_write6->mslba & 0x1F) << 16) | uint16_big_decode(p_write6->lslba);
- p_msc_ctx->current.process.blk_size = blk_size;
- p_msc_ctx->current.process.size_left = blocks * blk_size;
- return cmd_write_start(p_inst, p_msc, p_msc_ctx);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_INQUIRY handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_inquiry(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: INQUIRY");
- app_usbd_scsi_cmd_inquiry_t const * p_inq = (const void *)p_msc_ctx->cbw.cdb;
- if (p_inq->pagecode != 0)
- {
- NRF_LOG_WARNING("unsupported pagecode");
- return status_unsupported_start(p_inst);
- }
- if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_inquiry_resp_t))
- {
- return status_unsupported_start(p_inst);
- }
- uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
- if (resp_len == 0)
- {
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- p_msc_ctx->scsi_resp.inquiry.qualtype = APP_USBD_MSC_SCSI_INQ_QUAL_CONNECTED |
- APP_USBD_MSC_SCSI_INQ_TYPE_DIR_ACCESS;
- p_msc_ctx->scsi_resp.inquiry.flags1 = APP_USBD_MSC_SCSI_INQ_FLAG1_RMB;
- p_msc_ctx->scsi_resp.inquiry.version = APP_USBD_SCSI_INQ_VER_SPC4;
- p_msc_ctx->scsi_resp.inquiry.flags2 = APP_USBD_MSC_SCSI_INQ_FLAG2_RSP_SPC2 |
- APP_USBD_MSC_SCSI_INQ_FLAG2_HISUP;
- p_msc_ctx->scsi_resp.inquiry.len = sizeof(app_usbd_scsi_cmd_inquiry_resp_t) -
- offsetof(app_usbd_scsi_cmd_inquiry_resp_t, len);
- nrf_block_dev_t const * p_blkd =
- p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
- nrf_block_dev_info_strings_t * p_strings = NULL;
- UNUSED_RETURN_VALUE(nrf_blk_dev_ioctl(p_blkd,
- NRF_BLOCK_DEV_IOCTL_REQ_INFO_STRINGS,
- &p_strings));
- if (p_strings)
- {
- UNUSED_RETURN_VALUE(strncpy((char *)p_msc_ctx->scsi_resp.inquiry.vendorid,
- p_strings->p_vendor,
- sizeof(p_msc_ctx->scsi_resp.inquiry.vendorid)));
- UNUSED_RETURN_VALUE(strncpy((char *)p_msc_ctx->scsi_resp.inquiry.productid,
- p_strings->p_product,
- sizeof(p_msc_ctx->scsi_resp.inquiry.productid)));
- UNUSED_RETURN_VALUE(strncpy((char *)p_msc_ctx->scsi_resp.inquiry.revision,
- p_strings->p_revision,
- sizeof(p_msc_ctx->scsi_resp.inquiry.revision)));
- }
- else
- {
- memset(p_msc_ctx->scsi_resp.inquiry.vendorid,
- 0,
- sizeof(p_msc_ctx->scsi_resp.inquiry.vendorid));
- memset(p_msc_ctx->scsi_resp.inquiry.productid,
- 0,
- sizeof(p_msc_ctx->scsi_resp.inquiry.productid));
- memset(p_msc_ctx->scsi_resp.inquiry.revision,
- 0,
- sizeof(p_msc_ctx->scsi_resp.inquiry.revision));
- }
- return transfer_in_start(p_inst,
- &p_msc_ctx->scsi_resp,
- resp_len,
- APP_USBD_MSC_STATE_CMD_IN);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_MODESELECT6 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_modeselect6(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: MODESELECT6");
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_MODESENSE6 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_modesense6(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: MODESENSE6");
- app_usbd_scsi_cmd_modesense6_t const * p_sense6 = (const void *)p_msc_ctx->cbw.cdb;
- UNUSED_VARIABLE(p_sense6);
- if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_modesense6_t))
- {
- return status_unsupported_start(p_inst);
- }
- if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_modesense6_resp_t))
- {
- return status_unsupported_start(p_inst);
- }
- uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
- app_usbd_scsi_cmd_modesense6_resp_t * p_resp = &p_msc_ctx->scsi_resp.modesense6;
- p_resp->mdlen = sizeof(app_usbd_scsi_cmd_modesense6_resp_t) - 1;
- p_resp->type = 0;
- p_resp->param = 0;
- p_resp->bdlen = 0;
- return transfer_in_start(p_inst,
- &p_msc_ctx->scsi_resp,
- resp_len,
- APP_USBD_MSC_STATE_CMD_IN);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_STARTSTOPUNIT handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_startstopunit(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: STARTSTOPUNIT");
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_SENDDIAGNOSTIC handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_senddiagnostic(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: SENDDIAGNOSTIC");
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_PREVENTMEDIAREMOVAL handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_preventremoval(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: PREVENTMEDIAREMOVAL");
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_READCAPACITY10 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_readcapacity10(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: READCAPACITY10");
- app_usbd_scsi_cmd_readcapacity10_t const * p_cap10 = (const void *)p_msc_ctx->cbw.cdb;
- UNUSED_VARIABLE(p_cap10);
- if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_readcapacity10_t))
- {
- return status_unsupported_start(p_inst);
- }
- if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_readcapacity10_resp_t))
- {
- return status_unsupported_start(p_inst);
- }
- uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
- if (resp_len == 0)
- {
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- nrf_block_dev_t const * p_blkd =
- p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
- nrf_block_dev_geometry_t const * p_geometry = nrf_blk_dev_geometry(p_blkd);
- UNUSED_RETURN_VALUE(
- uint32_big_encode(p_geometry->blk_count - 1, p_msc_ctx->scsi_resp.readcapacity10.lba));
- UNUSED_RETURN_VALUE(
- uint32_big_encode(p_geometry->blk_size, p_msc_ctx->scsi_resp.readcapacity10.blklen));
- return transfer_in_start(p_inst,
- &p_msc_ctx->scsi_resp,
- resp_len,
- APP_USBD_MSC_STATE_CMD_IN);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_READ10 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_read10(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: READ10");
- app_usbd_scsi_cmd_read10_t const * p_read10 = (const void *)p_msc_ctx->cbw.cdb;
- if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_read10_t))
- {
- return status_unsupported_start(p_inst);
- }
- nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
- uint32_t blk_size = nrf_blk_dev_geometry(p_blkd)->blk_size;
- uint16_t blocks = uint16_big_decode(p_read10->xfrlen);
- p_msc_ctx->current.process.blk_idx = uint32_big_decode(p_read10->lba);
- p_msc_ctx->current.process.blk_size = blk_size;
- p_msc_ctx->current.process.size_left = blocks * blk_size;
- return cmd_read_start(p_inst, p_msc, p_msc_ctx);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_WRITE10 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_write10(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: WRITE10");
- app_usbd_scsi_cmd_write10_t const * p_write10 = (const void *)p_msc_ctx->cbw.cdb;
- if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_write10_t))
- {
- return status_unsupported_start(p_inst);
- }
- nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[p_msc_ctx->cbw.lun];
- uint32_t blk_size = nrf_blk_dev_geometry(p_blkd)->blk_size;
- uint16_t blocks = uint16_big_decode(p_write10->xfrlen);
- p_msc_ctx->current.process.blk_idx = uint32_big_decode(p_write10->lba);
- p_msc_ctx->current.process.blk_size = blk_size;
- p_msc_ctx->current.process.size_left = blocks * blk_size;
- return cmd_write_start(p_inst, p_msc, p_msc_ctx);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_MODESELECT10 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_modeselect10(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: MODESELECT10");
- return csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- }
- /**
- * @brief SCSI Command: @ref APP_USBD_SCSI_CMD_MODESENSE10 handle.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_msc MSC instance.
- * @param[in] p_msc_ctx MSC context.
- * @return Standard error code.
- * */
- static ret_code_t cmd_modesense10(app_usbd_class_inst_t const * p_inst,
- app_usbd_msc_t const * p_msc,
- app_usbd_msc_ctx_t * p_msc_ctx)
- {
- NRF_LOG_DEBUG("CMD: MODESENSE10");
- app_usbd_scsi_cmd_modesense10_t const * p_sense10 = (const void *)p_msc_ctx->cbw.cdb;
- UNUSED_VARIABLE(p_sense10);
- if (p_msc_ctx->cbw.cdb_length < sizeof(app_usbd_scsi_cmd_modesense10_t))
- {
- return status_unsupported_start(p_inst);
- }
- if (p_msc_ctx->cbw.lun >= p_msc->specific.inst.block_devs_count)
- {
- return status_unsupported_start(p_inst);
- }
- if (uint32_decode(p_msc_ctx->cbw.datlen) > sizeof(app_usbd_scsi_cmd_modesense6_resp_t))
- {
- return status_unsupported_start(p_inst);
- }
- uint32_t resp_len = uint32_decode(p_msc_ctx->cbw.datlen);
- app_usbd_scsi_cmd_modesense10_resp_t * p_resp = &p_msc_ctx->scsi_resp.modesense10;
- memset(p_resp, 0, sizeof(app_usbd_scsi_cmd_modesense10_resp_t));
- uint16_t len = sizeof(app_usbd_scsi_cmd_modesense10_resp_t) - sizeof(p_resp->mdlen);
- p_resp->mdlen[1] = len & 0xff;
- p_resp->mdlen[0] = (len >> 8) & 0xff;
- return transfer_in_start(p_inst,
- &p_msc_ctx->scsi_resp,
- resp_len,
- APP_USBD_MSC_STATE_CMD_IN);
- }
- /**
- * @brief Get the size of the last OUT transfer.
- *
- * @param p_inst Generic class instance.
- *
- * @return Number of received bytes or 0 if none.
- */
- static size_t get_last_out_size(app_usbd_class_inst_t const * p_inst)
- {
- nrf_drv_usbd_ep_t ep = ep_out_addr_get(p_inst);
- size_t size;
- ret_code_t ret = nrf_drv_usbd_ep_status_get(ep, &size);
- if (ret != NRF_SUCCESS)
- {
- size = 0;
- }
- return size;
- }
- /**
- * @brief SCSI Command Block Wrapper handler.
- *
- * @param[in] p_inst Generic class instance.
- * @return Standard error code.
- * */
- static ret_code_t state_cbw(app_usbd_class_inst_t const * p_inst)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- memset(&p_msc_ctx->current, 0, sizeof(p_msc_ctx->current));
- memset( p_msc_ctx->csw.tag, 0, sizeof(p_msc_ctx->csw.tag));
- /*Verify the transfer size*/
- if (get_last_out_size(p_inst) != sizeof(app_usbd_msc_cbw_t))
- {
- NRF_LOG_DEBUG("CMD: size error: %u", get_last_out_size(p_inst));
- status_cbwinvalid_start(p_inst);
- return NRF_SUCCESS;
- }
- /*Verify CBW signature*/
- if (memcmp(p_msc_ctx->cbw.signature,
- m_cbw_signature,
- sizeof(m_cbw_signature)) != 0)
- {
- NRF_LOG_DEBUG("CMD: header error: 0x%02x%02x%02x%02x",
- p_msc_ctx->cbw.signature[0], p_msc_ctx->cbw.signature[1],
- p_msc_ctx->cbw.signature[2], p_msc_ctx->cbw.signature[3]);
- status_cbwinvalid_start(p_inst);
- return NRF_SUCCESS;
- }
- /*Prepare the response*/
- memcpy(p_msc_ctx->csw.tag, p_msc_ctx->cbw.tag, sizeof(p_msc_ctx->csw.tag));
- p_msc_ctx->csw.status = APP_USBD_MSC_CSW_STATUS_PASS;
- p_msc_ctx->current.process.lun = p_msc_ctx->cbw.lun;
- p_msc_ctx->current.process.datalen_left = uint32_decode(p_msc_ctx->cbw.datlen);
- if (p_msc_ctx->current.process.lun >= p_msc->specific.inst.block_devs_count)
- {
- NRF_LOG_WARNING("Unsupported LUN");
- return status_unsupported_start(p_inst);
- }
- ret_code_t ret = NRF_SUCCESS;
- switch (p_msc_ctx->cbw.cdb[0])
- {
- case APP_USBD_SCSI_CMD_TESTUNITREADY:
- ret = cmd_testunitready(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_REQUESTSENSE:
- ret = cmd_requestsense(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_FORMAT_UNIT:
- ret = cmd_formatunit(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_READ6:
- ret = cmd_read6(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_WRITE6:
- ret = cmd_write6(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_INQUIRY:
- ret = cmd_inquiry(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_MODESELECT6:
- ret = cmd_modeselect6(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_MODESENSE6:
- ret = cmd_modesense6(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_STARTSTOPUNIT:
- ret = cmd_startstopunit(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_SENDDIAGNOSTIC:
- ret = cmd_senddiagnostic(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_PREVENTMEDIAREMOVAL:
- ret = cmd_preventremoval(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_READCAPACITY10:
- ret = cmd_readcapacity10(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_READ10:
- ret = cmd_read10(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_WRITE10:
- ret = cmd_write10(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_MODESELECT10:
- ret = cmd_modeselect10(p_inst, p_msc, p_msc_ctx);
- break;
- case APP_USBD_SCSI_CMD_MODESENSE10:
- ret = cmd_modesense10(p_inst, p_msc, p_msc_ctx);
- break;
- default:
- NRF_LOG_DEBUG("CMD: UNSUPPORTED");
- NRF_LOG_HEXDUMP_DEBUG(&(p_msc_ctx->cbw), sizeof(p_msc_ctx->cbw));
- if (uint32_decode(p_msc_ctx->cbw.datlen) != 0)
- {
- ret = status_unsupported_start(p_inst);
- }
- else
- {
- ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_FAIL);
- }
- break;
- }
- return ret;
- }
- /**
- * @brief Mark transfer block process.
- *
- * Common part of the @ref state_data_in_handle and @ref state_data_out_handle
- * that marks the current transfer state.
- *
- * @param p_msc_ctx MSC context.
- * @param size Number of bytes transfered.
- */
- static void state_data_in_out_process(app_usbd_msc_ctx_t * p_msc_ctx, size_t size)
- {
- p_msc_ctx->current.transfer.pending = false;
- p_msc_ctx->current.transfer.size_left =
- SUB_SAT0(p_msc_ctx->current.transfer.size_left, size);
- p_msc_ctx->current.transfer.datalen_left =
- SUB_SAT0(p_msc_ctx->current.transfer.datalen_left, size);
- }
- /**
- * @brief Handle read6/read10 command data stage.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] size Number of bytes sent.
- *
- * @return Standard error code.
- */
- static ret_code_t state_data_in_handle(app_usbd_class_inst_t const * p_inst, size_t size)
- {
- ret_code_t ret;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- NRF_LOG_DEBUG("APP_USBD_MSC_STATE_DATA_IN");
- /* For the in transfer direction, correctly transfered block have to match */
- ASSERT(current_size_calc(p_msc, p_msc_ctx->current.transfer.size_left) == size);
- /* Mark the fact the transfer block has been transfered */
- state_data_in_out_process(p_msc_ctx, size);
- msc_buff_free(p_msc);
- ret = read_transfer_processor(p_inst);
- if(ret == NRF_SUCCESS)
- {
- ret = read_blockmem_processor(p_inst);
- }
- if (ret != NRF_SUCCESS)
- {
- UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
- }
- return ret;
- }
- /**
- * @brief Endpoint IN event handler.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_setup_ev Setup event.
- *
- * @return Standard error code.
- */
- static ret_code_t endpoint_in_event_handler(app_usbd_class_inst_t const * p_inst,
- app_usbd_complex_evt_t const * p_event)
- {
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- size_t size;
- NRF_LOG_DEBUG("state: %d, ep in event, status: %d",
- p_msc_ctx->state,
- p_event->drv_evt.data.eptransfer.status);
- if (NRF_SUCCESS != nrf_drv_usbd_ep_status_get(p_event->drv_evt.data.eptransfer.ep, &size))
- {
- size = 0;
- }
- if (p_event->drv_evt.data.eptransfer.status != NRF_USBD_EP_OK)
- {
- return NRF_SUCCESS;
- }
- ret_code_t ret = NRF_SUCCESS;
- switch (p_msc_ctx->state)
- {
- case APP_USBD_MSC_STATE_CMD_IN:
- {
- p_msc_ctx->current.process.datalen_left -= size;
- ret = csw_wait_start(p_inst, APP_USBD_MSC_CSW_STATUS_PASS);
- break;
- }
- case APP_USBD_MSC_STATE_DATA_IN:
- {
- ret = state_data_in_handle(p_inst, size);
- break;
- }
- case APP_USBD_MSC_STATE_CSW:
- {
- break;
- }
- case APP_USBD_MSC_STATE_DATA_OUT:
- {
- break;
- }
- case APP_USBD_MSC_STATE_UNSUPPORTED:
- {
- ret = NRF_ERROR_NOT_SUPPORTED;
- break;
- }
- default:
- {
- ret = NRF_ERROR_INTERNAL;
- break;
- }
- }
- return ret;
- }
- /**
- * @brief Handle write6/write10 command data stage.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] size Number of bytes received.
- *
- * @return Standard error code.
- * @retval NRF_SUCCESS Request handled correctly.
- * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
- */
- static ret_code_t state_data_out_handle(app_usbd_class_inst_t const * p_inst, size_t size)
- {
- ret_code_t ret = NRF_SUCCESS;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- NRF_LOG_DEBUG("APP_USBD_MSC_STATE_DATA_OUT");
- /* For the OUT transfer direction we may get less than we expected */
- if (current_size_calc(p_msc, p_msc_ctx->current.transfer.size_left) != size)
- {
- p_msc_ctx->current.process.abort = true;
- }
- /* Mark the fact the transfer block has been transfered */
- state_data_in_out_process(p_msc_ctx, size);
- msc_buff_put(p_msc);
- ret = write_transfer_processor(p_inst);
- if(ret == NRF_SUCCESS)
- {
- ret = write_blockmem_processor(p_inst);
- }
- if (ret != NRF_SUCCESS)
- {
- UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
- }
- return ret;
- }
- /**
- * @brief Endpoint OUT event handler.
- *
- * @param[in] p_inst Generic class instance.
- * @param[in] p_setup_ev Setup event.
- *
- * @return Standard error code.
- * @retval NRF_SUCCESS Request handled correctly.
- * @retval NRF_ERROR_NOT_SUPPORTED Request is not supported.
- */
- static ret_code_t endpoint_out_event_handler(app_usbd_class_inst_t const * p_inst,
- app_usbd_complex_evt_t const * p_event)
- {
- ret_code_t ret = NRF_SUCCESS;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- size_t size;
- NRF_LOG_DEBUG("state: %d, ep out event, status: %d",
- p_msc_ctx->state,
- p_event->drv_evt.data.eptransfer.status);
- if (NRF_SUCCESS != nrf_drv_usbd_ep_status_get(p_event->drv_evt.data.eptransfer.ep, &size))
- {
- size = 0;
- }
- if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_WAITING)
- {
- if (p_msc_ctx->state == APP_USBD_MSC_STATE_DATA_OUT)
- {
- NRF_LOG_DEBUG("NRF_USBD_EP_WAITING");
- }
- else if (p_msc_ctx->state == APP_USBD_MSC_STATE_CSW ||
- p_msc_ctx->state == APP_USBD_MSC_STATE_IDLE)
- {
- ret = cbw_wait_start(p_inst);
- }
- return ret;
- }
- else if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_ABORTED)
- {
- p_msc_ctx->state = APP_USBD_MSC_STATE_IDLE;
- return NRF_SUCCESS;
- }
- else if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_OVERLOAD)
- {
- NRF_LOG_ERROR("Data overload");
- switch (p_msc_ctx->state)
- {
- case APP_USBD_MSC_STATE_DATA_OUT:
- {
- status_deverror_start(p_inst);
- break;
- }
- /* Default action is the same like CBW - stall totally until bulk reset */
- case APP_USBD_MSC_STATE_CBW:
- default:
- {
- status_cbwinvalid_start(p_inst);
- break;
- }
- }
- return NRF_SUCCESS;
- }
- else /*NRF_USBD_EP_OK*/
- {
- switch (p_msc_ctx->state)
- {
- case APP_USBD_MSC_STATE_CBW:
- {
- ret = state_cbw(p_inst);
- break;
- }
- case APP_USBD_MSC_STATE_DATA_OUT:
- {
- CRITICAL_REGION_ENTER();
- ret = state_data_out_handle(p_inst, size);
- CRITICAL_REGION_EXIT();
- break;
- }
- case APP_USBD_MSC_STATE_UNSUPPORTED:
- {
- ret = NRF_ERROR_NOT_SUPPORTED;
- break;
- }
- case APP_USBD_MSC_STATE_CSW:
- break;
- default:
- {
- ASSERT(0);
- ret = NRF_ERROR_NOT_SUPPORTED;
- break;
- }
- }
- }
- NRF_LOG_DEBUG("Ep proc status: %d", ret);
- return ret;
- }
- /**
- * @brief @ref app_usbd_class_methods_t::event_handler
- */
- static ret_code_t msc_event_handler(app_usbd_class_inst_t const * p_inst,
- app_usbd_complex_evt_t const * p_event)
- {
- ASSERT(p_inst != NULL);
- ASSERT(p_event != NULL);
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- UNUSED_VARIABLE(p_msc);
- UNUSED_VARIABLE(p_msc_ctx);
- ret_code_t ret = NRF_SUCCESS;
- switch (p_event->app_evt.type)
- {
- case APP_USBD_EVT_DRV_SOF:
- break;
- case APP_USBD_EVT_DRV_RESET:
- /* Initialize */
- memset(p_msc_ctx, 0, sizeof(app_usbd_msc_csw_t));
- /* Configure the CSW signature as it should never be changed when software works */
- memcpy(p_msc_ctx->csw.signature, m_csw_signature, sizeof(m_csw_signature));
- break;
- case APP_USBD_EVT_DRV_SETUP:
- ret = setup_event_handler(p_inst, (app_usbd_setup_evt_t const *)p_event);
- break;
- case APP_USBD_EVT_DRV_EPTRANSFER:
- if (NRF_USBD_EPIN_CHECK(p_event->drv_evt.data.eptransfer.ep))
- {
- ret = endpoint_in_event_handler(p_inst, p_event);
- }
- else
- {
- ret = endpoint_out_event_handler(p_inst, p_event);
- }
- break;
- case APP_USBD_EVT_DRV_SUSPEND:
- {
- /*Flush all block devices cache on suspend*/
- for (size_t i = 0; i < p_msc->specific.inst.block_devs_count; ++i)
- {
- nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[i];
- (void)nrf_blk_dev_ioctl(p_blkd, NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH, NULL);
- }
- break;
- }
- case APP_USBD_EVT_DRV_RESUME:
- break;
- case APP_USBD_EVT_INST_APPEND:
- {
- /*Verify serial number string*/
- uint16_t const * p_serial_str = app_usbd_string_desc_get(APP_USBD_STRING_ID_SERIAL, 0);
- if (p_serial_str == NULL)
- {
- return NRF_ERROR_NOT_SUPPORTED;
- }
- size_t len = app_usbd_string_desc_length(p_serial_str) / sizeof(uint16_t);
- if (len < APP_USBD_MSC_MINIMAL_SERIAL_STRING_SIZE)
- {
- return NRF_ERROR_NOT_SUPPORTED;
- }
- for (size_t i = 1; i < len; ++i)
- {
- if (isxdigit(p_serial_str[i]) == 0)
- {
- return NRF_ERROR_NOT_SUPPORTED;
- }
- }
- break;
- }
- case APP_USBD_EVT_INST_REMOVE:
- {
- break;
- }
- case APP_USBD_EVT_STARTED:
- {
- /*Initialize all block devices*/
- ASSERT(p_msc->specific.inst.block_devs_count <= 16);
- for (size_t i = 0; i < p_msc->specific.inst.block_devs_count; ++i)
- {
- nrf_block_dev_t const * p_blk_dev = p_msc->specific.inst.pp_block_devs[i];
- ret = nrf_blk_dev_init(p_blk_dev, msc_blockdev_ev_handler, p_msc);
- if (ret != NRF_SUCCESS)
- {
- continue;
- }
- p_msc_ctx->blk_dev_init_mask |= 1u << i;
- ASSERT(nrf_blk_dev_geometry(p_blk_dev)->blk_size <=
- p_msc->specific.inst.block_buff_size);
- }
- break;
- }
- case APP_USBD_EVT_STOPPED:
- {
- /*Un-initialize all block devices*/
- ASSERT(p_msc->specific.inst.block_devs_count <= 16);
- size_t i;
- for (i = 0; i < p_msc->specific.inst.block_devs_count; ++i)
- {
- nrf_block_dev_t const * p_blk_dev = p_msc->specific.inst.pp_block_devs[i];
- ret = nrf_blk_dev_uninit(p_blk_dev);
- if (ret != NRF_SUCCESS)
- {
- continue;
- }
- p_msc_ctx->blk_dev_init_mask &= ~(1u << i);
- }
- break;
- }
- default:
- ret = NRF_ERROR_NOT_SUPPORTED;
- break;
- }
- return ret;
- }
- /**
- * @brief @ref app_usbd_class_methods_t::feed_descriptors
- */
- static bool msc_feed_descriptors(app_usbd_class_descriptor_ctx_t * p_ctx,
- app_usbd_class_inst_t const * p_inst,
- uint8_t * p_buff,
- size_t max_size)
- {
- static uint8_t ifaces = 0;
- ifaces = app_usbd_class_iface_count_get(p_inst);
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size);
- static uint8_t i = 0;
- for (i = 0; i < ifaces; i++)
- {
- /* INTERFACE DESCRIPTOR */
- APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength
- APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType = Interface
- static app_usbd_class_iface_conf_t const * p_cur_iface = NULL;
- p_cur_iface = app_usbd_class_iface_get(p_inst, i);
- APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_number_get(p_cur_iface)); // bInterfaceNumber
- APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bAlternateSetting
- APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_ep_count_get(p_cur_iface)); // bNumEndpoints
- APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_MSC_CLASS); // bInterfaceClass = MSC
- APP_USBD_CLASS_DESCRIPTOR_WRITE(p_msc->specific.inst.subclass); // bInterfaceSubclass (Industry Standard Command Block)
- APP_USBD_CLASS_DESCRIPTOR_WRITE(p_msc->specific.inst.protocol); // bInterfaceProtocol
- APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface
- static uint8_t endpoints = 0;
- endpoints = app_usbd_class_iface_ep_count_get(p_cur_iface);
- static uint8_t j = 0;
- for (j = 0; j < endpoints; j++)
- {
- // ENDPOINT DESCRIPTOR
- APP_USBD_CLASS_DESCRIPTOR_WRITE(0x07); // bLength
- APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_ENDPOINT); // bDescriptorType = Endpoint
- static app_usbd_class_ep_conf_t const * p_cur_ep = NULL;
- p_cur_ep = app_usbd_class_iface_ep_get(p_cur_iface, j);
- APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_ep_address_get(p_cur_ep)); // bEndpointAddress
- APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK); // bmAttributes
- APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize LSB
- APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize MSB
- APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterval
- }
- }
- APP_USBD_CLASS_DESCRIPTOR_END();
- }
- const app_usbd_class_methods_t app_usbd_msc_class_methods = {
- .event_handler = msc_event_handler,
- .feed_descriptors = msc_feed_descriptors,
- };
- /**
- * @brief Mark block device process.
- *
- * Common part of the @ref msc_blockdev_read_done_handler and @ref msc_blockdev_write_done_handler
- * that marks the current processing state.
- *
- * @param p_blk_dev Block device handle.
- * @param p_event Block device event.
- */
- static void msc_blockdev_done_process(nrf_block_dev_t const * p_blk_dev,
- nrf_block_dev_event_t const * p_event)
- {
- app_usbd_class_inst_t const * p_inst = p_event->p_context;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- uint32_t blk_count = p_event->p_blk_req->blk_count;
- uint32_t size = blk_count * p_msc_ctx->current.process.blk_size;
- p_msc_ctx->current.process.blk_idx += blk_count;
- p_msc_ctx->current.process.size_left =
- SUB_SAT0(p_msc_ctx->current.process.size_left, size);
- p_msc_ctx->current.process.datalen_left =
- SUB_SAT0(p_msc_ctx->current.process.datalen_left, size);
- p_msc_ctx->current.process.pending = false;
- }
- /**
- * @brief Block device read done event handler.
- *
- * @ref NRF_BLOCK_DEV_EVT_BLK_READ_DONE
- *
- * @param p_blk_dev Block device handle.
- * @param p_event Block device event.
- *
- * */
- static void msc_blockdev_read_done_handler(nrf_block_dev_t const * p_blk_dev,
- nrf_block_dev_event_t const * p_event)
- {
- ret_code_t ret;
- app_usbd_class_inst_t const * p_inst = p_event->p_context;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- app_usbd_msc_ctx_t * p_msc_ctx = msc_ctx_get(p_msc);
- NRF_LOG_DEBUG("read_done_handler: p_buff: %p, size: %u",
- (uint32_t)p_event->p_blk_req->p_buff,
- p_event->p_blk_req->blk_count);
- msc_buff_put(p_msc);
- if (p_event->result == NRF_BLOCK_DEV_RESULT_SUCCESS)
- {
- msc_blockdev_done_process(p_blk_dev, p_event);
- }
- else
- {
- p_msc_ctx->current.transfer.abort = true;
- }
- ret = read_transfer_processor(p_inst);
- if(ret == NRF_SUCCESS)
- {
- ret = read_blockmem_processor(p_inst);
- }
- if (ret != NRF_SUCCESS)
- {
- UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
- }
- }
- /**
- * @brief Block device write done event handler.
- *
- * @ref NRF_BLOCK_DEV_EVT_BLK_WRITE_DONE
- *
- * @param p_blk_dev Block device handle.
- * @param p_event Block device event.
- *
- * */
- static void msc_blockdev_write_done_handler(nrf_block_dev_t const * p_blk_dev,
- nrf_block_dev_event_t const * p_event)
- {
- ret_code_t ret;
- app_usbd_class_inst_t const * p_inst = p_event->p_context;
- app_usbd_msc_t const * p_msc = msc_get(p_inst);
- NRF_LOG_DEBUG("write_done_handler: p_buff: %p, size: %u",
- (uint32_t)p_event->p_blk_req->p_buff,
- p_event->p_blk_req->blk_count);
- msc_buff_free(p_msc);
- if (p_event->result == NRF_BLOCK_DEV_RESULT_SUCCESS)
- {
- msc_blockdev_done_process(p_blk_dev, p_event);
- }
- else
- {
- UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
- }
- ret = write_transfer_processor(p_inst);
- if(ret == NRF_SUCCESS)
- {
- ret = write_blockmem_processor(p_inst);
- }
- if (ret != NRF_SUCCESS)
- {
- UNUSED_RETURN_VALUE(status_unsupported_start(p_inst));
- }
- }
- /**
- * @brief Block device event handler.
- *
- * Mass storage block device event handler. Need to be pined to all block devices
- * from initializer list.
- *
- * @param p_blk_dev Block device handle.
- * @param p_event Block device event.
- *
- * */
- static void msc_blockdev_ev_handler(nrf_block_dev_t const * p_blk_dev,
- nrf_block_dev_event_t const * p_event)
- {
- switch (p_event->ev_type)
- {
- case NRF_BLOCK_DEV_EVT_INIT:
- break;
- case NRF_BLOCK_DEV_EVT_UNINIT:
- break;
- case NRF_BLOCK_DEV_EVT_BLK_READ_DONE:
- CRITICAL_REGION_ENTER();
- msc_blockdev_read_done_handler(p_blk_dev, p_event);
- CRITICAL_REGION_EXIT();
- break;
- case NRF_BLOCK_DEV_EVT_BLK_WRITE_DONE:
- CRITICAL_REGION_ENTER();
- msc_blockdev_write_done_handler(p_blk_dev, p_event);
- CRITICAL_REGION_EXIT();
- break;
- default:
- break;
- }
- }
- /** @} */
- bool app_usbd_msc_sync(app_usbd_msc_t const * p_msc)
- {
- bool rc = true;
- ret_code_t ret = NRF_SUCCESS;
- for (size_t i = 0; i < p_msc->specific.inst.block_devs_count; ++i)
- {
- nrf_block_dev_t const * p_blkd = p_msc->specific.inst.pp_block_devs[i];
- bool flush_in_progress = true;
- ret = nrf_blk_dev_ioctl(p_blkd,
- NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH,
- &flush_in_progress);
- if ((ret != NRF_SUCCESS) || flush_in_progress)
- {
- rc = false;
- }
- }
- return rc;
- }
- #endif //NRF_MODULE_ENABLED(APP_USBD_MSC)
|