kerneltest/e32test/usbho/t_usbdi/inc/ControlTransferRequests.h
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

#ifndef __CONTROL_TRANSFER_REQUESTS_H
#define __CONTROL_TRANSFER_REQUESTS_H

/*
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
* @file ControlTransferRequests.h
* @internalComponent
* 
*
*/



#include <e32base.h>
#include <e32ver.h>
#include <d32usbdi.h>

namespace NUnitTesting_USBDI
	{

//These values MUST be kept in line with each other
const _LIT8(KNumberFormatString, "%08d");
const TUint KNumberStringLength = 8;

//These values MUST be kept in line with each other
const _LIT8(KTwoNumberFormatString, "%08d%08d");
const TUint KTwoNumberStringLength = 16;

//These values MUST be kept in line with each other
const _LIT8(KSplitWriteNumberFormatString, "%08d%08d%08d");
const TUint KSplitWriteNumberStringLength = 24;
const TUint KNumSplitWriteSections = 3;

//These values MUST be kept in line with each other
const _LIT8(KClientPassString, "PASS");
const _LIT8(KClientFailString, "FAIL");
const TUint KPassFailStringLength = 4;

const TUint KTestBufferLength = 32; //must be more than KPassFailStringLength

const TUint KMaxSendSize = 2048;	



// ------------- bRequest -----------------
const TUint8 KVendorEmptyRequest(0x00);
const TUint8 KVendorPutPayloadRequest(0x01);
const TUint8 KVendorGetPayloadRequest(0x02);
const TUint8 KVendorGetRecordedNumBytesReadInPayloadRequest (0x03);
const TUint8 KVendorGetRecordedNumBytesWrittenInPayloadRequest (0x04);
const TUint8 KVendorStallRequest(0x05);
const TUint8 KVendorRemoteWakeupRequest(0x06);
const TUint8 KVendorReconnectRequest(0x07);
const TUint8 KVendorWriteToEndpointRequest(0x08);
const TUint8 KVendorPatternWriteToEndpointRequest(0x09);
const TUint8 KVendorCancelWriteToEndpointRequest(0x0a);
const TUint8 KVendorPatternWriteSynchronousToEndpointRequest(0x0b);
const TUint8 KVendorPatternWriteSynchronousToAndHaltEndpointRequest(0x0c);
const TUint8 KVendorStringValidationRequest(0x0d);
const TUint8 KVendorWriteSynchronousCachedReadRequest(0x0e);
const TUint8 KVendorWriteCachedReadRequest(0x0f);
const TUint8 KVendorRepeatedPatternWriteDataRequest (0x10);
const TUint8 KVendorSplitWriteSynchronousCachedReadRequest(0x11);
const TUint8 KVendorReadFromEndpointRequest(0x12);
const TUint8 KVendorReadUntilShortFromEndpointRequest(0x13);
const TUint8 KVendorReadFromAndHaltEndpointRequest(0x14);
const TUint8 KVendorRepeatedReadAndValidateDataRequest(0x15);
const TUint8 KVendorRecordedValidationResultRequest (0x16);
const TUint8 KVendorCancelAnyReadFromEndpointRequest (0x17);
const TUint8 KVendorTestCasePassed(0x20);
const TUint8 KVendorTestCaseFailed(0x21);
const TUint8 KVendorUnrespondRequest(0x22);
const TUint8 KVendorDisconnectDeviceAThenConnectDeviceCRequest(0x23);
const TUint8 KVendorDisconnectDeviceCThenConnectDeviceARequest(0x24);

// class specific
// audio
const TUint8 KAudioClassSetCur(0x01);

// ------------- bmRequestType -----------------

// D7: Data phase transfer direction
const TUint8 KHostToDevice(0x00);
const TUint8 KDeviceToHost(0x80);

// D6..5: Type
const TUint8 KTypeStandard(0x00);
const TUint8 KTypeClass(0x20);
const TUint8 KTypeVendor(0x40);

// D4..0: Recipient
const TUint8 KRecipientDevice(0x00);
const TUint8 KRecipientInterface(0x01);
const TUint8 KRecipientEndpoint(0x02);
const TUint8 KRecipientOther(0x03);

// ------------------------------------------------------------------

// The customised requests (i.e. non standard control requests)

// ------------------------------------------------------------------
	
/**
This policy class represents the basic control request setup packet
that the user will derive from and customise to describe usable control requests
otherwise with the default values it represents a 'standard device request'
*/
class TControlSetupPacket : public ::RUsbInterface::TUsbTransferRequestDetails
	{
protected:
	TControlSetupPacket()
		{
		iRequestType = 0;
		iRequest = 0;
		iValue = 0;
		iIndex = 0;
		}
	};

/**
This class represents a control request to the client that does not request 
data from the client.  It merely instructs the client
*/
class TEmptyRequest : public TControlSetupPacket
	{
protected:
	TEmptyRequest()
		{
		iRequestType |= KHostToDevice;
		iRequestType |= KTypeVendor;
		iRequest = KVendorEmptyRequest;
		}
	};

/**
 */
 class TDataSendRequest : public TControlSetupPacket
 	{
 	friend class CEp0Transfer;

 protected:
 	TDataSendRequest()
 		{
		iRequestType |= KHostToDevice;
		iRequestType |= KTypeVendor;
		}
	
 	explicit TDataSendRequest(const TDesC8& aData)
 		{
 		iRequestType |= KHostToDevice;
 		iRequestType |= KTypeVendor;
 		iSendData.Copy(aData);
 		}

 	explicit TDataSendRequest(const TDesC16& aData)
 		{
 		iRequestType |= KHostToDevice;
 		iRequestType |= KTypeVendor;
 		iSendData.Copy(aData);
 		}
 	protected:
 	TBuf8<KMaxSendSize> iSendData;
 	};
 		
		
/**
*/
class TClassDataSendRequest : public TControlSetupPacket
	{
	friend class CEp0Transfer;

protected:
	explicit TClassDataSendRequest(const TDesC8& aData)
		{
		iRequestType |= KHostToDevice;
		iRequestType |= KTypeClass;
		iSendData.Copy(aData);
		}

	explicit TClassDataSendRequest(const TDesC16& aData)
		{
		iRequestType |= KHostToDevice;
		iRequestType |= KTypeClass;
		iSendData.Copy(aData);
		}
	protected:
	TBuf8<KMaxSendSize> iSendData;
	};


/**
This class represents a control request to the client that requests some data 
in response to the request
*/
class TDataRecvRequest : public TControlSetupPacket
	{
	friend class CEp0Transfer;

protected:
	explicit TDataRecvRequest(TDes8& aData) : iRecvData(aData)
		{
		iRequestType |= KDeviceToHost;
		iRequestType |= KTypeVendor;
		}

protected:
	TDes8& iRecvData;
	};


/**
*/
class TDescriptorGetRequest : public TDataRecvRequest
	{
public:
	/**
	Constructor, build a request to fetch a descriptor from the device
	@param aTypeAndIndex the type of the descriptor and the index
	@param aLanguage Id the identity of the language
	@param aData the symbian descriptor to hold the usb descriptor data 
	*/
	
	TDescriptorGetRequest(TUint16 aTypeAndIndex,TUint16 aLanguageId,TDes8& aData)
	:	TDataRecvRequest(aData)
		{
		iRequestType = 0; // Will overwrite KTypeVendor in base class
		iRequestType |= KDeviceToHost;	
		iRequest = 0x06; // Standard device GET_DESCRIPTOR
		iValue = aTypeAndIndex;
		iIndex = aLanguageId;
		}
	};

	
/**
This class represents an empty request that is directed at the device.
i.e. a request that does not require data from the client device
*/
class TEmptyDeviceRequest : public TEmptyRequest
	{
public:
	TEmptyDeviceRequest()
		{
		iRequestType |= KRecipientDevice;
		}
	};

/** 
This class represents an empty request that is directed at the interface.
i.e. a request that does not require data from the client interface
*/
class TEmptyInterfaceRequest : public TEmptyRequest
	{
public:
	explicit TEmptyInterfaceRequest(TUint16 aInterfaceNumber)
		{
		iRequestType |= KRecipientInterface;
		iIndex = aInterfaceNumber;
		}
	};
	
/**
This class represents a device directed request that send a payload
*/
class TDevicePutPayloadRequest : public TDataSendRequest
	{
public:
	TDevicePutPayloadRequest(const TDesC8& aData) : TDataSendRequest(aData)
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorPutPayloadRequest;
		iValue = 0;
		iIndex = 0;
		}
	};
	
