/*****************************************************************************
Copyright(c) 2005 Analog Devices, Inc.  All Rights Reserved. This software is 
proprietary and confidential to Analog Devices, Inc. and its licensors.
******************************************************************************

$RCSfile: adi_usbio.c,v $
$Revision: 1.4 $
$Date: 2007/11/15 01:40:16 $

Project:	BlackfinSDK
Title:		usbio service file for Blackfin (BlackfinSDK)
Author(s):	ADI
Revised by: bmk

Description:
			USB I/O functions supported by Blackfin (BlackfinSDK applications)
			
References:
			None

******************************************************************************
Tab Setting:			4
Target Processor:		ADSP-BF5xx
Target Tools Revision:	ADSP VisualDSP++ v4.5
******************************************************************************

Modification History:
====================
$Log: adi_usbio.c,v $
Revision 1.4  2007/11/15 01:40:16  randreol
Eliimate compiler warning for ConfigureEndpoints

Revision 1.3  2007/11/13 04:33:05  randreol
Modify USBDeviceHandle declaration

Revision 1.2  2007/08/29 04:39:22  randreol
Modified to support porting to new USB driver

Revision 1.2  2006/11/10 03:29:46  bmk
USBIO support for SDK 2.0

*****************************************************************************/

#pragma default_section(CODE, "sdram0_bank1")

#include <adi_ssl_Init.h>

#include <services/services.h>		// system services includes
#include <drivers/adi_dev.h>		// device manager includes
#include <stdio.h>					// stdio includes
#include <string.h>					// string includes
#include <device_int.h>				// Blackfin IO device includes

#ifndef _DEVICE_H
#include <device.h>					// Blackfin device includes
#endif // _DEVICE_H

// USB driver includes
#include <drivers\usb\usb_core\adi_usb_core.h>
#include <drivers\usb\class\peripheral\vendor_specific\adi\bulkadi\adi_usb_bulkadi.h>		// adi bulk driver header file
#include <adi_usbcmd.h>							// Supported USB commands
#include <adi_usbio_blackfin.h>					// USB I/O functions for Blackfin

#define USBIO_STDIO_BUFFER_SIZE (4096)			// // standard IO Buffer size (4KB)

#define USBIO_DEV_ID	123						// USBIO device ID
#define USBIO_STDIN_FILENAME	"usbio_stdin"	// USBIO stdin filename
#define USBIO_STDOUT_FILENAME	"usbio_stdout"	// USBIO stdout filename
#define USBIO_STDERR_FILENAME	"usbio_stderr"	// USBIO stderr filename

//static ADI_DEV_DEVICE_HANDLE USBDeviceHandle;	// USB device handle
volatile static ADI_DEV_1D_BUFFER UsbcbBuffer;			// 1D buffer for processing USB command block
volatile static ADI_DEV_1D_BUFFER DataBuffer;			// 1D buffer for processing data

section ("L1_data_b")
volatile static USBCB usbcb;								// USB command block
volatile static s32 g_ReadEpID;							// read endpoint ID
volatile static s32 g_WriteEpID;							// write endpoint ID

// Semaphores specific to Net2272 used for handshaking btwn ISR and foreground code.
volatile bool	Net2272Ready 	= FALSE;		// TRUE indicates Net2272 has been configured
volatile bool	Net2272TxDone	= FALSE;		// TRUE indicates present USB Tx operation is done
volatile bool	Net2272RxDone	= FALSE;		// TRUE indicates present USB Rx operation is done

// USBIO prototypes
int 	usbio_init	(struct DevEntry *dev);
int 	usbio_open	(const char *name, int mode);
int 	usbio_close	(int fd);
int 	usbio_write	(int fd, unsigned char *buf, int size);
int	 	usbio_read	(int fd, unsigned char *buf, int size);
long	usbio_seek	(int fd, long offset, int whence);

// DevEntry structure for USBIO
DevEntry _usbio_device =
{
	USBIO_DEV_ID,		// DeviceID
	0,					// data
	&usbio_init,		// init
	&usbio_open, 		// open
	&usbio_close, 		// close
	&usbio_write, 		// write
	&usbio_read,		// read
	&usbio_seek,		// seek

	// we will claim these for USBIO later
	dev_not_claimed,	// stdinfd
	dev_not_claimed,	// stdoutfd
	dev_not_claimed,	// stderrfd
};

