/** \file
 *
 *  This file contains special DoxyGen information for the generation of the main page and other special
 *  documentation pages. It is not a project source file.
 */

/**
\page Page_MSCBasic How to implement simple memory backed MSC device ?

This section introduces you to Mass Storage application development using USB ROM stack. The topics in this section provide step-by-step instructions on implementing a simple Mass Storage USB device using USB ROM stack. 

\section Sec_Init Initialization

After successfully initializing the USBD ROM stack i.e. \ref USBD_HW_API_T::Init, the mass storage class driver needs to be initialized as follows:
- Configure initialization parameters of the MSC class driver
\code

    USBD_MSC_INIT_PARAM_T msc_param;

    memset((void*)&msc_param, 0, sizeof(USBD_MSC_INIT_PARAM_T));
\endcode
- Set the memory location where the MSC class driver can allocate buffers and global variables. All the \em init() routines of the ROM components are written in such a way that the \em mem_base and \em mem_size members of \em XXX_INIT_PARAM_T are updated with free location and size before returning. So that the next component \em XXX_INIT_PARAM_T can use the update values for its \em init() routine. Applications can cascade the component initialization this way without worrying about memory wastage/overlap issues.
\code
    msc_param.mem_base = usb_param.mem_base;
    msc_param.mem_size = usb_param.mem_size;
\endcode
- Now set the MSC specific parameters. The Inquiry String is a 28 byte string with first 8 bytes for vendor identification, followed by 16 bytes of product identification and 4 bytes of product revision. The memory size and Block size are in bytes. 
\code
    /* mass storage params */
    msc_param.InquiryStr = (uint8_t*)InquiryStr; 
    msc_param.BlockCount = MSC_MemorySize / MSC_BlockSize;
    msc_param.BlockSize = MSC_BlockSize;
    msc_param.MemorySize = MSC_MemorySize;
	msc_param.MSC_Ep0_Hdlr = 
\endcode
- Obtain the address location of the interface descriptor, within the device configuration descriptor array, to which the class driver has to be attached. 
\code
    pIntfDesc =
       (USB_INTERFACE_DESCRIPTOR*)((uint32_t)desc.high_speed_desc + USB_CONFIGUARTION_DESC_SIZE);
    /* check we are referencing to the proper interface descriptor */ 
    if ((pIntfDesc == 0) ||
       (pIntfDesc->bInterfaceClass != USB_DEVICE_CLASS_STORAGE) ||
       (pIntfDesc->bInterfaceSubClass != MSC_SUBCLASS_SCSI) )
    return ERR_FAILED;
    msc_param.intf_desc = (uint8_t*)pIntfDesc;
\endcode   
 
- Define and set the MSC class callback routines. Optionally the application can also register its own class handler by providing the handle in the MSC Init Parameters, the USBD stack returns the default handler in the same parameter after the MSC initialization call. So the application could override or implement specific class requests and could call the default handler for requests that there not handled. Refer \ref Page_AdvancedUsers to understand how to change the default stack behavior by implementing custom overrides.
\code
    /* user defined functions */
    msc_param.MSC_Write = translate_wr; 
    msc_param.MSC_Read = translate_rd;
    msc_param.MSC_Verify = translate_verify;
    msc_param.MSC_GetWriteBuf = translate_GetWrBuf;
	msc_param.MSC_Ep0_Hdlr = msc_app_ep0_hdlr; /* Optional */
 \endcode

- Now call the \ref USBD_MSC_API_T::init routine of the MSC class.
\code
    
    ret = USBD_API->msc->init(hUsb, &msc_param);


if (ret != LPC_OK) {
  vCatchError(0); //"usb_msc_mem_init error!!!"
}
\endcode

- After a successful MSC Init update the memory base address and memory size from the MSC Init Param to the USB Init Param, so that any other class driver could start using the memory from the right location.
\code
    usb_param.mem_base = msc_param.mem_base;
    usb_param.mem_size = msc_param.mem_size;
\endcode

\subsection SSec_Desc Defining USB Descriptors

