usbmgmt/usbmgrtest/ObexClassController/test/src/simpleObexClient.cpp
changeset 0 c9bc50fca66e
child 15 f92a4f87e424
equal deleted inserted replaced
-1:000000000000 0:c9bc50fca66e
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <e32base.h>
       
    19 
       
    20 #include <bautils.h>
       
    21 #include <obexconstants.h>
       
    22 #include "simpleObexClient.h"
       
    23 #include "simpleObexApp.h"
       
    24 #include "obexAppConstants.h"
       
    25 
       
    26 
       
    27 
       
    28 /**
       
    29  * Constructor, ownership of Console is passed.
       
    30  */
       
    31 CObexClientHandler::CObexClientHandler(CActiveConsole* aParent)
       
    32     : CActive(CActive::EPriorityStandard),
       
    33       iParent(aParent)
       
    34     {
       
    35     iClient    = NULL;
       
    36     iObject    = NULL;
       
    37     iState     = EIdle;
       
    38     }
       
    39 
       
    40 
       
    41 /**
       
    42  * NewL function.
       
    43  */
       
    44 CObexClientHandler* CObexClientHandler::NewL(CActiveConsole* aParent, TTransport aTransport)
       
    45     {
       
    46     CObexClientHandler* self = new (ELeave) CObexClientHandler(aParent);
       
    47 
       
    48     CleanupStack::PushL (self);
       
    49     self->ConstructL(aTransport);
       
    50     CActiveScheduler::Add (self);
       
    51     CleanupStack::Pop ();
       
    52     return (self);
       
    53     }
       
    54 
       
    55 
       
    56 /**
       
    57  * 2nd phase constructor. Responsible for determining which
       
    58  * transport has been selected and to create a new OBEX Client.
       
    59  */
       
    60 void CObexClientHandler::ConstructL(TTransport aTransport)
       
    61     {
       
    62 	
       
    63 	// Construct client if bluetooth selected
       
    64 	if (aTransport == EBluetooth)
       
    65 		{
       
    66 		iDevAddr = devAddr;  // take the Bluetooth address
       
    67 
       
    68 		//start the SDP Query
       
    69 		delete iSdpServiceFinder;
       
    70 		iSdpServiceFinder=0;
       
    71 		iSdpServiceFinder = CRFCOMMServiceFinder::NewL(ftpUuid, iDevAddr, *this);
       
    72 		// Start search process
       
    73 		iSdpServiceFinder->FindPortL();
       
    74 		iParent->Console()->Printf(_L("\nSearching for SDP service....\n"));
       
    75 		}
       
    76 	else if (aTransport == EIrda)
       
    77 		{
       
    78 		// Create transport info
       
    79 		TObexIrProtocolInfo transportInfo;
       
    80 		//assigning the unique name for the irda transport
       
    81 		transportInfo.iTransport = KObexIrTTPProtocol; 
       
    82 		//assigning irda specific attributes
       
    83 		transportInfo.iClassName      = KIrdaClassName;					
       
    84 		transportInfo.iAttributeName = KIrdaTransportAttrName;
       
    85 		
       
    86   		iClient = CObexClient::NewL (transportInfo);	//create the obex client
       
    87 		iParent->iMode = E_Client;
       
    88 		}
       
    89 	else if (aTransport == EUsb)
       
    90 		{
       
    91 		// Create transport info
       
    92 		TObexUsbProtocolInfo aInfo;
       
    93 		aInfo.iTransport = KObexUsbProtocol;
       
    94 		aInfo.iInterfaceStringDescriptor = KClientInterfaceDescriptor;
       
    95 
       
    96 	    iClient = CObexClient::NewL (aInfo);// Create the CObexClient
       
    97 		}
       
    98 	else if (aTransport == EWin32Usb)
       
    99 		{
       
   100 		// Ensure win32usb Obex transport plugin exists
       
   101 		// Create transport info
       
   102 		TObexUsbProtocolInfo aInfo;
       
   103 		aInfo.iTransport = KObexWin32UsbProtocol;
       
   104 		aInfo.iInterfaceStringDescriptor = KClientInterfaceDescriptor;
       
   105 
       
   106 	    iClient = CObexClient::NewL (aInfo);
       
   107 		}
       
   108 	else
       
   109 		{
       
   110 		User::Invariant();
       
   111 		}
       
   112 
       
   113 	// Setup Obex objects
       
   114 	iFileObject = CObexFileObject::NewL();
       
   115 	iObjectBuffer = CBufFlat::NewL(KBufExpandSize);
       
   116     iObject = CObexBufObject::NewL(iObjectBuffer);
       
   117     iObexName = KNullDesC;
       
   118 	iGetType = KObjectType;
       
   119 	
       
   120 	// Create file session and create a new private path on drive C
       
   121 	RFs fileSession;
       
   122 	fileSession.Connect();
       
   123 	
       
   124 	fileSession.CreatePrivatePath(EDriveC);
       
   125 	fileSession.SetSessionToPrivate(EDriveC);	
       
   126 	fileSession.SessionPath(iSessionPath);
       
   127 	
       
   128 	// Copy the files from oby file ro the newly created path
       
   129 	BaflUtils::CopyFile(fileSession, KFilePath1, KFilename1,0);
       
   130 	BaflUtils::CopyFile(fileSession, KFilePath2, KFilename2,0);
       
   131 	BaflUtils::CopyFile(fileSession, KFilePath3, KFilename3,0);
       
   132  
       
   133 	fileSession.Close();
       
   134 	
       
   135 	// Assign file names
       
   136 	iFilename1 = KFilename1; 
       
   137 	iFilename2 = KFilename2;
       
   138 	iFilename3 = KFilename3;
       
   139 
       
   140 	
       
   141     }
       
   142 
       
   143 
       
   144 /**
       
   145  * Destructor.
       
   146  */
       
   147 CObexClientHandler::~CObexClientHandler()
       
   148     {
       
   149     // do cleanup
       
   150     Cancel();
       
   151     delete iObject;
       
   152 	delete iFileObject;
       
   153     delete iClient;
       
   154 	delete iObjectBuffer;
       
   155 	delete iTargetHeaderObject;
       
   156 	delete iSdpServiceFinder;
       
   157     }
       
   158     
       
   159 /**
       
   160  * This function is called when the SDP search finishes.
       
   161  * If search was successful then the OBEX port number is
       
   162  * taken an used in starting the OBEX client.
       
   163  * If unsuccessful, go back to the initial menu.
       
   164  */
       
   165 void CObexClientHandler::SearchResult(TInt aError, TUint8 aPort)
       
   166 	{
       
   167 	// Service not supported?
       
   168 	if (aError != KErrNone)
       
   169 		{
       
   170 		iParent->Console()->Printf(_L("\r\n Could not find SDP service in remote device : error %d \r\n"),aError);	
       
   171 		iParent->iMode = E_Inactive;
       
   172 		iParent->Cancel();
       
   173 		}
       
   174 	
       
   175 	
       
   176 	// Set protocol info for bluetooth
       
   177 		
       
   178 	TObexBluetoothProtocolInfo aInfo;
       
   179 	aInfo.iAddr.SetBTAddr(iDevAddr);
       
   180 	aInfo.iAddr.SetPort(aPort); 
       
   181 	aInfo.iTransport = KObexRfcommProtocol;
       
   182 	//now create the obex client...
       
   183 	TRAPD(error,iClient = CObexClient::NewL (aInfo));
       
   184 	if (error)
       
   185 		{
       
   186 		iParent->Console()->Printf(_L("\r\n Could not create client! : error %d \r\n"),error);
       
   187 		iParent->iMode = E_Inactive;
       
   188 		iParent->Cancel();
       
   189 		}
       
   190 		
       
   191 	iParent->Console()->Printf(_L("\nSDP search complete OK!\n"));
       
   192 	iParent->iMode = E_Client;
       
   193 	
       
   194 	iParent->RequestCharacter();
       
   195 
       
   196 	}
       
   197 
       
   198 
       
   199 
       
   200 /**
       
   201  * This function performs the actual connection of client to server.
       
   202  */
       
   203 
       
   204 void CObexClientHandler::Connect()
       
   205     {
       
   206     if(IsActive())
       
   207 		{
       
   208 		iParent->Console()->Printf(KAlreadyActive);
       
   209 		return;
       
   210 		}
       
   211    
       
   212     TObexConnectInfo iLocalInfo = iClient->LocalInfo();
       
   213     iLocalInfo.iWho = KNullDesC8;
       
   214     iLocalInfo.iWho = EPOCIDENT;  
       
   215     iLocalInfo.iWho.Append(KLocalInfoAppend);
       
   216 	// Connect to Obex client
       
   217     iClient->Connect(iStatus);
       
   218     SetActive();
       
   219     iState = EConnecting;
       
   220     }
       
   221 
       
   222     
       
   223 /**
       
   224  * This fucntion performs the disconnection from OBEX client and server
       
   225  */    
       
   226 void CObexClientHandler::Disconnect()
       
   227     {
       
   228     if(IsActive())
       
   229 		{
       
   230 		iParent->Console()->Printf(KAlreadyActive);
       
   231 		return;
       
   232 		} 
       
   233     // Disconnect from Obex client
       
   234 	iClient->Disconnect(iStatus);
       
   235     SetActive();
       
   236     iState = EDisconnecting;
       
   237     }
       
   238 
       
   239 
       
   240 /**
       
   241  * This function is called when an OBEX get is requested by name.
       
   242  * It takes the current name of the OBEX object, replaces it with
       
   243  * a user defined name. it then performs a Get on this object name. 
       
   244  */
       
   245 void CObexClientHandler::GetByNameL()
       
   246     {
       
   247     if(IsActive())
       
   248 		{
       
   249 		iParent->Console()->Printf(KAlreadyActive);
       
   250 		return;
       
   251 		}
       
   252 	
       
   253     iObject->Reset ();
       
   254     // Call SetName passing current name
       
   255     // This will set a newly selected name from the user
       
   256 	SetName(iObexName);
       
   257 	// Set the name
       
   258     iObject->SetNameL (iObexName);
       
   259     // Call get with required object
       
   260     iClient->Get(*iObject, iStatus);
       
   261     SetActive();
       
   262     iState = EGetting;
       
   263     }
       
   264 
       
   265 
       
   266 
       
   267 /**
       
   268  * This function is a wrapper for the CObexClient::Put function.
       
   269  * It is responsible for setting up a new Obex object from a specified file.
       
   270  * It then performs the Put operation.
       
   271  */    
       
   272 void CObexClientHandler::Put(TDes& aFilename)
       
   273     {
       
   274     if(IsActive())
       
   275 		{
       
   276 		iParent->Console()->Printf(KAlreadyActive);
       
   277 		return;
       
   278 		}
       
   279 		
       
   280 	// Setup the object from file
       
   281 	TInt err = SetUpObjectFromFile (aFilename);
       
   282 	// Advise user if unsuccessful
       
   283 	if( err != KErrNone)
       
   284 		{
       
   285 		iParent->Console()->Printf(_L("\r\n Couldnt set up object : error %d \r\n"),err);
       
   286 		Disconnect();
       
   287 		return;
       
   288 		}
       
   289 	// Call the put	
       
   290 	iClient->Put(*iFileObject,iStatus);
       
   291 	SetActive();
       
   292 	iState = EPutting;
       
   293 	}
       
   294 
       
   295 
       
   296 /**
       
   297  * This function is responsible for initiating a 
       
   298  * client/server connection with authentication.
       
   299  * The password is set in source.
       
   300  */
       
   301 void CObexClientHandler::ConnectWithAuthenticationL()
       
   302 	{
       
   303     if(IsActive())
       
   304 		{
       
   305 		iParent->Console()->Printf(KAlreadyActive);
       
   306 		return;
       
   307 		}
       
   308 	// Set generic password
       
   309     iChallengePassword = KAuthPassword;
       
   310     // Connect client to server sending password
       
   311     iClient->ConnectL(iChallengePassword, iStatus);
       
   312     // Active the active object
       
   313     SetActive();
       
   314     iState = EConnecting;
       
   315 	}
       
   316 	
       
   317 /**
       
   318  * This function is called from within the GetByName function.
       
   319  * It takes in the current object name and changes it to a user
       
   320  * defined alternative.
       
   321  */
       
   322 void CObexClientHandler::SetName(TDes& aName)
       
   323     {
       
   324 	TBuf<64> oldName;
       
   325 	oldName = aName;
       
   326 
       
   327 	TKeyCode aCode;
       
   328 	TBuf<1> aChar;
       
   329 	iParent->Console()->Printf(_L("\nEnter a name: %S"),&aName);
       
   330 	FOREVER
       
   331 		{
       
   332 		aCode = iParent->Console()->Getch();
       
   333 		aChar.SetLength(0);
       
   334 		aChar.Append(aCode);
       
   335 
       
   336 		iParent->Console()->Printf(_L("%S"),&aChar);
       
   337 	
       
   338 		// If <CR> finish editing string
       
   339 		if (aCode ==  EStdKeyDelete)
       
   340 			break;
       
   341 		
       
   342 		// if <BS> remove last character
       
   343 		if ((aCode == EStdKeyHome)&&(aName.Length() != 0))
       
   344 			aName.SetLength((aName.Length()-1));
       
   345 		else
       
   346 			aName.Append(aCode);
       
   347 		}
       
   348 	iParent->Console()->Printf(_L("\n"));
       
   349 
       
   350 
       
   351     }
       
   352 
       
   353 
       
   354 
       
   355 /**
       
   356  * This is the active object RunL function.
       
   357  * When the function is called the currently selected mode of operation
       
   358  * is examined and then dealt with accordingly.
       
   359  * It displays the active object iStatus current state to the user.
       
   360  */
       
   361 void CObexClientHandler::RunL ()
       
   362     {
       
   363     if (iStatus != KErrNone)
       
   364 		{// Handle error
       
   365 		}
       
   366 
       
   367     TBuf<80> filename;
       
   368     switch (iState)
       
   369 		{
       
   370 		// If we were connecting, and iStatus has completed then we want to change iState to EConnected
       
   371 		case EConnecting:
       
   372 			iParent->Console()->Printf(_L("\r\nConnect completed with error code: %d\r\n\r\n"),iStatus.Int());
       
   373 			iState = EConnected;
       
   374 			break;
       
   375 		// If we were performing a put and the iStatus has completed change iState to EConnected
       
   376 		case EPutting:
       
   377 			iState = EConnected;
       
   378 			iParent->Console()->Printf(_L("\r\nPut completed with error code: %d\r\n\r\n"),iStatus.Int());
       
   379 			break;
       
   380 		// If we were performing a get and the iStatus has completed change iState to EConnected
       
   381 		// Also we want to write the received object to file
       
   382 		case EGetting:
       
   383 			iState = EConnected;
       
   384 			iParent->Console()->Printf(_L("\r\nGet completed with error code: %d\r\n\r\n"),iStatus.Int());
       
   385 			DisplayObjectInformation();
       
   386 			filename = iSessionPath;
       
   387 			filename.Append(iObject->Name());		
       
   388 			// Write objects data to file, test if the file already exists as well
       
   389 			if (iObject->WriteToFile(filename) == KErrAlreadyExists)
       
   390 				{
       
   391 				iParent->Console()->Printf(_L("\r\nWrite failed, File Already Exists\n"));
       
   392 				}
       
   393 			iObject->Reset ();
       
   394 			break;
       
   395 		// If we wanted to disconnect and iStatus has completed, then go back to original state 
       
   396 		case EDisconnecting:
       
   397 			iParent->Console()->Printf(_L("\r\nDisconnect completed with error code: %d\r\n\r\n"),iStatus.Int());
       
   398 			iState = EIdle;
       
   399 		
       
   400 		default:
       
   401 			iParent->Console()->Printf(_L("\r\nTest Code is in an incorrect state: %d\r\n\r\n"),iState);
       
   402 			break;
       
   403 		}
       
   404    
       
   405     }
       
   406 
       
   407 /**
       
   408  * This is the active object DoCancel function.
       
   409  */
       
   410 void CObexClientHandler::DoCancel()
       
   411     {
       
   412     delete iClient;
       
   413     iClient = NULL;
       
   414     }
       
   415     
       
   416     
       
   417 /**
       
   418  * DisplayObjectInformation prints information of the received object.
       
   419  */    
       
   420 void CObexClientHandler::DisplayObjectInformation()
       
   421     {
       
   422     // Display Contents of CBufFlat data on current console
       
   423 	iParent->Console()->Printf(_L("Size of received object = %d\n"),iObjectBuffer->Size());
       
   424 	TDateTime dt = iObject->Time().DateTime();
       
   425 	iParent->Console()->Printf(_L("\r\nTimestamp: %d/%d/%d, %d:%d:%d\r\n\r\n"),
       
   426 				   dt.Day(), dt.Month()+1, dt.Year(), dt.Hour(), dt.Minute(), dt.Second());
       
   427 
       
   428     TBuf8<1024> tempBuffer;
       
   429 	iObjectBuffer->Read(0, tempBuffer, tempBuffer.MaxSize() < iObjectBuffer->Size() ? tempBuffer.MaxSize() : iObjectBuffer->Size());
       
   430 	// Printf fails with Descriptor bigger than X hundred bytes so write byte at a time
       
   431 	for(TInt count = 0; count < tempBuffer.Size(); count++) 
       
   432 		{
       
   433 		iParent->Console()->Printf(_L("%C"),tempBuffer[count]);
       
   434 		}
       
   435     }
       
   436 
       
   437 
       
   438 
       
   439 /**
       
   440  * This function is called when a Put operation has started.
       
   441  * It takes a filename and then attempts to setup an OBEX object
       
   442  * from that file. Returns the appropriate error code, if the  
       
   443  * file didn't exist then this function creates a new file of
       
   444  * the same name. 
       
   445  */
       
   446 TInt CObexClientHandler::SetUpObjectFromFile(TDes& aFilename)
       
   447     {
       
   448     // Try to create CObexFileObject with filename 
       
   449 	TRAPD (err, iFileObject->InitFromFileL (aFilename));
       
   450 	if (err != KErrNone)
       
   451 		{
       
   452 		RFs fs;
       
   453 		RFile f;
       
   454 		err = fs.Connect();
       
   455 		if (err== KErrNone)
       
   456 			{
       
   457 			err = fs.CreatePrivatePath(EDriveC);
       
   458 		 	}
       
   459 		 
       
   460 		if (err== KErrNone || err == KErrAlreadyExists )
       
   461 			{
       
   462 			err = fs.SetSessionToPrivate(EDriveC);
       
   463 			}
       
   464 			
       
   465 		if (err == KErrNone)
       
   466 			{
       
   467 			// File didn't exist so create a file of same name in it place	
       
   468 			err = f.Create (fs, aFilename, EFileShareExclusive | EFileWrite);
       
   469 			}
       
   470 			
       
   471 		if (err != KErrNone)
       
   472 			{
       
   473 			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 ());			
       
   474 			}
       
   475 		else
       
   476 			{
       
   477 			f.Write (_L8("Test file for sending from EPOC\r\n\r\nLooks like obex is sending OK!!\r\n"));
       
   478 			f.Close ();
       
   479 			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 ());	
       
   480 			}
       
   481 		fs.Close ();
       
   482 		
       
   483 		}
       
   484 	
       
   485 	return (err);
       
   486 
       
   487     }
       
   488 
       
   489 
       
   490     
       
   491 /**
       
   492  * NewL function for CRFCOMMServiceFinder 
       
   493  */
       
   494 
       
   495 CRFCOMMServiceFinder* CRFCOMMServiceFinder::NewL(	const TUUID& aServiceClass,
       
   496 							const TBTDevAddr& aDevAddr,
       
   497 							MRFCOMMServiceSeeker& aSeeker)
       
   498 	{
       
   499 	CRFCOMMServiceFinder* self= new (ELeave) CRFCOMMServiceFinder(aSeeker);
       
   500 	CleanupStack::PushL(self);
       
   501 	self->ConstructL(aDevAddr, aServiceClass);
       
   502 	CleanupStack::Pop();
       
   503 	return (self);
       
   504 	}
       
   505 
       
   506 /**
       
   507  * Destructor.
       
   508  */
       
   509 CRFCOMMServiceFinder::~CRFCOMMServiceFinder()
       
   510 	{
       
   511 	delete iPattern;
       
   512 	delete iAgent;
       
   513 	}
       
   514 
       
   515 /**
       
   516  * Constructor.
       
   517  */	
       
   518 CRFCOMMServiceFinder::CRFCOMMServiceFinder(MRFCOMMServiceSeeker& aSeeker)
       
   519 : iSeeker(aSeeker)
       
   520 	{
       
   521 	}
       
   522 
       
   523 /**
       
   524  * 2nd phase constructor. Sets the seach pattern for SDP with the UUID supplied.
       
   525  * Then Creates a new SDP agent with the device address supplied.
       
   526  */
       
   527 void CRFCOMMServiceFinder::ConstructL(const TBTDevAddr& aDevAddr, const TUUID& aServiceClass)
       
   528 	{
       
   529 	iPattern=CSdpSearchPattern::NewL();
       
   530 	iPattern->AddL(aServiceClass);
       
   531 	iAgent=CSdpAgent::NewL(*this, aDevAddr);
       
   532 	// Filter out classes that arent FTP
       
   533 	iAgent->SetRecordFilterL(*iPattern);
       
   534 	}
       
   535 
       
   536 /**
       
   537  * This function is responsible for calling the SDP agent NextRecordRequestL
       
   538  * function, this gets the next service record that the device has registered
       
   539  * in the SDP database.
       
   540  */
       
   541 void CRFCOMMServiceFinder::FindPortL()
       
   542 	{
       
   543 	iPort=KNotAPort;	//0xFF will never be returned from a query, 
       
   544 			//because RFCOMM server channels only
       
   545 			//go up to 30.
       
   546 	
       
   547 	iAgent->NextRecordRequestL();
       
   548 	}
       
   549 
       
   550 
       
   551 /**
       
   552  * This function is from the MSdpAgentNotify interface and is called when there
       
   553  * are no more SDP records registered in the database. It calls SearchResult implemented 
       
   554  * by this class.
       
   555  */
       
   556 void CRFCOMMServiceFinder::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt /*aTotalRecordsCount*/) 
       
   557 	{
       
   558 	if(aError)
       
   559 		iSeeker.SearchResult(aError,KNoPort);	
       
   560 	else
       
   561 		{
       
   562 		//We have the record, kick off the attribute request
       
   563 		TRAPD(err,iAgent->AttributeRequestL(aHandle,KSdpAttrIdProtocolDescriptorList )); 
       
   564 		if(err)
       
   565 			iSeeker.SearchResult(err,KNoPort);
       
   566 		}
       
   567 	}
       
   568 
       
   569 
       
   570 	
       
   571 /**
       
   572  * This function comes from the MSdpAgentNotifer interface, It is called when
       
   573  * the attribute request process has finished.
       
   574  */
       
   575 void CRFCOMMServiceFinder::AttributeRequestComplete(TSdpServRecordHandle /*aHandle*/, TInt aError)
       
   576 	{
       
   577 	if(aError!=KErrNone || iPort==KNotAPort)
       
   578 		iSeeker.SearchResult(aError?aError:KErrNotFound,KNoPort);
       
   579 	else
       
   580 		iSeeker.SearchResult(KErrNone, iPort);
       
   581 	}
       
   582 
       
   583  
       
   584 
       
   585