/**
This class represents a device directed request that retrieves a payload
from the client device
*/
class TDeviceGetPayloadRequest : public TDataRecvRequest
	{
public:
	explicit TDeviceGetPayloadRequest(TDes8& aData) : TDataRecvRequest(aData)
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorGetPayloadRequest;
		iValue = 0;
		iIndex = 0;
		}
	};
	
/**
This class represents a device directed request that retrieves a payload
from the client device containing the number of bytes read on an endpoint 
performing a 'Repeated Read'. 
*/
class TInterfaceGetRecordedNumBytesReadInPayload : public TDataRecvRequest
	{
public:
	explicit TInterfaceGetRecordedNumBytesReadInPayload(const TUint16 aInterfaceNumber,const TUint8 aReadEndpointNumber,TDes8& aData) : TDataRecvRequest(aData)
		{
		iRequestType |= KRecipientInterface;
		iRequest = KVendorGetRecordedNumBytesReadInPayloadRequest;
		iValue = aReadEndpointNumber;
		iIndex = aInterfaceNumber;
		}
	};
	
/**
This class represents a device directed request that retrieves a payload
from the client device containing the number of bytes written on an endpoint 
performing a 'Repeated Write'. 
*/
class TInterfaceGetRecordedNumBytesWrittenInPayload : public TDataRecvRequest
	{
public:
	explicit TInterfaceGetRecordedNumBytesWrittenInPayload(const TUint16 aInterfaceNumber,const TUint8 aWriteEndpointNumber,TDes8& aData) : TDataRecvRequest(aData)
		{
		iRequestType |= KRecipientInterface;
		iRequest = KVendorGetRecordedNumBytesWrittenInPayloadRequest;
		iValue = aWriteEndpointNumber;
		iIndex = aInterfaceNumber;
		}
	};
	