#pragma align 4
section ("sdram0_bank1")
static char stdiobuff[USBIO_STDIO_BUFFER_SIZE];	// stdio buffer (in L3)

FILE *fpin, *fpout, *fperr;						// stdio file ptrs

/*********************************************************************

    Function:       ConfigureEndpoints

    Description:    We get the endpoint IDs from the driver stack.

*********************************************************************/
unsigned int ConfigureEndpoints(void)
{
	ADI_ENUM_ENDPOINT_INFO EnumEpInfo;              // Binded Endpoint information
	static ADI_USB_APP_EP_INFO g_UsbAppEpInfo[2] = {0};
	unsigned int Result;

	//USBDeviceHandle = DeviceHandle;
	
	// Get Read and Write Endpoints
	EnumEpInfo.pUsbAppEpInfo = &g_UsbAppEpInfo[0];
	EnumEpInfo.dwEpTotalEntries = sizeof(g_UsbAppEpInfo)/sizeof(ADI_USB_APP_EP_INFO);
	EnumEpInfo.dwEpProcessedEntries = 0;

	// Get the enumerated endpoints
	Result = adi_dev_Control( USBDeviceHandle, ADI_USB_CMD_CLASS_ENUMERATE_ENDPOINTS, (void*)&EnumEpInfo);

	if (Result != ADI_DEV_RESULT_SUCCESS)
		return 1; //failure();

	if(g_UsbAppEpInfo[0].eDir == USB_EP_IN)
	{
		g_WriteEpID = g_UsbAppEpInfo[0].dwEndpointID;
		g_ReadEpID  = g_UsbAppEpInfo[1].dwEndpointID;
	}
	else
	{
		g_ReadEpID = g_UsbAppEpInfo[0].dwEndpointID;
		g_WriteEpID = g_UsbAppEpInfo[1].dwEndpointID;
	}

	return(Result);
}

/*********************************************************************

    Function:       ConfigUSB_IO
    
    Description:    Sets USB to be the default IO device to perform 
    				file I/O and stdio over USB with the host.  
    				This function uses all the supported capabilities 
					of file I/O such as open, close, read, write, and 
					seek and also uses the three stdio streams (stdin, 
					stdout, and stderr).

*********************************************************************/
u32 ConfigUSB_IO( 
	ADI_DEV_DEVICE_HANDLE	DeviceHandle	// USB Device Handle
){
	static int   	AddEntryResult = 0;					// add entry result
	

	// only setup USBIO if we haven't already
	if( USBIO_DEV_ID != AddEntryResult )
	{
    
		// add the device to the table
		AddEntryResult = add_devtab_entry( &_usbio_device );
		// make it the default IO device
		set_default_io_device(USBIO_DEV_ID);
		
		// reopening with USBIO as the default will send stdio to USBIO instead
		fpin = freopen(USBIO_STDIN_FILENAME, "r", stdin);	
		fpout = freopen(USBIO_STDOUT_FILENAME, "w", stdout);
		fperr = freopen(USBIO_STDERR_FILENAME, "w", stderr);
		
		// setup stdout and stderr for line buffering meaning newline will call write()
		setvbuf(fpout, stdiobuff, _IOLBF, sizeof(stdiobuff));
		setvbuf(fperr, stdiobuff, _IOLBF, sizeof(stdiobuff));
	}

	// check for USBIO setup success/fail
	if( USBIO_DEV_ID != AddEntryResult )
		return	1;	// return generic failure
	else
		return	0;	// return success
}

/*********************************************************************

    Function:       StopUSB_IO
    
    Description:    Informs host to Stop and free the USBIO

*********************************************************************/
u32 StopUSB_IO(
	ADI_DEV_DEVICE_HANDLE	DeviceHandle	// USB Device Handle
){
	// init buffer
	UsbcbBuffer.Data = (void*)&usbcb;
	UsbcbBuffer.ElementCount = sizeof(usbcb);
	UsbcbBuffer.ElementWidth = 1;
	UsbcbBuffer.CallbackParameter = NULL;
	UsbcbBuffer.pNext = NULL;

	// setup the USBCB
	usbcb.ulCommand = USBIO_STOP;	// command

	// Send the Stop command to Host
	return(USB_Write(DeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,FALSE));
}

