1 /*******************************************************************************
2  * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  * PolarFire SoC MSS USB Host logical driver layer Implementation.
25  *
26  * PolarFire SoC MSS USB Driver Stack
27  *      USB Logical Layer (USB-LL)
28  *          USBH-MSC class driver.
29  *
30  * USBH-MSC driver public API.
31  *
32  */
33 
34 /*=========================================================================*//**
35   @mainpage PolarFire SoC MSS USB driver (USBH-MSC)
36 
37   ==============================================================================
38   Introduction
39   ==============================================================================
40   The Mass Storage Class host driver implements the USB host controller as per
41   the USB MSC class specified by the USB-IF. This driver enables easy detection
42   and data transfers with the attached USB mass storage devices.
43 
44   This driver implements the MSC class using Bulk Only transport (BOT). One
45   BULK IN and one BULK OUT endpoints are used to implement BOT. This MSC class
46   host supports one LUN.
47 
48   This driver uses the USBH driver interface functions to implement the USB MSC
49   host. This host controller will be able to work with all the USB flash drives
50   which fall in "Memory stick" category.
51 
52   ==============================================================================
53   Theory of Operation
54   ==============================================================================
55   The following steps are involved in the operation of USBH-MSC driver:
56     - Configuration
57     - Initialization
58     - Enumeration
59     - Class Specific requests
60     - Data transfer
61 
62   --------------------------------
63   Configuration
64   --------------------------------
65   The MSS USB driver must first be configured in the USB Host mode using the
66   MSS_USB_HOST_MODE to use this driver. No other configuration is necessary.
67 
68   --------------------------------
69   Initialization
70   --------------------------------
71   The MSC class driver must be initialized using the MSS_USBH_MSC_init() function.
72   A pointer to the structure of type mss_usbh_msc_user_cb_t must be provided as
73   parameter with this function. This pointer is used to call the application
74   call-back functions by the USBH-MSC driver. These call-back functions can be
75   used by the application to provide error/status messages to the user or for
76   performing application specific handling of the events.
77 
78   --------------------------------
79   Class Specific requests
80   --------------------------------
81   The class specific requests are handled internally by this driver. Both the
82   GET_MAX_LUN and the RESET_RECOVERY requests are supported. The GET_MAX_LUN
83   request is executed after the enumeration process to find out the number of
84   LUNs on the attached device. This driver supports one LUN (index 0).
85 
86   --------------------------------
87   Application call-back interface
88   --------------------------------
89   After the USBH-Class driver is assigned to the attached device by the USBH
90   driver, as indicated by usbh_class_allocate call-back, this driver can take
91   over the communication with the attached device. This driver will then extend
92   the enumeration process by requesting the class specific information from the
93   device. During this process it will also call the call-back functions to
94   indicate the progress of the enumeration process. These call-back functions
95   must be implemented by application. These call-back functions can be used to
96   take application specific action on specific event or can be used to provide
97   error/status messages to the user. A type mss_usbh_msc_user_cb_t is provided
98   by this driver which has all these call-back functions as its elements.
99   Implementing these call-back functions is optional.
100 
101   |           Element                      |     Call-back Event               |
102   |----------------------------------------|-----------------------------------|
103   | void (*msch_valid_config)(void)        | Called to indicate that a valid   |
104   |                                        | MSC class configuration was found |
105   |                                        | on the attached device and the    |
106   |                                        | device is configured for this     |
107   |                                        | configuration.                    |
108   |                                        |                                   |
109   | void (*msch_tdev_ready)(void)          | Called when this driver is able   |
110   |                                        | to retrieve all the MSC class     |
111   |                                        | specific info (including sector   |
112   |                                        | size and sector number) from the  |
113   |                                        | attached device and is ready to   |
114   |                                        | perform data transfers.           |
115   |                                        |                                   |
116   | void (*msch_driver_released)(void)     | Called to indicate to the         |
117   |                                        | application that this driver is   |
118   |                                        | released by the USBH driver       |
119   |                                        |                                   |
120   | void (*msch_error)(int8_t error_code)  | Called to indicate that there was |
121   |                                        | an error while retrieving the     |
122   |                                        | class specific descriptor         |
123   |                                        | information from the attached MSC |
124   |                                        | class device.                     |
125 
126   --------------------------------
127   Data transfer
128   --------------------------------
129   The MSC class driver performs the data transfers using one BULK IN endpoint
130   and one BULK OUT endpoint. The data transfers use transparent SCSI commands
131   and follow the BoT specification. The BoT read/write operations happen on
132   logical units of fixed block size. During initialization this driver takes
133   care of finding all information about the attached device. The
134   MSS_USBH_MSC_get_sector_count() and MSS_USBH_MSC_get_sector_size() functions
135   can be used to find out the sector count and the sector size on the attached
136   MSC class device.
137 
138   Most of the times the read (READ_10) and write (WRITE_10) are the only SCSI
139   operations that the application needs to do. The MSS_USBH_MSC_read() and
140   MSS_USBH_MSC_write() functions are provided for this purpose. The application
141   can use the MSS_USBH_MSC_scsi_req() function if it needs to perform any other
142   SCSI operation. This function can be used for READ_10 and WRITE_10 commands as
143   well. Once the SCSI request is initiated using any of the above functions,
144   the MSS_USBH_MSC_is_scsi_req_complete() function can be used to find out when
145   the operation is complete.
146 
147   The USBH driver supports multi-packet Bulk transfers. The USBH-MSC driver makes
148   full use of this feature by passing on the multi-sector transfers from the
149   application to the USBH driver. To free up the application from transferring
150   data to/from MSS USB FIFO, this driver can configure USBH driver to use the
151   MSS USB internal DMA.
152 
153   The MSS_USBH_MSC_construct_cbw_cb10byte() and MSS_USBH_MSC_construct_cbw_cb6byte()
154   functions are provided so that the user can easily prepare the CBW format
155   buffer by providing appropriate parameters instead of manually creating the
156   CBW command buffer.
157 
158  *//*=========================================================================*/
159 
160 #ifndef __MSS_USB_HOST_MSC_H_
161 #define __MSS_USB_HOST_MSC_H_
162 
163 #include <stdint.h>
164 #include "mss_usb_config.h"
165 
166 #ifdef __cplusplus
167 extern "C" {
168 #endif
169 
170 #ifdef MSS_USB_HOST_ENABLED
171 
172 /*-------------------------------------------------------------------------*//**
173  Types exported from USBH-MSC driver
174   ============================
175  */
176 /*-------------------------------------------------------------------------*//**
177   The mss_usbh_msc_err_code_t provides a type to identify the error occurred
178   during retrieving configuration and other class specific descriptors from the
179   attached MSC class device. This type can be used with msch_error  call-back
180   function element of mss_usbh_msc_user_cb_t type to identify the exact cause
181   of the error. The meaning of the constants is as described below
182 
183   |   Value                      | Description                                  |
184   |----------------------------- |----------------------------------------------|
185   | USBH_MSC_EP_NOT_VALID        | Indicates that the endpoint information      |
186   |                              | retrieved from the attached device was not   |
187   |                              | consistent with the MSC class.               |
188   |                              |                                              |
189   | USBH_MSC_CLR_CEP_STALL_ERROR | Indicates that the host controller was not   |
190   |                              | able to clear the stall condition on the     |
191   |                              | attached device even after multiple retries. |
192   |                              |                                              |
193   | USBH_MSC_SECTOR_SIZE_NOT_    | Indicates that the attached device sector    |
194   | SUPPORTED                    | size is not supported by this driver.        |
195 
196  */
197 typedef enum {
198     USBH_MSC_NO_ERROR = 0,
199     USBH_MSC_EP_NOT_VALID = -1,
200     USBH_MSC_CLR_CEP_STALL_ERROR = -2,
201     USBH_MSC_SECTOR_SIZE_NOT_SUPPORTED = -3,
202     USBH_MSC_WRONG_DESCR = -4,
203 } mss_usbh_msc_err_code_t;
204 
205 /*-------------------------------------------------------------------------*//**
206   The mss_usbh_msc_state_t provides a type for the states of operation of the
207   USBH-MSC driver. Most of the states are internally used by the USBH-MSC driver
208   during the enumeration process. The USBH-MSC driver is ready to perform data
209   transfers with the attached device when the driver is in state
210   USBH_MSC_DEVICE_READY. The USBH_MSC_ERROR state indicates that the error was
211   detected either during enumeration or during the normal data transfer
212   operations with the attached device even after retries.
213  */
214 typedef enum {
215     USBH_MSC_IDLE,
216     USBH_MSC_GET_CLASS_DESCR,
217     USBH_MSC_WAIT_GET_CLASS_DESCR,
218     USBH_MSC_SET_CONFIG,
219     USBH_MSC_WAIT_SET_CONFIG,
220     USBH_MSC_WAIT_DEV_SETTLE,
221     USBH_MSC_GET_MAX_LUN,
222     USBH_MSC_WAIT_GET_MAX_LUN,
223     USBH_MSC_CLR_CEP_STALL,
224     USBH_MSC_WAIT_CLR_CEP_STALL,
225     USBH_MSC_CONFIG_BULK_ENDPOINTS,
226 
227     USBH_MSC_TEST_UNIT_READY_CPHASE,
228     USBH_MSC_TEST_UNIT_READY_SPHASE,
229     USBH_MSC_TEST_UNIT_READY_WAITCOMPLETE,
230 
231     USBH_MSC_SCSI_INQUIRY_CPHASE,
232     USBH_MSC_SCSI_INQUIRY_DPHASE,
233     USBH_MSC_SCSI_INQUIRY_SPHASE,
234     USBH_MSC_SCSI_INQUIRY_WAITCOMPLETE,
235 
236     USBH_MSC_SCSI_REQSENSE_CPHASE,
237     USBH_MSC_SCSI_REQSENSE_DPHASE,
238     USBH_MSC_SCSI_REQSENSE_SPHASE,
239     USBH_MSC_SCSI_REQSENSE_WAITCOMPLETE,
240 
241     USBH_MSC_SCSI_READ_CAPACITY_CPHASE,
242     USBH_MSC_SCSI_READ_CAPACITY_DPHASE,
243     USBH_MSC_SCSI_READ_CAPACITY_SPHASE,
244     USBH_MSC_SCSI_READ_CAPACITY_WAITCOMPLETE,
245 
246     USBH_MSC_DEVICE_READY,
247     USBH_MSC_BOT_RETRY,
248     USBH_MSC_ERROR
249 } mss_usbh_msc_state_t;
250 
251 /*----------------------------------------------------------------------------*/
252 /*---------------Data structures exported by USBH-MSC driver   ---------------*/
253 /*----------------------------------------------------------------------------*/
254 
255 /*-------------------------------------------------------------------------*//**
256   The mss_usbh_msc_user_cb_t provides the prototype for all the call-back
257   functions which must be implemented by the user application. The user
258   application must define and initialize a structure of this type and provide
259   the address of that structure as parameter to the MSS_USBH_MSC_init() function.
260 
261   msch_valid_config
262   The function pointed by the msch_valid_config function pointer will be called
263   to indicate that a valid MSC class configuration was found on the attached
264   device and the device is configured for this configuration.
265 
266   msch_tdev_ready
267   The function pointed by the msch_tdev_ready function pointer is called when
268   this driver is able to retrieve all the MSC class specific information
269   (including sector size and sector number) from the attached device and is
270   ready to perform the data transfers.
271 
272   msch_driver_released
273   The function pointed by the msch_driver_released function pointer is called to
274   indicate to the application that this driver is released by the USBH driver.
275   This could be either because the MSC class device is now detached or there is
276   permanent error with the USBH driver.
277 
278   msch_error
279   The function pointed by the msch_error function pointer is called to indicate
280   that there was an error while retrieving the class specific descriptor
281   information from the attached MSC class device. The error_code parameter
282   indicates the exact cause of the error.
283 */
284 typedef struct mss_usbh_msc_user_cb
285 {
286   void (*msch_valid_config)(void);
287   void (*msch_tdev_ready)(void);
288   void (*msch_driver_released)(void);
289   void (*msch_error)(int8_t error_code);
290 } mss_usbh_msc_user_cb_t;
291 
292 /*-------------------------------------------------------------------------*//**
293   The msd_cbw_t type provides the prototype for the Command Block Wrapper (CBW)
294   as defined in Universal Serial Bus Mass Storage Class Bulk-Only Transport
295   Revision 1.0. This type can be used by the application to create buffer of
296   this type for creating the CBW which can then be passed on to functions
297   provided by this driver as parameter.
298 
299   dCBWSignature
300   Signature that helps identify this data packet as a CBW. The signature field
301   shall contain the value 43425355h (little endian), indicating a CBW.
302 
303   dCBWTag
304   A Command Block Tag sent by the host. The device shall echo the contents of
305   this field back to the host in the dCSWTagfield of the associated CSW. The
306   dCSWTagpositively associates a CSW with the corresponding CBW.
307 
308   dCBWDataTransferLength
309   The number of bytes of data that the host expects to transfer on the Bulk-In
310   or Bulk-Out endpoint (as indicated by the Direction-bit) during the execution
311   of this command. If this field is zero, the device and the host shall transfer
312   no data between the CBW and the associated CSW, and the device shall ignore
313   the value of the Direction-bit in bmCBWFlags.
314 
315   bCBWFlags
316   The bits of this field are defined as follows:
317 
318     | Bit        | Description                                                 |
319     |------------|-------------------------------------------------------------|
320     | Bit 7      | Direction- the device shall ignore this bit if the          |
321     |            | dCBWDataTransferLengthfield is zero, otherwise:             |
322     |            | 0 = Data-Out from host to the device,                       |
323     |            | 1 = Data-In from the device to the host.                    |
324     |            |                                                             |
325     | Bit 6      | Obsolete. The host shall set this bit to zero.              |
326     | Bits 5..0  | Reserved - the host shall set these bits to zero.           |
327 
328   bCBWLUN
329   The device Logical Unit Number (LUN) to which the command block is being sent.
330   For devices that support multiple LUNs, the host shall place into this field
331   the LUN to which this command block is addressed. Otherwise, the host shall
332   set this field to zero.
333 
334   bCBWCBLength
335   The valid length of the CBWCBin bytes. This defines the valid length of the
336   command block. The only legal values are 1 through 16 (01h through 10h).
337   All other values are reserved.
338 
339   CBWCB[16]
340   The command block to be executed by the device. The device shall interpret the
341   first bCBWCBLength bytes in this field as a command block as defined by the
342   command set identified by bInterfaceSubClass. If the command set supported by
343   the device uses command blocks of fewer than 16 (10h) bytes in length, the
344   significant bytes shall be transferred first, beginning with the byte at
345   offset 15 (0Fh). The device shall ignore the content of the CBWCBfield past
346   the byte at offset (15 + bCBWCBLength- 1)
347  */
348 typedef struct {
349  uint32_t dCBWSignature;
350  uint32_t dCBWTag;
351  uint32_t dCBWDataTransferLength;
352  uint8_t bCBWFlags;
353  uint8_t bCBWLUN;
354  uint8_t bCBWCBLength;
355  uint8_t CBWCB[16];
356 } msd_cbw_t;
357 
358 /*-------------------------------------------------------------------------*//**
359   The msd_csw_t type provides the prototype for the Command Status Wrapper (CSW)
360   as defined in Universal Serial Bus Mass Storage Class Bulk-Only Transport
361   Revision 1.0. This type can be used by application to create buffer of this
362   type for creating CSW which can then be passed on to APIs provided by this
363   driver as parameter.
364 
365   dCSWSignature
366     Signature that helps identify this data packet as a CSW. The signature field
367     shall contain the value 53425355h (little endian), indicating CSW.
368 
369   dCSWTag
370     The device shall set this field to the value received in the dCBWTag of the
371     associated CBW.
372 
373   dCSWDataResidue
374     For Data-Out the device shall report in the dCSWDataResiduethe difference
375     between the amount of data expected as stated in the dCBWDataTransferLength,
376     and the actual amount of data processed by the device. For Data-In the device
377     shall report in the dCSWDataResiduethe difference between the amount of data
378     expected as stated in the dCBWDataTransferLengthand the actual amount of
379     relevant data sent by the device. The dCSWDataResidueshall not exceed the
380     value sent in the dCBWDataTransferLength.
381 
382   dCSWStatus
383     bCSWStatusindicates the success or failure of the command. The device shall
384     set this byte to zero if the command completed successfully. A non-zero value
385     shall indicate a failure during command execution according to the following
386     table:
387     |    Value             |  Description                          |
388     |----------------------|---------------------------------------|
389     |   00h                | Command Passed ("good status")        |
390     |   01h                | Command Failed                        |
391     |   02h                | Phase Error                           |
392     |   03h and 04h        | Reserved (Obsolete)                   |
393     |   05h to FFh         | Reserved
394  */
395 typedef struct {
396  uint32_t dCSWSignature;
397  uint32_t dCSWTag;
398  uint32_t dCSWDataResidue;
399  uint32_t dCSWStatus;
400 } msd_csw_t;
401 
402 /*-------------------------------------------------------------------------*//**
403   EXPORTED APIs from USBH-MSC driver
404   ============================
405  */
406 /*-------------------------------------------------------------------------*//**
407   The MSS_USBH_MSC_init() function must be used by the application to initialize
408   the USBH-MSC driver. This function must be called before any other function of
409   the USBH-MSC driver.
410 
411   @param user_cb
412     The user_cb parameter provides a pointer to the structure of type
413     mss_usbh_msc_user_cb_t. This pointer is used to call the application
414     call-back functions by the USBH-MSC driver. These call-back functions can be
415     used by the application to provide error/status messages to the user or for
416     performing the application specific handling of the events.
417 
418   @return
419     This function does not return a value.
420 
421   Example:
422   @code
423       Initialize the USBH driver
424       MSS_USBH_init(&MSS_USBH_user_cb);
425 
426       Initialize the USBH-MSC driver
427       MSS_USBH_MSC_init(&MSS_USBH_MSC_user_cb);
428 
429 
430       Get Class driver handle from the USBH-MSC class driver and register it with
431       the USBH driver.
432       On Device attachment, USBH driver will look for Device information through
433       Descriptors and if match it with the Class driver using this Handle.
434       MSS_USBH_register_class_driver(MSS_USBH_MSC_get_handle());
435     @endcode
436  */
437 void
438 MSS_USBH_MSC_init
439 (
440     mss_usbh_msc_user_cb_t* user_sb
441 );
442 
443 /*-------------------------------------------------------------------------*//**
444   The MSS_USBH_MSC_task() function is the main task of the USBH-MSC driver.
445   This function monitors the events from the USBH driver as well as the user
446   application and makes decisions. This function must be called repeatedly by
447   the application to allow the USBH-MSC driver to perform the housekeeping tasks.
448   A timer/scheduler can be used to call this function at regular intervals or
449   it can be called from the main continuous foreground loop of the application.
450 
451   @param
452     This function does not take any parameters.
453 
454   @return
455     This function does not return a value.
456 
457   Example:
458   @code
459       #define SYS_TICK_LOAD_VALUE                             48000u
460       int main()
461       {
462           Initialize SysTick
463           SysTick_Config(SYS_TICK_LOAD_VALUE);
464           NVIC_EnableIRQ(SysTick_IRQn);
465       }
466       void SysTick_Handler(void)
467       {
468           MSS_USBH_MSC_task();
469       }
470   @endcode
471  */
472 void
473 MSS_USBH_MSC_task
474 (
475     void
476 );
477 
478 /*-------------------------------------------------------------------------*//**
479   The MSS_USBH_MSC_get_handle() function must be used by the application to get
480   the handle from the USBH-MSC driver. This handle must then be used to register
481   this driver with the USBH driver.
482 
483   @param
484     This function does not take any parameters.
485 
486   @return
487     This function returns a pointer to the class-handle structure.
488 
489   Example:
490   @code
491       MSS_USBH_init(&MSS_USBH_user_cb);
492       MSS_USBH_MSC_init(&MSS_USBH_MSC_user_cb);
493       MSS_USBH_register_class_driver(MSS_USBH_MSC_get_handle());
494     @endcode
495 */
496 void*
497 MSS_USBH_MSC_get_handle
498 (
499     void
500 );
501 
502 /*-------------------------------------------------------------------------*//**
503   The MSS_USBH_MSC_get_state() function can be used to find out the current state
504   of the USBH-MSC driver. This information can be used by the application to check
505   the readiness of the USBH-MSC driver to start the data transfers. The USBH-MSC
506   driver can perform data transfers only when it is in the USBH_MSC_DEVICE_READY
507   state.
508 
509   @param
510     This function does not take any parameters.
511 
512   @return
513     This function returns a value of type mss_usbh_msc_state_t indicating the
514     current state of the USBH-MSC driver.
515 
516   Example:
517   @code
518       if(USBH_MSC_DEVICE_READY == MSS_USBH_MSC_get_state())
519       {
520           *result = MSS_USBH_MSC_get_sector_count();
521           return RES_OK;
522       }
523       else if(USBH_MSC_DEVICE_READY < MSS_USBH_MSC_get_state())
524       {
525           *result = 0u;
526           return RES_NOTRDY;
527       }
528   @endcode
529  */
530 mss_usbh_msc_state_t
531 MSS_USBH_MSC_get_state
532 (
533     void
534 );
535 
536 /*-------------------------------------------------------------------------*//**
537   The MSS_USBH_MSC_read() function can be used to read data from the attached
538   mass storage device. This is a non-blocking function. The function prepares
539   the MSS USB for the USB IN transfer. Once prepared, the MSS USB will start
540   this IN transfer depending on the configuration of the IN pipe on which this
541   transfer is occurring. The USBH-MSC driver takes care of the allocation and
542   configuration of the IN pipe during enumeration process depending on the
543   attached mass storage device. After preparing the IN pipe for the IN transfer,
544   the MSS_USBH_MSC_is_scsi_req_complete() function can be used to find out the
545   completion of the transfer.
546 
547   @param buf
548     The buf parameter is a pointer to the buffer where the data received in the
549     IN transfer from the attached MSC class device is stored.
550 
551   @param sector
552     The sector parameter indicates the sector number (logical block address) on
553     the mass storage device starting from which the data is to be read.
554 
555   @param count
556     The count parameter indicates the number of sectors to be read.
557 
558   @return
559     This function returns a zero value when execution was successful.
560 
561   Example:
562   @code
563       DRESULT disk_read (BYTE drv,
564           BYTE *buff,
565           DWORD sector,
566           BYTE count)
567       {
568           if (0u != drv)
569               return(RES_ERROR);
570           if (USBH_MSC_DEVICE_READY < MSS_USBH_MSC_get_state())
571           {
572               return(RES_NOTRDY);
573           }
574           else if (USBH_MSC_DEVICE_READY == MSS_USBH_MSC_get_state())
575           {
576               MSS_USBH_MSC_read(buff, sector, count);
577               while (MSS_USBH_MSC_is_scsi_req_complete());
578               return (RES_OK);
579           }
580           else
581               return (RES_ERROR);
582       }
583   @endcode
584 */
585 int8_t
586 MSS_USBH_MSC_read
587 (
588     uint8_t* buf,
589     uint32_t sector,
590     uint32_t count
591 );
592 
593 /*-------------------------------------------------------------------------*//**
594   The MSS_USBH_MSC_write() function can be used to write data to the attached
595   mass storage device. This is a non-blocking function. The function readies the
596   MSS USB for the USB OUT transfer. Once ready, the MSS USB will start this OUT
597   transfer depending on the configuration of the OUT pipe on which this transfer
598   is occurring. The USBH-MSC driver takes care of the allocation and
599   configuration of the OUT pipe during enumeration process depending on the
600   attached mass storage device. After starting the OUT transfer on the specified
601   OUT pipe, the MSS_USBH_MSC_is_scsi_req_complete() function can be used to find
602   out the completion of the transfer.
603 
604   @param buf
605     The buf parameter is a pointer to the buffer from which data need to be
606     transmitted to the attached MSC class device.
607 
608   @param sector
609     The sector parameter indicates the sector number (logical block address) on
610     the mass storage device starting from which the data is to be written.
611 
612   @param count
613     The count parameter indicates the number of sectors to be written.
614 
615   @return
616     This function returns a zero value when execution was successful.
617 
618   Example:
619   @code
620       DRESULT disk_write (BYTE pdrv,
621           const BYTE *buff,
622           DWORD sector,
623           BYTE count)
624       {
625           if (0u != pdrv)
626               return(RES_ERROR);
627 
628           if (USBH_MSC_DEVICE_READY < MSS_USBH_MSC_get_state())
629           {
630               return(RES_NOTRDY);
631           }
632           else if (USBH_MSC_DEVICE_READY == MSS_USBH_MSC_get_state())
633           {
634               MSS_USBH_MSC_write((uint8_t*)buff, sector, count);
635               while (MSS_USBH_MSC_is_scsi_req_complete());
636               return (RES_OK);
637           }
638           else
639               return (RES_ERROR);
640       }
641   @endcode
642 */
643 int8_t
644 MSS_USBH_MSC_write
645 (
646     uint8_t* buf,
647     uint32_t sector,
648     uint32_t count
649 );
650 
651 /*-------------------------------------------------------------------------*//**
652   The MSS_USBH_MSC_get_sector_count() function can be used to find out the
653   number of sectors (logical blocks) available on the attached MSC class device.
654 
655   @param
656     This function does not take any parameters.
657 
658   @return
659     This function returns a value of type uint32_t indicating the number of
660     sectors (logical blocks) available on the attached MSC class device.
661 
662   Example:
663   @code
664       DRESULT disk_ioctl (
665           BYTE pdrv,
666           BYTE ctrl,
667           void *buff)
668       )
669       {
670           UINT *result = (UINT *)buff;
671 
672           switch (ctrl) {
673           case GET_SECTOR_COUNT:
674               if (USBH_MSC_DEVICE_READY == MSS_USBH_MSC_get_state())
675               {
676                   *result = MSS_USBH_MSC_get_sector_count();
677                   return RES_OK;
678               }
679               else if (USBH_MSC_DEVICE_READY < MSS_USBH_MSC_get_state())
680               {
681                   *result = 0u;
682                   return RES_NOTRDY;
683               }
684               else
685               {
686                   *result = 0u;
687                   return RES_ERROR;
688               }
689               break;
690 
691           default:
692               return RES_NOTRDY;
693           }
694       }
695   @endcode
696  */
697 uint32_t
698 MSS_USBH_MSC_get_sector_count
699 (
700     void
701 );
702 
703 /*-------------------------------------------------------------------------*//**
704   The MSS_USBH_MSC_get_sector_size() function can be used to find out the size
705   of a sector (in bytes) on the attached MSC class device.
706 
707   @param
708     This function does not take any parameters.
709 
710   @return
711     This function returns a value of type uint32_t indicating the sector size
712     (in bytes) on the attached MSC class device.
713 
714   Example:
715   @code
716       DRESULT disk_ioctl (
717       BYTE pdrv,
718       BYTE ctrl,
719       void *buff
720       )
721       {
722           UINT *result = (UINT *)buff;
723 
724           switch (ctrl) {
725           case GET_SECTOR_SIZE:
726               if(USBH_MSC_DEVICE_READY == MSS_USBH_MSC_get_state())
727               {
728                   *result = MSS_USBH_MSC_get_sector_size();
729                   return RES_OK;
730               }
731               else if(USBH_MSC_DEVICE_READY < MSS_USBH_MSC_get_state())
732               {
733                   *result = 0u;
734                   return RES_NOTRDY;
735               }
736               else
737               {
738                   *result = 0u;
739                   return RES_ERROR;
740               }
741           break;
742 
743           default:
744               return RES_NOTRDY;
745           }
746       }
747   @endcode
748  */
749 uint32_t
750 MSS_USBH_MSC_get_sector_size
751 (
752     void
753 );
754 
755 /*-------------------------------------------------------------------------*//**
756   The MSS_USBH_MSC_construct_cbw_cb10byte() function can be used to create the
757   SCSI request command block wrapper (CBW) as per MSC class which has command
758   block(CB) of length 10bytes.
759 
760   @param command_opcode
761     The command_opcode parameter provides the transparent SCSI command code.
762 
763   @param lun
764     The lun parameter indicates the logical unit number on the attached MSC
765     class device.
766 
767   @param lb_addr
768     The lb_addr parameter provides the logical block address on which the
769     operation indicated by the command_opcode parameter is applicable. For the
770     commands where logical block address is not applicable, a zero value must
771     be provided.
772 
773   @param num_of_lb
774     The num_of_addr parameter provides the number of logical blocks on which
775     the operation indicated by the command_opcode parameter is applicable. For
776     the commands where logical block address is not applicable, a zero value
777     must be provided.
778 
779   @param lb_size
780     The lb_size parameter provides the size of the logical block on the attached
781     MSC class device.
782 
783   @param buf
784     The buf parameter provides the pointer to the buffer where the formatted SCSI
785     command is to be stored.
786 
787   @return
788     This function does not return any value.
789 
790   Example:
791   @code
792       int8_t
793       MSS_USBH_MSC_read(uint8_t* buf, uint32_t sector, uint32_t count)
794       {
795           MSS_USBH_MSC_construct_cbw_cb10byte(USB_MSC_SCSI_READ_10,
796                                               0u,
797                                               sector,
798                                               count,
799                                               512u,
800                                               &g_bot_cbw);
801 
802 
803           MSS_USBH_MSC_scsi_req((uint8_t*)&g_bot_cbw,
804                                 buf,
805                                 (count*512u),
806                                 (uint8_t*)&g_bot_csw);
807           return(0);
808       }
809   @endcode
810  */
811 void
812 MSS_USBH_MSC_construct_cbw_cb10byte
813 (
814     uint8_t command_opcode,
815     uint8_t lun,
816     uint32_t lb_addr,
817     uint16_t num_of_lb,
818     uint16_t lb_size,
819     msd_cbw_t* buf
820 );
821 
822 /*-------------------------------------------------------------------------*//**
823   The MSS_USBH_MSC_construct_cbw_cb6byte() function can be used to create the
824   SCSI request command block wrapper (CBW) as per MSC class which has command
825   block(CB) of length 6 bytes.
826 
827   @param command_opcode
828     The command_opcode parameter provides the transparent SCSI command code.
829 
830   @param xfr_length
831     The xfr_length parameter provides the number of bytes to be transferred in
832     the data phase of the command.
833 
834   @param buf
835     The buf parameter provides the pointer to the buffer where the formatted
836     SCSI command is to be stored.
837 
838   @return
839     This function does not return any value.
840 
841   Example:
842   @code
843       MSS_USBH_MSC_construct_cbw_cb6byte(USB_MSC_SCSI_TEST_UNIT_READY,
844                                          0u,
845                                          &g_bot_cbw);
846 
847       MSS_USBH_write_out_pipe(g_msd_tdev_addr,
848                               USBH_MSC_BULK_TX_PIPE,
849                               g_tdev_out_ep.num,
850                               g_tdev_out_ep.maxpktsz,
851                               (uint8_t*)&g_bot_cbw,
852                               31u);
853   @endcode
854  */
855 void
856 MSS_USBH_MSC_construct_cbw_cb6byte
857 (
858     uint8_t command_opcode,
859     uint32_t data_xfr_len,
860     msd_cbw_t* buf
861 );
862 
863 /*-------------------------------------------------------------------------*//**
864   The MSS_USBH_MSC_scsi_req() function can be used to execute any SCSI command
865   required by the MSC class  on the attached MSC device. In most cases using
866   the MSS_USBH_MSC_write() and MSS_USBH_MSC_read() functions is enough for the
867   application. However, if the application wants to execute other SCSI commands
868   it can use the MSS_USBH_MSC_scsi_req() function. This function can be used as
869   alternative to MSS_USBH_MSC_write() and MSS_USBH_MSC_read() functions.
870 
871   The MSS_USBH_MSC_is_scsi_req_complete() function can be used to find out when
872   the transfer started using this function is complete.
873 
874   @param command_buf
875     The command_buf parameter provides the pointer to the buffer where the SCSI
876     command (CBW format) to be executed is stored.
877 
878   @param data_buf
879     The data_buf parameter provides the pointer to the data buffer which is to
880     be used in the data phase of the command. This parameter is the source of
881     the data when the data direction is from the host to the device. This
882     parameter is the destination for the data when the data direction is from
883     the device to the host. This function extracts the data direction from the
884     CBW format command provided using command_buf parameter.
885 
886   @param data_buf_len
887     The data_buf_len parameter indicates the number of bytes to be transferred
888     in the data phase of the current command.
889 
890   @param status_buf
891     The status_buf parameter provides the pointer to the buffer where the status
892     (CSW format) received from the attached MSC device for the current SCSI
893     operation is to be stored.
894 
895   @return
896     This function returns zero value when successfully executed.
897 
898   Example:
899   @code
900       int8_t
901       MSS_USBH_MSC_read
902       (
903           uint8_t* buf,
904           uint32_t sector,
905           uint32_t count
906       )
907       {
908           MSS_USBH_MSC_construct_cbw_cb10byte(USB_MSC_SCSI_READ_10,
909                                               0u,
910                                               sector,
911                                               count,
912                                               512u,
913                                               &g_bot_cbw);
914 
915           MSS_USBH_MSC_scsi_req((uint8_t*)&g_bot_cbw,
916                                 buf,
917                                 (count*512u),
918                                 (uint8_t*)&g_bot_csw);
919           return(0);
920       }
921   @endcode
922  */
923 uint8_t
924 MSS_USBH_MSC_scsi_req
925 (
926     uint8_t* command_buf,   /* always31bytes */
927     uint8_t* data_buf,
928     uint32_t data_buf_len,
929     uint8_t* status_buf     /* status always 13bytes */
930 );
931 
932 /*-------------------------------------------------------------------------*//**
933   The MSS_USBH_MSC_is_scsi_req_complete() function must be used to find out
934   whether the SCSI request initiated using MSS_USBH_MSC_scsi_req() or
935   MSS_USBH_MSC_read() or MSS_USBH_MSC_write() function is complete.
936 
937   @param
938     This function does not take any parameters.
939 
940   @return
941     This function returns zero value when the current command is completed.
942 
943   Example:
944   @code
945       MSS_USBH_MSC_write((uint8_t*)buff, sector, count);
946       while (MSS_USBH_MSC_is_scsi_req_complete());
947       return (RES_OK);
948   @endcode
949  */
950 uint8_t
951 MSS_USBH_MSC_is_scsi_req_complete
952 (
953     void
954 );
955 
956 #endif  /* MSS_USB_HOST_ENABLED */
957 
958 #ifdef __cplusplus
959 }
960 #endif
961 
962 #endif  /* __MSS_USB_HOST_MSC_H_ */
963 
964