app_usbd_msc_internal.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. #ifndef APP_USBD_MSC_INTERNAL_H__
  41. #define APP_USBD_MSC_INTERNAL_H__
  42. #include "app_util.h"
  43. #ifdef __cplusplus
  44. extern "C" {
  45. #endif
  46. /**
  47. * @defgroup app_usbd_msc_internals USB MSC internals
  48. * @ingroup app_usbd_msc
  49. *
  50. * @brief @tagAPI52840 Internals of the USB MSC class.
  51. * @{
  52. */
  53. /**
  54. * @brief Minimal serial string descriptor length.
  55. * */
  56. #define APP_USBD_MSC_MINIMAL_SERIAL_STRING_SIZE (12 + 1)
  57. /**
  58. * @brief Number of block buffers
  59. *
  60. * Number of buffers used for the transfer.
  61. * The library is designed to work with double buffering.
  62. * Not tested with other configuration.
  63. */
  64. #define APP_USBD_MSC_BUFFER_CNT 2
  65. /**
  66. * @brief Create the name of the block buffer
  67. *
  68. * @param instance_name The name of the MSC instance
  69. *
  70. * @return The name of the block buffer used with the instance
  71. */
  72. #define APP_USBD_MSC_BUFFER_NAME(instance_name) CONCAT_2(instance_name, _block)
  73. /**
  74. * @brief Create the name of the block device list
  75. *
  76. * @param instance_name The name of the MSC instance
  77. *
  78. * @return The name of the block device list
  79. */
  80. #define APP_USBD_MSC_BLKDEVS_NAME(instance_name) CONCAT_2(instance_name, _blkdevs)
  81. /**
  82. * @brief Forward declaration of Mass Storage Class type.
  83. *
  84. */
  85. APP_USBD_CLASS_FORWARD(app_usbd_msc);
  86. /*lint -save -e165*/
  87. /**
  88. * @brief Forward declaration of @ref app_usbd_msc_user_event_e
  89. *
  90. */
  91. enum app_usbd_msc_user_event_e;
  92. /*lint -restore*/
  93. /**
  94. * @brief User event handler.
  95. *
  96. * @param[in] p_inst Class instance.
  97. * @param[in] event User event.
  98. *
  99. * */
  100. typedef void (*app_usbd_msc_user_ev_handler_t)(app_usbd_class_inst_t const * p_inst,
  101. enum app_usbd_msc_user_event_e event);
  102. /**
  103. * @brief MSC part of class instance data.
  104. */
  105. typedef struct {
  106. void * p_block_buff; //!< Block buffer
  107. size_t block_buff_size; //!< Block buffer size (typically 512 bytes)
  108. size_t block_buff_count; //!< Number of buffers (typically 2)
  109. nrf_block_dev_t const ** pp_block_devs; //!< Block devices list
  110. size_t block_devs_count; //!< Block device list size
  111. app_usbd_msc_user_ev_handler_t user_ev_handler; //!< User event handler
  112. app_usbd_msc_subclass_t subclass; //!< MSC subclass
  113. app_usbd_msc_protocol_t protocol; //!< MSC protocol
  114. } app_usbd_msc_inst_t;
  115. /**
  116. * @brief Internal module state.
  117. */
  118. typedef enum {
  119. APP_USBD_MSC_STATE_DISABLED, /**< Internal module state DISABLED */
  120. APP_USBD_MSC_STATE_IDLE, /**< Internal module state IDLE */
  121. APP_USBD_MSC_STATE_CBW, /**< Internal module state CBW */
  122. APP_USBD_MSC_STATE_CMD_IN, /**< Internal module state CMD_IN */
  123. APP_USBD_MSC_STATE_DATA_IN, /**< Internal module state DATA_IN */
  124. APP_USBD_MSC_STATE_DATA_OUT, /**< Internal module state DATA_OUT */
  125. APP_USBD_MSC_STATE_CSW, /**< Internal module state CSW */
  126. APP_USBD_MSC_STATE_UNSUPPORTED, /**< Internal module state UNSUPPORTED */
  127. APP_USBD_MSC_STATE_CBW_INVALID, /**< Endpoint is stalled until
  128. * the command @ref APP_USBD_MSC_REQ_BULK_RESET */
  129. APP_USBD_MSC_STATE_DEVICE_ERROR, /**< Endpoint is stalled and it is required
  130. * to send PE error when clearing */
  131. } app_usbd_msc_state_t;
  132. /**
  133. * @brief MSC context.
  134. *
  135. * */
  136. typedef struct {
  137. app_usbd_msc_state_t state; //!< Internal module state
  138. app_usbd_msc_cbw_t cbw; //!< SCSI command block wrapper
  139. app_usbd_msc_csw_t csw; //!< SCSI Command status wrapper
  140. /** @brief Currently processed command with data */
  141. struct
  142. {
  143. /** @brief Buffer data */
  144. struct
  145. {
  146. uint8_t rd_idx; //!< Buffer read index
  147. uint8_t d_count; //!< Number of blocks inside the buffer ready to process
  148. uint8_t a_count; //!< Number of blocks allocated in the buffer
  149. } buff;
  150. /** @brief Currently transfered block */
  151. struct
  152. {
  153. size_t size_left; //!< Number of bytes left to transfer
  154. size_t datalen_left; //!< Number of bytes left that was requested by the host
  155. bool pending; //!< The flag marking the pending transfer
  156. bool abort; //!< Something fails during reading - abort transfer and mark an error,
  157. //!< Used for read access.
  158. } transfer;
  159. /** @brief The block currently processed by block device */
  160. struct
  161. {
  162. uint8_t lun; //!< The logical unit for current transfer block
  163. size_t blk_size; //!< The size of the block of the selected lun
  164. size_t size_left; //!< Number of bytes left to be processed by block device
  165. size_t datalen_left; //!< Number of bytes left that was requested by the host
  166. uint32_t blk_idx; //!< Current block index
  167. bool pending; //!< The flag marking the pending transfer
  168. bool abort; //!< Something fails during transfer - abort processing and mark an error,
  169. //!< Used for write access.
  170. } process;
  171. } current;
  172. /** @brief SCSI response container*/
  173. union {
  174. app_usbd_scsi_cmd_inquiry_resp_t inquiry; //!< @ref APP_USBD_SCSI_CMD_INQUIRY response
  175. app_usbd_scsi_cmd_requestsense_resp_t requestsense; //!< @ref APP_USBD_SCSI_CMD_REQUESTSENSE response
  176. app_usbd_scsi_cmd_readcapacity10_resp_t readcapacity10; //!< @ref APP_USBD_SCSI_CMD_READCAPACITY10 response
  177. app_usbd_scsi_cmd_modesense6_resp_t modesense6; //!< @ref APP_USBD_SCSI_CMD_MODESENSE6 response
  178. app_usbd_scsi_cmd_modesense10_resp_t modesense10; //!< @ref APP_USBD_SCSI_CMD_MODESENSE10 response
  179. } scsi_resp;
  180. uint16_t blk_dev_init_mask; //!< Block devices init mask
  181. } app_usbd_msc_ctx_t;
  182. /**
  183. * @brief MSC configuration macro.
  184. *
  185. * Used by @ref APP_USBD_MSC_GLOBAL_DEF
  186. *
  187. * @param iface Interface number.
  188. * @param endpoints Endpoint list.
  189. * */
  190. #define APP_USBD_MSC_CONFIG(iface, endpoints) ((iface, BRACKET_EXTRACT(endpoints)))
  191. /**
  192. * @brief Specific class constant data for MSC.
  193. *
  194. * @ref app_usbd_msc_inst_t
  195. */
  196. #define APP_USBD_MSC_INSTANCE_SPECIFIC_DEC app_usbd_msc_inst_t inst;
  197. /**
  198. * @brief Configures MSC instance.
  199. *
  200. * @param p_devs Block devices list that is array of pointers of @ref nrf_block_dev_t type.
  201. * @param devs_cnt Number of block devices connected.
  202. * @param p_buff Block buffer.
  203. * @param block_size Total size of the single block in the buffer.
  204. * @param block_cnt Number of available block buffers.
  205. * @param user_event_handler User event handler.
  206. */
  207. #define APP_USBD_MSC_INST_CONFIG(p_devs, \
  208. devs_cnt, \
  209. p_buff, \
  210. block_size, \
  211. block_cnt, \
  212. user_event_handler) \
  213. .inst = { \
  214. .pp_block_devs = (p_devs), \
  215. .block_devs_count = (devs_cnt), \
  216. .p_block_buff = (p_buff), \
  217. .block_buff_size = (block_size), \
  218. .block_buff_count = (block_cnt), \
  219. .user_ev_handler = (user_event_handler), \
  220. .subclass = APP_USBD_MSC_SUBCLASS_TRANSPARENT, \
  221. .protocol = APP_USBD_MSC_PROTOCOL_BULK, \
  222. }
  223. /**
  224. * @brief Specific class data for MSC.
  225. *
  226. * @ref app_usbd_msc_ctx_t
  227. * */
  228. #define APP_USBD_MSC_DATA_SPECIFIC_DEC app_usbd_msc_ctx_t ctx;
  229. /**
  230. * @brief MSC descriptors config macro.
  231. *
  232. * @param interface_number Interface number.
  233. * @param ... Extracted endpoint list.
  234. * */
  235. #define APP_USBD_MSC_DSC_CONFIG(interface_number, ...) { \
  236. APP_USBD_MSC_INTERFACE_DSC(interface_number, \
  237. APP_USBD_MSC_SUBCLASS_TRANSPARENT, \
  238. APP_USBD_MSC_PROTOCOL_BULK) \
  239. APP_USBD_MSC_EP_DSC(GET_VA_ARG_1(__VA_ARGS__), \
  240. GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__)), \
  241. 64) \
  242. }
  243. /**
  244. * @brief Public MSC class interface.
  245. *
  246. * */
  247. extern const app_usbd_class_methods_t app_usbd_msc_class_methods;
  248. /**
  249. * @brief Global definition of mass storage class instance.
  250. */
  251. #define APP_USBD_MSC_GLOBAL_DEF_INTERNAL(instance_name, \
  252. interface_number, \
  253. user_ev_handler, \
  254. endpoint_list, \
  255. blockdev_list, \
  256. workbuffer_size) \
  257. static const nrf_block_dev_t * APP_USBD_MSC_BLKDEVS_NAME(instance_name)[] = \
  258. { BRACKET_EXTRACT(blockdev_list) }; \
  259. static uint32_t APP_USBD_MSC_BUFFER_NAME(instance_name) \
  260. [APP_USBD_MSC_BUFFER_CNT * CEIL_DIV(workbuffer_size, sizeof(uint32_t))]; \
  261. APP_USBD_CLASS_INST_GLOBAL_DEF( \
  262. instance_name, \
  263. app_usbd_msc, \
  264. &app_usbd_msc_class_methods, \
  265. APP_USBD_MSC_CONFIG(interface_number, endpoint_list), \
  266. (APP_USBD_MSC_INST_CONFIG(APP_USBD_MSC_BLKDEVS_NAME(instance_name), \
  267. ARRAY_SIZE(APP_USBD_MSC_BLKDEVS_NAME(instance_name)), \
  268. APP_USBD_MSC_BUFFER_NAME (instance_name), \
  269. sizeof(APP_USBD_MSC_BUFFER_NAME(instance_name)) \
  270. / APP_USBD_MSC_BUFFER_CNT, \
  271. APP_USBD_MSC_BUFFER_CNT, \
  272. user_ev_handler)) \
  273. )
  274. /** @} */
  275. #ifdef __cplusplus
  276. }
  277. #endif
  278. #endif /* APP_USBD_MSC_INTERNAL_H__ */