/*********************************************************************

    Function:       usbio_init
    
    Description:    Initialise USB IO

*********************************************************************/
int usbio_init( struct DevEntry *dev )
{
	// do init here, we just return success
	return 1;
}

/*********************************************************************

    Function:       usbio_open
    
    Description:    Opens USB IO

*********************************************************************/
int usbio_open( const char *name, int mode )
{
	char *pcInfo;		// data ptr
	size_t sz_name;		// size of filename
	size_t sz_info;		// size of info block
	int fd = -1;		// file descriptor
	int Result;			// result

	// first check for stdio streams, if so return the FD that indicates
	if ( !strcmp(name, USBIO_STDIN_FILENAME) )
		return USBIO_STDIN_FD;
	else if ( !strcmp(name, USBIO_STDOUT_FILENAME) )
		return USBIO_STDOUT_FD;
	else if ( !strcmp(name, USBIO_STDERR_FILENAME) )
		return USBIO_STDERR_FD;

	// get the sizes
	sz_name = strlen(name);
	sz_info = sz_name + 8;

	// if the info block is larger than MAX_DATA_BYTES_EZEXTENDER just fail
	if ( sz_info > MAX_DATA_BYTES_EZEXTENDER)
		return -1;

	// create an info block with mode and name to send to the host, add
	// a little padding for NULL terminator and mode
	pcInfo = (char*) malloc(sz_info);

	// make sure the malloc worked
	if (!pcInfo)
		return -1;

	// fill in the info block, use "sz + 1" to include the NULL terminator
	memcpy( (void*)(pcInfo + FILE_OPEN_MODE_OFFSET), (void*)&mode, sizeof(int) );
	memcpy( (void*)(pcInfo + FILE_OPEN_FILENAME_OFFSET), (void*)name, sz_name + 1 );

	// init buffers
	UsbcbBuffer.Data = (void*)&usbcb;
	UsbcbBuffer.ElementCount = sizeof(usbcb);
	UsbcbBuffer.ElementWidth = 1;
	UsbcbBuffer.CallbackParameter = NULL;
	UsbcbBuffer.pNext = NULL;

	DataBuffer.Data = pcInfo;
	DataBuffer.ElementCount = sz_info;
	DataBuffer.ElementWidth = 1;
	DataBuffer.CallbackParameter = NULL;
	DataBuffer.pNext = NULL;

	// setup the USBCB
	usbcb.ulCommand = USBIO_OPEN;	// command
	usbcb.ulCount = sz_info;		// how many data bytes host should expect

	// wait for host to take the USBCB
	Result = USB_Write(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE);

	// then wait for the host to take the info block
	Result = USB_Write(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&DataBuffer,TRUE);

	// finally wait for the host to send back the file descriptor or negative value
	// which would indicate a failure opening the file on the host
	UsbcbBuffer.Data = (void*)&usbcb;
	UsbcbBuffer.ElementCount = sizeof(usbcb);
	UsbcbBuffer.ElementWidth = 1;
	UsbcbBuffer.CallbackParameter = NULL;
	UsbcbBuffer.pNext = NULL;

	// get the data from the host
	Result = USB_Read(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE);

	// if we got back NULL, that means the open failed on the host, we must return
	// a negative value to indicate failure
	if ( usbcb.ulData == 0x0 )
		fd = -1;
	else
		fd = usbcb.ulData;

	// free the memory
	free(pcInfo);

	// return the file descriptor
	return fd;
}

