/*****************************************************************************\

  File Name: io_usbdevice.c

  Description: This module contains USB device specific functions.

  Copyright(c) 2007 Analog Devices Incorporated. All Rights Reserved.

  Revision History:


\*****************************************************************************/

//-----------------------------------------------------------------------------
//  I N C L U D E S
//-----------------------------------------------------------------------------

#include <services\services.h>		/* System service includes */
#include <drivers\adi_dev.h>		/* Device manager includes */

#include <SDK-ezkitutilities.h>

#include <drivers\usb\usb_core\adi_usb_objects.h>
#include <drivers\usb\usb_core\adi_usb_core.h>
#include <drivers\usb\usb_core\adi_usb_ids.h>

#include <drivers\usb\class\peripheral\mass_storage\adi_usb_msd_class.h>
//#include <drivers\usb\controller\otg\adi\bf54x\adi_usb_bf54x.h>
#include <drivers\usb\controller\otg\adi\hdrc\adi_usb_hdrc.h>

#include "adi_ssl_init.h"
#include "mediaplayer.h"

#define _USE_ONBOARD_HARD_DISK_
/*-------------------------------------------------------------------------
 * DEFINES
 *-------------------------------------------------------------------------*/
 /* handle to the driver*/
ADI_DEV_DEVICE_HANDLE USBDriverHandle;
ADI_DEV_PDD_HANDLE PeripheralDevHandle;
static 	ADI_DEV_1D_BUFFER usbBuffer;

#pragma align 4
u8  USB_Buffer[MAX_USB_PKT_SIZE];

extern ADI_DEV_PDD_ENTRY_POINT ADI_USBDRC_Entrypoint;

static void callback_usb(void *AppHandle,u32  Event,void *pArg );

int init_usb(void);
int close_usb(void);

#define _USE_ONBOARD_HARD_DISK_

/*********************************************************************

	Function:		failure

	Description:	In case of failure we toggle LEDs.

*********************************************************************/

void failure(void)
{
      printf("Failure\n");
}


/*********************************************************************

	Function:		USB Callback

	Description:	

*********************************************************************/

static void callback_usb(void *AppHandle,u32  Event,void *pArg )
{

    switch (Event)
    {

    	case ADI_USB_EVENT_SET_CONFIG:
			break;
		case ADI_USB_EVENT_SUSPEND:
			break;
	//	case ADI_USB_EVENT_DISCONNECT:
	//		printf("Disconnect");
	//		break;
        default:
        	break;
    }
}





