usbmgmt/usbmgrtest/ObexClassController/test/src/simpleObexClient.cpp
changeset 0 c9bc50fca66e
child 25 4ddb65515edd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbmgmt/usbmgrtest/ObexClassController/test/src/simpleObexClient.cpp	Tue Feb 02 02:02:59 2010 +0200
@@ -0,0 +1,585 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+*/
+
+#include <e32base.h>
+
+#include <bautils.h>
+#include <obexconstants.h>
+#include "simpleObexClient.h"
+#include "simpleObexApp.h"
+#include "obexAppConstants.h"
+
+
+
+/**
+ * Constructor, ownership of Console is passed.
+ */
+CObexClientHandler::CObexClientHandler(CActiveConsole* aParent)
+    : CActive(CActive::EPriorityStandard),
+      iParent(aParent)
+    {
+    iClient    = NULL;
+    iObject    = NULL;
+    iState     = EIdle;
+    }
+
+
+/**
+ * NewL function.
+ */
+CObexClientHandler* CObexClientHandler::NewL(CActiveConsole* aParent, TTransport aTransport)
+    {
+    CObexClientHandler* self = new (ELeave) CObexClientHandler(aParent);
+
+    CleanupStack::PushL (self);
+    self->ConstructL(aTransport);
+    CActiveScheduler::Add (self);
+    CleanupStack::Pop ();
+    return (self);
+    }
+
+
+/**
+ * 2nd phase constructor. Responsible for determining which
+ * transport has been selected and to create a new OBEX Client.
+ */
+void CObexClientHandler::ConstructL(TTransport aTransport)
+    {
+	
+	// Construct client if bluetooth selected
+	if (aTransport == EBluetooth)
+		{
+		iDevAddr = devAddr;  // take the Bluetooth address
+
+		//start the SDP Query
+		delete iSdpServiceFinder;
+		iSdpServiceFinder=0;
+		iSdpServiceFinder = CRFCOMMServiceFinder::NewL(ftpUuid, iDevAddr, *this);
+		// Start search process
+		iSdpServiceFinder->FindPortL();
+		iParent->Console()->Printf(_L("\nSearching for SDP service....\n"));
+		}
+	else if (aTransport == EIrda)
+		{
+		// Create transport info
+		TObexIrProtocolInfo transportInfo;
+		//assigning the unique name for the irda transport
+		transportInfo.iTransport = KObexIrTTPProtocol; 
+		//assigning irda specific attributes
+		transportInfo.iClassName      = KIrdaClassName;					
+		transportInfo.iAttributeName = KIrdaTransportAttrName;
+		
+  		iClient = CObexClient::NewL (transportInfo);	//create the obex client
+		iParent->iMode = E_Client;
+		}
+	else if (aTransport == EUsb)
+		{
+		// Create transport info
+		TObexUsbProtocolInfo aInfo;
+		aInfo.iTransport = KObexUsbProtocol;
+		aInfo.iInterfaceStringDescriptor = KClientInterfaceDescriptor;
+
+	    iClient = CObexClient::NewL (aInfo);// Create the CObexClient
+		}
+	else if (aTransport == EWin32Usb)
+		{
+		// Ensure win32usb Obex transport plugin exists
+		// Create transport info
+		TObexUsbProtocolInfo aInfo;
+		aInfo.iTransport = KObexWin32UsbProtocol;
+		aInfo.iInterfaceStringDescriptor = KClientInterfaceDescriptor;
+
+	    iClient = CObexClient::NewL (aInfo);
+		}
+	else
+		{
+		User::Invariant();
+		}
+
+	// Setup Obex objects
+	iFileObject = CObexFileObject::NewL();
+	iObjectBuffer = CBufFlat::NewL(KBufExpandSize);
+    iObject = CObexBufObject::NewL(iObjectBuffer);
+    iObexName = KNullDesC;
+	iGetType = KObjectType;
+	
+	// Create file session and create a new private path on drive C
+	RFs fileSession;
+	fileSession.Connect();
+	
+	fileSession.CreatePrivatePath(EDriveC);
+	fileSession.SetSessionToPrivate(EDriveC);	
+	fileSession.SessionPath(iSessionPath);
+	
+	// Copy the files from oby file ro the newly created path
+	BaflUtils::CopyFile(fileSession, KFilePath1, KFilename1,0);
+	BaflUtils::CopyFile(fileSession, KFilePath2, KFilename2,0);
+	BaflUtils::CopyFile(fileSession, KFilePath3, KFilename3,0);
+ 
+	fileSession.Close();
+	
+	// Assign file names
+	iFilename1 = KFilename1; 
+	iFilename2 = KFilename2;
+	iFilename3 = KFilename3;
+
+	
+    }
+
+
+/**
+ * Destructor.
+ */
+CObexClientHandler::~CObexClientHandler()
+    {
+    // do cleanup
+    Cancel();
+    delete iObject;
+	delete iFileObject;
+    delete iClient;
+	delete iObjectBuffer;
+	delete iTargetHeaderObject;
+	delete iSdpServiceFinder;
+    }
+    
+/**
+ * This function is called when the SDP search finishes.
+ * If search was successful then the OBEX port number is
+ * taken an used in starting the OBEX client.
+ * If unsuccessful, go back to the initial menu.
+ */
+void CObexClientHandler::SearchResult(TInt aError, TUint8 aPort)
+	{
+	// Service not supported?
+	if (aError != KErrNone)
+		{
+		iParent->Console()->Printf(_L("\r\n Could not find SDP service in remote device : error %d \r\n"),aError);	
+		iParent->iMode = E_Inactive;
+		iParent->Cancel();
+		}
+	
+	
+	// Set protocol info for bluetooth
+		
+	TObexBluetoothProtocolInfo aInfo;
+	aInfo.iAddr.SetBTAddr(iDevAddr);
+	aInfo.iAddr.SetPort(aPort); 
+	aInfo.iTransport = KObexRfcommProtocol;
+	//now create the obex client...
+	TRAPD(error,iClient = CObexClient::NewL (aInfo));
+	if (error)
+		{
+		iParent->Console()->Printf(_L("\r\n Could not create client! : error %d \r\n"),error);
+		iParent->iMode = E_Inactive;
+		iParent->Cancel();
+		}
+		
+	iParent->Console()->Printf(_L("\nSDP search complete OK!\n"));
+	iParent->iMode = E_Client;
+	
+	iParent->RequestCharacter();
+
+	}
+
+
+
+/**
+ * This function performs the actual connection of client to server.
+ */
+
+void CObexClientHandler::Connect()
+    {
+    if(IsActive())
+		{
+		iParent->Console()->Printf(KAlreadyActive);
+		return;
+		}
+   
+    TObexConnectInfo iLocalInfo = iClient->LocalInfo();
+    iLocalInfo.iWho = KNullDesC8;
+    iLocalInfo.iWho = EPOCIDENT;  
+    iLocalInfo.iWho.Append(KLocalInfoAppend);
+	// Connect to Obex client
+    iClient->Connect(iStatus);
+    SetActive();
+    iState = EConnecting;
+    }
+
+    
+/**
+ * This fucntion performs the disconnection from OBEX client and server
+ */    
+void CObexClientHandler::Disconnect()
+    {
+    if(IsActive())
+		{
+		iParent->Console()->Printf(KAlreadyActive);
+		return;
+		} 
+    // Disconnect from Obex client
+	iClient->Disconnect(iStatus);
+    SetActive();
+    iState = EDisconnecting;
+    }
+
+
+/**
+ * This function is called when an OBEX get is requested by name.
+ * It takes the current name of the OBEX object, replaces it with
+ * a user defined name. it then performs a Get on this object name. 
+ */
+void CObexClientHandler::GetByNameL()
+    {
+    if(IsActive())
+		{
+		iParent->Console()->Printf(KAlreadyActive);
+		return;
+		}
+	
+    iObject->Reset ();
+    // Call SetName passing current name
+    // This will set a newly selected name from the user
+	SetName(iObexName);
+	// Set the name
+    iObject->SetNameL (iObexName);
+    // Call get with required object
+    iClient->Get(*iObject, iStatus);
+    SetActive();
+    iState = EGetting;
+    }
+
+
+
+/**
+ * This function is a wrapper for the CObexClient::Put function.
+ * It is responsible for setting up a new Obex object from a specified file.
+ * It then performs the Put operation.
+ */    
+void CObexClientHandler::Put(TDes& aFilename)
+    {
+    if(IsActive())
+		{
+		iParent->Console()->Printf(KAlreadyActive);
+		return;
+		}
+		
+	// Setup the object from file
+	TInt err = SetUpObjectFromFile (aFilename);
+	// Advise user if unsuccessful
+	if( err != KErrNone)
+		{
+		iParent->Console()->Printf(_L("\r\n Couldnt set up object : error %d \r\n"),err);
+		Disconnect();
+		return;
+		}
+	// Call the put	
+	iClient->Put(*iFileObject,iStatus);
+	SetActive();
+	iState = EPutting;
+	}
+
+
+/**
+ * This function is responsible for initiating a 
+ * client/server connection with authentication.
+ * The password is set in source.
+ */
+void CObexClientHandler::ConnectWithAuthenticationL()
+	{
+    if(IsActive())
+		{
+		iParent->Console()->Printf(KAlreadyActive);
+		return;
+		}
+	// Set generic password
+    iChallengePassword = KAuthPassword;
+    // Connect client to server sending password
+    iClient->ConnectL(iChallengePassword, iStatus);
+    // Active the active object
+    SetActive();
+    iState = EConnecting;
+	}
+	
+/**
+ * This function is called from within the GetByName function.
+ * It takes in the current object name and changes it to a user
+ * defined alternative.
+ */
+void CObexClientHandler::SetName(TDes& aName)
+    {
+	TBuf<64> oldName;
+	oldName = aName;
+
+	TKeyCode aCode;
+	TBuf<1> aChar;
+	iParent->Console()->Printf(_L("\nEnter a name: %S"),&aName);
+	FOREVER
+		{
+		aCode = iParent->Console()->Getch();
+		aChar.SetLength(0);
+		aChar.Append(aCode);
+
+		iParent->Console()->Printf(_L("%S"),&aChar);
+	
+		// If <CR> finish editing string
+		if (aCode ==  EStdKeyDelete)
+			break;
+		
+		// if <BS> remove last character
+		if ((aCode == EStdKeyHome)&&(aName.Length() != 0))
+			aName.SetLength((aName.Length()-1));
+		else
+			aName.Append(aCode);
+		}
+	iParent->Console()->Printf(_L("\n"));
+
+
+    }
+
+
+
+/**
+ * This is the active object RunL function.
+ * When the function is called the currently selected mode of operation
+ * is examined and then dealt with accordingly.
+ * It displays the active object iStatus current state to the user.
+ */
+void CObexClientHandler::RunL ()
+    {
+    if (iStatus != KErrNone)
+		{// Handle error
+		}
+
+    TBuf<80> filename;
+    switch (iState)
+		{
+		// If we were connecting, and iStatus has completed then we want to change iState to EConnected
+		case EConnecting:
+			iParent->Console()->Printf(_L("\r\nConnect completed with error code: %d\r\n\r\n"),iStatus.Int());
+			iState = EConnected;
+			break;
+		// If we were performing a put and the iStatus has completed change iState to EConnected
+		case EPutting:
+			iState = EConnected;
+			iParent->Console()->Printf(_L("\r\nPut completed with error code: %d\r\n\r\n"),iStatus.Int());
+			break;
+		// If we were performing a get and the iStatus has completed change iState to EConnected
+		// Also we want to write the received object to file
+		case EGetting:
+			iState = EConnected;
+			iParent->Console()->Printf(_L("\r\nGet completed with error code: %d\r\n\r\n"),iStatus.Int());
+			DisplayObjectInformation();
+			filename = iSessionPath;
+			filename.Append(iObject->Name());		
+			// Write objects data to file, test if the file already exists as well
+			if (iObject->WriteToFile(filename) == KErrAlreadyExists)
+				{
+				iParent->Console()->Printf(_L("\r\nWrite failed, File Already Exists\n"));
+				}
+			iObject->Reset ();
+			break;
+		// If we wanted to disconnect and iStatus has completed, then go back to original state 
+		case EDisconnecting:
+			iParent->Console()->Printf(_L("\r\nDisconnect completed with error code: %d\r\n\r\n"),iStatus.Int());
+			iState = EIdle;
+		
+		default:
+			iParent->Console()->Printf(_L("\r\nTest Code is in an incorrect state: %d\r\n\r\n"),iState);
+			break;
+		}
+   
+    }
+
+/**
+ * This is the active object DoCancel function.
+ */
+void CObexClientHandler::DoCancel()
+    {
+    delete iClient;
+    iClient = NULL;
+    }
+    
+    
+/**
+ * DisplayObjectInformation prints information of the received object.
+ */    
+void CObexClientHandler::DisplayObjectInformation()
+    {
+    // Display Contents of CBufFlat data on current console
+	iParent->Console()->Printf(_L("Size of received object = %d\n"),iObjectBuffer->Size());
+	TDateTime dt = iObject->Time().DateTime();
+	iParent->Console()->Printf(_L("\r\nTimestamp: %d/%d/%d, %d:%d:%d\r\n\r\n"),
+				   dt.Day(), dt.Month()+1, dt.Year(), dt.Hour(), dt.Minute(), dt.Second());
+
+    TBuf8<1024> tempBuffer;
+	iObjectBuffer->Read(0, tempBuffer, tempBuffer.MaxSize() < iObjectBuffer->Size() ? tempBuffer.MaxSize() : iObjectBuffer->Size());
+	// Printf fails with Descriptor bigger than X hundred bytes so write byte at a time
+	for(TInt count = 0; count < tempBuffer.Size(); count++) 
+		{
+		iParent->Console()->Printf(_L("%C"),tempBuffer[count]);
+		}
+    }
+
+
+
+/**
+ * This function is called when a Put operation has started.
+ * It takes a filename and then attempts to setup an OBEX object
+ * from that file. Returns the appropriate error code, if the  
+ * file didn't exist then this function creates a new file of
+ * the same name. 
+ */
+TInt CObexClientHandler::SetUpObjectFromFile(TDes& aFilename)
+    {
+    // Try to create CObexFileObject with filename 
+	TRAPD (err, iFileObject->InitFromFileL (aFilename));
+	if (err != KErrNone)
+		{
+		RFs fs;
+		RFile f;
+		err = fs.Connect();
+		if (err== KErrNone)
+			{
+			err = fs.CreatePrivatePath(EDriveC);
+		 	}
+		 
+		if (err== KErrNone || err == KErrAlreadyExists )
+			{
+			err = fs.SetSessionToPrivate(EDriveC);
+			}
+			
+		if (err == KErrNone)
+			{
+			// File didn't exist so create a file of same name in it place	
+			err = f.Create (fs, aFilename, EFileShareExclusive | EFileWrite);
+			}
+			
+		if (err != KErrNone)
+			{
+			iParent->Console()->Printf(_L("\r\nError reading '%s'.\r\nI tried to create this file for you, but failed to do that too. Sorry.\r\n\r\n"), aFilename.PtrZ ());			
+			}
+		else
+			{
+			f.Write (_L8("Test file for sending from EPOC\r\n\r\nLooks like obex is sending OK!!\r\n"));
+			f.Close ();
+			iParent->Console()->Printf(_L("\r\nFile '%s' did not exist, so I've created one.\r\nPlease try again.\r\n\r\n"), aFilename.PtrZ ());	
+			}
+		fs.Close ();
+		
+		}
+	
+	return (err);
+
+    }
+
+
+    
+/**
+ * NewL function for CRFCOMMServiceFinder 
+ */
+
+CRFCOMMServiceFinder* CRFCOMMServiceFinder::NewL(	const TUUID& aServiceClass,
+							const TBTDevAddr& aDevAddr,
+							MRFCOMMServiceSeeker& aSeeker)
+	{
+	CRFCOMMServiceFinder* self= new (ELeave) CRFCOMMServiceFinder(aSeeker);
+	CleanupStack::PushL(self);
+	self->ConstructL(aDevAddr, aServiceClass);
+	CleanupStack::Pop();
+	return (self);
+	}
+
+/**
+ * Destructor.
+ */
+CRFCOMMServiceFinder::~CRFCOMMServiceFinder()
+	{
+	delete iPattern;
+	delete iAgent;
+	}
+
+/**
+ * Constructor.
+ */	
+CRFCOMMServiceFinder::CRFCOMMServiceFinder(MRFCOMMServiceSeeker& aSeeker)
+: iSeeker(aSeeker)
+	{
+	}
+
+/**
+ * 2nd phase constructor. Sets the seach pattern for SDP with the UUID supplied.
+ * Then Creates a new SDP agent with the device address supplied.
+ */
+void CRFCOMMServiceFinder::ConstructL(const TBTDevAddr& aDevAddr, const TUUID& aServiceClass)
+	{
+	iPattern=CSdpSearchPattern::NewL();
+	iPattern->AddL(aServiceClass);
+	iAgent=CSdpAgent::NewL(*this, aDevAddr);
+	// Filter out classes that arent FTP
+	iAgent->SetRecordFilterL(*iPattern);
+	}
+
+/**
+ * This function is responsible for calling the SDP agent NextRecordRequestL
+ * function, this gets the next service record that the device has registered
+ * in the SDP database.
+ */
+void CRFCOMMServiceFinder::FindPortL()
+	{
+	iPort=KNotAPort;	//0xFF will never be returned from a query, 
+			//because RFCOMM server channels only
+			//go up to 30.
+	
+	iAgent->NextRecordRequestL();
+	}
+
+
+/**
+ * This function is from the MSdpAgentNotify interface and is called when there
+ * are no more SDP records registered in the database. It calls SearchResult implemented 
+ * by this class.
+ */
+void CRFCOMMServiceFinder::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt /*aTotalRecordsCount*/) 
+	{
+	if(aError)
+		iSeeker.SearchResult(aError,KNoPort);	
+	else
+		{
+		//We have the record, kick off the attribute request
+		TRAPD(err,iAgent->AttributeRequestL(aHandle,KSdpAttrIdProtocolDescriptorList )); 
+		if(err)
+			iSeeker.SearchResult(err,KNoPort);
+		}
+	}
+
+
+	
+/**
+ * This function comes from the MSdpAgentNotifer interface, It is called when
+ * the attribute request process has finished.
+ */
+void CRFCOMMServiceFinder::AttributeRequestComplete(TSdpServRecordHandle /*aHandle*/, TInt aError)
+	{
+	if(aError!=KErrNone || iPort==KNotAPort)
+		iSeeker.SearchResult(aError?aError:KErrNotFound,KNoPort);
+	else
+		iSeeker.SearchResult(KErrNone, iPort);
+	}
+
+ 
+
+