/**
This class represents an interface directed request that sends a payload
*/
class TInterfacePutPayloadRequest : public TDataSendRequest
	{
public:
	TInterfacePutPayloadRequest(TUint16 aInterfaceNumber,const TDesC8& aData) : TDataSendRequest(aData)
		{
		iRequestType |= KRecipientInterface;
		iRequest = KVendorPutPayloadRequest;
		iValue = 0;
		iIndex = aInterfaceNumber;
		}
	};
	
/**
This class represents a device directed request that retrieves a payload
from the client device
*/
class TInterfaceGetPayloadRequest : public TDataRecvRequest
	{
public:
	explicit TInterfaceGetPayloadRequest(TUint16 aInterfaceNumber,TDes8& aData) : TDataRecvRequest(aData)
		{
		iRequestType |= KRecipientInterface;
		iRequest = KVendorGetPayloadRequest;
		iValue = 0;
		iIndex = aInterfaceNumber;
		}
	};

/**
This class represents a control request to stall a specified endpoint
*/
class TInterfaceEndpointBaseRequest : public TEmptyRequest
	{
public:
	/**
	Constructor, build a request containing a specified endpoint and a specified interface
	@param aEndpointNumber the endpoint to use
	@param aInterfaceNumber the interface to use
	*/
	
	TInterfaceEndpointBaseRequest(TUint16 aEndpointNumber,TUint16 aInterfaceNumber)
	: TEmptyRequest()
		{
		iRequestType |= KRecipientInterface;
		iValue = aEndpointNumber;
		iIndex = aInterfaceNumber;
		}
	};

/**
This class represents a control request to stall a specified endpoint
*/
class TStallEndpointRequest : public TInterfaceEndpointBaseRequest
	{
public:
	/**
	Constructor, build a request to stall a specified endpoint
	@param aEndpointNumber the endpoint to stall
	*/
	
	TStallEndpointRequest(TUint16 aEndpointNumber,TUint16 aInterfaceNumber)
	: TInterfaceEndpointBaseRequest(aEndpointNumber, aInterfaceNumber)
		{
		iRequest = KVendorStallRequest;
		}
	};

/**
This class represents a control request to use a validation previously recorded in the endpoint
to update the interface's PASS\FAIL string.
*/
class TRecordedValidationResultRequest : public TInterfaceEndpointBaseRequest
	{
public:
	/**
	Constructor, build a request to update the interface's PASS\FAIL 
	string using a previously recorded validation.
	@param aEndpointNumber the endpoint to from which to retrieve the previously recorded validation
	*/
	
TRecordedValidationResultRequest(TUint16 aEndpointNumber,TUint16 aInterfaceNumber)
	: TInterfaceEndpointBaseRequest(aEndpointNumber, aInterfaceNumber)
		{
		iRequest = KVendorRecordedValidationResultRequest;
		}
	};