/*********************************************************************

    Function:       usbio_close
    
    Description:    Closes USB IO

*********************************************************************/
int usbio_close( int fd )
{
	// init buffer
	UsbcbBuffer.Data = (void*)&usbcb;
	UsbcbBuffer.ElementCount = sizeof(usbcb);
	UsbcbBuffer.ElementWidth = 1;
	UsbcbBuffer.CallbackParameter = NULL;
	UsbcbBuffer.pNext = NULL;

	// send a USBCB to the host indicating to stop waiting for data
	usbcb.ulCount = 0x0;
	usbcb.ulCommand = USBIO_CLOSE;
	usbcb.ulData = (unsigned int)fd;

	// wait for host to take the USBCB
	return(USB_Write(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE));
}

/*********************************************************************

    Function:       usbio_write
    
    Description:    Writes data to host via USB

*********************************************************************/
int usbio_write( int fd, unsigned char *buf, int size )
{
	int bytes_written = 0x0;		// track bytes written overall
	int bytes_current = 0x0;		// track bytes written current
	int bytes_left = size;			// track bytes left to write
	int Result;						// result
	bool bClosed = false;			// closed flag
	bool bError = false;			// error flag

	// init buffers
	UsbcbBuffer.Data = (void*)&usbcb;
	UsbcbBuffer.ElementCount = sizeof(usbcb);
	UsbcbBuffer.ElementWidth = 1;
	UsbcbBuffer.CallbackParameter = NULL;
	UsbcbBuffer.pNext = NULL;

	DataBuffer.ElementWidth = 1;
	DataBuffer.CallbackParameter = NULL;
	DataBuffer.pNext = NULL;

	// loop until all the bytes are written or we get closed or error
	while ( (bytes_written < size) && !bClosed && !bError )
	{
		// limit each write to MAX_DATA_BYTES_EZEXTENDER bytes
		if ( bytes_left > MAX_DATA_BYTES_EZEXTENDER)
			bytes_current = MAX_DATA_BYTES_EZEXTENDER;
		else
			bytes_current = bytes_left;

		// setup USBCB
		usbcb.ulCommand = USBIO_WRITE;	// command
		usbcb.ulData = fd;				// file descriptor
		usbcb.ulCount = bytes_current;	// how many data bytes to write this time

		// wait for host to take the USBCB
		Result = USB_Write(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE);

		// update data buffer count and pointer
		DataBuffer.ElementCount = bytes_current;
		DataBuffer.Data = buf + bytes_written;

		// wait for host to take the data
		Result = USB_Write(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&DataBuffer,TRUE);

		// host will send back USBCB containing actual bytes written which can differ
		// from what was requested and flag indicating if file closed or error occured
		Result = USB_Read(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE);

		// update bytes written and bytes left
		bytes_written += usbcb.ulCount;
		bytes_left = size - bytes_written;

		// check for closed or error, this would break us out of the loop
		if ( 0x0 == usbcb.ulData )
			bClosed = true;
		else if ( 0xffffffff == usbcb.ulData )
			bError = true;
	}

	// if closed and we didn't write any data return 0x0
	if ( bClosed && (usbcb.ulCount == 0x0) )
		return 0x0;

	// else if error return negative value
	else if ( bError )
		return -1;

	// else return total bytes written
	else
		return bytes_written;
}

