1 /***********************************************************************
2 * $Id:: mw_usbd_mscuser.h 577 2012-11-20 01:42:04Z usb10131                   $
3 *
4 * Project: USB device ROM Stack
5 *
6 * Description:
7 *     Mass Storage Class Custom User Module definitions.
8 *
9 ***********************************************************************
10 *   Copyright(C) 2011, NXP Semiconductor
11 *   All rights reserved.
12 *
13 * Software that is described herein is for illustrative purposes only
14 * which provides customers with programming information regarding the
15 * products. This software is supplied "AS IS" without any warranties.
16 * NXP Semiconductors assumes no responsibility or liability for the
17 * use of the software, conveys no license or title under any patent,
18 * copyright, or mask work right to the product. NXP Semiconductors
19 * reserves the right to make changes in the software without
20 * notification. NXP Semiconductors also make no representation or
21 * warranty that such application will be suitable for the specified
22 * use without further testing or modification.
23 **********************************************************************/
24 #ifndef __MSCUSER_H__
25 #define __MSCUSER_H__
26 
27 #include "error.h"
28 #include "usbd.h"
29 #include "usbd_msc.h"
30 #include "usbd_core.h"
31 #include "app_usbd_cfg.h"
32 
33 /** \file
34  *  \brief Mass Storage Class (MSC) API structures and function prototypes.
35  *
36  *  Definition of functions exported by ROM based MSC function driver.
37  *
38  */
39 
40 /** \ingroup Group_USBD
41  *  @defgroup USBD_MSC Mass Storage Class (MSC) Function Driver
42  *  \section Sec_MSCModDescription Module Description
43  *  MSC Class Function Driver module. This module contains an internal implementation of the USB MSC Class.
44  *  User applications can use this class driver instead of implementing the MSC class manually
45  *  via the low-level USBD_HW and USBD_Core APIs.
46  *
47  *  This module is designed to simplify the user code by exposing only the required interface needed to interface with
48  *  Devices using the USB MSC Class.
49  */
50 
51 /** \brief Mass Storage class function driver initialization parameter data structure.
52  *  \ingroup USBD_MSC
53  *
54  *  \details  This data structure is used to pass initialization parameters to the
55  *  Mass Storage class function driver's init function.
56  *
57  */
58 typedef struct USBD_MSC_INIT_PARAM
59 {
60   /* memory allocation params */
61   uint32_t mem_base;  /**< Base memory location from where the stack can allocate
62                       data and buffers. \note The memory address set in this field
63                       should be accessible by USB DMA controller. Also this value
64                       should be aligned on 4 byte boundary.
65                       */
66   uint32_t mem_size;  /**< The size of memory buffer which stack can use.
67                       \note The \em mem_size should be greater than the size
68                       returned by USBD_MSC_API::GetMemSize() routine.*/
69   /* mass storage params */
70   uint8_t*  InquiryStr; /**< Pointer to the 28 character string. This string is
71                         sent in response to the SCSI Inquiry command. \note The data
72                         pointed by the pointer should be of global scope.
73                         */
74   uint32_t  BlockCount; /**< Number of blocks present in the mass storage device */
75   uint32_t  BlockSize; /**< Block size in number of bytes */
76   uint32_t  MemorySize; /**< Memory size in number of bytes */
77   /** Pointer to the interface descriptor within the descriptor
78   * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T
79   * structure. The stack assumes both HS and FS use same BULK endpoints.
80   */
81 
82   uint8_t* intf_desc;
83   /* user defined functions */
84 
85  /**
86   *  MSC Write callback function.
87   *
88   *  This function is provided by the application software. This function gets called
89   *  when host sends a write command.
90   *
91   *  \param[in] offset Destination start address.
92   *  \param[in, out] src  Pointer to a pointer to the source of data. Pointer-to-pointer
93   *                       is used to implement zero-copy buffers. See \ref USBD_ZeroCopy
94   *                       for more details on zero-copy concept.
95   *  \param[in] length  Number of bytes to be written.
96   *  \return Nothing.
97   *
98   */
99   void (*MSC_Write)( uint32_t offset, uint8_t** src, uint32_t length, uint32_t high_offset);
100  /**
101   *  MSC Read callback function.
102   *
103   *  This function is provided by the application software. This function gets called
104   *  when host sends a read command.
105   *
106   *  \param[in] offset Source start address.
107   *  \param[in, out] dst  Pointer to a pointer to the source of data. The MSC function drivers
108   *         implemented in stack are written with zero-copy model. Meaning the stack doesn't make an
109   *          extra copy of buffer before writing/reading data from USB hardware FIFO. Hence the
110   *          parameter is pointer to a pointer containing address buffer (<em>uint8_t** dst</em>).
111   *          So that the user application can update the buffer pointer instead of copying data to
112   *          address pointed by the parameter. /note The updated buffer address should be accessible
113   *          by USB DMA master. If user doesn't want to use zero-copy model, then the user should copy
114   *          data to the address pointed by the passed buffer pointer parameter and shouldn't change
115   *          the address value. See \ref USBD_ZeroCopy for more details on zero-copy concept.
116   *  \param[in] length  Number of bytes to be read.
117   *  \return Nothing.
118   *
119   */
120   void (*MSC_Read)( uint32_t offset, uint8_t** dst, uint32_t length, uint32_t high_offset);
121  /**
122   *  MSC Verify callback function.
123   *
124   *  This function is provided by the application software. This function gets called
125   *  when host sends a verify command. The callback function should compare the buffer
126   *  with the destination memory at the requested offset and
127   *
128   *  \param[in] offset Destination start address.
129   *  \param[in] buf  Buffer containing the data sent by the host.
130   *  \param[in] length  Number of bytes to verify.
131   *  \return Returns \ref ErrorCode_t type to indicate success or error condition.
132   *          \retval LPC_OK If data in the buffer matches the data at destination
133   *          \retval ERR_FAILED  At least one byte is different.
134   *
135   */
136   ErrorCode_t (*MSC_Verify)( uint32_t offset, uint8_t buf[], uint32_t length, uint32_t high_offset);
137   /**
138   *  Optional callback function to optimize MSC_Write buffer transfer.
139   *
140   *  This function is provided by the application software. This function gets called
141   *  when host sends SCSI_WRITE10/SCSI_WRITE12 command. The callback function should
142   *  update the \em buff_adr pointer so that the stack transfers the data directly
143   *  to the target buffer. /note The updated buffer address should be accessible
144   *  by USB DMA master. If user doesn't want to use zero-copy model, then the user
145   *  should not update the buffer pointer. See \ref USBD_ZeroCopy for more details
146   *  on zero-copy concept.
147   *
148   *  \param[in] offset Destination start address.
149   *  \param[in,out] buf  Buffer containing the data sent by the host.
150   *  \param[in] length  Number of bytes to write.
151   *  \return Nothing.
152   *
153   */
154   void (*MSC_GetWriteBuf)( uint32_t offset, uint8_t** buff_adr, uint32_t length, uint32_t high_offset);
155 
156   /**
157   *  Optional user override-able function to replace the default MSC class handler.
158   *
159   *  The application software could override the default EP0 class handler with their
160   *  own by providing the handler function address as this data member of the parameter
161   *  structure. Application which like the default handler should set this data member
162   *  to zero before calling the USBD_MSC_API::Init().
163   *  \n
164   *  \note
165   *
166   *  \param[in] hUsb Handle to the USB device stack.
167   *  \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
168   *  \param[in] event  Type of endpoint event. See \ref USBD_EVENT_T for more details.
169   *  \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
170   *          \retval LPC_OK On success.
171   *          \retval ERR_USBD_UNHANDLED  Event is not handled hence pass the event to next in line.
172   *          \retval ERR_USBD_xxx  For other error conditions.
173   *
174   */
175   ErrorCode_t (*MSC_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
176 
177   uint64_t  MemorySize64;
178 
179 } USBD_MSC_INIT_PARAM_T;
180 
181 /** \brief MSC class API functions structure.
182  *  \ingroup USBD_MSC
183  *
184  *  This module exposes functions which interact directly with USB device controller hardware.
185  *
186  */
187 typedef struct USBD_MSC_API
188 {
189   /** \fn uint32_t GetMemSize(USBD_MSC_INIT_PARAM_T* param)
190    *  Function to determine the memory required by the MSC function driver module.
191    *
192    *  This function is called by application layer before calling pUsbApi->msc->Init(), to allocate memory used
193    *  by MSC function driver module. The application should allocate the memory which is accessible by USB
194    *  controller/DMA controller.
195    *  \note Some memory areas are not accessible by all bus masters.
196    *
197    *  \param[in] param Structure containing MSC function driver module initialization parameters.
198    *  \return Returns the required memory size in bytes.
199    */
200   uint32_t (*GetMemSize)(USBD_MSC_INIT_PARAM_T* param);
201 
202   /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param)
203    *  Function to initialize MSC function driver module.
204    *
205    *  This function is called by application layer to initialize MSC function driver module.
206    *
207    *  \param[in] hUsb Handle to the USB device stack.
208    *  \param[in, out] param Structure containing MSC function driver module initialization parameters.
209    *  \return Returns \ref ErrorCode_t type to indicate success or error condition.
210    *          \retval LPC_OK On success
211    *          \retval ERR_USBD_BAD_MEM_BUF  Memory buffer passed is not 4-byte
212    *              aligned or smaller than required.
213    *          \retval ERR_API_INVALID_PARAM2 Either MSC_Write() or MSC_Read() or
214    *              MSC_Verify() callbacks are not defined.
215    *          \retval ERR_USBD_BAD_INTF_DESC  Wrong interface descriptor is passed.
216    *          \retval ERR_USBD_BAD_EP_DESC  Wrong endpoint descriptor is passed.
217    */
218   ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param);
219 
220 } USBD_MSC_API_T;
221 
222 /*-----------------------------------------------------------------------------
223  *  Private functions & structures prototypes
224  *-----------------------------------------------------------------------------*/
225 /** @cond  ADVANCED_API */
226 
227 typedef struct _MSC_CTRL_T
228 {
229   /* If it's a USB HS, the max packet is 512, if it's USB FS,
230   the max packet is 64. Use 512 for both HS and FS. */
231   /*ALIGNED(4)*/ uint8_t  BulkBuf[USB_HS_MAX_BULK_PACKET]; /* Bulk In/Out Buffer */
232   /*ALIGNED(4)*/MSC_CBW CBW;                   /* Command Block Wrapper */
233   /*ALIGNED(4)*/MSC_CSW CSW;                   /* Command Status Wrapper */
234 
235   USB_CORE_CTRL_T*  pUsbCtrl;
236 
237   uint64_t Offset;                  /* R/W Offset */
238   uint32_t Length;                  /* R/W Length */
239   uint32_t BulkLen;                 /* Bulk In/Out Length */
240   uint8_t* rx_buf;
241 
242   uint8_t BulkStage;               /* Bulk Stage */
243   uint8_t if_num;                  /* interface number */
244   uint8_t epin_num;                /* BULK IN endpoint number */
245   uint8_t epout_num;               /* BULK OUT endpoint number */
246   uint32_t MemOK;                  /* Memory OK */
247 
248   uint8_t*  InquiryStr;
249   uint32_t  BlockCount;
250   uint32_t  BlockSize;
251   uint64_t  MemorySize;
252   /* user defined functions */
253   void (*MSC_Write)( uint32_t offset, uint8_t** src, uint32_t length, uint32_t high_offset);
254   void (*MSC_Read)( uint32_t offset, uint8_t** dst, uint32_t length, uint32_t high_offset);
255   ErrorCode_t (*MSC_Verify)( uint32_t offset, uint8_t src[], uint32_t length, uint32_t high_offset);
256   /* optional call back for MSC_Write optimization */
257   void (*MSC_GetWriteBuf)( uint32_t offset, uint8_t** buff_adr, uint32_t length, uint32_t high_offset);
258 
259 
260 }USB_MSC_CTRL_T;
261 
262 /** @cond  DIRECT_API */
263 extern uint32_t mwMSC_GetMemSize(USBD_MSC_INIT_PARAM_T* param);
264 extern ErrorCode_t mwMSC_init(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param);
265 /** @endcond */
266 
267 /** @endcond */
268 
269 
270 #endif  /* __MSCUSER_H__ */
271