/**
This class represents a control request to stall a specified endpoint
*/
class TEndpointCancelWriteRequest : public TInterfaceEndpointBaseRequest
	{
public:
	/**
	Constructor, build a request to stall a specified endpoint
	@param aEndpointNumber the endpoint to stall
	*/
	
	TEndpointCancelWriteRequest(TUint16 aEndpointNumber,TUint16 aInterfaceNumber)
	: TInterfaceEndpointBaseRequest(aEndpointNumber, aInterfaceNumber)
		{
		iRequest = KVendorCancelWriteToEndpointRequest;
		}
	};

/**
This class represents a control request to stall a specified endpoint
*/
class TEndpointCancelReadRequest : public TInterfaceEndpointBaseRequest
	{
public:
	/**
	Constructor, build a request to stall a specified endpoint
	@param aEndpointNumber the endpoint to stall
	*/
	
	TEndpointCancelReadRequest(TUint16 aEndpointNumber,TUint16 aInterfaceNumber)
	: TInterfaceEndpointBaseRequest(aEndpointNumber, aInterfaceNumber)
		{
		iRequest = KVendorCancelAnyReadFromEndpointRequest;
		}
	};

/**
This class represents a control request to the device to initiate a remote
wake-up after the supplied interval has elapsed.
*/
class TRemoteWakeupRequest : public TEmptyRequest
	{
public:
	explicit TRemoteWakeupRequest(TUint16 aWakeupInterval)
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorRemoteWakeupRequest;
		iValue = aWakeupInterval;
		}
	};

/**
This class represents a control request to the device to reconnect to the host after 
the supplied interval has elapsed
*/
class TReconnectRequest : public TEmptyRequest
	{
public:
	explicit TReconnectRequest(TUint16 aReconnectInterval)
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorReconnectRequest;
		iValue = aReconnectInterval;		
		}
	};
	
/**
This class represents a control request to the device to disconnect device A and connect 
device C to the host 
*/
class TDisconnectDeviceAThenConnectDeviceCRequest : public TEmptyRequest
	{
public:
	/**
	Constructor, build a request that informs the client device of a successful test case status
	*/
	
	TDisconnectDeviceAThenConnectDeviceCRequest()
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorDisconnectDeviceAThenConnectDeviceCRequest;
		iValue = KErrNone;
		}
	};

/**
This class represents a control request to the device to disconnect device C and connect 
device A to the host 
*/
class TDisconnectDeviceCThenConnectDeviceARequest : public TEmptyRequest
	{
public:
	/**
	Constructor, build a request that informs the client device of a successful test case status
	*/
	
	TDisconnectDeviceCThenConnectDeviceARequest()
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorDisconnectDeviceCThenConnectDeviceARequest;
		iValue = KErrNone;
		}
	};
	
/**
This class represents an instruction to the client to write the data 
supplied to an endpoint that is specified
*/
class TEndpointWriteRequest : public TDataSendRequest
	{
public:
	/**
	Constructor, build a request that instructs an interface on the client device to write data
	to a specified endpoint
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	@param aData the data to write to that endpoint
	*/
	
	TEndpointWriteRequest(TUint16 aInterfaceNumber,TUint16 aEndpointNumber,const TDesC8& aData) : TDataSendRequest(aData)
		{
		iRequestType |= KRecipientInterface;
		iRequest = KVendorWriteToEndpointRequest;
		iValue = aEndpointNumber;
		iIndex = aInterfaceNumber;
		}
	};

/**
This class represents an instruction to the client to write specified data a number of times 
on a given endpoint
*/
class TEndpointPatternWriteRequest : public TDataSendRequest
 	{
 	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to write specified data
	to an endpoint
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	@param aData the data pattern to use when writing to that endpoint
	@param aNumBytes the number of bytes to write using that data pattern
	*/
	TEndpointPatternWriteRequest(TUint16 aInterfaceNumber,TUint16 aEndpointNumber,const TDesC8& aData,const TUint aNumBytes)
		{
		iRequestType |= KRecipientInterface;
		iRequest = KVendorPatternWriteToEndpointRequest;
		iValue = aEndpointNumber; 
		iIndex = aInterfaceNumber;

		iSendData.Zero();
 		iSendData.Format(KNumberFormatString, aNumBytes);
 		iSendData.Append(aData);
 		}
 	};

	
		