/*********************************************************************

    Function:       usbio_read
    
    Description:    Reads data from host via USB

*********************************************************************/
int usbio_read( int fd, unsigned char *buf, int size )
{
	int bytes_read = 0x0;			// track bytes read overall
	int bytes_current = 0x0;		// track bytes read current
	int bytes_left = size;			// track bytes left to read
	int Result;						// result
	bool bEOF = false;				// EOF flag
	bool bError = false;			// error flag

	// init USBCB buffer
	UsbcbBuffer.Data = (void*)&usbcb;
	UsbcbBuffer.ElementCount = sizeof(usbcb);
	UsbcbBuffer.ElementWidth = 1;
	UsbcbBuffer.CallbackParameter = NULL;
	UsbcbBuffer.pNext = NULL;

	DataBuffer.ElementWidth = 1;
	DataBuffer.CallbackParameter = NULL;
	DataBuffer.pNext = NULL;

	// loop until all the bytes are read or we get EOF or error
	while ( (bytes_read < size) && !bEOF && !bError )
	{
		// limit each read to MAX_DATA_BYTES_EZEXTENDER bytes
		if ( bytes_left > MAX_DATA_BYTES_EZEXTENDER)
			bytes_current = MAX_DATA_BYTES_EZEXTENDER;
		else
			bytes_current = bytes_left;

		// setup the USBCB
		usbcb.ulCommand = USBIO_READ;	// command
		usbcb.ulData = fd;				// file descriptor
		usbcb.ulCount = bytes_current;	// how many data bytes to read this time

		// wait for host to take the USBCB
		Result = USB_Write(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE);

		// host will send back USBCB containing actual bytes read which can differ
		// from what was requested and flag indicating if end-of-file or error occured
		Result = USB_Read(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE);

		// if there's data to read, get it
		if ( usbcb.ulCount )
		{
			// update data buffer count and pointer
			DataBuffer.Data = buf + bytes_read;
			DataBuffer.ElementCount = usbcb.ulCount;	// actual bytes to read

			// then wait for the host to send the data
			Result = USB_Read(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&DataBuffer,TRUE);
		}

		// update bytes read and bytes left
		bytes_read += usbcb.ulCount;
		bytes_left = size - bytes_read;

		// check for EOF or error, this would break us out of the loop
		if ( 0x0 == usbcb.ulData )
			bEOF = true;
		else if ( 0xffffffff == usbcb.ulData )
			bError = true;

		// for now if STDIN, just get data one time because we're requesting
		// more than they'll probably enter
		if ( USBIO_STDIN_FD == fd )
			bEOF = true;
	}

	// if EOF and we didn't read any data return 0x0
	if ( bEOF && (usbcb.ulCount == 0x0) )
		return 0x0;

	// else if error return negative value
	else if ( bError )
		return -1;

	// else return total bytes read
	else
		return bytes_read;
}

/*********************************************************************

    Function:       usbio_seek
    
    Description:    Seeks position/info of a file in the Host side

*********************************************************************/
long usbio_seek( int fd, long offset, int whence )
{
	int Result;				// result

	// init buffers
	UsbcbBuffer.Data = (void*)&usbcb;
	UsbcbBuffer.ElementCount = sizeof(usbcb);
	UsbcbBuffer.ElementWidth = 1;
	UsbcbBuffer.CallbackParameter = NULL;
	UsbcbBuffer.pNext = NULL;

	// determine the origin
	if ( 0x0 == whence )
		usbcb.ulCommand = USBIO_SEEK_SET;
	else if ( 0x1 == whence )
		usbcb.ulCommand = USBIO_SEEK_CUR;
	else if ( 0x2 == whence )
		usbcb.ulCommand = USBIO_SEEK_END;

	usbcb.ulData = fd;			// file descriptor
	usbcb.ulCount = offset;		// how many bytes from origin

	// wait for host to take the USBCB
	Result = USB_Write(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE);

	// host will send back USBCB containing new file position and status
	Result = USB_Read(USBDeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,TRUE);

	// if there was no error return the new file position
	if ( 0x0 == usbcb.ulData )
		return usbcb.ulCount;

	// else there was an error
	else
		return -1;
}

/*********************************************************************

    Function:       QueryUSBSupport
    
    Description:    Checks whether a given command is supported by this 
    				firmware. The host can use this to verify that 
    				a command it wants to execute is supported ahead 
    				of time.

*********************************************************************/
u32 QueryUSBSupport(
	ADI_DEV_DEVICE_HANDLE	DeviceHandle,	// USB Device Handle
	u32 	Command			// command queried for support
){
	// init buffer
	UsbcbBuffer.Data 				= (void*)&usbcb;
	UsbcbBuffer.ElementCount 		= sizeof(usbcb);
	UsbcbBuffer.ElementWidth 		= 1;
	UsbcbBuffer.CallbackParameter 	= NULL;
	UsbcbBuffer.pNext 				= NULL;
	

	// check for a supported command (list of supported available in adi_usbcmd.h)
	if (	QUERY_SUPPORT 	== Command || GET_FW_VERSION == Command ||
			USBIO_START 	== Command || MEMORY_READ 	== Command ||
			MEMORY_WRITE 	== Command || SET_PARAMS 	== Command ||
			GET_APP_ID		== Command)
		usbcb.ulData = TRUE;
	else
		usbcb.ulData = FALSE;

	// send a USBCB to the host with the result
	usbcb.ulCount = 0x0;
	usbcb.ulCommand = QUERY_REPLY;

	// wait for host to take the USBCB
	return(USB_Write(DeviceHandle, ADI_DEV_1D, (ADI_DEV_BUFFER *)&UsbcbBuffer,FALSE));
}