/*********************************************************************

	Function:		init_usb

	Description:	Initializes USB.  

*********************************************************************/
//section ("sdram0_bank3_app")
int init_usb(void) {
	
    PDEVICE_DESCRIPTOR pDevDesc;				/* device descriptor ptr */
    u16 i;      								/* index */
	
    u32 Result = ADI_DEV_RESULT_SUCCESS;		/* result */
    bool bRunning = TRUE;						/* keep running flag */
	u32 IsHDConnected = FALSE;
	u32 IsDeviceReady = FALSE;					/* has device been configured by host */


              
   /* Initialize USB Core 	 */
    adi_usb_CoreInit((void*)&Result);
     
    /* Open the USB Controller driver */
    Result = adi_dev_Open(	adi_dev_ManagerHandle, 			/* DevMgr handle */
							&ADI_USBDRC_Entrypoint,			/* pdd entry point */
							0,                          	/* device instance */
							(void*)1,						/* client handle callback identifier */
							&PeripheralDevHandle,	/* device handle */
							ADI_DEV_DIRECTION_BIDIRECTIONAL,/* data direction for this device */
							NULL,						/* handle to DmaMgr for this device */
							NULL,							/* handle to deferred callback service */
							callback_usb);                /* callback function */
							

    if (Result != ADI_DEV_RESULT_SUCCESS)
        failure();
       
    /* Open the Mass Storage Class driver */
    Result = adi_dev_Open(	adi_dev_ManagerHandle,					/* DevMgr handle */
                            &ADI_USB_Device_MassStorageClass_Entrypoint,/* pdd entry point */
                            0,										/* device instance */
                            (void*)0x1,								/* client handle callback identifier */
                            &USBDriverHandle,								/* DevMgr handle for this device */
                            ADI_DEV_DIRECTION_BIDIRECTIONAL,		/* data direction for this device */
                            adi_dma_ManagerHandle,								/* handle to DmaMgr for this device */
                            NULL,									/* handle to deferred callback service */
                            callback_usb);    	    			/* client's callback function */
                            
    if (Result != ADI_DEV_RESULT_SUCCESS)
        failure();
        
	/* Give the controller handle to the Mass storage class driver */
    Result = adi_dev_Control(USBDriverHandle, ADI_USB_CMD_CLASS_SET_CONTROLLER_HANDLE, (void*)PeripheralDevHandle);
	if (Result != ADI_DEV_RESULT_SUCCESS)
		failure();

	/* Configure the Mass stroage class driver */
	Result = adi_dev_Control(USBDriverHandle, ADI_USB_CMD_CLASS_CONFIGURE, (void*)0);
	if (Result != ADI_DEV_RESULT_SUCCESS)
		failure();

#ifdef _USE_ONBOARD_HARD_DISK_        
	// See if a HD is connected                 
    Result = adi_dev_Control(USBDriverHandle,
                             ADI_USB_MSD_CMD_INIT_RAW_PID,
                             &IsHDConnected);
    if (Result != ADI_DEV_RESULT_SUCCESS)
        failure();
    
	// If HD is not connected to this board
	if(IsHDConnected == FALSE)
	{  
		failure();                             
	}
#else
	// Using Memory Set the max memory size (8MB)
   	Result = adi_dev_Control(USBDriverHandle,
       	                     ADI_USB_MSD_CMD_SET_MEMORY_SIZE,
           	                 (void *)0x800000);
    if (Result != ADI_DEV_RESULT_SUCCESS)
   	    failure();
#endif
		
	/* Initialize memory and the SCSI handlers */                             	        
    Result = adi_dev_Control(USBDriverHandle,
                             ADI_USB_MSD_CMD_SCSI_INIT,
                             (void*)0);
    if (Result != ADI_DEV_RESULT_SUCCESS)
        failure();

	/* Set the Vendor ID */
    Result = adi_dev_Control(USBDriverHandle,
                             ADI_USB_MSD_CMD_SET_VID,
                             (void *)USB_VID_ADI_TOOLS);
                             //(void *)0x064B);

    if (Result != ADI_DEV_RESULT_SUCCESS)
        failure();

	/* Set the Product ID */                             	        
    Result = adi_dev_Control(USBDriverHandle,
                             ADI_USB_MSD_CMD_SET_PID,
                             (void *)USB_PID_BF548KIT_MASSSTORAGE_CLASS);
    if (Result != ADI_DEV_RESULT_SUCCESS)
        failure();
        
	/* Set the Serial Number */                             	        
	char MSDSerialNumber[] = MSD_SERIAL_NUMBER;
    Result = adi_dev_Control(USBDriverHandle,
                             ADI_USB_MSD_CMD_SET_SERIAL_NUMBER,
                             &MSDSerialNumber[0]);
    if (Result != ADI_DEV_RESULT_SUCCESS)
        failure();
     
   	usbBuffer.Data = &USB_Buffer;
   	usbBuffer.ElementCount = MAX_USB_PKT_SIZE;
   	usbBuffer.ElementWidth = 1;
   	usbBuffer.ProcessedFlag = FALSE;
   	usbBuffer.ProcessedElementCount = 0;
   	usbBuffer.CallbackParameter = &usbBuffer;
   	usbBuffer.pNext = NULL;
    	
    /* Configure the Peripheral mode */
    Result = adi_dev_Control(USBDriverHandle,
                             ADI_DEV_CMD_SET_DATAFLOW_METHOD,
                             (void*)ADI_DEV_MODE_CHAINED);
    if (Result != ADI_INT_RESULT_SUCCESS)
        failure();
        
	/* Enable data flow */
    Result = adi_dev_Control(USBDriverHandle,
                             ADI_DEV_CMD_SET_DATAFLOW,
                             (void*)TRUE);
    if (Result != ADI_INT_RESULT_SUCCESS)
        failure();
		
    /* Enable the USB peripheral driver */
    Result = adi_dev_Control(PeripheralDevHandle,
                             ADI_USB_CMD_ENABLE_USB,
                             (void*)0);
    if (Result != ADI_INT_RESULT_SUCCESS)
            failure();

	/* Wait until the device is configured by the host */              
    while(IsDeviceReady == FALSE)
    {
	    adi_dev_Control(USBDriverHandle,
                            ADI_USB_MSD_CMD_IS_DEVICE_CONFIGURED,
                            &IsDeviceReady); 
 	}

	/* Pass our buffer down to MSD */
    Result = adi_dev_Control(USBDriverHandle,
                             ADI_USB_MSD_CMD_SET_BUFFER,
                             (void*)&usbBuffer);
    if (Result != ADI_INT_RESULT_SUCCESS)
        failure();  
        
	return(Result);            
}

*********************************************************************

	Function:		close_usb

	Description:	Closes USB.  

*********************************************************************/

int close_usb(void) {
	
    u32 Result = ADI_DEV_RESULT_SUCCESS;		/* result */ 

    if (Result == ADI_DEV_RESULT_SUCCESS)
        Result = adi_dev_Control(PeripheralDevHandle,
    						     ADI_USB_CMD_DISABLE_USB,
    						     (void*)0);
    						     
    if (Result == ADI_DEV_RESULT_SUCCESS)    						        
        Result = adi_dev_Close(USBDriverHandle);  
        
    if (Result == ADI_DEV_RESULT_SUCCESS)
        Result = adi_dev_Close(PeripheralDevHandle);
      
	return(Result);            
}