/**
This class represents an instruction to the client to synchronously write specified data a number of times 
on a given endpoint
*/
class TEndpointPatternSynchronousWriteRequest : public TEndpointPatternWriteRequest
 	{
 	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to write specified data
	to an endpoint
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	@param aData the data pattern to use when writing to that endpoint
	@param aNumBytes the number of bytes to write using that data pattern
	*/
	TEndpointPatternSynchronousWriteRequest(TUint16 aInterfaceNumber,TUint16 aEndpointNumber,const TDesC8& aData,const TUint aNumBytes)
	: TEndpointPatternWriteRequest(aInterfaceNumber,aEndpointNumber,aData,aNumBytes)
		{
		iRequest = KVendorPatternWriteSynchronousToEndpointRequest;
		}
 	};

	
		
/**
This class represents an instruction to the client synchronously to write specified data a number of times 
on a given endpoint and then halt that endpoint
*/
class TEndpointPatternSynchronousWriteAndHaltRequest : public TEndpointPatternSynchronousWriteRequest
 	{
 	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to write specified data
	to an endpoint and then halt that endpoint
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	@param aData the data pattern to use when writing to that endpoint
	@param aNumBytes the number of bytes to write using that data pattern
	*/
	TEndpointPatternSynchronousWriteAndHaltRequest(TUint16 aInterfaceNumber,TUint16 aEndpointNumber,const TDesC8& aData,const TUint aNumBytes)
	: TEndpointPatternSynchronousWriteRequest(aInterfaceNumber, aEndpointNumber, aData, aNumBytes)
		{
		iRequest = KVendorPatternWriteSynchronousToAndHaltEndpointRequest;
 		}
 	};

/**
This class represents an instruction to the client to validate data read on an endpoint with specified data 
on a given endpoint
*/
 class TEndpointStringValidationRequest : public TEndpointPatternWriteRequest
 	{
 	friend class CEp0Transfer;

 public:
	/**
	Constructor, build a request that instructs an interface on the client device to 
	verify data on an endpoint using the data pattern provided
	@param aInterfaceNumber the number of the interface which has this endpoint
	@param aEndpointNumber the number of the endpoint to use (a pipe must be open on this endpoint)
	@param aData the data pattern to use when verifying on that endpoint
	@param aNumBytes the number of bytes to write using that data pattern	*/
	TEndpointStringValidationRequest(TUint16 aInterfaceNumber,TUint16 aEndpointNumber,const TDesC8& aData,const TUint aNumBytes)
 	: TEndpointPatternWriteRequest(aInterfaceNumber,aEndpointNumber,aData,aNumBytes)
 		{
 		iRequest = KVendorStringValidationRequest;
		}
 	};
	 	
	
		
/**
This class represents an instruction to the client to write back data just read.
*/
class TWriteSynchronousCachedReadDataRequest : public TControlSetupPacket
	{
	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to use the data
	just read on one endpoint to send back on another.
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aReadEndpointNumber the number of the endpoint that has just been read from (a pipe must be open on this endpoint)
	@param aWriteEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	*/
	TWriteSynchronousCachedReadDataRequest(const TUint16 aInterfaceNumber,const TUint8 aReadEndpointNumber,const TUint8 aWriteEndpointNumber)
		{
		iRequestType |= KHostToDevice;
		iRequestType |= KTypeVendor;
		iRequestType |= KRecipientInterface;
		iRequest = KVendorWriteSynchronousCachedReadRequest;
		iValue = aReadEndpointNumber << 8 | aWriteEndpointNumber; 
		iIndex = aInterfaceNumber;
		}
	};
	
/**
This class represents an instruction to the client to write back data just read.
*/
class TWriteCachedReadDataRequest : public TWriteSynchronousCachedReadDataRequest
	{
	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to use the data
	just read on one endpoint to send back on another.
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aReadEndpointNumber the number of the endpoint that has just been read from (a pipe must be open on this endpoint)
	@param aWriteEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	*/
	TWriteCachedReadDataRequest(const TUint16 aInterfaceNumber,const TUint8 aReadEndpointNumber,const TUint8 aWriteEndpointNumber)
	: TWriteSynchronousCachedReadDataRequest(aInterfaceNumber, aReadEndpointNumber, aWriteEndpointNumber)
		{
		iRequest = KVendorWriteCachedReadRequest;
		}
	};
	
	
