obex/obexprotocol/obexusbtransport/src/usbconn.cpp
changeset 0 d0791faffa3f
child 11 4843bb5893b6
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     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 			foundIn = ETrue;
       
  1060 			}
       
  1061 		else if (!foundOut && (caps->iTypesAndDir & KBulkOutFlags) == KBulkOutFlags)
       
  1062 			{
       
  1063 			dataifc2().iEndpointData[KReceiveEndpoint - 1].iType = KUsbEpTypeBulk;
       
  1064 			dataifc2().iEndpointData[KReceiveEndpoint - 1].iDir = KUsbEpDirOut;
       
  1065 			TInt maxSize = caps->MaxPacketSize();
       
  1066 			if (maxSize > maxPacketSize)
       
  1067 				{
       
  1068 				maxSize = maxPacketSize;
       
  1069 				}
       
  1070 			dataifc2().iEndpointData[KReceiveEndpoint - 1].iSize  = maxSize;
       
  1071 			foundOut = ETrue;
       
  1072 			}
       
  1073 		}
       
  1074 		
       
  1075 	if (!(foundIn && foundOut)) 
       
  1076 		{
       
  1077 		LEAVEIFERRORL(KErrHardwareNotAvailable);
       
  1078 		}
       
  1079 	
       
  1080 	// Set the active interface.
       
  1081 	dataifc2().iString = NULL;
       
  1082 	dataifc2().iClass.iClassNum = KObexDataClass;		
       
  1083 	dataifc2().iClass.iSubClassNum = KObexDataSubClass;
       
  1084 	dataifc2().iClass.iProtocolNum = 0;
       
  1085 	dataifc2().iTotalEndpointsUsed = KObexTotalEndpoints;
       
  1086 	
       
  1087 	// Indicate that this interface does not expect any control transfers 
       
  1088 	// from EP0.
       
  1089 	dataifc2().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease;
       
  1090 		
       
  1091 #ifdef NO_ALTERNATE_USB_INTERFACE_SUPPORT
       
  1092 	// For devices that don't suport alternate interfaces, have to place the "function active"
       
  1093 	// interface at alternate setting 0, although the CDC specification says if should be alternate setting 1
       
  1094 	FLOG(_L("Setting data class interface (no alternate interface support)"));
       
  1095 	
       
  1096 	err = iUsb.SetInterface(0 /*alternate setting*/, dataifc2, iBandwidthPriority);
       
  1097 
       
  1098 	if (err != KErrNone) 
       
  1099 		{
       
  1100 		//FTRACE(FPrint(_L("Cannot set data interface (no alternate interface support): error %d"), err));
       
  1101 		LOG1(_L("Cannot set data interface (no alternate interface support): error %d"), err);
       
  1102 		LEAVEIFERRORL(err);
       
  1103 		}
       
  1104 #else
       
  1105 	FLOG(_L("Setting data class interface (alternate setting 1)"));
       
  1106 	
       
  1107 	err = iUsb.SetInterface(1 /*alternate setting*/, dataifc2, iBandwidthPriority); 
       
  1108 
       
  1109 	if (err != KErrNone) 
       
  1110 		{
       
  1111 		//FTRACE(FPrint(_L("Cannot set data interface (alternate setting 1): error %d"), err));
       
  1112 		LOG1(_L("Cannot set data interface (alternate setting 1): error %d"), err);
       
  1113 		LEAVEIFERRORL(err);
       
  1114 		}
       
  1115 
       
  1116 	CleanupStack::Pop(); // ReleaseInterface0
       
  1117 #endif
       
  1118 
       
  1119 	FLOG(_L("CObexUsbHandler::RegInterfacesL - finished."));
       
  1120 	}
       
  1121 
       
  1122 
       
  1123 /**
       
  1124 Utility function which releases the first alternate setting of the specified
       
  1125 interface. Used when setting up Obex interfaces.
       
  1126 
       
  1127 @param	aInterface	The interface to release
       
  1128 */
       
  1129 void CObexUsbHandler::CleanupReleaseInterface0(TAny* aInterface)
       
  1130 	{
       
  1131 	reinterpret_cast<RDevUsbcClient*>(aInterface)->ReleaseInterface(0 /*alternate setting*/);
       
  1132 	}
       
  1133 
       
  1134 
       
  1135 /**
       
  1136 Accept an incoming connection.
       
  1137 */
       
  1138 void CObexUsbHandler::Start()
       
  1139 	{
       
  1140 	LOG_FUNC
       
  1141 
       
  1142 	// Await notification of a state change (this is like waiting for a connect...).
       
  1143 	iUsb.AlternateDeviceStatusNotify(iStatus, iUsbState);
       
  1144 	SetActive();
       
  1145 	}
       
  1146 
       
  1147 	
       
  1148 /**
       
  1149 Utility function to allocate DMA to the bulk endpoints - if they have been requested
       
  1150 This function is called during a connect, once the device is configured,
       
  1151 so if the allocations fail it wont complain in release builds but debug builds will
       
  1152 panic with either EDmaAllocationFailedEndpointIn or EDmaAllocationFailedEndpointOut. 
       
  1153 */
       
  1154 void CObexUsbHandler::AllocateDma()
       
  1155 	{
       
  1156 	LOG_FUNC
       
  1157 
       
  1158 	if (iRequestDmaOnInEndpoint)
       
  1159 		{
       
  1160 		TInt err = iUsb.AllocateEndpointResource(KTransmitEndpoint, EUsbcEndpointResourceDMA);
       
  1161 		// The following log message is checked for in the test code - change with caution!
       
  1162 		LOG1(_L("IN Endpoint DMA resource allocation result %d"), err);
       
  1163 		(void)err; // to stop compilers complaining about unused variables
       
  1164 		}
       
  1165 
       
  1166 	if (iRequestDmaOnOutEndpoint)
       
  1167 		{
       
  1168 		TInt err = iUsb.AllocateEndpointResource(KReceiveEndpoint, EUsbcEndpointResourceDMA);
       
  1169 		// The following log message is checked for in the test code - change with caution!
       
  1170 		LOG1(_L("OUT Endpoint DMA resource allocation result %d"), err);
       
  1171 		(void)err; // to stop compilers complaining about unused variables
       
  1172 		}
       
  1173 	}
       
  1174 
       
  1175 
       
  1176 //
       
  1177 
       
  1178 /**
       
  1179 Constructs a CObexUsbStaller object
       
  1180 
       
  1181 @param	aUsb			Reference to a RDevUsbcClient object.
       
  1182 @param	aOwner			Reference to a MObexUsbConnector that owns this handler
       
  1183 
       
  1184 @return	A new CObexUsbStaller object
       
  1185 */
       
  1186 CObexUsbStaller* CObexUsbStaller::NewL(RDevUsbcClient& aUsb, MObexUsbConnector& aOwner)
       
  1187 	{
       
  1188 	CObexUsbStaller* self = new(ELeave) CObexUsbStaller(aUsb, aOwner);
       
  1189 	return self;
       
  1190 	}
       
  1191 
       
  1192 /**
       
  1193 CObexUsbStaller constructor.
       
  1194 
       
  1195 @param	aUsb			Reference to a RDevUsbcClient object.
       
  1196 @param	aOwner			Reference to a MObexUsbConnector that owns this handler
       
  1197 */
       
  1198 CObexUsbStaller::CObexUsbStaller(RDevUsbcClient& aUsb, MObexUsbConnector& aOwner)
       
  1199 	: CActive(EPriorityStandard), iUsb(aUsb), iOwner(aOwner)
       
  1200 	{
       
  1201 	CActiveScheduler::Add(this);
       
  1202 	}
       
  1203 
       
  1204 
       
  1205 /**
       
  1206 CObexUsbStaller destructor.
       
  1207 */
       
  1208 CObexUsbStaller::~CObexUsbStaller()
       
  1209 	{
       
  1210 	Cancel();
       
  1211 	}
       
  1212 
       
  1213 
       
  1214 /**
       
  1215 Starts the staller
       
  1216 */
       
  1217 void CObexUsbStaller::Start()
       
  1218 	{
       
  1219 	LOG_FUNC
       
  1220 	
       
  1221 	if (!IsActive())
       
  1222 		{
       
  1223 		FLOG(_L("Halting transmit endpoint..."));
       
  1224 		iUsb.HaltEndpoint(KTransmitEndpoint);
       
  1225 		iUsb.EndpointStatusNotify(iStatus, iEndpointStatus);
       
  1226 		SetActive();
       
  1227 		}
       
  1228 	}
       
  1229 	
       
  1230 
       
  1231 /**
       
  1232 Called when the transmit endpoint has changed state
       
  1233 */
       
  1234 void CObexUsbStaller::RunL()
       
  1235 	{
       
  1236 	LOG_FUNC
       
  1237 	
       
  1238 	TEndpointState endpointState;
       
  1239 	iUsb.EndpointStatus(KTransmitEndpoint, endpointState);	
       
  1240 #ifdef __FLOG_ACTIVE
       
  1241 	switch (endpointState)
       
  1242 		{
       
  1243 		case EEndpointStateNotStalled:
       
  1244 			{
       
  1245 			FLOG(_L("Receive endpoint not stalled"));
       
  1246 			break;
       
  1247 			}
       
  1248 		case EEndpointStateStalled:
       
  1249 			{
       
  1250 			FLOG(_L("Receive endpoint stalled"));
       
  1251 			break;
       
  1252 			}
       
  1253 		case EEndpointStateUnknown:
       
  1254 			{
       
  1255 			FLOG(_L("Receive endpoint unknown state"));
       
  1256 			break;
       
  1257 			}
       
  1258 		}
       
  1259 #endif		 
       
  1260 	if (endpointState == EEndpointStateNotStalled)
       
  1261 		{
       
  1262 		LOG1(_L("CObexUsbStallWatcher::RunL -- endpoint no longer stalled (0x%08x)"), iEndpointStatus);
       
  1263 		iOwner.StallCleared();
       
  1264 		}
       
  1265 	else
       
  1266 		{
       
  1267 		LOG1(_L("CObexUsbStallWatcher::RunL -- endpoint still stalled (0x%08x)"), iEndpointStatus);
       
  1268 		iUsb.EndpointStatusNotify(iStatus, iEndpointStatus);
       
  1269 		SetActive();
       
  1270 		}
       
  1271 	}
       
  1272 
       
  1273 
       
  1274 /**
       
  1275 Standard active object error function.
       
  1276 
       
  1277 @return	KErrNone because currently nothing should cause this to be called.
       
  1278 */
       
  1279 TInt CObexUsbStaller::RunError(TInt /*aError*/)
       
  1280 	{
       
  1281 	LOG_FUNC
       
  1282 	
       
  1283 	return KErrNone;
       
  1284 	}
       
  1285 	
       
  1286 
       
  1287 /**
       
  1288 Standard active object cancellation function.
       
  1289 */	
       
  1290 void CObexUsbStaller::DoCancel()
       
  1291 	{
       
  1292 	FLOG(_L("CObexUsbStaller -- Cancelling status notification"));
       
  1293 	iUsb.EndpointStatusNotifyCancel();
       
  1294 	}
       
  1295