The following example shows the configuration descriptor for the USB Mass storage class device:
\code
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
ALIGNED(4)  uint8_t USB_FsConfigDescriptor[] = {
/* Configuration 1 */
  USB_CONFIGUARTION_DESC_SIZE,       /* bLength. Set to 0x09. */
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType. Set to 0x02.*/
  WBVAL(                             /* wTotalLength: contains total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration.  */
    1*USB_CONFIGUARTION_DESC_SIZE +
    1*USB_INTERFACE_DESC_SIZE     +
    2*USB_ENDPOINT_DESC_SIZE
  ),
  0x01,                              /* bNumInterfaces: total number of interfaces the device supports */
  0x01,                              /* bConfigurationValue: This field indicates the index for the configuration defined in the firmware of the device. The host functional driver uses that index value to select an active configuration. */
  0x00,                              /* iConfiguration */

  USB_CONFIG_SELF_POWERED,           /* bmAttributes: contains a bitmask that indicates whether the configuration supports the remote wake-up feature, and whether the device is bus-powered or self-powered. */
  
  USB_CONFIG_POWER_MA(100),          /* bMaxPower: specifies the maximum power (in milliamp units) that the device can draw from the host, when the device is bus-powered.  */

/* Interface 0, Alternate Setting 0, MSC Class */
  USB_INTERFACE_DESC_SIZE,           /* bLength */
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
  0x00,                              /* bInterfaceNumber */
  0x00,                              /* bAlternateSetting */
  0x02,                              /* bNumEndpoints */
  USB_DEVICE_CLASS_STORAGE,          /* bInterfaceClass */
  MSC_SUBCLASS_SCSI,                 /* bInterfaceSubClass */
  MSC_PROTOCOL_BULK_ONLY,            /* bInterfaceProtocol */
  0x04,                              /* iInterface: Index to string descriptor containing interface description. */

/* Bulk In Endpoint */
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  MSC_EP_IN,                         /* bEndpointAddress */
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
  WBVAL(64),                         /* wMaxPacketSize */
  0,                                 /* bInterval */
/* Bulk Out Endpoint */
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  MSC_EP_OUT,                        /* bEndpointAddress */
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
  WBVAL(64),                         /* wMaxPacketSize */
  0,                                 /* bInterval */
/* Terminator */
  0                                  /* bLength: Indicates to ROM stack the end of descriptor array. */
};

\endcode

\section Sec_Execute Execution 

After a successful MSC Initialization the stack is ready to receive the packets from host. Even if the device is physically connected to the host using an USB cable the host does not recognize the presence of device until the D+ line is pulled up using 1.5K ohm resistor (LPC device controllers operate in high-speed or full-speed mode only). To enable the connection the application software should call \ref USBD_HW_API_T::Connect with \em enable set to 1. Before enabling the connection the application should enable the USB interrupt.

\code
NVIC_EnableIRQ(USB0_IRQn); //  enable USB0 interrupts
/* now connect */
USBD_API->hw->Connect(g_hUsb, 1);

\endcode

After connection the MSC class executes through callback functions setup during initialization. 

\subsection SSec_IRQ Installing IRQ handlers
USBD ROM stack implements the interrupt handler for USB device controller and invokes the USBD ROM stack routines according to the event type.  Hence application should connect this handler to the application vector table. This is done by calling \ref USBD_HW_API_T::ISR from the USB IRQ handler as shown in the code snippet below. The USBD ROM handle passed to the \em ISR() routine is the one obtained in previous step.

\code
void USB0_IRQHandler(void)
{
    USBD_API->hw->ISR(g_hUsb);
}
\endcode

\section Sec_Callback Implementing callback

The MSC Class executes by calling callback routines setup during MSC initialization. The 4 call backs used in MSC are:

-MSC_Write: Called when a write request is sent from the host, the lower 32 bit offset and the high 32 bit offset together produce the 64 bit offset for the memory device, the source double pointer points to the data to be written to the memory device and the length indicates the number of bytes to be written. The implementation of the write procedure is dependent on the memory device used by the application.

-MSC_Read: Called when a read request is sent from the host, the lower 32 bit offset and the high 32 bit offset together produce the 64 bit offset for the memory device, the destination double pointer points to the buffer where the data read from the memory device should be updated and the length indicates the number of bytes to be read.

-MSC_Verify: Called when a verify request is sent from the host, the lower 32 bit offset and the high 32 bit offset together produce the 64 bit offset for the memory device, the buffer points to the data that needs to be compared with the data in the memory device and the length indicates the number of bytes to compare. The callback function should compare the buffer with the destination memory at the requested offset and the return 0 if the data matches else return -1.

-MSC_GetWriteBuf: Called during the command transport stage when host sends a write request , the lower 32 bit offset and the high 32 bit offset together produce the 64 bit offset for the memory device for the following write, the buff_adr double pointer points to the buffer where the stack can copy the write data and the length indicates the number of bytes that will be written. The callback function should update the buff_adr pointer so that the stack transfers the data directly to the target buffer. \note The updated buffer address should be accessible by USB DMA master. If user doesn't want to use zero-copy model, then the user should not update the buffer pointer. See \ref USBD_ZeroCopy for more details on zero-copy concept.

<b>Subsections:</b>
\li \subpage Page_MSCDemo

*/