/**
This class represents an instruction to the client to write back data just read - in sections.
*/
class TSplitWriteCachedReadDataRequest : public TDataSendRequest
	{
	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to use the data
	just read on one endpoint to send back on another.
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aReadEndpointNumber the number of the endpoint that has just been read from (a pipe must be open on this endpoint)
	@param aWriteEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	*/
	TSplitWriteCachedReadDataRequest(const TUint16 aInterfaceNumber,const TUint8 aReadEndpointNumber,const TUint8 aWriteEndpointNumber,const TUint aNumBytes[KNumSplitWriteSections])
		{
		iRequestType |= KHostToDevice;
		iRequestType |= KTypeVendor;
		iRequestType |= KRecipientInterface;
		iRequest = KVendorSplitWriteSynchronousCachedReadRequest;
		iValue = aReadEndpointNumber << 8 | aWriteEndpointNumber; 
		iIndex = aInterfaceNumber;

		iSendData.Zero();
		for(TUint i = 0; i<KNumSplitWriteSections; ++i)
			{
			TBuf8<KNumberStringLength> buf;
			buf.Format(KNumberFormatString, aNumBytes[i]);
			iSendData.Append(buf);
			}
 		}
	};
	
/**
This class represents an instruction to the client to write back data just read - in sections.
*/
class TRepeatedWriteDataRequest : public TDataSendRequest
	{
	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to perform 
	a repeated read using the data as a pattern to validate the data as it arrives.
	Constructor, build a request that instructs an interface on the client device to perform 
	a repeated write using the data as a pattern.
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aReadEndpointNumber the number of the endpoint that has just been read from (a pipe must be open on this endpoint)
	@param aData the data pattern to be used for validation
	@param aNumBytesPerRead the number of bytes to read at each 'Read'
	@param aTotalNumBytes the total number of bytes to read (over all 'Read's)
	*/
TRepeatedWriteDataRequest(const TUint16 aInterfaceNumber,const TUint8 aReadEndpointNumber,const TDesC8& aDataPattern,const TUint aNumBytesPerRead,const TUint aTotalNumBytes)
		{
		iRequestType |= KHostToDevice;
		iRequestType |= KTypeVendor;
		iRequestType |= KRecipientInterface;
		iRequest = KVendorRepeatedPatternWriteDataRequest;
		iValue = aReadEndpointNumber; 
		iIndex = aInterfaceNumber;

		iSendData.Zero();
		TBuf8<KTwoNumberStringLength> buf;
		buf.Format(KTwoNumberFormatString, aNumBytesPerRead, aTotalNumBytes);
		iSendData.Append(buf);
		iSendData.Append(aDataPattern);
		}
	};
	
	 	
	
/**
This class represents an instruction to the client to read a number of bytes of data 
on an the endpoint.
*/
class TEndpointReadRequest : public TControlSetupPacket
	{
	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to read a specified amount data
	on the specified endpoint
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	@param aNumBytes the amount of data to read on that endpoint
	*/
	TEndpointReadRequest(TUint16 aInterfaceNumber,TUint16 aEndpointNumber,const TUint aNumBytes)
		{
		iRequestType |= KHostToDevice;
		iRequestType |= KTypeVendor;
		iRequestType |= KRecipientInterface;
		iRequest = KVendorReadFromEndpointRequest;
		iValue = aEndpointNumber; 
		iIndex = aInterfaceNumber;

		iReadSpecificationData.Zero();
		iReadSpecificationData.Format(KNumberFormatString, aNumBytes);
		}

protected:
	TBuf8<KNumberStringLength> iReadSpecificationData;
	};

/**
This class represents an instruction to the client to read a number of bytes of data 
on an the endpoint. Reading will complete early if a short packet is detected.
*/
class TEndpointReadUntilShortRequest : public TEndpointReadRequest
	{
	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to read the data
	on the specified endpoint
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	@param aNumBytes the amount of data to read on that endpoint (if a short packet does not arrive sooner)
	*/
	TEndpointReadUntilShortRequest(TUint16 aInterfaceNumber,TUint16 aEndpointNumber,const TUint aNumBytes)
	: TEndpointReadRequest(aInterfaceNumber, aEndpointNumber, aNumBytes)
		{
		iRequest = KVendorReadUntilShortFromEndpointRequest;
		}
	};