/*********************************************************************

	Function:		USB_Read

	Description:	Wrapper for adi_dev_Read() which lets the user specify if
					they want to wait for completion or not.

	Arguments:		ADI_DEV_DEVICE_HANDLE devhandle -	device handle
					ADI_DEV_BUFFER_TYPE BufferType -	buffer type
					ADI_DEV_BUFFER *pBuffer -			pointer to buffer
					bool bWaitForCompletion -			completion flag

	Return value:	u32 - return status

*********************************************************************/
u32 USB_Read (
	ADI_DEV_DEVICE_HANDLE 	DeviceHandle, 		// device handle
	ADI_DEV_BUFFER_TYPE 	BufferType,			// buffer type
	ADI_DEV_BUFFER 			*pBuffer, 			// pointer to buffer
	bool 					bWaitForCompletion	// completion flag
){
    u32 Result = ADI_DEV_RESULT_SUCCESS;
    ADI_DEV_1D_BUFFER		*p1DBuff;
    
    p1DBuff = (ADI_DEV_1D_BUFFER*)pBuffer;
    
    // Place the Read Endpoint ID
    p1DBuff->Reserved[BUFFER_RSVD_EP_ADDRESS] = g_ReadEpID;
    
 	// if the user wants to wait until the operation is complete
    if (bWaitForCompletion)
    {
        // clear the Rx flag and call read
   		Net2272RxDone = FALSE;   		
		Result = adi_dev_Read(DeviceHandle, BufferType, pBuffer);

		// wait for the Rx flag to be set
		while (!Net2272RxDone)
		{
		   // make sure we are still configured, if not we should fail
			if (!Net2272Ready)
				return ADI_DEV_RESULT_FAILED;
		}

		return Result;
    }

    // else do not wait for completion
    else
    {
        return (adi_dev_Read(DeviceHandle, BufferType, pBuffer));
    }    
    
}

/*********************************************************************

	Function:		USB_Write

	Description:	Wrapper for adi_dev_Write() which lets the user specify if
					they want to wait for completion or not.

	Arguments:		ADI_DEV_DEVICE_HANDLE devhandle -	device handle
					ADI_DEV_BUFFER_TYPE BufferType -	buffer type
					ADI_DEV_BUFFER *pBuffer -			pointer to buffer
					bool bWaitForCompletion -			completion flag

	Return value:	u32 - return status

*********************************************************************/
u32 USB_Write (
	ADI_DEV_DEVICE_HANDLE 	DeviceHandle, 		// device handle
	ADI_DEV_BUFFER_TYPE 	BufferType,			// buffer type
	ADI_DEV_BUFFER 			*pBuffer, 			// pointer to buffer
	bool 					bWaitForCompletion	// completion flag
){
    u32 Result = ADI_DEV_RESULT_SUCCESS;
    ADI_DEV_1D_BUFFER		*p1DBuff;

    p1DBuff = (ADI_DEV_1D_BUFFER*)pBuffer;
    
    // Place the Endpoint ID
    p1DBuff->Reserved[BUFFER_RSVD_EP_ADDRESS] = g_WriteEpID;
    
 	// if the user wants to wait until the operation is complete
    if (bWaitForCompletion)
    {
        // clear the Tx flag and call write
   		Net2272TxDone = FALSE;
   		
		Result = adi_dev_Write(DeviceHandle, BufferType, pBuffer);

		// wait for the Tx flag to be set
		while (!Net2272TxDone)
		{
		   // make sure we are still configured, if not we should fail
			if (!Net2272Ready)
				return ADI_DEV_RESULT_FAILED;
		}

		return Result;
    }

    // else do not wait for completion
    else
    {
        return (adi_dev_Write(DeviceHandle, BufferType, pBuffer));
    }    
    
}

/*****/


