obex/obexprotocol/obexusbtransport/src/usbconn.cpp
changeset 54 4dc88a4ac6f4
parent 52 866b4af7ffbe
child 57 f6055a57ae18
equal deleted inserted replaced
52:866b4af7ffbe 54:4dc88a4ac6f4
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent 
       
    19 */
       
    20 
       
    21 
       
    22 #include <obexusbtransportinfo.h>
       
    23 #include "usbconn.h"
       
    24 #include <obex/transport/obexconnector.h>
       
    25 #include "logger.h"
       
    26 #include "obexusbfaults.h"
       
    27 
       
    28 #ifdef __FLOG_ACTIVE
       
    29 _LIT8(KLogComponent, "USB");
       
    30 #endif
       
    31 
       
    32 #ifdef _DEBUG
       
    33 _LIT(KPanicCat, "ObexUsbHandler");
       
    34 #endif
       
    35 
       
    36 
       
    37 //
       
    38 
       
    39 /**
       
    40 CObexUsbActiveWriter factory function
       
    41 
       
    42 @param	aTransport	Reference to a CObexUsbTransportController object. Required for a call to the CObexUsbActiveReader
       
    43 @param	aOwner		Reference to a MObexTransportNotify object
       
    44 @param	aUsb		Reference to a RDevUsbcClient object
       
    45 @param	aInfo		Reference to a TObexConnectionInfo object
       
    46 @param  aPacketSize The size of packets used on the underlying link, dependent on High Speed mode.
       
    47 @return Ownership of a new CObexUsbActiveWriter.
       
    48 */
       
    49 CObexUsbActiveWriter* CObexUsbActiveWriter::NewL(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb,
       
    50 										   TObexConnectionInfo& aInfo, TInt aPacketSize)
       
    51 	{
       
    52 	CObexUsbActiveWriter* self = new(ELeave) CObexUsbActiveWriter(aOwner, aUsb, aInfo, aPacketSize);
       
    53 	CleanupStack::PushL(self);
       
    54 	self->BaseConstructL();
       
    55 	CleanupStack::Pop(self);
       
    56 	return self;
       
    57 	}
       
    58 
       
    59 /**
       
    60 CObexUsbActiveWriter constructor
       
    61 
       
    62 @param	aTransport	Reference to a CObexUsbTransportController object. Required for a call to the CObexUsbActiveReader
       
    63 @param	aOwner		Reference to a MObexTransportNotify object
       
    64 @param	aUsb		Reference to a RDevUsbcClient object
       
    65 @param	aInfo		Reference to a TObexConnectionInfo object
       
    66 @param  aPacketSize The size of packets used on the underlying link, dependent on High Speed mode.
       
    67 */
       
    68 CObexUsbActiveWriter::CObexUsbActiveWriter(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb,
       
    69 										   TObexConnectionInfo& aInfo, TInt aPacketSize)
       
    70 : CObexWriterBase(EPriorityHigh, aOwner, aInfo),
       
    71  iUsb(aUsb), iPacketSize(aPacketSize)
       
    72 	{
       
    73 	}
       
    74 
       
    75 
       
    76 /**
       
    77 CObexUsbActiveWriter destructor.
       
    78 */
       
    79 CObexUsbActiveWriter::~CObexUsbActiveWriter()
       
    80 	{
       
    81 	LOG_FUNC
       
    82 
       
    83 	Cancel();
       
    84 	}
       
    85 
       
    86 
       
    87 /**
       
    88 Start actual transfer.  May be called several times by CObexActiveRW::RunL.
       
    89 Queues a write on USB endpoint.
       
    90 */
       
    91 void CObexUsbActiveWriter::DoTransfer()
       
    92 	{
       
    93 	LOG_FUNC
       
    94 	LOG1(_L("CObexUsbActiveWriter::DoTransfer [Length=%d]"),iLocation.Length());
       
    95 	
       
    96 	iLocation.SetMax();
       
    97 	iUsb.Write(iStatus, KTransmitEndpoint, iLocation, iLocation.Length(), ETrue);
       
    98 	SetActive();
       
    99 	}
       
   100 
       
   101 
       
   102 /**
       
   103 Cancels an outstanding write.
       
   104 */
       
   105 void CObexUsbActiveWriter::DoCancel()
       
   106 	{
       
   107 	LOG_FUNC
       
   108 
       
   109 	//Only cancel the write if there's more than 1 packet left to write.
       
   110 	//This restriction is imposed to prevent the SUCCESS response being
       
   111 	//cancelled when an ObexServer is handling a disconnect and bringing 
       
   112 	//the transport down.
       
   113 	if(Remaining() > iPacketSize)
       
   114 		{
       
   115 		iUsb.WriteCancel(KTransmitEndpoint);
       
   116 		}		
       
   117 	}
       
   118 		
       
   119 
       
   120 //
       
   121 
       
   122 /**
       
   123 CObexUsbActiveReader factory function
       
   124 
       
   125 @param	aOwner		Reference to a MObexTransportNotify object
       
   126 @param	aUsb		Reference to a RDevUsbcClient object
       
   127 @param	aInfo		Reference to a TObexConnectionInfo object
       
   128 @return Ownership of a new CObexUsbActiveWriter.
       
   129 */
       
   130 CObexUsbActiveReader* CObexUsbActiveReader::NewL(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb,
       
   131 										   TObexConnectionInfo& aInfo)
       
   132 	{
       
   133 	CObexUsbActiveReader* self = new(ELeave) CObexUsbActiveReader(aOwner, aUsb, aInfo);
       
   134 	CleanupStack::PushL(self);
       
   135 	self->BaseConstructL();
       
   136 	CleanupStack::Pop(self);
       
   137 	return self;
       
   138 	}
       
   139 
       
   140 /**
       
   141 CObexUsbActiveReader constructor
       
   142 
       
   143 @param	aOwner		Reference to a MObexTransportNotify object
       
   144 @param	aUsb		Reference to a RDevUsbcClient object
       
   145 @param	aInfo		Reference to a TObexConnectionInfo object
       
   146 */
       
   147 CObexUsbActiveReader::CObexUsbActiveReader(MObexTransportNotify& aOwner, RDevUsbcClient& aUsb,
       
   148 										   TObexConnectionInfo& aInfo)
       
   149 : CObexReaderBase(EPriorityStandard, aOwner, aInfo), iUsb(aUsb)
       
   150 	{
       
   151 	}
       
   152 
       
   153 
       
   154 /**
       
   155 CObexUsbActiveReader destructor.
       
   156 */
       
   157 CObexUsbActiveReader::~CObexUsbActiveReader()
       
   158 	{
       
   159 	LOG_FUNC
       
   160 
       
   161 	Cancel();
       
   162 	}
       
   163 
       
   164 
       
   165 /**
       
   166 Start actual transfer.  May be called several times by CObexActiveRW::RunL.
       
   167 Queues a read on USB endpoint.
       
   168 */
       
   169 void CObexUsbActiveReader::DoTransfer()
       
   170 	{
       
   171 	LOG_FUNC
       
   172 	LOG1(_L("CObexUsbActiveReader::DoTransfer [maxLength=%d]"),iLocation.MaxLength());
       
   173 
       
   174 	iUsb.ReadUntilShort(iStatus, KReceiveEndpoint, iLocation);
       
   175 	SetActive();
       
   176 	}
       
   177 
       
   178 
       
   179 /**
       
   180 Cancels an outstanding read,
       
   181  */
       
   182 void CObexUsbActiveReader::DoCancel()
       
   183 	{
       
   184 	FLOG(_L("CObexUsbActiveReader::DoCancel"));
       
   185 
       
   186 	iUsb.ReadCancel(KReceiveEndpoint);
       
   187 	}
       
   188 
       
   189 
       
   190 /**
       
   191 Return the maximum packet size
       
   192 @return TInt the maximum packet size for this transport
       
   193 */
       
   194 TInt CObexUsbActiveReader::GetMaxPacketSize()
       
   195 	{
       
   196 	LOG_FUNC
       
   197 
       
   198 	return GetObexPacketDataLimit();
       
   199 	}
       
   200 
       
   201 
       
   202 /**
       
   203 Returns a initial packet size when the packet size of iPacket is not know.  This is used
       
   204 when determining the remaining bytes to be read.  
       
   205 @return TInt the initial packet size
       
   206 */
       
   207 TInt CObexUsbActiveReader::GetInitialPacketSize ()
       
   208 	{
       
   209 	LOG_FUNC
       
   210 	
       
   211 	return GetObexPacketBufferSize();
       
   212 	}
       
   213 //
       
   214 
       
   215 /**
       
   216 CObexUsbConnector constructor.
       
   217 */
       
   218 CObexUsbConnector::CObexUsbConnector(MObexTransportNotify& aObserver, TObexUsbTransportInfo& aUsbTransportInfo)
       
   219  :	CObexConnector(aObserver), 
       
   220 	iObexTransportInfo(aUsbTransportInfo), 
       
   221 	iMode(EDefaultClient)
       
   222 	{
       
   223 	LOG_FUNC
       
   224 	// Note iObexTransportInfo reference is only kept so that it can be used in the ConstructL
       
   225 	// It may not be safe to use this variables outside of the construction phases
       
   226 	}
       
   227 
       
   228 
       
   229 /*
       
   230 Returns an instance of CObexUsbConnector
       
   231 
       
   232 @param	aController  	Reference to a MObexTransportNotify object (the CObexUsbTransportController that owns this)
       
   233 @param	aTransportInfo 	Reference to a TObexUsbTransportInfo object containing the transport information
       
   234 
       
   235 @return	A pointer to a CObexUsbConnector object
       
   236 */
       
   237 CObexUsbConnector* CObexUsbConnector::NewL(MObexTransportNotify& aController, TObexUsbTransportInfo& aTransportInfo)
       
   238 	{
       
   239 	CObexUsbConnector* self = new(ELeave) CObexUsbConnector(aController, aTransportInfo);
       
   240 	CleanupStack::PushL(self);
       
   241 	self->ConstructL();
       
   242 	CleanupStack::Pop(self);
       
   243 	return(self);
       
   244 	}
       
   245 
       
   246 
       
   247 /**
       
   248 Second phase construction.
       
   249 */
       
   250 void CObexUsbConnector::ConstructL()
       
   251 	{
       
   252 	LOG_FUNC
       
   253 
       
   254 	OpenUsbL(0);
       
   255 
       
   256 	FLOG(_L("USB opened"));
       
   257 
       
   258 	iHandler  = CObexUsbHandler::NewL(iObexTransportInfo, *this, iUsb);
       
   259 	iCallback = new(ELeave) CAsyncCallBack(EPriorityHigh);
       
   260 	iStaller = CObexUsbStaller::NewL(iUsb, *this);
       
   261 	iHandler->Start();
       
   262 
       
   263 	BaseConstructL();
       
   264 	}
       
   265 
       
   266 
       
   267 /**
       
   268 CObexUsbConnector destructor. Releases endpoint and closes USB object if we have an open connection.
       
   269 */
       
   270 CObexUsbConnector::~CObexUsbConnector()
       
   271 	{
       
   272 	LOG_FUNC
       
   273 
       
   274 	delete iCallback;
       
   275 	delete iHandler;
       
   276 	delete iStaller;
       
   277 	
       
   278 	if (iUsb.Handle())
       
   279 		{	
       
   280 		iUsb.Close();
       
   281 		}
       
   282 	}
       
   283 
       
   284 
       
   285 /**
       
   286 Attempt to open a client-type connection.
       
   287 This will succeed if the USB host has already opened a connection to us
       
   288 */
       
   289 void CObexUsbConnector::ConnectL()
       
   290 	{
       
   291 	LOG_FUNC
       
   292 
       
   293 	if (iMode == EServer)
       
   294 		{
       
   295 		// Already performed a server-type connect, so can't act as a
       
   296 		// client as well.
       
   297 		FLOG(_L(" -- In server mode, give up"));
       
   298 		LEAVEIFERRORL(KErrNotSupported);		
       
   299 		}
       
   300 		
       
   301 		
       
   302 	FLOG(_L(" -- Not in server mode"));
       
   303 
       
   304 	iMode = EClient;
       
   305 	if (iTransportLinkAvailable)
       
   306 		{
       
   307 		FLOG(_L(" -- Link available, set a callback"));
       
   308 
       
   309 		TCallBack callback(LinkUp, this);
       
   310 		iCallback->Set(callback);
       
   311 		iCallback->CallBack();
       
   312 		iConnectRequested = ETrue;
       
   313 		}
       
   314 	else
       
   315 		{
       
   316 		FLOG(_L(" -- No link available, set a callback"));
       
   317 
       
   318 		TCallBack callback(NoDevice, this);
       
   319 		iCallback->Set(callback);
       
   320 		iCallback->CallBack();
       
   321 		}
       
   322 	}
       
   323 
       
   324 
       
   325 /*
       
   326 @param	aConn	A pointer to a connector object. Will be cast to CObexUsbConnector
       
   327 
       
   328 @return	KErrNone
       
   329 */
       
   330 TInt CObexUsbConnector::LinkUp(TAny* aConn)
       
   331 	{
       
   332 	FLOG(_L("CObexUsbConnector::LinkUp"));
       
   333 
       
   334 	reinterpret_cast<CObexUsbConnector*>(aConn)->SignalUp();
       
   335 	return KErrNone;
       
   336 	}
       
   337 
       
   338 
       
   339 /*
       
   340 @param	aConn	A pointer to a connector object. Will be cast to CObexUsbConnector
       
   341 
       
   342 @return	KErrNone
       
   343 */
       
   344 TInt CObexUsbConnector::NoDevice(TAny* aConn)
       
   345 	{
       
   346 	FLOG(_L("CObexUsbConnector::NoDevice"));
       
   347 
       
   348 	reinterpret_cast<CObexUsbConnector*>(aConn)->SignalDown(KErrIrObexClientPeerDoesNotHaveObex);
       
   349 	return KErrNone;
       
   350 	}
       
   351 
       
   352 
       
   353 /**
       
   354 Cancel an active connection attempt.  This is unlikely to succeed, as a client
       
   355 connection over USB will complete almost immediately.
       
   356 */
       
   357 void CObexUsbConnector::CancelConnect()
       
   358 	{
       
   359 	LOG_FUNC
       
   360 
       
   361 	if (iMode == EClient)
       
   362 		{
       
   363 		iCallback->Cancel();
       
   364 		}
       
   365 	
       
   366 	iConnectRequested = EFalse;
       
   367 	}
       
   368 
       
   369 
       
   370 /**
       
   371 Start listening for a connection to us.
       
   372 */
       
   373 void CObexUsbConnector::AcceptL()
       
   374 	{
       
   375 	LOG_FUNC
       
   376 
       
   377 	if (iMode == EClient)
       
   378 		{
       
   379 		// Already carried out a client side connection.  Therefore we
       
   380 		// can't be a server as well.
       
   381 		FLOG(_L(" -- In client mode, give up"));
       
   382 
       
   383 		LEAVEIFERRORL(KErrNotSupported);		
       
   384 		}
       
   385 	
       
   386 	FLOG(_L(" -- Not in client mode"));
       
   387 
       
   388 	iMode = EServer;
       
   389 	if (iTransportLinkAvailable)
       
   390 		{
       
   391 		FLOG(_L(" -- Transport link currently available, set a callback"));
       
   392 
       
   393 		TCallBack callback(LinkUp, this);
       
   394 		iCallback->Set(callback);
       
   395 		iCallback->CallBack();
       
   396 		}
       
   397 	else
       
   398 		{
       
   399 		FLOG(_L(" -- No link available, wait for one"));
       
   400 
       
   401 		iWaitingForLink = ETrue;
       
   402 		}
       
   403 	}
       
   404 
       
   405 /**
       
   406 Stop listening for connections.
       
   407 */
       
   408 void CObexUsbConnector::CancelAccept()
       
   409 	{
       
   410 	LOG_FUNC
       
   411 
       
   412 	if (iMode == EServer)
       
   413 		{
       
   414 		iWaitingForLink = EFalse;
       
   415 		iCallback->Cancel();
       
   416 		}
       
   417 	}
       
   418 
       
   419 
       
   420 /**
       
   421 Called to indicate transport layer has come up.
       
   422 */
       
   423 void CObexUsbConnector::TransportUp()
       
   424 	{
       
   425 	LOG_FUNC
       
   426 	
       
   427 	SetTransportPacketSize();
       
   428 
       
   429 	iTransportLinkAvailable = ETrue;
       
   430 	
       
   431 	if ((iMode == EServer) && (iWaitingForLink))
       
   432 		{
       
   433 		FLOG(_L(" -- Signalling link available"));
       
   434 
       
   435 		iWaitingForLink = EFalse;
       
   436 		SignalUp();
       
   437 		}
       
   438 	}
       
   439 
       
   440 /**
       
   441 Called to indicate transport layer has gone down.
       
   442 
       
   443 @param	aErr 	Any error code associated with disconnection. Defaults to KErrDisconnected.
       
   444 */
       
   445 void CObexUsbConnector::TransportDown(TInt aErr)
       
   446 	{
       
   447 	LOG_FUNC
       
   448 	
       
   449 	ResetTransportPacketSize();
       
   450 	
       
   451 	iStaller->Cancel();
       
   452 
       
   453 	iTransportLinkAvailable = EFalse;
       
   454 		
       
   455 	if (iMode == EServer)
       
   456 		{
       
   457 		FLOG(_L(" -- In server mode, signal link down"));
       
   458 
       
   459 		SignalDown(aErr);
       
   460 		}
       
   461 	else
       
   462 		{
       
   463 		FLOG(_L(" -- In client mode"));
       
   464 
       
   465 		// Client or default client state
       
   466 		if (iConnectRequested)
       
   467 			{
       
   468 			FLOG(_L(" -- Outstanding client connection. Signal link down"));
       
   469 
       
   470 			iConnectRequested = EFalse;
       
   471 			SignalDown(aErr);
       
   472 			}
       
   473 		}
       
   474 	}
       
   475 
       
   476 /**
       
   477 Signals to the transport controller that the transport is up
       
   478 */
       
   479 void CObexUsbConnector::SignalUp()
       
   480 	{
       
   481 	LOG_FUNC
       
   482 
       
   483 	// Indicate transport now up
       
   484 	TObexConnectionInfo sockinfo;
       
   485 	sockinfo.iMaxRecvSize = 0;	// set these to zero as we can't find them out
       
   486 	sockinfo.iMaxSendSize = 0;	// and they are not used
       
   487 	sockinfo.iSocketType = TObexConnectionInfo::EUsbStream;
       
   488 	Observer().TransportUp(sockinfo);
       
   489 	}
       
   490 
       
   491 
       
   492 /**
       
   493 Signals (with an error code) to the transport controller that the transport has gone down 
       
   494 */
       
   495 void CObexUsbConnector::SignalDown(TInt aErr)
       
   496 	{
       
   497 	FLOG(_L("CObexUsbConnector::SignalDown"));
       
   498 
       
   499 	Observer().Error(aErr);
       
   500 	}
       
   501 
       
   502 
       
   503 /**
       
   504 The Obex server running over USB is not able to bring the transport
       
   505 down itself. It will only delete the transport object when an error
       
   506 has occurred (such as the link being brought down) and hence the
       
   507 transport is no longer valid.
       
   508 
       
   509 @return	ETrue
       
   510 */
       
   511 TBool CObexUsbConnector::BringTransportDown()
       
   512 {
       
   513 	// This cancel function needs to be called here because it
       
   514 	// doesn't get called anywhere else. Bluetooth and IrDA rely
       
   515 	// on the socket shutdown to cancel the accept.
       
   516 	CancelAccept();
       
   517 	return ETrue;
       
   518 }
       
   519 
       
   520 
       
   521 /**
       
   522 Return the transport layer object for use by USB transport objects
       
   523 
       
   524 @return Pointer to the USB transport layer object
       
   525 */
       
   526 RDevUsbcClient* CObexUsbConnector::TransportObject()
       
   527 	{
       
   528 	return &iUsb;
       
   529 	}
       
   530 
       
   531 
       
   532 /**
       
   533 Sets a bus stall condition on the IN endpoint.  This will cause the USB
       
   534 host to initiate a CLEAR_FEATURE sequence, which notifies the server that the
       
   535 Obex link has been reset (equivalent to dropping the Obex level connection)
       
   536 */
       
   537 void CObexUsbConnector::SignalTransportError()
       
   538 	{
       
   539 	LOG_FUNC
       
   540 	
       
   541 	iStaller->Start();
       
   542 	iTransportLinkAvailable = EFalse;
       
   543 	iConnectRequested = EFalse;
       
   544 	}
       
   545 
       
   546 
       
   547 /**
       
   548 Stall cleared => transport available.
       
   549 This upcall has been separated from the TransportUp upcall for two
       
   550 reasons---it's called from a different class and it happens when an
       
   551 error condition has been cleared.  Currently it has no special
       
   552 meaning, but this could change in future.
       
   553 */
       
   554 void CObexUsbConnector::StallCleared()
       
   555 	{
       
   556 	LOG_FUNC
       
   557 	
       
   558 	TransportUp();
       
   559 	}
       
   560 
       
   561 
       
   562 /**
       
   563 Opens USB and prepares it for use.
       
   564 
       
   565 @param	aUnit	According to the RDevUsbcClient documentation, this should be 0. 
       
   566 */
       
   567 void CObexUsbConnector::OpenUsbL(TInt aUnit)
       
   568 	{
       
   569 	LOG1(_L("CObexUsbConnector::OpenUsbL called for unit=%d"), aUnit);
       
   570 	
       
   571 	// Load ldd
       
   572 	TInt err = User::LoadLogicalDevice(KUsbLddName);
       
   573 
       
   574 	if (err != KErrNone && err != KErrAlreadyExists)
       
   575 		{
       
   576 		LEAVEIFERRORL(err);
       
   577 		}
       
   578 
       
   579 	// Open the requested unit and initialise local state
       
   580 	LEAVEIFERRORL(iUsb.Open(aUnit));
       
   581 	}
       
   582 
       
   583 
       
   584 void CObexUsbConnector::ResetTransportPacketSize()
       
   585 	{
       
   586 	iPacketSize = 0;
       
   587 	}
       
   588 
       
   589 
       
   590 void CObexUsbConnector::SetTransportPacketSize()
       
   591 	{
       
   592 	if (iUsb.CurrentlyUsingHighSpeed())
       
   593 		{
       
   594 		iPacketSize = KMaxPacketTypeBulkHS;
       
   595 		}
       
   596 	else
       
   597 		{
       
   598 		iPacketSize = KMaxPacketTypeBulkFS;
       
   599 		}
       
   600 	}
       
   601 
       
   602 
       
   603 TInt CObexUsbConnector::GetTransportPacketSize()
       
   604 	{
       
   605 	return iPacketSize;
       
   606 	}
       
   607 
       
   608 
       
   609 //
       
   610 
       
   611 /**
       
   612 Constructs a CObexUsbHandler object
       
   613 
       
   614 @param	aUsbTransportInfo	Reference to a TObexTransportInfo object. Will be cast to TObexUsbTransportInfo.
       
   615 @param	aOwner				Reference to a MObexUsbConnector that owns this handler
       
   616 @param	aUsb				Reference to a RDevUsbcClient object.
       
   617 
       
   618 @return	A new CObexUsbHandler object
       
   619 */
       
   620 CObexUsbHandler* CObexUsbHandler::NewL(TObexUsbTransportInfo& aUsbTransportInfo,
       
   621 									   MObexUsbConnector& aOwner,
       
   622 									   RDevUsbcClient& aUsb)
       
   623 	{
       
   624 	FLOG(_L("CObexUsbHandler::NewL"));
       
   625 	
       
   626 	CObexUsbHandler* self = new (ELeave) CObexUsbHandler(aUsbTransportInfo, aOwner, aUsb);
       
   627 	CleanupStack::PushL(self);
       
   628 	self->ConstructL();
       
   629 	CleanupStack::Pop(self);
       
   630 	return self;
       
   631 	}
       
   632 
       
   633 
       
   634 /**
       
   635 CObexUsbHandler constructor.
       
   636 
       
   637 Note that the iObexTransportInfo may not be valid outside of the construction phases
       
   638 The constructor copies out most of the information it needs into member variables
       
   639 apart from the interface string descriptor, which is used from RegInterfacesL
       
   640 
       
   641 @param	aUsbTransportInfo	Reference to a TObexTransportInfo object. Will be cast to TObexUsbTransportInfo.
       
   642 @param	aOwner				Reference to a MObexUsbConnector that owns this handler
       
   643 @param	aUsb				Reference to a RDevUsbcClient object.
       
   644 */
       
   645 CObexUsbHandler::CObexUsbHandler(TObexUsbTransportInfo& aUsbTransportInfo,
       
   646 								 MObexUsbConnector& aOwner,
       
   647 								 RDevUsbcClient& aUsb)
       
   648  : CActive(EPriorityStandard), iObexTransportInfo(aUsbTransportInfo),
       
   649    iOwner(aOwner), iUsb(aUsb)
       
   650 	{
       
   651 	LOG_FUNC
       
   652 	
       
   653 	CActiveScheduler::Add(this);
       
   654 
       
   655 	// Set interface performance configuration parameters
       
   656 	if (aUsbTransportInfo.iTransportName == KObexUsbProtocol)
       
   657 		// Default values if transport is normal USB - no extra bandwidth, no DMA
       
   658 		{
       
   659 		FLOG(_L("CObexUsbHandler - Using default USB protocol info"));
       
   660 		iBandwidthPriority = EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault;
       
   661 		iRequestDmaOnOutEndpoint = EFalse;
       
   662 		iRequestDmaOnInEndpoint = EFalse;
       
   663 		}
       
   664 	else if (aUsbTransportInfo.iTransportName == KObexUsbProtocolV2)
       
   665 		// If transport is extended USB take values from the protocol info
       
   666 		{
       
   667 		FLOG(_L("CObexUsbHandler - Using USB protocol extended info"));
       
   668 		TObexUsbV2TransportInfo& infoV2 = static_cast<TObexUsbV2TransportInfo&>(aUsbTransportInfo);
       
   669 		iBandwidthPriority       = infoV2.iBandwidthPriority;
       
   670 		iRequestDmaOnOutEndpoint = infoV2.iDmaOnOutEndpoint;
       
   671 		iRequestDmaOnInEndpoint  = infoV2.iDmaOnInEndpoint;
       
   672 		}
       
   673 	else
       
   674 		{
       
   675 		//aUsbTransportInfo.iTransportName is used to load the correct plug-in, so if this code
       
   676 		//is being executed it must have contained one of the options above. Else something
       
   677 		//has gone badly wrong.
       
   678 		__ASSERT_DEBUG(false, PANIC(KPanicCat, EUnknownUsbTransport));
       
   679 		}
       
   680 
       
   681 	LOG3(_L("CObexUsbHandler - iBandwidthPriority 0x%X, iDmaOnOutEndpoint, %d iDmaOnInEndpoint %d"),
       
   682 						iBandwidthPriority, iRequestDmaOnOutEndpoint, iRequestDmaOnInEndpoint);
       
   683 	}
       
   684 
       
   685 
       
   686 /**
       
   687 Second phase construction.
       
   688 */
       
   689 void CObexUsbHandler::ConstructL()
       
   690 	{
       
   691 
       
   692 	// Check bandwidth priority to make sure it makes sense
       
   693 	// Reasoning is that the bitwise OR of the maximum values of IN and OUT priorities
       
   694 	// covers all the bits that can be set in iBandwidthPriority so, using this as a mask,
       
   695 	// anything set outside of this indicates that iBandwidthPriority is corrupt
       
   696 	if ( ( iBandwidthPriority & ~( EUsbcBandwidthOUTMaximum | EUsbcBandwidthINMaximum ) ) != 0 )
       
   697 		{
       
   698 		LEAVEIFERRORL(KErrArgument);
       
   699 		}
       
   700 
       
   701 	FLOG(_L("About to open USB comms interface connection"));
       
   702 
       
   703 	LEAVEIFERRORL(iUsbComms.Open(0));
       
   704 
       
   705 	FLOG(_L("Registering interfaces"));
       
   706 
       
   707 	RegInterfacesL();
       
   708 	}
       
   709 
       
   710 
       
   711 /**
       
   712 CObexUsbHandler destructor.
       
   713 */
       
   714 CObexUsbHandler::~CObexUsbHandler()
       
   715 	{
       
   716 	LOG_FUNC
       
   717 	Cancel();
       
   718 
       
   719 	// Must release interfaces from highest alternate setting downwards
       
   720 	if (iUsb.Handle())
       
   721 		{
       
   722 #ifndef NO_ALTERNATE_USB_INTERFACE_SUPPORT
       
   723 		iUsb.ReleaseInterface(1 /*alternate setting*/);
       
   724 #endif
       
   725 		iUsb.ReleaseInterface(0 /*alternate setting*/);
       
   726 		}
       
   727 
       
   728 	if (iUsbComms.Handle())
       
   729 		{	
       
   730 		iUsbComms.ReleaseInterface(0 /*alternate setting*/);
       
   731 		}
       
   732 
       
   733 	iUsbComms.Close();
       
   734 	}
       
   735 
       
   736 
       
   737 /**
       
   738 Standard active object error function.
       
   739 
       
   740 @return	KErrNone because currently nothing should cause this to be called.
       
   741 */
       
   742 TInt CObexUsbHandler::RunError(TInt /*aError*/)
       
   743 	{
       
   744 	return KErrNone;
       
   745 	}
       
   746 
       
   747 
       
   748 /**
       
   749 This function will be called upon a change in the state of the device
       
   750 (as set up in AcceptL).
       
   751 */
       
   752 void CObexUsbHandler::RunL()
       
   753 	{
       
   754 	LOG1(_L("CObexUsbHandler::RunL called state=0x%X"), iUsbState);
       
   755 	
       
   756 	if (iStatus != KErrNone)
       
   757 		{
       
   758 		LOG1(_L("CObexUsbHandler::RunL() - Error = %d"),iStatus.Int());
       
   759 
       
   760 		iTransportUp = EFalse;
       
   761 		iOwner.TransportDown(iStatus.Int());
       
   762 		return;
       
   763 		}
       
   764 
       
   765 	// Check whether the alternate setting to use or the device state has changed.
       
   766 	// We have to check the device state to handle the unplugging of the cable. We can't
       
   767 	// rely on the always-outstanding read to complete with an error, because the driver
       
   768 	// doesn't have a well-defined error code for this.
       
   769 
       
   770 	if (iUsbState & KUsbAlternateSetting)
       
   771 		{
       
   772 		iUsbState &= ~KUsbAlternateSetting;
       
   773 
       
   774 		LOG1(_L("switched to alternate setting %d"), iUsbState);
       
   775 
       
   776 		if (iUsbState == KObexAlt0)
       
   777 			{
       
   778 			// alternate setting 0 - function inactive
       
   779 			if (iTransportUp)
       
   780 				{
       
   781 				FLOG(_L("CObexUsbHandler::RunL - transport layer going down..."));
       
   782 
       
   783 				iTransportUp = EFalse;
       
   784 				iOwner.TransportDown();
       
   785 				}
       
   786 			}
       
   787 		else if (iUsbState == KObexAlt1)
       
   788 			{
       
   789 			// alternate setting 1 - function active
       
   790 			if (!iTransportUp)
       
   791 				{
       
   792 				FLOG(_L("CObexUsbHandler::RunL - transport layer coming up..."));
       
   793 
       
   794 				// Now the transport is selected, DMA can be allocated to the endpoints, if required
       
   795 				AllocateDma();
       
   796 
       
   797 				iTransportUp = ETrue;
       
   798 
       
   799 				iOwner.TransportUp();
       
   800 				}
       
   801 			}
       
   802 		else
       
   803 			{
       
   804 			FLOG(_L("WARNING: unknown setting!"));
       
   805 			}
       
   806 		}
       
   807 	else
       
   808 		{
       
   809 		TUsbcDeviceState deviceState = static_cast<TUsbcDeviceState>(iUsbState);
       
   810 
       
   811 		switch(deviceState)
       
   812 			{
       
   813 			case EUsbcDeviceStateUndefined:
       
   814 			case EUsbcDeviceStateAttached:
       
   815 			case EUsbcDeviceStatePowered:
       
   816 			case EUsbcDeviceStateDefault:
       
   817 			case EUsbcDeviceStateAddress:
       
   818 #ifdef ERRONEOUS_SUSPEND_INDICATIONS
       
   819 			// On Lubbock, we sometimes get "suspended" when the cable is unplugged.
       
   820 			case EUsbcDeviceStateSuspended:
       
   821 #endif // ERRONEOUS_SUSPEND_INDICATIONS
       
   822 				if (iTransportUp)
       
   823 					{
       
   824 					FLOG(_L("CObexUsbHandler::RunL - transport layer going down..."));
       
   825 
       
   826 					iTransportUp = EFalse;
       
   827 					iOwner.TransportDown();
       
   828 					}
       
   829 				break;
       
   830 
       
   831 #ifndef ERRONEOUS_SUSPEND_INDICATIONS
       
   832 			case EUsbcDeviceStateSuspended:
       
   833 				break;
       
   834 #endif // !ERRONEOUS_SUSPEND_INDICATIONS
       
   835 
       
   836 			case EUsbcDeviceStateConfigured:
       
   837 				// Normally, we don't do anything here, because the transport only goes up when
       
   838 				// we actually receive the alternate interface change.
       
   839 #ifdef NO_ALTERNATE_USB_INTERFACE_SUPPORT
       
   840 				if (!iTransportUp)
       
   841 					{
       
   842 					FLOG(_L("Device now configured: transport layer coming up..."));
       
   843 
       
   844 					iTransportUp = ETrue;
       
   845 
       
   846 					// DMA can be allocated to the endpoints, if required
       
   847 					// This has to be done here for no alternate interface devices
       
   848 					// as they will not receive interface change notification
       
   849 					AllocateDma();
       
   850 
       
   851 					iOwner.TransportUp();
       
   852 					}
       
   853 #endif // NO_ALTERNATE_USB_INTERFACE_SUPPORT
       
   854 				break;
       
   855 
       
   856 			default:
       
   857 				__ASSERT_DEBUG(false, PANIC(KPanicCat, EUnknownUsbState));
       
   858 				break;
       
   859 			}
       
   860 		}
       
   861 
       
   862 	// Await further notification of a state change. We may have called Error(), which
       
   863 	// would already have set this notification request.
       
   864 	if (!IsActive())
       
   865 		{
       
   866 		iUsb.AlternateDeviceStatusNotify(iStatus, iUsbState);
       
   867 		SetActive();
       
   868 		}
       
   869 
       
   870 	FLOG(_L("CObexUsbHandler::RunL finished"));
       
   871 	}
       
   872 
       
   873 
       
   874 /**
       
   875 Standard active object cancellation function.
       
   876 */
       
   877 void CObexUsbHandler::DoCancel()
       
   878 	{
       
   879 	LOG_FUNC
       
   880 
       
   881 	iUsb.AlternateDeviceStatusNotifyCancel();
       
   882 	}
       
   883 
       
   884 
       
   885 /**
       
   886 Registers the required comms and data interfaces.
       
   887 */
       
   888 void CObexUsbHandler::RegInterfacesL()
       
   889 	{
       
   890 	LOG_FUNC
       
   891 
       
   892 	// Setup a CDC Communication Class interface
       
   893 	TUsbcInterfaceInfoBuf ifc;
       
   894 
       
   895 	// Extract the interface string from the transport info structure we were
       
   896 	// passed on construction. This isn't const because the SetInterface API
       
   897 	// requires it not to be.
       
   898 	// This is the only point where iObexTransportInfo is used directly
       
   899 	// Do not use iObexTransportInfo outside of construction phases
       
   900 	TPtrC string(iObexTransportInfo.iInterfaceStringDescriptor);
       
   901 
       
   902 	LOG1(_L("Using interface string \"%S\""), &string);
       
   903 		
       
   904 	ifc().iString = &string;
       
   905 	ifc().iClass.iClassNum = KObexClassNumber;		
       
   906 	ifc().iClass.iSubClassNum = KObexSubClassNumber;
       
   907 	ifc().iClass.iProtocolNum = KObexProtocolNumber;
       
   908 	ifc().iTotalEndpointsUsed = 0;
       
   909 	
       
   910 	// Indicate that this interface does not expect any control transfers 
       
   911 	// from EP0.
       
   912 	ifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease;
       
   913 	
       
   914 	FLOG(_L("CObexUsbListeningConnector::RegInterfacesL - setting comms interface")); 
       
   915 	
       
   916 	TInt err = iUsbComms.SetInterface(0, ifc);
       
   917 
       
   918 	if (err != KErrNone) 
       
   919 		{ 
       
   920 		LOG1(_L("SetInterface failed with error %d"), err);
       
   921 		LEAVEIFERRORL(err);
       
   922 		}
       
   923 
       
   924 	// Get the interface number for later 
       
   925 	TInt intDescSize;
       
   926 	err = iUsbComms.GetInterfaceDescriptorSize(0,intDescSize);	
       
   927 	if(err != KErrNone)
       
   928 		{
       
   929 		LOG1(_L("Failed to get interface descriptor size. Err = %d"),err);
       
   930 		intDescSize = KObexDefaultInterfaceDescriptorLength; //Default is 100
       
   931 		}
       
   932 	HBufC8* interfaceDescriptor;
       
   933 	interfaceDescriptor = HBufC8::NewLC(intDescSize);
       
   934 	TPtr8 pIntDesc = interfaceDescriptor->Des();
       
   935 	iUsbComms.GetInterfaceDescriptor(0, pIntDesc);
       
   936 	TUint8 obexIntNo = interfaceDescriptor->Ptr()[2];
       
   937 	CleanupStack::PopAndDestroy();
       
   938 
       
   939 	TBuf8<KObexInterfaceDescriptorBlockLength> desc;
       
   940 
       
   941 	// Comms Class Header Functional Descriptor
       
   942 
       
   943 	desc.Append(KObexFunctionalDescriptorLength);
       
   944 	desc.Append(KUsbDescType_CS_Interface);
       
   945 	desc.Append(KHeaderFunctionalDescriptor);
       
   946 	desc.Append(KCdcVersionNumber[0]);
       
   947 	desc.Append(KCdcVersionNumber[1]);
       
   948 
       
   949 	// Obex Functional Descriptor
       
   950 
       
   951 	desc.Append(KObexFunctionalDescriptorLength);
       
   952 	desc.Append(KUsbDescType_CS_Interface);
       
   953 	desc.Append(KObexFunctionalDescriptor);
       
   954 	desc.Append(KWmcdcVersionNumber[0]);
       
   955 	desc.Append(KWmcdcVersionNumber[1]);
       
   956 
       
   957 	// Union Functional Descriptor
       
   958 	
       
   959 	desc.Append(KObexFunctionalDescriptorLength);
       
   960 	desc.Append(KUsbDescType_CS_Interface); 
       
   961 	desc.Append(KUnionFunctionalDescriptor);
       
   962 	desc.Append(obexIntNo); 
       
   963 	TInt dataInt = obexIntNo + 1;
       
   964 	desc.Append(static_cast<TUint8>(dataInt));		
       
   965 
       
   966 	err = iUsbComms.SetCSInterfaceDescriptorBlock(0, desc);
       
   967 	if (err != KErrNone)
       
   968 		{
       
   969 		LOG1(_L("SetCSInterfaceDescriptorBlock failed with error %d"), err);
       
   970 		LEAVEIFERRORL(err);
       
   971 		}
       
   972 
       
   973 	// Setup CDC Data Class interfaces
       
   974 
       
   975 	// Only set the "function inactive" interface (alternate setting 0)
       
   976 	// if the device can support alternate interfaces
       
   977 #ifndef NO_ALTERNATE_USB_INTERFACE_SUPPORT
       
   978 	TUsbcInterfaceInfoBuf dataifc;
       
   979 
       
   980 	dataifc().iString = NULL;
       
   981 	dataifc().iClass.iClassNum = KObexDataClass;		
       
   982 	dataifc().iClass.iSubClassNum = KObexDataSubClass;
       
   983 	dataifc().iClass.iProtocolNum = 0;
       
   984 	dataifc().iTotalEndpointsUsed = 0;
       
   985 
       
   986 	// Indicate that this interface does not expect any control transfers 
       
   987 	// from EP0.
       
   988 	dataifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease;
       
   989 
       
   990 	FLOG(_L("Setting data class interface (alt setting 0")); 
       
   991 	
       
   992 	err = iUsb.SetInterface(0 /*alternate setting*/, dataifc, iBandwidthPriority);
       
   993 	if (err != KErrNone) 
       
   994 		{
       
   995 		LOG1(_L("Cannot set data interface (alternate setting 0): error %d"), err);
       
   996 		LEAVEIFERRORL(err);
       
   997 		}
       
   998 
       
   999 	// If anything below this point leaves, make sure this alternate setting
       
  1000 	// gets released.
       
  1001 	CleanupStack::PushL(TCleanupItem(CleanupReleaseInterface0, &iUsb));
       
  1002 #endif // NO_ALTERNATE_USB_INTERFACE_SUPPORT
       
  1003 
       
  1004 	// Check the device has enough endpoints for the "function active" data interface
       
  1005 	TUsbDeviceCaps dCaps;
       
  1006 	LEAVEIFERRORL(iUsb.DeviceCaps(dCaps));
       
  1007 	
       
  1008 	TInt n = dCaps().iTotalEndpoints;
       
  1009 	if (n < KObexMinNumEndpoints) 
       
  1010 		{
       
  1011 		LEAVEIFERRORL(KErrOverflow);
       
  1012 		}
       
  1013 	
       
  1014 	// Use the hardware's HS capability to determine maximum bulk transfer packet size
       
  1015 	TInt maxPacketSize = (dCaps().iHighSpeed) ? KMaxPacketTypeBulkHS : KMaxPacketTypeBulkFS;
       
  1016 	
       
  1017 		
       
  1018 	// Get information on the available endpoints from the driver
       
  1019 	TUsbcEndpointData data[KUsbcMaxEndpoints];
       
  1020 	TPtr8 dataptr(REINTERPRET_CAST(TUint8*, data), sizeof(data), sizeof(data));
       
  1021 	LEAVEIFERRORL(iUsb.EndpointCaps(dataptr));
       
  1022 
       
  1023 	// Check to see if there are suitably capable IN and OUT endpoints available
       
  1024 	// and fill dataifc2 structure accordingly.
       
  1025 	//
       
  1026 	// NOTE: The order the iEndpointData array is filled matches the order used for the
       
  1027 	// virtual endpoint numbers KTransmitEndpoint and KReceiveEndpoint - so change with caution!
       
  1028 	//
       
  1029 	// The virtual endpoint numbers are 1-based, whereas the iEndpointData array is 0 based
       
  1030 	// hence the subtraction in the array indices
       
  1031 	//
       
  1032 	// NOTE: IN and OUT refer to the host so in this case:
       
  1033 	//			IN  => device to PC = KTransmitEndpoint
       
  1034 	//			OUT => PC to device = KReceiveEndpoint
       
  1035 	TUsbcInterfaceInfoBuf dataifc2;
       
  1036 	TBool foundIn = EFalse;
       
  1037 	TBool foundOut = EFalse;
       
  1038 	for (TInt i = 0; !(foundIn && foundOut) && i < n; i++)
       
  1039 		{
       
  1040 		const TUsbcEndpointCaps* caps = &data[i].iCaps;
       
  1041 		if (data[i].iInUse)
       
  1042 			{
       
  1043 			continue;
       
  1044 			}
       
  1045 			
       
  1046 		const TUint KBulkInFlags = KUsbEpTypeBulk | KUsbEpDirIn;
       
  1047 		const TUint KBulkOutFlags = KUsbEpTypeBulk | KUsbEpDirOut;
       
  1048 
       
  1049 		if (!foundIn && (caps->iTypesAndDir & KBulkInFlags) == KBulkInFlags)
       
  1050 			{
       
  1051 			dataifc2().iEndpointData[KTransmitEndpoint - 1].iType  = KUsbEpTypeBulk;
       
  1052 			dataifc2().iEndpointData[KTransmitEndpoint - 1].iDir   = KUsbEpDirIn;	
       
  1053 			TInt maxSize = caps->MaxPacketSize();
       
  1054 			if (maxSize > maxPacketSize)
       
  1055 				{
       
  1056 				maxSize = maxPacketSize;
       
  1057 				}
       
  1058 			dataifc2().iEndpointData[KTransmitEndpoint - 1].iSize  = maxSize;
       
  1059 			
       
  1060 			// Allocate dma if requested and the device support resource allocation scheme version 2
       
  1061 			// for resource allocation scheme version1, refer to AllocateDma()
       
  1062 			if (iRequestDmaOnInEndpoint && 
       
  1063 				((dCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0))
       
  1064 				{
       
  1065 				dataifc2().iEndpointData[KTransmitEndpoint - 1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA;
       
  1066 				}
       
  1067 
       
  1068 			foundIn = ETrue;
       
  1069 			}
       
  1070 		else if (!foundOut && (caps->iTypesAndDir & KBulkOutFlags) == KBulkOutFlags)
       
  1071 			{
       
  1072 			dataifc2().iEndpointData[KReceiveEndpoint - 1].iType = KUsbEpTypeBulk;
       
  1073 			dataifc2().iEndpointData[KReceiveEndpoint - 1].iDir = KUsbEpDirOut;
       
  1074 			TInt maxSize = caps->MaxPacketSize();
       
  1075 			if (maxSize > maxPacketSize)
       
  1076 				{
       
  1077 				maxSize = maxPacketSize;
       
  1078 				}
       
  1079 			dataifc2().iEndpointData[KReceiveEndpoint - 1].iSize  = maxSize;
       
  1080 			
       
  1081 			//Allocate dma here if requested and the device support resource allocation scheme version 2
       
  1082 			// for resource allocation scheme version1, refer to AllocateDma()
       
  1083 			if (iRequestDmaOnOutEndpoint && 
       
  1084 				((dCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0))
       
  1085 				{
       
  1086 				dataifc2().iEndpointData[KReceiveEndpoint - 1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA;
       
  1087 				}
       
  1088 			
       
  1089 			foundOut = ETrue;
       
  1090 			}
       
  1091 		}
       
  1092 		
       
  1093 	if (!(foundIn && foundOut)) 
       
  1094 		{
       
  1095 		LEAVEIFERRORL(KErrHardwareNotAvailable);
       
  1096 		}
       
  1097 	
       
  1098 	// Set the active interface.
       
  1099 	dataifc2().iString = NULL;
       
  1100 	dataifc2().iClass.iClassNum = KObexDataClass;		
       
  1101 	dataifc2().iClass.iSubClassNum = KObexDataSubClass;
       
  1102 	dataifc2().iClass.iProtocolNum = 0;
       
  1103 	dataifc2().iTotalEndpointsUsed = KObexTotalEndpoints;
       
  1104 	
       
  1105 	// Indicate that this interface does not expect any control transfers 
       
  1106 	// from EP0.
       
  1107 	dataifc2().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease;
       
  1108 		
       
  1109 #ifdef NO_ALTERNATE_USB_INTERFACE_SUPPORT
       
  1110 	// For devices that don't suport alternate interfaces, have to place the "function active"
       
  1111 	// interface at alternate setting 0, although the CDC specification says if should be alternate setting 1
       
  1112 	FLOG(_L("Setting data class interface (no alternate interface support)"));
       
  1113 	
       
  1114 	err = iUsb.SetInterface(0 /*alternate setting*/, dataifc2, iBandwidthPriority);
       
  1115 
       
  1116 	if (err != KErrNone) 
       
  1117 		{
       
  1118 		//FTRACE(FPrint(_L("Cannot set data interface (no alternate interface support): error %d"), err));
       
  1119 		LOG1(_L("Cannot set data interface (no alternate interface support): error %d"), err);
       
  1120 		LEAVEIFERRORL(err);
       
  1121 		}
       
  1122 #else
       
  1123 	FLOG(_L("Setting data class interface (alternate setting 1)"));
       
  1124 	
       
  1125 	err = iUsb.SetInterface(1 /*alternate setting*/, dataifc2, iBandwidthPriority); 
       
  1126 
       
  1127 	if (err != KErrNone) 
       
  1128 		{
       
  1129 		//FTRACE(FPrint(_L("Cannot set data interface (alternate setting 1): error %d"), err));
       
  1130 		LOG1(_L("Cannot set data interface (alternate setting 1): error %d"), err);
       
  1131 		LEAVEIFERRORL(err);
       
  1132 		}
       
  1133 
       
  1134 	CleanupStack::Pop(); // ReleaseInterface0
       
  1135 #endif
       
  1136 
       
  1137 	FLOG(_L("CObexUsbHandler::RegInterfacesL - finished."));
       
  1138 	}
       
  1139 
       
  1140 
       
  1141 /**
       
  1142 Utility function which releases the first alternate setting of the specified
       
  1143 interface. Used when setting up Obex interfaces.
       
  1144 
       
  1145 @param	aInterface	The interface to release
       
  1146 */
       
  1147 void CObexUsbHandler::CleanupReleaseInterface0(TAny* aInterface)
       
  1148 	{
       
  1149 	reinterpret_cast<RDevUsbcClient*>(aInterface)->ReleaseInterface(0 /*alternate setting*/);
       
  1150 	}
       
  1151 
       
  1152 
       
  1153 /**
       
  1154 Accept an incoming connection.
       
  1155 */
       
  1156 void CObexUsbHandler::Start()
       
  1157 	{
       
  1158 	LOG_FUNC
       
  1159 
       
  1160 	// Await notification of a state change (this is like waiting for a connect...).
       
  1161 	iUsb.AlternateDeviceStatusNotify(iStatus, iUsbState);
       
  1162 	SetActive();
       
  1163 	}
       
  1164 
       
  1165 	
       
  1166 /**
       
  1167 Utility function to allocate DMA to the bulk endpoints - if they have been requested
       
  1168 This function is called during a connect, once the device is configured,
       
  1169 so if the allocations fail it wont complain in release builds but debug builds will
       
  1170 panic with either EDmaAllocationFailedEndpointIn or EDmaAllocationFailedEndpointOut. 
       
  1171 */
       
  1172 void CObexUsbHandler::AllocateDma()
       
  1173 	{
       
  1174 	LOG_FUNC
       
  1175 
       
  1176 	TUsbDeviceCaps dCaps;
       
  1177 	iUsb.DeviceCaps(dCaps);
       
  1178 	if ((dCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0)
       
  1179 		{
       
  1180 		// for resource allocation version2, refer to CObexUsbHandler::RegInterfacesL()
       
  1181 		return;
       
  1182 		}
       
  1183 
       
  1184 	if (iRequestDmaOnInEndpoint)
       
  1185 		{
       
  1186 		TInt err = iUsb.AllocateEndpointResource(KTransmitEndpoint, EUsbcEndpointResourceDMA);
       
  1187 		// The following log message is checked for in the test code - change with caution!
       
  1188 		LOG1(_L("IN Endpoint DMA resource allocation result %d"), err);
       
  1189 		(void)err; // to stop compilers complaining about unused variables
       
  1190 		}
       
  1191 
       
  1192 	if (iRequestDmaOnOutEndpoint)
       
  1193 		{
       
  1194 		TInt err = iUsb.AllocateEndpointResource(KReceiveEndpoint, EUsbcEndpointResourceDMA);
       
  1195 		// The following log message is checked for in the test code - change with caution!
       
  1196 		LOG1(_L("OUT Endpoint DMA resource allocation result %d"), err);
       
  1197 		(void)err; // to stop compilers complaining about unused variables
       
  1198 		}
       
  1199 	}
       
  1200 
       
  1201 
       
  1202 //
       
  1203 
       
  1204 /**
       
  1205 Constructs a CObexUsbStaller object
       
  1206 
       
  1207 @param	aUsb			Reference to a RDevUsbcClient object.
       
  1208 @param	aOwner			Reference to a MObexUsbConnector that owns this handler
       
  1209 
       
  1210 @return	A new CObexUsbStaller object
       
  1211 */
       
  1212 CObexUsbStaller* CObexUsbStaller::NewL(RDevUsbcClient& aUsb, MObexUsbConnector& aOwner)
       
  1213 	{
       
  1214 	CObexUsbStaller* self = new(ELeave) CObexUsbStaller(aUsb, aOwner);
       
  1215 	return self;
       
  1216 	}
       
  1217 
       
  1218 /**
       
  1219 CObexUsbStaller constructor.
       
  1220 
       
  1221 @param	aUsb			Reference to a RDevUsbcClient object.
       
  1222 @param	aOwner			Reference to a MObexUsbConnector that owns this handler
       
  1223 */
       
  1224 CObexUsbStaller::CObexUsbStaller(RDevUsbcClient& aUsb, MObexUsbConnector& aOwner)
       
  1225 	: CActive(EPriorityStandard), iUsb(aUsb), iOwner(aOwner)
       
  1226 	{
       
  1227 	CActiveScheduler::Add(this);
       
  1228 	}
       
  1229 
       
  1230 
       
  1231 /**
       
  1232 CObexUsbStaller destructor.
       
  1233 */
       
  1234 CObexUsbStaller::~CObexUsbStaller()
       
  1235 	{
       
  1236 	Cancel();
       
  1237 	}
       
  1238 
       
  1239 
       
  1240 /**
       
  1241 Starts the staller
       
  1242 */
       
  1243 void CObexUsbStaller::Start()
       
  1244 	{
       
  1245 	LOG_FUNC
       
  1246 	
       
  1247 	if (!IsActive())
       
  1248 		{
       
  1249 		FLOG(_L("Halting transmit endpoint..."));
       
  1250 		iUsb.HaltEndpoint(KTransmitEndpoint);
       
  1251 		iUsb.EndpointStatusNotify(iStatus, iEndpointStatus);
       
  1252 		SetActive();
       
  1253 		}
       
  1254 	}
       
  1255 	
       
  1256 
       
  1257 /**
       
  1258 Called when the transmit endpoint has changed state
       
  1259 */
       
  1260 void CObexUsbStaller::RunL()
       
  1261 	{
       
  1262 	LOG_FUNC
       
  1263 	
       
  1264 	TEndpointState endpointState;
       
  1265 	iUsb.EndpointStatus(KTransmitEndpoint, endpointState);	
       
  1266 #ifdef __FLOG_ACTIVE
       
  1267 	switch (endpointState)
       
  1268 		{
       
  1269 		case EEndpointStateNotStalled:
       
  1270 			{
       
  1271 			FLOG(_L("Receive endpoint not stalled"));
       
  1272 			break;
       
  1273 			}
       
  1274 		case EEndpointStateStalled:
       
  1275 			{
       
  1276 			FLOG(_L("Receive endpoint stalled"));
       
  1277 			break;
       
  1278 			}
       
  1279 		case EEndpointStateUnknown:
       
  1280 			{
       
  1281 			FLOG(_L("Receive endpoint unknown state"));
       
  1282 			break;
       
  1283 			}
       
  1284 		}
       
  1285 #endif		 
       
  1286 	if (endpointState == EEndpointStateNotStalled)
       
  1287 		{
       
  1288 		LOG1(_L("CObexUsbStallWatcher::RunL -- endpoint no longer stalled (0x%08x)"), iEndpointStatus);
       
  1289 		iOwner.StallCleared();
       
  1290 		}
       
  1291 	else
       
  1292 		{
       
  1293 		LOG1(_L("CObexUsbStallWatcher::RunL -- endpoint still stalled (0x%08x)"), iEndpointStatus);
       
  1294 		iUsb.EndpointStatusNotify(iStatus, iEndpointStatus);
       
  1295 		SetActive();
       
  1296 		}
       
  1297 	}
       
  1298 
       
  1299 
       
  1300 /**
       
  1301 Standard active object error function.
       
  1302 
       
  1303 @return	KErrNone because currently nothing should cause this to be called.
       
  1304 */
       
  1305 TInt CObexUsbStaller::RunError(TInt /*aError*/)
       
  1306 	{
       
  1307 	LOG_FUNC
       
  1308 	
       
  1309 	return KErrNone;
       
  1310 	}
       
  1311 	
       
  1312 
       
  1313 /**
       
  1314 Standard active object cancellation function.
       
  1315 */	
       
  1316 void CObexUsbStaller::DoCancel()
       
  1317 	{
       
  1318 	FLOG(_L("CObexUsbStaller -- Cancelling status notification"));
       
  1319 	iUsb.EndpointStatusNotifyCancel();
       
  1320 	}
       
  1321