/**
This class represents an instruction to the client to read a number of bytes of data 
on an the endpoint, and then, when the specified number of bytes have been read, to stall the endpoint.
*/
class TEndpointReadAndHaltRequest : public TEndpointReadRequest
	{
	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to read the data
	on the specified endpoint
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aEndpointNumber the number of the endpoint to write to (a pipe must be open on this endpoint)
	@param aNumBytes the amount of data to read on that endpoint (if a short packet does not arrive sooner)
	*/
	TEndpointReadAndHaltRequest(TUint16 aInterfaceNumber,TUint16 aEndpointNumber,const TUint aNumBytes)
	: TEndpointReadRequest(aInterfaceNumber, aEndpointNumber, aNumBytes)
		{
		iRequest = KVendorReadFromAndHaltEndpointRequest;
		}
	};

/**
This class represents an instruction to the client to write back data just read - in sections.
*/
class TRepeatedReadAndValidateDataRequest : public TRepeatedWriteDataRequest
	{
	friend class CEp0Transfer;

public:
	/**
	Constructor, build a request that instructs an interface on the client device to perform 
	a repeated read using the data as a pattern to validate the data as it arrives.
	@param aInterfaceNumber the number of the interface which has this endpoint to write to
	@param aReadEndpointNumber the number of the endpoint that has just been read from (a pipe must be open on this endpoint)
	@param aData the data pattern to be used for validation
	@param aNumBytesPerRead the number of bytes to read at each 'Read'
	@param aTotalNumBytes the total number of bytes to read (over all 'Read's)
	*/
TRepeatedReadAndValidateDataRequest(const TUint16 aInterfaceNumber,const TUint8 aReadEndpointNumber,const TDesC8& aDataPattern,const TUint aNumBytesPerRead,const TUint aTotalNumBytes)
: TRepeatedWriteDataRequest(aInterfaceNumber,aReadEndpointNumber,aDataPattern,aNumBytesPerRead,aTotalNumBytes)		
		{
		iRequest = KVendorRepeatedReadAndValidateDataRequest;
		}
	};
	
	 	
/**
This class represents a request that requests the client device
to negatively acknowledge the request
*/
class TNakRequest : public TEmptyRequest
	{
public:
	/**
	Constructor, build a request that instructs an interface to continually NAK the request
	@param aInterfaceNumber the interface number
	*/
	
	explicit TNakRequest(TUint16 aInterfaceNumber)
		{
		iRequestType |= KRecipientInterface;
		iRequest = KVendorUnrespondRequest;
		iIndex = aInterfaceNumber;
		}
	};
	
/**
This class represents a control request to the device to indicate that test case
has successfully completed and to disconnect the device
*/
class TTestCasePassed : public TEmptyRequest
	{
public:
	/**
	Constructor, build a request that informs the client device of a successful test case status
	*/
	
	TTestCasePassed()
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorTestCasePassed;
		iValue = KErrNone;
		}
	};
	
/**
This class represents a control request to the device of an unsuccessful test case execution
and to complete the device side test case with the supplied error and error message
*/
class TTestCaseFailed : public TDataSendRequest	
	{
public:
	/**
	Constructor, build a request that informs the client device of an unsuccessful test case status
	@param aError the error that the host side test case reports
	@param aErrorMsg the message text (non-unicode) for the client to display when this request has been received 
	*/
	
	TTestCaseFailed(TInt aError,const TDesC8& aErrorMsg) : TDataSendRequest(aErrorMsg)
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorTestCaseFailed;
		iValue = -aError; // Invert the error as symbian system errors are negative
		}
	
	/**
	Constructor, build a request that informs the client device of an unsuccessful test case status
	@param aError the error that the host side test case reports
	@param aErrorMsg the message text (unicode) for the client to display when this request has been received 
	*/
	
	TTestCaseFailed(TInt aError,const TDesC16& aErrorMsg) : TDataSendRequest(aErrorMsg)
		{
		iRequestType |= KRecipientDevice;
		iRequest = KVendorTestCaseFailed;
		iValue = -aError; // Invert the error as symbian system errors are negative
		}
	};


/**
This class represents the SET_CUR audio class control request
*/
class TSetCurRequest : public TClassDataSendRequest
	{
public:
	explicit TSetCurRequest(const TDesC8& aData, const TUint aEndpointAddress) : TClassDataSendRequest(aData) //TUint16 aSamplingFrequency)
		{
		iRequestType |= KRecipientEndpoint;
		iRequest = KAudioClassSetCur;		
		iValue = 0x0100;
		iIndex = aEndpointAddress;
		}
	};

	
/**
This class describes an observer to the Ep0 control transfer
*/
class MCommandObserver
	{
public:
	/**
	Called when an endpoint zero test command transfer has completed
	@param aCompletionCode the completion code of the asynchronous transfer to Ep0
	*/
	virtual void Ep0TransferCompleteL(TInt aCompletionCode) = 0;
	};

/**
This class represents a transfer to a control endpoint 0
*/
class CEp0Transfer : public CActive
	{
public:
	/**
	Constructor, build a test command to send to the connected client
	@param aToken the token 
	*/
	CEp0Transfer(RUsbInterface& aInterface0);
	
	/**
	Destructor
	*/
	~CEp0Transfer();
	
	/**
	Send a control transfer request to endpoint zero of the client
	@param aSetupPacket a control request
	@param aObserver the observer that will be notified of transfer completion
	*/
	void SendRequest(TEmptyRequest& aSetupPacket,MCommandObserver* aObserver);
	
	/**
	Send a control transfer request to endpoint zero of the client
	@param aSetupPacket a control request
	@param aObserver the observer that will be notified of transfer completion
	*/
	void SendRequest(TDataRecvRequest& aSetupPacket,MCommandObserver* aObserver);
	
	/**
	Send a control transfer request to endpoint zero of the client that will also send a payload in data packets
	@param aSetupPacket a control request
	@param aObserver the observer that will be notified of transfer completion
	*/
	void SendRequest(TDataSendRequest& aSetupPacket,MCommandObserver* aObserver);

	/**
	Send a control transfer request to endpoint zero of the client
	@param aSetupPacket a control request
	@param aObserver the observer that will be notified of transfer completion
	*/
	void SendRequest(TWriteSynchronousCachedReadDataRequest& aSetupPacket,MCommandObserver* aObserver);

	/**
	Send a control transfer request to endpoint zero of the client that will also send a payload in data packets
	@param aSetupPacket a control request
	@param aObserver the observer that will be notified of transfer completion
	*/
	void SendRequest(TEndpointReadRequest& aSetupPacket,MCommandObserver* aObserver);

	/**
	Send a class control transfer request to endpoint zero of the client that will also send a payload in data packets
	@param aSetupPacket a class control request
	@param aObserver the observer that will be notified of transfer completion
	*/
	void SendRequest(TClassDataSendRequest& aSetupPacket,MCommandObserver* aObserver);
	
	/**
	Cancel last SendRequest if still active. This does NOT cancel the active object
	which must be done separately using the normal 'Cancel' function.
	*/
	void CancelSendRequest();

	/**
	Gets the time the last SendRequest was sent.
	*/
	void LastRequestStartTime( TTime& aDuration);

	/**
	Gets the time the last SendRequest was completed in RunL.
	*/
	void LastRequestCompletionTime( TTime& aDuration);

private:
	
	/**
	Currently no way to cancel a single transfer, so not going to try
	*/
	void DoCancel();

	/**
	*/
	void RunL();
	
	/**
	*/
	TInt RunError(TInt aError);

private:

	/**
	The USB interface endpoint zero which receives the command
	For the test devices modelled 
	*/
	RUsbInterface& iUsbInterface0;
	
	/**
	The observer of client responses to host commands (uses-a)
	*/
	MCommandObserver* iObserver;

	/**
	The actual amount of data received by the host from the client
	in response to a command sent by the host
	*/
	TInt iActualLength;
	
	/**
	The flag to indicate if the request sent required the clieent device to answer with
	some data
	*/
	TBool iDataRequest;
	
	TBuf8<1> iTemp;

	/**
	 The time the last SendRequest was sent.
	 */
	TTime iRequestTime;

	/**
	 The time the last SendRequest was completed in RunL
	 */
	TTime iCompletionTime;
	};


	}


#endif