usbmgmt/usbmgr/usbman/server/SRC/CUsbSession.cpp
changeset 0 c9bc50fca66e
child 6 96e575696901
equal deleted inserted replaced
-1:000000000000 0:c9bc50fca66e
       
     1 /*
       
     2 * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 * Implements a Session of a Symbian OS server for the RUsb API
       
    16 *
       
    17 */
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #include <usb/usblogger.h>
       
    24 #include "CUsbSession.h"
       
    25 #include "CUsbDevice.h"
       
    26 #include "CUsbServer.h"
       
    27 
       
    28 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
    29 #include "CUsbOtg.h"
       
    30 #include "cusbhost.h"
       
    31 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
    32 
       
    33 #include <usbstates.h>
       
    34 #include <usberrors.h>
       
    35 
       
    36 #include <usb/usbshared.h>
       
    37 #include "CPersonality.h"
       
    38 #include "rusb.h"
       
    39 #include "UsbSettings.h"
       
    40 
       
    41 #ifdef __FLOG_ACTIVE
       
    42 _LIT8(KLogComponent, "USBSVR");
       
    43 #endif
       
    44 
       
    45 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
    46 CUsbSession* CUsbSession::iCtlSession = NULL;
       
    47 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
    48 
       
    49 /**
       
    50  * Construct a Symbian OS session object.
       
    51  *
       
    52  * @internalComponent
       
    53  * @param	aServer		Service the session will be a member of
       
    54  *
       
    55  * @return	A new CUsbSession object
       
    56  */
       
    57 CUsbSession* CUsbSession::NewL(CUsbServer* aServer)
       
    58 	{
       
    59 	LOG_STATIC_FUNC_ENTRY
       
    60 
       
    61 	//this class has moved away from standard NewL() semantics
       
    62 	//and now uses the virtual CSession2::CreateL() function
       
    63 	//[instead of ConstructL()] which is called by CServer2
       
    64 	//and finalises the construction of the session
       
    65 	return (new (ELeave) CUsbSession(aServer));
       
    66 	}
       
    67 
       
    68 
       
    69 /**
       
    70  * Constructor.
       
    71  *
       
    72  * @internalComponent
       
    73  * @param	aServer	Service the session will be a member of
       
    74  */
       
    75 CUsbSession::CUsbSession(CUsbServer* aServer)
       
    76 	: iUsbServer(aServer)
       
    77 	{
       
    78 	LOG_FUNC
       
    79 
       
    80 	iUsbServer->IncrementSessionCount();
       
    81 	}
       
    82 
       
    83 
       
    84 /**
       
    85  * Destructor.
       
    86  */
       
    87 CUsbSession::~CUsbSession()
       
    88 	{
       
    89 	LOG_FUNC
       
    90 
       
    91 	LOGTEXT2(_L8("About to Device().DeRegisterObserver(%08x"),this);
       
    92 	iUsbServer->Device().DeRegisterObserver(*this);
       
    93 
       
    94 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
    95 #ifndef __OVER_DUMMYUSBDI__
       
    96 	LOGTEXT2(_L8("About to Otg().DeRegisterObserver(%08x"),this);
       
    97 	iUsbServer->Otg().DeRegisterObserver(*this);
       
    98 #endif
       
    99 
       
   100 	LOGTEXT2(_L8("About to Host().DeRegisterObserver(%08x"),this);
       
   101 	iUsbServer->Host().DeregisterObserver(*this);
       
   102 
       
   103 	if ( iCtlSession && (iCtlSession == this) )
       
   104 		{
       
   105 		iCtlSession = NULL;
       
   106 		}
       
   107 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   108 
       
   109 	LOGTEXT(_L8("About to iUsbServer->DecrementSessionCount()"));
       
   110 	iUsbServer->DecrementSessionCount();
       
   111 	}
       
   112 
       
   113 
       
   114 /**
       
   115  * Called when a message is received from the client.
       
   116  *
       
   117  * @param	aMessage	Message received from the client
       
   118  */
       
   119 void CUsbSession::ServiceL(const RMessage2& aMessage)
       
   120 	{
       
   121 	LOG_FUNC
       
   122 
       
   123 	DispatchMessageL(aMessage);
       
   124 	}
       
   125 
       
   126 /**
       
   127  * Handles 2nd Phase Construction.  Implementation of the virtual method defined in CSession2 and called from
       
   128  * CServer2::DoConnectL() which executes when the client makes a connection request through CServer2::Connect().  If
       
   129  * a Leave occurs at any point the CUsbSession object is cleaned up in CServer2::DoConnect().
       
   130  */
       
   131 void CUsbSession::CreateL()
       
   132 	{
       
   133 	LOG_FUNC
       
   134 
       
   135 	// This code originally existed in the typical non-virtual ConstructL() method.
       
   136 	// However it was moved to this method for minor optimisation reasons [three less
       
   137 	// function calls and several lines less code in the NewL() method].
       
   138 
       
   139 	iPersonalityCfged = iUsbServer->Device().isPersonalityCfged();
       
   140 
       
   141     LOGTEXT(_L8("Registering Device Observer\n"));
       
   142 	iUsbServer->Device().RegisterObserverL(*this);
       
   143 
       
   144 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   145 #ifndef __OVER_DUMMYUSBDI__
       
   146 	LOGTEXT(_L8("Registering OTG Observer\n"));
       
   147 	iUsbServer->Otg().RegisterObserverL(*this);
       
   148 #endif
       
   149 
       
   150 	LOGTEXT(_L8("Registering HOST Observer\n"));
       
   151 	iUsbServer->Host().RegisterObserverL(*this);
       
   152 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   153 	}
       
   154 
       
   155 /**
       
   156  * Called by CUsbDevice when the service state changes.
       
   157  * CUsbSession is an observer of the device.
       
   158  *
       
   159  * @param	aLastError	The last error happened
       
   160  * @param	aOldState	The device's service state just before it changed
       
   161  * @param	aNewState	The device's new and current service state
       
   162  */
       
   163 void CUsbSession::UsbServiceStateChange(TInt aLastError, TUsbServiceState aOldState,
       
   164 										TUsbServiceState aNewState)
       
   165 	{
       
   166 	LOG_FUNC
       
   167 	LOGTEXT3(_L8("    aOldState=0x%X, aNewState=0x%X"), aOldState, aNewState);
       
   168 	(void) aOldState; // a-void build warning in UREL
       
   169 
       
   170 	// Note that it's possible to have both a start and a stop outstanding!
       
   171 
       
   172 	if (iStartOutstanding)
       
   173 		{
       
   174 		HandleServiceStateChangeWhileStarting(aLastError, aNewState);
       
   175 		}
       
   176 
       
   177 	if (iStopOutstanding)
       
   178 		{
       
   179 		HandleServiceStateChangeWhileStopping(aLastError, aNewState);
       
   180 		}
       
   181 
       
   182 	// Check whether we have an observer of the service state.
       
   183 
       
   184 	if (iServiceObserverOutstanding)
       
   185 		{
       
   186 		TPckg<TUint32> pckg(aNewState);
       
   187 		iServiceObserverOutstanding = EFalse;
       
   188 		const TInt err = iServiceObserverMessage.Write(0, pckg);
       
   189 		iServiceObserverMessage.Complete(err);
       
   190 		}
       
   191 	}
       
   192 
       
   193 /**
       
   194  * Handles a state change while a start request is currently outstanding.
       
   195  *
       
   196  * @param aLastError The last error happened
       
   197  * @param aNewState The state we've moved to
       
   198  */
       
   199 void CUsbSession::HandleServiceStateChangeWhileStarting(TInt aLastError,
       
   200 												 TUsbServiceState aNewState)
       
   201 	{
       
   202 	LOG_FUNC
       
   203 
       
   204 	switch (aNewState)
       
   205 		{
       
   206 	case EUsbServiceStarted:
       
   207 		LOGTEXT(_L8("    Completing Start successfully"));
       
   208 
       
   209 		// If the user has tried to cancel the start, they're too late!
       
   210 		if (iCancelOutstanding)
       
   211 			{
       
   212 			LOGTEXT(_L8("    Completing cancel request with KErrNone"));
       
   213 			iCancelOutstanding = EFalse;
       
   214 			iCancelMessage.Complete(KErrNone);
       
   215 			}
       
   216 
       
   217 		iStartMessage.Complete(KErrNone);
       
   218 		iStartOutstanding = EFalse;
       
   219 		break;
       
   220 
       
   221 	case EUsbServiceIdle:
       
   222 		LOGTEXT2(_L8("    Completing Start with error=%d"), aLastError);
       
   223 
       
   224 		// If there hasn't actually been an error, but we're in an unexpected
       
   225 		// state now, that means that this client cancelled the request, or
       
   226 		// another client stopped the service.
       
   227 		if (aLastError == KErrNone)
       
   228 			{
       
   229 			// If there's a cancel outstanding, then that message succeeded, but
       
   230 			// the start message should be completed with KErrCancel.
       
   231 			if (iCancelOutstanding)
       
   232 				{
       
   233 				LOGTEXT(_L8("    Completing original message with KErrCancel"));
       
   234 				iCancelOutstanding = EFalse;
       
   235 				iCancelMessage.Complete(KErrNone);
       
   236 				iStartMessage.Complete(KErrCancel);
       
   237 				}
       
   238 			else
       
   239 				{
       
   240 				iStartMessage.Complete(KErrUsbServiceStopped);
       
   241 				}
       
   242 			}
       
   243 		else
       
   244 			{
       
   245 			// There's been some kind of error, so complete the original message
       
   246 			// with the right error code.
       
   247 			if (iCancelOutstanding)
       
   248 				{
       
   249 				iCancelOutstanding = EFalse;
       
   250 				iCancelMessage.Complete(KErrNone);
       
   251 				}
       
   252 			iStartMessage.Complete(aLastError);
       
   253 			}
       
   254 
       
   255 		iStartOutstanding = EFalse;
       
   256 		break;
       
   257 
       
   258 	default:
       
   259 		break;
       
   260 		}
       
   261 	}
       
   262 
       
   263 /**
       
   264  * Handles a state change while a stop request is currently outstanding.
       
   265  *
       
   266  * @param aLastError The last error happened
       
   267  * @param aNewState The state we've moved to
       
   268  */
       
   269 void CUsbSession::HandleServiceStateChangeWhileStopping(TInt aLastError,
       
   270 												 TUsbServiceState aNewState)
       
   271 	{
       
   272 	LOG_FUNC
       
   273 
       
   274 	switch (aNewState)
       
   275 		{
       
   276 	case EUsbServiceStarted:
       
   277 		LOGTEXT2(_L8("    Completing Stop with error=%d"), aLastError);
       
   278 
       
   279 		// If there hasn't actually been an error, but we're in an unexpected
       
   280 		// state now, that means that this client cancelled the request, or
       
   281 		// another client has started the service.
       
   282 		if (aLastError == KErrNone)
       
   283 			{
       
   284 			// If there's a cancel outstanding, then that message succeeded, but
       
   285 			// the stop message should be completed with KErrCancel.
       
   286 			if (iCancelOutstanding)
       
   287 				{
       
   288 				LOGTEXT(_L8("    Completing original message with KErrCancel"));
       
   289 				iCancelOutstanding = EFalse;
       
   290 				iCancelMessage.Complete(KErrNone);
       
   291 				iStopMessage.Complete(KErrCancel);
       
   292 				}
       
   293 			else
       
   294 				{
       
   295 				iStopMessage.Complete(KErrUsbServiceStarted);
       
   296 				}
       
   297 			}
       
   298 		else
       
   299 			{
       
   300 			// There's been some kind of error, so complete the original message
       
   301 			// with the right error code.
       
   302 			if (iCancelOutstanding)
       
   303 				{
       
   304 				iCancelOutstanding = EFalse;
       
   305 				iCancelMessage.Complete(KErrNone);
       
   306 				}
       
   307 			iStopMessage.Complete(aLastError);
       
   308 			}
       
   309 
       
   310 		iStopOutstanding = EFalse;
       
   311 		break;
       
   312 
       
   313 	case EUsbServiceIdle:
       
   314 		LOGTEXT(_L8("    Completing Stop with KErrNone"));
       
   315 
       
   316 		// If the user has tried to cancel the stop, they're too late!
       
   317 		if (iCancelOutstanding)
       
   318 			{
       
   319 			LOGTEXT(_L8("    Completing cancel request with KErrNone"));
       
   320 			iCancelOutstanding = EFalse;
       
   321 			iCancelMessage.Complete(KErrNone);
       
   322 			}
       
   323 
       
   324 		iStopMessage.Complete(KErrNone);
       
   325 		iStopOutstanding = EFalse;
       
   326 		break;
       
   327 
       
   328 	default:
       
   329 		break;
       
   330 		}
       
   331 	}
       
   332 
       
   333 /**
       
   334  * Called by CUsbDevice when it state change. CUsbSession is an observer of
       
   335  * the device. If the client has an Observer outstanding then complete it,
       
   336  * otherwise put it in a circular queue.
       
   337  *
       
   338  * @internalComponent
       
   339  * @param	aLastError	The last error happened
       
   340  * @param	aOldState	The device's state just before it changed
       
   341  * @param	aNewState	The device's new and current state
       
   342  */
       
   343 void CUsbSession::UsbDeviceStateChange(TInt /*aLastError*/, TUsbDeviceState /*aOldState*/,
       
   344 									   TUsbDeviceState aNewState)
       
   345 	{
       
   346 	LOG_FUNC
       
   347 
       
   348 	// can we bypass the queue?
       
   349  	if ((iDeviceObserverOutstanding) && (iDevStateQueueHead == iDevStateQueueTail))
       
   350 		{
       
   351 		if ((iDeviceObserverMessage.Int0() & aNewState) ||
       
   352 			(aNewState == EUsbDeviceStateUndefined))
       
   353 			{
       
   354 			TPckg<TUint32> pckg(aNewState);
       
   355 
       
   356 			iNotifiedDevState = aNewState;
       
   357 
       
   358 			iDeviceObserverOutstanding = EFalse;
       
   359 			const TInt err = iDeviceObserverMessage.Write(1, pckg);
       
   360 			iDeviceObserverMessage.Complete(err);
       
   361 			}
       
   362 		}
       
   363 	else if (iObserverQueueEvents)
       
   364 		{
       
   365 		TBool addToQueue = ETrue;
       
   366 
       
   367  		// Search queue for similar event, truncate event queue if found
       
   368  		if (aNewState == EUsbDeviceStateUndefined)
       
   369  			{
       
   370  			// erase Event queue, just want this event - not interested in how we got here
       
   371  			iDevStateQueueTail = iDevStateQueueHead;
       
   372 
       
   373  			// if this is also the event mostly recently notified then don't bother to queue it
       
   374  			if(aNewState == iNotifiedDevState)
       
   375  				addToQueue = EFalse;
       
   376  			}
       
   377  		else
       
   378  			{
       
   379  			TInt queuePtr = iDevStateQueueTail;
       
   380 
       
   381  			// search forward from tail to head
       
   382  			while (queuePtr != iDevStateQueueHead)
       
   383  				{
       
   384  				if (aNewState == iDeviceStateQueue[queuePtr])
       
   385  					{
       
   386  					// Event is already queued; discard the duplicate and in-between events
       
   387  					LOGTEXT3(_L8("--- collapsing queue head (%d, %d)"),
       
   388 						iDevStateQueueHead,
       
   389 						(queuePtr + 1) % KDeviceStatesQueueSize);
       
   390 
       
   391  					// queue head moved to position following the match
       
   392  					iDevStateQueueHead = (queuePtr + 1) % KDeviceStatesQueueSize;
       
   393  					addToQueue = EFalse;
       
   394  					break;
       
   395  					}
       
   396 
       
   397  				// work our way through queue
       
   398  				queuePtr = (queuePtr + 1) % KDeviceStatesQueueSize;
       
   399  				}
       
   400  			}
       
   401 
       
   402  		// still want to add to queue?
       
   403  		if (addToQueue)
       
   404  			{
       
   405  			// add event to head of queue
       
   406  			iDeviceStateQueue[iDevStateQueueHead] = aNewState;
       
   407  			iDevStateQueueHead = (iDevStateQueueHead + 1) % KDeviceStatesQueueSize;
       
   408  			LOGTEXT3(_L8("+++ addqueue (%d, %d)"), iDevStateQueueHead,
       
   409 				iDevStateQueueTail);
       
   410  			}
       
   411 
       
   412  		// UsbDeviceDequeueEvent() will read from queue when RegisterObserver()
       
   413 		// is next called.
       
   414 		}
       
   415 	}
       
   416 
       
   417 /**
       
   418  * Dequeues an event and completes the observer's request with it.
       
   419  */
       
   420 void CUsbSession::UsbDeviceDequeueEvent()
       
   421  	{
       
   422 	LOG_FUNC
       
   423 
       
   424  	// Work our way through the queue, until we reach the end
       
   425  	// OR we find an event the current observer wants.
       
   426  	while ((iDeviceObserverOutstanding) && (iDevStateQueueHead != iDevStateQueueTail))
       
   427  		{
       
   428  		// inform the observer of state changes they are interested in AND
       
   429  		// if the cable is pulled out (EUsbDeviceStateUndefined)
       
   430  		TUsbDeviceState newState = iDeviceStateQueue[iDevStateQueueTail];
       
   431 
       
   432  		// advance tail towards the head
       
   433  		iDevStateQueueTail = (iDevStateQueueTail + 1) % KDeviceStatesQueueSize;
       
   434 
       
   435  		// is this state one the Observer wants?
       
   436  		if ((iDeviceObserverMessage.Int0() & newState) ||
       
   437 			(newState == EUsbDeviceStateUndefined))
       
   438  			{
       
   439  			TPckg<TUint32> pckg(newState);
       
   440 
       
   441  			iNotifiedDevState = newState;
       
   442 
       
   443  			LOGTEXT3(_L8(">>> dequeued event #%d (0x%x)"), iDevStateQueueTail, newState);
       
   444 
       
   445   			iDeviceObserverOutstanding = EFalse;
       
   446 			const TInt err = iDeviceObserverMessage.Write(1, pckg);
       
   447  			iDeviceObserverMessage.Complete(err);
       
   448  			break;
       
   449    			}
       
   450    		}
       
   451    	}
       
   452 
       
   453 /**
       
   454  * Handles the request (in the form of a the message) received from the client
       
   455  *
       
   456  * @internalComponent
       
   457  * @param	aMessage	The received message
       
   458  */
       
   459 void CUsbSession::DispatchMessageL(const RMessage2& aMessage)
       
   460 	{
       
   461 	LOG_FUNC
       
   462 
       
   463 	TBool complete = ETrue;
       
   464 	TInt ret = KErrNone;
       
   465 
       
   466 	LOGTEXT2(_L8("CUsbSession::DispatchMessageL(): func# %d"), aMessage.Function());
       
   467 
       
   468 	switch (aMessage.Function())
       
   469 		{
       
   470 	case EUsbStart:
       
   471 		ret = StartDeviceL(aMessage, complete);
       
   472 		break;
       
   473 	case EUsbStop:
       
   474 		ret = StopDeviceL(aMessage, complete);
       
   475 		break;
       
   476 	case EUsbGetCurrentState:
       
   477 		ret = GetCurrentServiceState(aMessage);
       
   478 		break;
       
   479 	case EUsbGetCurrentDeviceState:
       
   480 		ret = GetCurrentDeviceState(aMessage);
       
   481 		break;
       
   482 	case EUsbRegisterServiceObserver:
       
   483 		ret = RegisterServiceObserver(aMessage, complete);
       
   484 		break;
       
   485 	case EUsbRegisterObserver:
       
   486 		ret = RegisterDeviceObserver(aMessage, complete);
       
   487 		break;
       
   488 	case EUsbStartCancel:
       
   489 		ret = StartCancel(aMessage, complete);
       
   490 		break;
       
   491 	case EUsbStopCancel:
       
   492 		ret = StopCancel(aMessage, complete);
       
   493 		break;
       
   494 	case EUsbCancelServiceObserver:
       
   495 		ret = DeRegisterServiceObserver();
       
   496 		break;
       
   497 	case EUsbCancelObserver:
       
   498 		ret = DeRegisterDeviceObserver();
       
   499 		break;
       
   500 	case EUsbTryStart:
       
   501 		ret = TryStartDeviceL(aMessage, complete);
       
   502 		break;
       
   503 	case EUsbTryStop:
       
   504 		ret = TryStopDeviceL(aMessage, complete);
       
   505 		break;
       
   506 	case EUsbCancelInterest:
       
   507 		ret = CancelInterest(aMessage);
       
   508 		break;
       
   509 	case EUsbGetCurrentPersonalityId:
       
   510 		ret = GetCurrentPersonalityId(aMessage);
       
   511 		break;
       
   512 	case EUsbGetSupportedClasses:
       
   513 		ret = GetSupportedClasses(aMessage);
       
   514 		break;
       
   515 	case EUsbGetPersonalityIds:
       
   516 		ret = GetPersonalityIds(aMessage);
       
   517 		break;
       
   518 	case EUsbGetDescription:
       
   519 		ret = GetDescription(aMessage);
       
   520 		break;
       
   521 	case EUsbGetDetailedDescription:
       
   522 		ret = GetDetailedDescription(aMessage);
       
   523 		break;
       
   524 	case EUsbGetPersonalityProperty:
       
   525 		ret = GetPersonalityProperty(aMessage);
       
   526 		break;
       
   527 	case EUsbClassSupported:
       
   528 		ret = ClassSupported(aMessage);
       
   529 		break;
       
   530 
       
   531 #ifdef _DEBUG
       
   532 	// Heap failure debug APIs.
       
   533 
       
   534 	case EUsbDbgMarkHeap:
       
   535 		LOGTEXT(_L8("Marking heap"));
       
   536 		__UHEAP_MARK;
       
   537 		break;
       
   538 	case EUsbDbgCheckHeap:
       
   539 		LOGTEXT2(_L8("Checking heap (expecting %d cells)"), aMessage.Int0());
       
   540 		__UHEAP_CHECK(aMessage.Int0());
       
   541 		break;
       
   542 	case EUsbDbgMarkEnd:
       
   543 		LOGTEXT2(_L8("End of marking heap (expecting %d cells)"), aMessage.Int0());
       
   544 		__UHEAP_MARKENDC(aMessage.Int0());
       
   545 		break;
       
   546 	case EUsbDbgFailNext:
       
   547 		{
       
   548 		LOGTEXT2(_L8("Simulating failure after %d allocation(s)"), aMessage.Int0());
       
   549 		if (aMessage.Int0() == 0)
       
   550 			__UHEAP_RESET;
       
   551 		else
       
   552 			__UHEAP_FAILNEXT(aMessage.Int0());
       
   553 		}
       
   554 		break;
       
   555 	case EUsbDbgAlloc:
       
   556 		{
       
   557 		ret = KErrNone;
       
   558 #ifdef _DEBUG
       
   559 		LOGTEXT(_L8("\tallocate on the heap"));
       
   560 		TInt* x = NULL;
       
   561 		TRAP(ret, x = new(ELeave) TInt);
       
   562 		delete x;
       
   563 #endif // _DEBUG
       
   564 		}
       
   565 		break;
       
   566 
       
   567 #endif
       
   568 
       
   569 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   570 	case EUsbSetCtlSessionMode:
       
   571 		ret = SetCtlSessionMode(aMessage);
       
   572 		break;
       
   573 	case EUsbRegisterMessageObserver:
       
   574 		ret = RegisterMsgObserver(aMessage, complete);
       
   575 		break;
       
   576 	case EUsbCancelMessageObserver:
       
   577 		ret = DeRegisterMsgObserver();
       
   578 		break;
       
   579 #ifndef __OVER_DUMMYUSBDI__
       
   580 	case EUsbBusRequest:
       
   581 		ret = BusRequest();
       
   582 		break;
       
   583 	case EUsbBusRespondSrp:
       
   584 		ret = BusRespondSrp();
       
   585 		break;
       
   586 	case EUsbBusClearError:
       
   587 		ret = BusClearError();
       
   588 		break;
       
   589 	case EUsbBusDrop:
       
   590 		ret = BusDrop();
       
   591 		break;
       
   592 #else
       
   593 	case EUsbBusRequest:
       
   594 	case EUsbBusRespondSrp:
       
   595 	case EUsbBusClearError:
       
   596 	case EUsbBusDrop:
       
   597 		ret = KErrNone;
       
   598 		break;
       
   599 #endif
       
   600 	case EUsbRegisterHostObserver:
       
   601 		ret = RegisterHostObserver(aMessage, complete);
       
   602 		break;
       
   603 	case EUsbCancelHostObserver:
       
   604 		ret = DeRegisterHostObserver();
       
   605 		break;
       
   606 	case EUsbEnableFunctionDriverLoading:
       
   607 		ret = EnableFunctionDriverLoading();
       
   608 		break;
       
   609 	case EUsbDisableFunctionDriverLoading:
       
   610 		ret = DisableFunctionDriverLoading();
       
   611 		break;
       
   612 	case EUsbGetSupportedLanguages:
       
   613 		ret = GetSupportedLanguages(aMessage);
       
   614 		break;
       
   615 	case EUsbGetManufacturerStringDescriptor:
       
   616 		ret = GetManufacturerStringDescriptor(aMessage);
       
   617 		break;
       
   618 	case EUsbGetProductStringDescriptor:
       
   619 		ret = GetProductStringDescriptor(aMessage);
       
   620 		break;
       
   621 	case EUsbGetOtgDescriptor:
       
   622 		ret = GetOtgDescriptor(aMessage);
       
   623 		break;
       
   624 	case EUsbRequestSession:
       
   625 		ret = RequestSession();
       
   626 		break;
       
   627 #else // !SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   628 	case EUsbSetCtlSessionMode:
       
   629 	case EUsbRegisterMessageObserver:
       
   630 	case EUsbCancelMessageObserver:
       
   631 	case EUsbBusRequest:
       
   632 	case EUsbBusRespondSrp:
       
   633 	case EUsbBusClearError:
       
   634 	case EUsbBusDrop:
       
   635 	case EUsbRegisterHostObserver:
       
   636 	case EUsbCancelHostObserver:
       
   637 	case EUsbEnableFunctionDriverLoading:
       
   638 	case EUsbDisableFunctionDriverLoading:
       
   639 	case EUsbGetSupportedLanguages:
       
   640 	case EUsbGetManufacturerStringDescriptor:
       
   641 	case EUsbGetProductStringDescriptor:
       
   642 	case EUsbGetOtgDescriptor:
       
   643 	case EUsbRequestSession:
       
   644 		ret = KErrNotSupported;
       
   645 		break;
       
   646 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   647 
       
   648 	default:
       
   649 		LOGTEXT2(_L8("Illegal IPC argument(%d) - Panicking Client..."), aMessage.Function());
       
   650 		aMessage.Panic(KUsbCliPncCat, EUsbPanicIllegalIPC);
       
   651 		complete = EFalse;
       
   652 		break;
       
   653 		}
       
   654 
       
   655 	if (complete)
       
   656 		aMessage.Complete(ret);
       
   657 	}
       
   658 
       
   659 
       
   660 /**
       
   661  * Client request to start the device.
       
   662  *
       
   663  * @param	aMessage	Message received from the client
       
   664  * @param	aComplete	Whether the request is complete or not
       
   665  * @return	Any error that occurred or KErrNone
       
   666  */
       
   667 TInt CUsbSession::StartDeviceL(const RMessage2& aMessage, TBool& aComplete)
       
   668 	{
       
   669 	LOG_FUNC
       
   670 
       
   671 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   672 	// Only 'control' session is allowed to start USB support
       
   673 	if ( !iSessionCtlMode )
       
   674 		{
       
   675 		return KErrAccessDenied;
       
   676 		}
       
   677 #endif
       
   678 
       
   679 	if (iStartOutstanding)
       
   680 		return KErrInUse;
       
   681 
       
   682 #ifndef __OVER_DUMMYUSBDI__
       
   683 
       
   684 	// If the service is idle or stopping, then we just need to start it.
       
   685 	// If it's starting (ie. by another client), then we need to perform nothing
       
   686 	// but wait for the start to complete.
       
   687 	// If it's already started, we just return immediately.
       
   688 	TUsbServiceState state = iUsbServer->Device().ServiceState();
       
   689 
       
   690 	if ((state == EUsbServiceIdle) || (state == EUsbServiceStopping))
       
   691 		{
       
   692 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   693 		iUsbServer->Host().StartL();
       
   694 #endif
       
   695 		iUsbServer->Device().StartL();
       
   696 
       
   697 		aComplete = EFalse;
       
   698 		iStartMessage = aMessage;
       
   699 		iStartOutstanding = ETrue;
       
   700 		}
       
   701 	else if (state == EUsbServiceStarting)
       
   702 		{
       
   703 		aComplete = EFalse;
       
   704 		iStartMessage = aMessage;
       
   705 		iStartOutstanding = ETrue;
       
   706 		}
       
   707 
       
   708 	return KErrNone;
       
   709 
       
   710 #else
       
   711 	// pretend that the server is in Started state
       
   712 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   713 	iUsbServer->Host().StartL();
       
   714 #endif
       
   715 	iStartOutstanding = EFalse;
       
   716 	aMessage.IsNull();
       
   717 	aComplete = ETrue;
       
   718 	return KErrNone;
       
   719 
       
   720 #endif
       
   721 	}
       
   722 
       
   723 /**
       
   724  * Client request to stop the device.
       
   725  *
       
   726  * @param	aMessage	Message received from the client
       
   727  * @param	aComplete	Whether the request is complete or not
       
   728  * @return	Any error that occurred or KErrNone
       
   729  */
       
   730 TInt CUsbSession::StopDeviceL(const RMessage2& aMessage, TBool& aComplete)
       
   731     {
       
   732 	LOG_FUNC
       
   733 
       
   734 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   735 	// Only 'control' session is allowed to stop USB support
       
   736 	if ( !iSessionCtlMode )
       
   737 		{
       
   738 		return KErrAccessDenied;
       
   739 		}
       
   740 #endif
       
   741 
       
   742 	if (iStopOutstanding)
       
   743 		{
       
   744 		return KErrInUse;
       
   745 		}
       
   746 
       
   747 #ifndef __OVER_DUMMYUSBDI__
       
   748 
       
   749 	// Only do anything if the service isn't currently idle. If it is, we just
       
   750 	// need to complete the user's request immediately.
       
   751 	if (iUsbServer->Device().ServiceState() != EUsbServiceIdle)
       
   752 		{
       
   753 		iUsbServer->Device().Stop();
       
   754 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   755 		iUsbServer->Host().Stop();
       
   756 #endif
       
   757 
       
   758 		aComplete = EFalse;
       
   759 		iStopMessage = aMessage;
       
   760 		iStopOutstanding = ETrue;
       
   761 		}
       
   762 
       
   763 	return KErrNone;
       
   764 
       
   765 #else
       
   766 	// pretend that the server is in Started state
       
   767 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   768 	iUsbServer->Host().Stop();
       
   769 #endif
       
   770 	aComplete = ETrue;
       
   771 	aMessage.IsNull();
       
   772 	iStopOutstanding = EFalse;
       
   773 	return KErrNone;
       
   774 
       
   775 #endif
       
   776     }
       
   777 
       
   778 /**
       
   779  * Cancel the pending start operation. Note that this can just be implemented
       
   780  * as a synchronous stop, if the start operation is pending. However, we have to
       
   781  * retain the cancel message, so we can complete it when the stop completes.
       
   782  *
       
   783  * @param aMessage The message from the client
       
   784  * @param aComplete Whether the message is complete or not
       
   785  * @return Always KErrNone
       
   786  */
       
   787 TInt CUsbSession::StartCancel(const RMessage2& aMessage, TBool& aComplete)
       
   788 	{
       
   789 	LOG_FUNC
       
   790 
       
   791 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   792 	// Only 'control' session is allowed to cancel outstaning start request
       
   793 	if ( !iSessionCtlMode )
       
   794 		{
       
   795 		return KErrAccessDenied;
       
   796 		}
       
   797 #endif
       
   798 
       
   799 	if (!iStartOutstanding)
       
   800 		return KErrNone;
       
   801 
       
   802 	aComplete = EFalse;
       
   803 	iCancelMessage = aMessage;
       
   804 	iCancelOutstanding = ETrue;
       
   805 
       
   806 	if (iUsbServer->Device().ServiceState() != EUsbServiceIdle)
       
   807 		{
       
   808 		iUsbServer->Device().Stop();
       
   809 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   810 		iUsbServer->Host().Stop();
       
   811 #endif
       
   812 		}
       
   813 
       
   814 	return KErrNone;
       
   815 	}
       
   816 
       
   817 /**
       
   818  * Cancel the pending stop operation. Note that this can just be implemented as
       
   819  * a synchronous start, if the stop operation is pending. However, we have to
       
   820  * retain the cancel message, so we can complete it when the start completes.
       
   821  *
       
   822  * @param aMessage The message from the client
       
   823  * @param aComplete Whether the message is complete or not
       
   824  * @return KErrNone on success, otherwise standard error codes
       
   825  */
       
   826 TInt CUsbSession::StopCancel(const RMessage2& aMessage, TBool& aComplete)
       
   827 	{
       
   828 	LOG_FUNC
       
   829 
       
   830 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   831 	// Only 'control' session is allowed to cancel outstaning stop request
       
   832 	if ( !iSessionCtlMode )
       
   833 		{
       
   834 		return KErrAccessDenied;
       
   835 		}
       
   836 #endif
       
   837 
       
   838 	if (!iStopOutstanding)
       
   839 		{
       
   840 		return KErrNone;
       
   841 		}
       
   842 
       
   843 	aComplete = EFalse;
       
   844 	iCancelMessage = aMessage;
       
   845 	iCancelOutstanding = ETrue;
       
   846 
       
   847 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
   848 	TRAPD(errHost,iUsbServer->Host().StartL());
       
   849 	if (errHost != KErrNone)
       
   850 		return errHost;
       
   851 #endif
       
   852 	TRAPD(err, iUsbServer->Device().StartL());
       
   853 	return err;
       
   854 	}
       
   855 
       
   856 /**
       
   857  * Client request to observe the device (for state changes).
       
   858  * Asks the device to register the session as an observer.
       
   859  * Assures initialisation/dequeueing of Event queue.
       
   860  *
       
   861  * @param	aMessage	Message received from the client
       
   862  * @param	aComplete	set to true to complete the request
       
   863  *
       
   864  * @return	Any error that occurred or KErrNone
       
   865  */
       
   866 TInt CUsbSession::RegisterDeviceObserver(const RMessage2& aMessage, TBool& aComplete)
       
   867 	{
       
   868 	LOG_FUNC
       
   869 
       
   870 	if (iDeviceObserverOutstanding)
       
   871 		{
       
   872 		return KErrInUse;
       
   873 		}
       
   874 
       
   875 	iDeviceObserverMessage = aMessage;
       
   876 	iDeviceObserverOutstanding = ETrue;
       
   877 	aComplete = EFalse;
       
   878 
       
   879  	if (iObserverQueueEvents == EFalse)
       
   880 	 	{
       
   881  		// This is the first observer after c'tor or DeregisterObserver(),
       
   882  		// so zap the device event queue.
       
   883  		LOGTEXT(_L8("    Reset Device Event Queue"));
       
   884  		iDevStateQueueHead = 0;
       
   885  		iDevStateQueueTail = 0;
       
   886  		iObserverQueueEvents = ETrue;
       
   887 	 	}
       
   888  	else if (iDevStateQueueHead != iDevStateQueueTail)
       
   889 	 	{
       
   890  		// event(s) queued, we can de-queue one now
       
   891  		UsbDeviceDequeueEvent();
       
   892 	 	}
       
   893 
       
   894 	return KErrNone;
       
   895 	}
       
   896 
       
   897 /**
       
   898  * Client request to observe the service (for state changes)
       
   899  * Asks the device to register the session as an observer
       
   900  *
       
   901  * @internalComponent
       
   902  * @param	aMessage	Message received from the client
       
   903  * @param	aComplete	set to true to complete the request
       
   904  *
       
   905  * @return	Any error that occurred or KErrNone
       
   906  */
       
   907 TInt CUsbSession::RegisterServiceObserver(const RMessage2& aMessage, TBool& aComplete)
       
   908 	{
       
   909 	LOG_FUNC
       
   910 
       
   911 	if (iServiceObserverOutstanding)
       
   912 		{
       
   913 		return KErrInUse;
       
   914 		}
       
   915 
       
   916 	iServiceObserverMessage = aMessage;
       
   917 	iServiceObserverOutstanding = ETrue;
       
   918 	aComplete = EFalse;
       
   919 	return KErrNone;
       
   920 	}
       
   921 
       
   922 
       
   923 /**
       
   924  * Client request to fetch the current service state of the device
       
   925  * Asks the device for its current service state
       
   926  *
       
   927  * @internalComponent
       
   928  * @param	aMessage	Message received from the client
       
   929  *
       
   930  * @return	Any errors that occurred or KErrNone
       
   931  */
       
   932 TInt CUsbSession::GetCurrentServiceState(const RMessage2& aMessage)
       
   933 	{
       
   934 	LOG_FUNC
       
   935 
       
   936 	TUsbServiceState state = iUsbServer->Device().ServiceState();
       
   937 	LOGTEXT2(_L8("\tstate = %d"), state);
       
   938 	TPckg<TUint32> pckg(state);
       
   939 	return aMessage.Write(0, pckg);
       
   940 	}
       
   941 
       
   942 /**
       
   943  * Client request to fetch the current device state of the device
       
   944  * Asks the device for its current device state
       
   945  *
       
   946  * @internalComponent
       
   947  * @param	aMessage	Message received from the client
       
   948  *
       
   949  * @return	Any errors that occurred or KErrNone
       
   950  */
       
   951 TInt CUsbSession::GetCurrentDeviceState(const RMessage2& aMessage)
       
   952 	{
       
   953 	LOG_FUNC
       
   954 
       
   955 	TUsbDeviceState state = iUsbServer->Device().DeviceState();
       
   956 	LOGTEXT2(_L8("\tstate = %d"), state);
       
   957 	TPckg<TUint32> pckg(state);
       
   958 	return aMessage.Write(0, pckg);
       
   959 	}
       
   960 
       
   961 
       
   962 /**
       
   963  * Deregister the client as an observer of device state changes. Note that we don't
       
   964  * deregister ourselves as an observer, because we need to be notified when the
       
   965  * device state changes, so we can complete Start and Stop requests.
       
   966  *
       
   967  * @return Always KErrNone
       
   968  */
       
   969 TInt CUsbSession::DeRegisterDeviceObserver()
       
   970 	{
       
   971 	LOG_FUNC
       
   972 
       
   973 	if (!iDeviceObserverOutstanding)
       
   974 		{
       
   975 		return KErrNone;
       
   976 		}
       
   977 
       
   978 	iDeviceObserverOutstanding = EFalse;
       
   979 	iDeviceObserverMessage.Complete(KErrCancel);
       
   980 
       
   981 	// client doesn't need events queuing any more
       
   982  	iObserverQueueEvents = EFalse;
       
   983 
       
   984 	return KErrNone;
       
   985 	}
       
   986 
       
   987 /**
       
   988  * Deregister the client as an observer of service state changes. Note that we don't
       
   989  * deregister ourselves as an observer, because we need to be notified when the
       
   990  * service state changes, so we can complete Start and Stop requests.
       
   991  *
       
   992  * @return Always KErrNone
       
   993  */
       
   994 TInt CUsbSession::DeRegisterServiceObserver()
       
   995 	{
       
   996 	LOG_FUNC
       
   997 
       
   998 	if (!iServiceObserverOutstanding)
       
   999 		{
       
  1000 		return KErrNone;
       
  1001 		}
       
  1002 
       
  1003 	iServiceObserverOutstanding = EFalse;
       
  1004 	iServiceObserverMessage.Complete(KErrCancel);
       
  1005 	return KErrNone;
       
  1006 	}
       
  1007 
       
  1008 /**
       
  1009  * Try starting the USB device.
       
  1010  *
       
  1011  * @internalComponent
       
  1012  * @param	aMessage	Message received from the client
       
  1013  * @param	aComplete	set to true to complete the request
       
  1014  * @return	Any error that occurred or KErrNone
       
  1015  */
       
  1016 TInt CUsbSession::TryStartDeviceL(const RMessage2& aMessage, TBool& aComplete)
       
  1017 	{
       
  1018 	LOG_FUNC
       
  1019 
       
  1020 #ifndef __OVER_DUMMYUSBDI__
       
  1021 
       
  1022 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
  1023 	// Only 'control' session is allowed to start USB support
       
  1024 	if ( !iSessionCtlMode )
       
  1025 		{
       
  1026 		return KErrAccessDenied;
       
  1027 		}
       
  1028 #endif
       
  1029 
       
  1030 	if (!iPersonalityCfged)
       
  1031 	{
       
  1032 	return KErrNotSupported;
       
  1033 	}
       
  1034 
       
  1035 	if (iStartOutstanding || iStopOutstanding)
       
  1036 		{
       
  1037 		return KErrServerBusy;
       
  1038 		}
       
  1039 
       
  1040 	// Obtains the curent service state
       
  1041 	TUsbServiceState state = iUsbServer->Device().ServiceState();
       
  1042 
       
  1043 
       
  1044 	// USB Peripheral Stack Starting sequence:
       
  1045 	// if the server is in the idle state
       
  1046 	//		start it;
       
  1047 	// if the server is in the started state
       
  1048 	//		return KErrNone immediately;
       
  1049 	// if the server is in the stopping state
       
  1050 	//		return KErrServerBusy immediately;
       
  1051  	// if the server is in the starting state
       
  1052 	// (was already called by this very session in OTG/Host configuration and/or
       
  1053 	//  by another session for Client Only configuration)
       
  1054 	// 		if requested personality is not equal to the current one
       
  1055 	//			return KErrAbort;
       
  1056 	//		else
       
  1057  	//			mark this request as outstanding and let the caller to wait
       
  1058 	//			for start operation to complete;
       
  1059 	if (state == EUsbServiceIdle)
       
  1060 		{
       
  1061 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
  1062 		iUsbServer->Host().StartL();
       
  1063 #endif
       
  1064 		iUsbServer->Device().TryStartL(aMessage.Int0());
       
  1065 		aComplete = EFalse;
       
  1066 		iStartMessage = aMessage;
       
  1067 		iStartOutstanding = ETrue;
       
  1068 		}
       
  1069 	else if (state == EUsbServiceStarting || state == EUsbServiceStarted)
       
  1070 		{
       
  1071 		if (aMessage.Int0() != iUsbServer->Device().CurrentPersonalityId())
       
  1072 			{
       
  1073 			return KErrAbort;
       
  1074 			}
       
  1075 
       
  1076 		if (state == EUsbServiceStarting)
       
  1077 			{
       
  1078 			aComplete = EFalse;
       
  1079 			iStartMessage = aMessage;
       
  1080 			iStartOutstanding = ETrue;
       
  1081 			}
       
  1082 		}
       
  1083 	else if (state == EUsbServiceStopping)
       
  1084 		{
       
  1085 		return KErrServerBusy;
       
  1086 		}
       
  1087 
       
  1088 	return KErrNone;
       
  1089 
       
  1090 #else
       
  1091 	// pretend that the server is in Started state
       
  1092 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
  1093 	iUsbServer->Host().StartL();
       
  1094 #endif
       
  1095 	iStartOutstanding = EFalse;
       
  1096 	aMessage.IsNull();
       
  1097 	aComplete = ETrue;
       
  1098 	return KErrNone;
       
  1099 #endif
       
  1100 	}
       
  1101 
       
  1102 /**
       
  1103  * Try stopping the USB device.
       
  1104  *
       
  1105  * @internalComponent
       
  1106  * @param	aMessage	Message received from the client
       
  1107  * @param	aComplete	Whether the request is complete or not
       
  1108  * @return	Any error that occurred or KErrNone
       
  1109  */
       
  1110 TInt CUsbSession::TryStopDeviceL(const RMessage2& aMessage, TBool& aComplete)
       
  1111 	{
       
  1112 	LOG_FUNC
       
  1113 
       
  1114 #ifndef __OVER_DUMMYUSBDI__
       
  1115 
       
  1116 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
  1117 	// Only 'control' session is allowed to stop USB support
       
  1118 	if ( !iSessionCtlMode )
       
  1119 		{
       
  1120 		return KErrAccessDenied;
       
  1121 		}
       
  1122 #endif
       
  1123 
       
  1124 	if (!iPersonalityCfged)
       
  1125 		{
       
  1126 		return KErrNotSupported;
       
  1127 		}
       
  1128 
       
  1129 	if (iStartOutstanding || iStopOutstanding)
       
  1130 		{
       
  1131 		return KErrServerBusy;
       
  1132 		}
       
  1133 
       
  1134 	// Obtains the curent service state
       
  1135 	TUsbServiceState state = iUsbServer->Device().ServiceState();
       
  1136 
       
  1137 	// USB Peripheral Stack Stopping sequence:
       
  1138 	// if the server is in the started state
       
  1139 	//		stop it;
       
  1140 	// if the server is in the starting state
       
  1141 	//		return KErrServerBusy immediately;
       
  1142 	// if the server is in the idle state
       
  1143 	//		return KErrNone immediately;
       
  1144 	// if the server is in the stopping state (must by another client)
       
  1145  	//			mark this request as outstanding and let the caller to wait
       
  1146 	//			for stop operation to complete;
       
  1147 	if (state == EUsbServiceStarted)
       
  1148 		{
       
  1149 		iUsbServer->Device().Stop();
       
  1150 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
  1151 		iUsbServer->Host().Stop();
       
  1152 #endif
       
  1153 
       
  1154 		aComplete = EFalse;
       
  1155 		iStopMessage = aMessage;
       
  1156 		iStopOutstanding = ETrue;
       
  1157 		}
       
  1158 	else if (state == EUsbServiceStarting)
       
  1159 		{
       
  1160 		return KErrServerBusy;
       
  1161 		}
       
  1162 	else if (state == EUsbServiceStopping)
       
  1163 		{
       
  1164 		aComplete = EFalse;
       
  1165 		iStopMessage = aMessage;
       
  1166 		iStopOutstanding = ETrue;
       
  1167 		}
       
  1168 
       
  1169 	return KErrNone;
       
  1170 
       
  1171 #else
       
  1172 	// pretend that the server is in Started state
       
  1173 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
  1174 	iUsbServer->Host().Stop();
       
  1175 #endif
       
  1176 	aMessage.IsNull();
       
  1177 	aComplete = ETrue;
       
  1178 	iStopOutstanding = EFalse;
       
  1179 	return KErrNone;
       
  1180 #endif
       
  1181 	}
       
  1182 
       
  1183 /**
       
  1184  * Cancels the interest to the outstanding request. The acutal request itself
       
  1185  * is not cancelled.
       
  1186  *
       
  1187  * @internalComponent
       
  1188  * @param	aMessage	Message received from the client
       
  1189  * @return	KErrCancel
       
  1190  */
       
  1191 TInt CUsbSession::CancelInterest(const RMessage2& aMessage)
       
  1192 	{
       
  1193 	LOG_FUNC
       
  1194 
       
  1195 	if (!iPersonalityCfged)
       
  1196 		{
       
  1197 		return KErrNotSupported;
       
  1198 		}
       
  1199 
       
  1200 	TUsbMessages toBeCancelledMsg = static_cast<TUsbMessages>(aMessage.Int0());
       
  1201 	if (toBeCancelledMsg == EUsbStart || toBeCancelledMsg == EUsbTryStart)
       
  1202 		{
       
  1203 		if (iStartOutstanding)
       
  1204 			{
       
  1205 			iStartMessage.Complete(KErrNone);
       
  1206 			iStartOutstanding = EFalse;
       
  1207 			}
       
  1208 		}
       
  1209 	else if (toBeCancelledMsg == EUsbStop || toBeCancelledMsg == EUsbTryStop)
       
  1210 		{
       
  1211 		if (iStopOutstanding)
       
  1212 			{
       
  1213 			iStopMessage.Complete(KErrNone);
       
  1214 			iStopOutstanding = EFalse;
       
  1215 			}
       
  1216 		}
       
  1217 
       
  1218 	return KErrCancel;
       
  1219 	}
       
  1220 
       
  1221 /**
       
  1222  * Gets the current personality id.
       
  1223  *
       
  1224  * @internalComponent
       
  1225  * @param	aMessage	Message received from the client
       
  1226  * @return	Any error that occurred or KErrNone
       
  1227  */
       
  1228 TInt CUsbSession::GetCurrentPersonalityId(const RMessage2& aMessage)
       
  1229 	{
       
  1230 	LOG_FUNC
       
  1231 
       
  1232 	if (!iPersonalityCfged)
       
  1233 		{
       
  1234 		return KErrNotSupported;
       
  1235 		}
       
  1236 
       
  1237 	TInt currentPersonalityId = iUsbServer->Device().CurrentPersonalityId();
       
  1238 	LOGTEXT2(_L8("\tcurrentPersonalityId = %d"), currentPersonalityId);
       
  1239 	TPckgC<TInt> pckg(currentPersonalityId);
       
  1240 	return aMessage.Write(0, pckg);
       
  1241 	}
       
  1242 
       
  1243 /**
       
  1244  * Gets supported classes.
       
  1245  *
       
  1246  * @internalComponent
       
  1247  * @param	aMessage	Message received from the client
       
  1248  * @return	KerrTooBig if supported class > KUsbMaxSupportedClasses;
       
  1249  *          KErrNotSupported if personality is not configured
       
  1250  * 			return code from RMessage2.Write()
       
  1251  */
       
  1252 TInt CUsbSession::GetSupportedClasses(const RMessage2& aMessage)
       
  1253 	{
       
  1254 	LOG_FUNC
       
  1255 
       
  1256 	if (!iPersonalityCfged)
       
  1257 		{
       
  1258 		return KErrNotSupported;
       
  1259 		}
       
  1260 
       
  1261 	// +1 for the size of actual class uid count
       
  1262 	TInt32 classUids[KUsbMaxSupportedClasses + 1];
       
  1263 	classUids[0] = 0;	// initializes class uids count to zero
       
  1264 	// Gets all class uids for the given personality
       
  1265 	const RPointerArray<CPersonality>&  personalities = iUsbServer->Device().Personalities();
       
  1266 	TInt personalityCount = personalities.Count();
       
  1267 	for (TInt i = 0; i < personalityCount; i++)
       
  1268 		{
       
  1269 		__ASSERT_ALWAYS(personalities[i] != NULL, _USB_PANIC(KUsbSvrPncCat, ENullPersonalityPointer));
       
  1270 		if (aMessage.Int0() == personalities[i]->PersonalityId())
       
  1271 			{
       
  1272 			classUids[0] = personalities[i]->SupportedClasses().Count();
       
  1273 			for (TInt j = 1; j <= classUids[0]; j++)
       
  1274 				{
       
  1275 				if (j < KUsbMaxSupportedClasses + 1)
       
  1276 					{
       
  1277 					classUids[j] = personalities[i]->SupportedClasses()[j - 1].iUid;
       
  1278 					LOGTEXT3(_L8("\tclassUids[%d] = %d"), j, classUids[j]);
       
  1279 					}
       
  1280 				else
       
  1281 					{
       
  1282 					return KErrTooBig;
       
  1283 					}
       
  1284 				}
       
  1285 			break;
       
  1286 			}
       
  1287 		}
       
  1288 
       
  1289 	if (classUids[0] == 0)
       
  1290 		{
       
  1291 		// No supported classes are found
       
  1292 		return KErrNotSupported;
       
  1293 		}
       
  1294 
       
  1295 	TInt ret;
       
  1296 	HBufC8* buf = NULL;
       
  1297 	TRAP(ret, buf = HBufC8::NewL((classUids[0] + 1)*sizeof(TInt32)));
       
  1298 	if (ret == KErrNone)
       
  1299 		{
       
  1300 		TPtr8 ptr8 = buf->Des();
       
  1301 		ptr8.Copy(reinterpret_cast<TUint8*>(classUids), (classUids[0] + 1)*sizeof(TInt32));
       
  1302 		ret = aMessage.Write(1, ptr8);
       
  1303 		}
       
  1304 
       
  1305 	delete buf;
       
  1306 	return ret;
       
  1307 	}
       
  1308 
       
  1309 /**
       
  1310  * Gets all personality ids.
       
  1311  *
       
  1312  * @internalComponent
       
  1313  * @param	aMessage	Message received from the client
       
  1314  * @return	Any error that occurred or KErrNone
       
  1315  */
       
  1316 TInt CUsbSession::GetPersonalityIds(const RMessage2& aMessage)
       
  1317 	{
       
  1318 	LOG_FUNC
       
  1319 
       
  1320 	if (!iPersonalityCfged)
       
  1321 		{
       
  1322 		return KErrNotSupported;
       
  1323 		}
       
  1324 
       
  1325 	// +1 for the size of actual personality id count
       
  1326 	TInt personalityIds[KUsbMaxSupportedPersonalities + 1];
       
  1327 
       
  1328 	const RPointerArray<CPersonality>&  personalities = iUsbServer->Device().Personalities();
       
  1329 	TInt personalityCount = personalities.Count();
       
  1330 	for (TInt i = 0; i < personalityCount; ++i)
       
  1331 		{
       
  1332 		__ASSERT_ALWAYS(personalities[i] != NULL, _USB_PANIC(KUsbSvrPncCat, ENullPersonalityPointer));
       
  1333 		personalityIds[i + 1] = personalities[i]->PersonalityId();
       
  1334 		}
       
  1335 	personalityIds[0] = personalityCount;
       
  1336 
       
  1337 	TInt ret;
       
  1338 	HBufC8* buf = NULL;
       
  1339 	TRAP(ret, buf = HBufC8::NewL((personalityCount + 1)*sizeof(TInt)));
       
  1340 	if (ret == KErrNone)
       
  1341 		{
       
  1342 		TPtr8 ptr8 = buf->Des();
       
  1343 		ptr8.Copy(reinterpret_cast<TUint8*>(personalityIds), (personalityCount + 1)*sizeof(TInt));
       
  1344 		ret = aMessage.Write(0, ptr8);
       
  1345 		}
       
  1346 
       
  1347 	delete buf;
       
  1348 	return ret;
       
  1349 	}
       
  1350 
       
  1351 /**
       
  1352  * Gets personality description
       
  1353  *
       
  1354  * @internalComponent
       
  1355  * @param	aMessage	Message received from the client
       
  1356  * @return	Any error that occurred or KErrNone
       
  1357  */
       
  1358 TInt CUsbSession::GetDescription(const RMessage2& aMessage)
       
  1359 	{
       
  1360 	LOG_FUNC
       
  1361 
       
  1362 	if (!iPersonalityCfged)
       
  1363 		{
       
  1364 		return KErrNotSupported;
       
  1365 		}
       
  1366 
       
  1367 	TInt personalityId = aMessage.Int0();
       
  1368 	const CPersonality* personality = iUsbServer->Device().GetPersonality(personalityId);
       
  1369 	if (personality)
       
  1370 		{
       
  1371 		return aMessage.Write(1, *(personality->Description()));
       
  1372 		}
       
  1373 
       
  1374 	// We should never reach here
       
  1375 	return KErrNotSupported;
       
  1376 	}
       
  1377 
       
  1378 /**
       
  1379  * Gets personality detailed description
       
  1380  *
       
  1381  * @internalComponent
       
  1382  * @param   aMessage    Message received from the client
       
  1383  * @return  Any error that occurred or KErrNone
       
  1384  */
       
  1385 TInt CUsbSession::GetDetailedDescription(const RMessage2& aMessage)
       
  1386 	{
       
  1387 	LOG_FUNC
       
  1388 
       
  1389  	if (!iPersonalityCfged)
       
  1390 		{
       
  1391 		return KErrNotSupported;
       
  1392 		}
       
  1393 
       
  1394 	TInt personalityId = aMessage.Int0();
       
  1395 	const CPersonality* personality = iUsbServer->Device().GetPersonality(personalityId);
       
  1396     	if (personality)
       
  1397         	{
       
  1398         	if(personality->Version() < EUsbManagerResourceVersionTwo)
       
  1399             		{
       
  1400             		return KErrNotFound;
       
  1401             		}
       
  1402 		return aMessage.Write(1, *(personality->DetailedDescription()));
       
  1403 		}
       
  1404 
       
  1405 	// We should never reach here
       
  1406 	return KErrNotSupported;
       
  1407 	}
       
  1408 
       
  1409 /**
       
  1410  * Gets personality property
       
  1411  *
       
  1412  * @internalComponent
       
  1413  * @param   aMessage    Message received from the client
       
  1414  * @return  Any error that occurred or KErrNone
       
  1415  */
       
  1416 TInt CUsbSession::GetPersonalityProperty(const RMessage2& aMessage)
       
  1417 	{
       
  1418 		LOG_FUNC
       
  1419 
       
  1420 		if (!iPersonalityCfged)
       
  1421 			{
       
  1422 			return KErrNotSupported;
       
  1423 			}
       
  1424 
       
  1425 		TInt personalityId = aMessage.Int0();
       
  1426 		const CPersonality* personality = iUsbServer->Device().GetPersonality(personalityId);
       
  1427 		if (personality)
       
  1428 			{
       
  1429 			if(personality->Version() < EUsbManagerResourceVersionThree)
       
  1430 				{
       
  1431 				return KErrNotFound;
       
  1432 				}
       
  1433 			TPckg<TUint32> pckg(personality->Property());
       
  1434 			return aMessage.Write(1, pckg);
       
  1435 			}
       
  1436 
       
  1437 		return KErrNotSupported;
       
  1438 	}
       
  1439 
       
  1440 /**
       
  1441  * Checks if a given class is supported by a personality.
       
  1442  *
       
  1443  * @internalComponent
       
  1444  * @param	aMessage	Message received from the client
       
  1445  * @return	Any error that occurred or KErrNone
       
  1446  */
       
  1447 TInt CUsbSession::ClassSupported(const RMessage2& aMessage)
       
  1448 	{
       
  1449 	LOG_FUNC
       
  1450 
       
  1451 	if (!iPersonalityCfged)
       
  1452 		{
       
  1453 		return KErrNotSupported;
       
  1454 		}
       
  1455 
       
  1456 	TBool isSupported = EFalse;
       
  1457 	TInt personalityId = aMessage.Int0();
       
  1458 	TUid classUid = TUid::Uid(aMessage.Int1());
       
  1459 	const CPersonality* personality = iUsbServer->Device().GetPersonality(personalityId);
       
  1460 	if (personality)
       
  1461 		{
       
  1462 		isSupported = (personality->ClassSupported(classUid) != KErrNotFound);
       
  1463 		TPckg<TBool> pkg2(isSupported);
       
  1464 		return aMessage.Write(2, pkg2);
       
  1465 		}
       
  1466 
       
  1467 	// We should never reach here
       
  1468 	return KErrNotSupported;
       
  1469 	}
       
  1470 
       
  1471 #ifdef SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
  1472 /**
       
  1473  * Sets or resets the control mode flag for this session.
       
  1474  *
       
  1475  * @internalComponent
       
  1476  * @param	aMessage	Message received from the client
       
  1477  * @return	Any error that occurred or KErrNone
       
  1478  */
       
  1479 TInt CUsbSession::SetCtlSessionMode(const RMessage2& aMessage)
       
  1480 	{
       
  1481 	LOG_FUNC
       
  1482 
       
  1483 	TInt ret = KErrNone;
       
  1484 
       
  1485 	TBool value = (TBool)aMessage.Int0();
       
  1486 	LOGTEXT2(_L8("\tSetting = %d"), static_cast<TInt>(value));
       
  1487 
       
  1488 	// Verify if this is the same session which set the value before
       
  1489 	if ( iCtlSession && (iCtlSession != this) )
       
  1490 		{
       
  1491 		ret = KErrAccessDenied;
       
  1492 		}
       
  1493 	else
       
  1494 		{
       
  1495 		iSessionCtlMode = value;
       
  1496 
       
  1497 		// Set control session pointer if the flag is set
       
  1498 		if ( iSessionCtlMode )
       
  1499 			{
       
  1500 			iCtlSession = this;
       
  1501 			}
       
  1502 		else
       
  1503 			{
       
  1504 			iCtlSession = NULL;
       
  1505 			}
       
  1506 		}
       
  1507 
       
  1508 	return ret;
       
  1509 	}
       
  1510 
       
  1511 /**
       
  1512  * Asserts a request to drive VBus.
       
  1513  *
       
  1514  * @internalComponent
       
  1515  * @return	If control mode flag is not set returns KErrAccessDenied
       
  1516  * 			An error code for all other cases
       
  1517  */
       
  1518 TInt CUsbSession::BusRequest()
       
  1519 	{
       
  1520 	LOG_FUNC
       
  1521 
       
  1522 	TInt ret = KErrNone;
       
  1523 	if ( iSessionCtlMode )
       
  1524 		{
       
  1525 		ret = iUsbServer->Otg().BusRequest();
       
  1526 		}
       
  1527 	else
       
  1528 		{
       
  1529 		ret = KErrAccessDenied;
       
  1530 		}
       
  1531 
       
  1532 	return ret;
       
  1533 	}
       
  1534 
       
  1535 /**
       
  1536  * Asserts a request to raise VBUS but assumes this is after B-Device
       
  1537  * has used SRP to make a request to become session Host, so may be able
       
  1538  * to take some short cuts when enumerating the B-Device.
       
  1539  *
       
  1540  * @internalComponent
       
  1541  * @return	If control mode flag is not set returns KErrAccessDenied
       
  1542  * 			Any error that occurred or KErrNone for all other cases
       
  1543  */
       
  1544 TInt CUsbSession::BusRespondSrp()
       
  1545 	{
       
  1546 	LOG_FUNC
       
  1547 
       
  1548 	TInt ret = KErrNone;
       
  1549 	if ( iSessionCtlMode )
       
  1550 		{
       
  1551 		ret = iUsbServer->Otg().BusRespondSrp();
       
  1552 		}
       
  1553 	else
       
  1554 		{
       
  1555 		ret = KErrAccessDenied;
       
  1556 		}
       
  1557 
       
  1558 	return ret;
       
  1559 	}
       
  1560 
       
  1561 /**
       
  1562  * Clears a possible VBUS error condition (VBUS inexplicably low after
       
  1563  * having been driven)
       
  1564  *
       
  1565  * @internalComponent
       
  1566  * @return	If control mode flag is not set returns KErrAccessDenied
       
  1567  * 			Any error that occurred or KErrNone for all other cases
       
  1568  */
       
  1569 TInt CUsbSession::BusClearError()
       
  1570 	{
       
  1571 	LOG_FUNC
       
  1572 
       
  1573 	TInt ret = KErrNone;
       
  1574 	if ( iSessionCtlMode )
       
  1575 		{
       
  1576 		ret = iUsbServer->Otg().BusClearError();
       
  1577 		}
       
  1578 	else
       
  1579 		{
       
  1580 		ret = KErrAccessDenied;
       
  1581 		}
       
  1582 
       
  1583 	return ret;
       
  1584 	}
       
  1585 
       
  1586 /**
       
  1587  * Drops VBus.
       
  1588  *
       
  1589  * @internalComponent
       
  1590  * @return	If control mode flag is not set returns KErrAccessDenied
       
  1591  * 			Any error that occurred or KErrNone for all other cases
       
  1592  */
       
  1593 TInt CUsbSession::BusDrop()
       
  1594 	{
       
  1595 	LOG_FUNC
       
  1596 
       
  1597 	TInt ret = KErrNone;
       
  1598 	if ( iSessionCtlMode )
       
  1599 		{
       
  1600 		ret = iUsbServer->Otg().BusDrop();
       
  1601 		}
       
  1602 	else
       
  1603 		{
       
  1604 		ret = KErrAccessDenied;
       
  1605 		}
       
  1606 
       
  1607 	return ret;
       
  1608 	}
       
  1609 
       
  1610 /**
       
  1611  * Enables loading of Function Drivers.
       
  1612  *
       
  1613  * @internalComponent
       
  1614  * @return	If control mode flag is not set returns KErrAccessDenied
       
  1615  * 			Any error that occurred or KErrNone for all other cases
       
  1616  */
       
  1617 TInt CUsbSession::EnableFunctionDriverLoading()
       
  1618 	{
       
  1619 	LOG_FUNC
       
  1620 
       
  1621 	TInt ret = KErrNone;
       
  1622 	if ( iSessionCtlMode )
       
  1623 		{
       
  1624 		ret = iUsbServer->Host().EnableDriverLoading();
       
  1625 		}
       
  1626 	else
       
  1627 		{
       
  1628 		ret = KErrAccessDenied;
       
  1629 		}
       
  1630 
       
  1631 	return ret;
       
  1632 	}
       
  1633 
       
  1634 /**
       
  1635  * Disables loading of Function Drivers.
       
  1636  *
       
  1637  * @internalComponent
       
  1638  * @return	If control mode flag is not set returns KErrAccessDenied
       
  1639  * 			KErrNone for all other cases
       
  1640  */
       
  1641 TInt CUsbSession::DisableFunctionDriverLoading()
       
  1642 	{
       
  1643 	LOG_FUNC
       
  1644 
       
  1645 	TInt ret = KErrNone;
       
  1646 	if ( iSessionCtlMode )
       
  1647 		{
       
  1648 		iUsbServer->Host().DisableDriverLoading();
       
  1649 		}
       
  1650 	else
       
  1651 		{
       
  1652 		ret = KErrAccessDenied;
       
  1653 		}
       
  1654 
       
  1655 	return ret;
       
  1656 	}
       
  1657 
       
  1658 /**
       
  1659  * Requests an array of language identifiers supported by connected device.
       
  1660  *
       
  1661  * @internalComponent
       
  1662  * @param	aMessage	Message received from the client
       
  1663  * @return	Any error that occurred or KErrNone
       
  1664  */
       
  1665 TInt CUsbSession::GetSupportedLanguages(const RMessage2& aMessage)
       
  1666 	{
       
  1667 	LOG_FUNC
       
  1668 	TRAPD(err, GetSupportedLanguagesL(aMessage));
       
  1669 	return err;
       
  1670 	}
       
  1671 
       
  1672 /**
       
  1673  * Requests an array of language identifiers supported by connected device.
       
  1674  *
       
  1675  * @internalComponent
       
  1676  * @param	aMessage	Message received from the client
       
  1677  * @return	Any error that occurred or KErrNone
       
  1678  */
       
  1679 TInt CUsbSession::GetSupportedLanguagesL(const RMessage2& aMessage)
       
  1680 	{
       
  1681 	LOG_FUNC
       
  1682 
       
  1683 
       
  1684 	const TUint deviceId = aMessage.Int0();
       
  1685 	LOGTEXT2(_L8("\tdeviceId = %d"), deviceId);
       
  1686 
       
  1687 	RArray<TUint> langIds;
       
  1688 	CleanupClosePushL(langIds);
       
  1689 	TInt ret = iUsbServer->Host().GetSupportedLanguages(deviceId,langIds);
       
  1690 
       
  1691 	if (ret == KErrNone)
       
  1692 		{
       
  1693 		const TUint count = langIds.Count();
       
  1694 		LOGTEXT2(_L8("\tcount = %d"), count);
       
  1695 
       
  1696 		// Set error code if there is no languages or there are too many
       
  1697 		if ( count == 0 )
       
  1698 			{
       
  1699 			ret = KErrNotSupported;
       
  1700 			}
       
  1701 		else if ( count > KUsbMaxSupportedLanguageIds )
       
  1702 			{
       
  1703 			ret = KErrTooBig;
       
  1704 			}
       
  1705 
       
  1706 		if ( ret == KErrNone )
       
  1707 			{
       
  1708 			// Create a buffer to keep an array size and all received language Ids
       
  1709 			RBuf8 buf;
       
  1710 			buf.CreateL((count + 1) * sizeof(TUint));
       
  1711 			CleanupClosePushL(buf);
       
  1712 
       
  1713 			// Save the length of the array
       
  1714 			buf.Append((TUint8*)&count, sizeof(TUint));
       
  1715 
       
  1716 			// Save all received language Ids
       
  1717 			for ( TUint ii = 0 ; ii < count; ++ii )
       
  1718 				{
       
  1719 				buf.Append((TUint8*)&(langIds[ii]), sizeof(TUint));
       
  1720 				LOGTEXT3(_L8("Append langID[%d] = %d"),ii,langIds[ii]);
       
  1721 				}
       
  1722 
       
  1723 			// Write back to the client.
       
  1724 			ret = aMessage.Write(1, buf);
       
  1725 			CleanupStack::PopAndDestroy(&buf);
       
  1726 			}
       
  1727 		}
       
  1728 
       
  1729 	CleanupStack::PopAndDestroy();
       
  1730 
       
  1731 	return ret;
       
  1732 	}
       
  1733 
       
  1734 /**
       
  1735  * Requests a manufacturer string descriptor of connected device.
       
  1736  *
       
  1737  * @internalComponent
       
  1738  * @param	aMessage	Message received from the client
       
  1739  * @return	Any error that occurred or KErrNone
       
  1740  */
       
  1741 TInt CUsbSession::GetManufacturerStringDescriptor(const RMessage2& aMessage)
       
  1742 	{
       
  1743 	LOG_FUNC
       
  1744 
       
  1745 	const TUint deviceId = aMessage.Int0();
       
  1746 	const TUint langId = aMessage.Int1();
       
  1747 	LOGTEXT3(_L8("\tdeviceId = %d, langId = %d"), deviceId, langId);
       
  1748 
       
  1749 	TName string;
       
  1750 	TInt ret = iUsbServer->Host().GetManufacturerStringDescriptor(deviceId,langId,string);
       
  1751 	if (ret == KErrNone)
       
  1752 		{
       
  1753 		LOGTEXT2(_L("\tstring = \"%S\""), &string);
       
  1754 		ret = aMessage.Write(2, string);
       
  1755 		}
       
  1756 
       
  1757 	return ret;
       
  1758 	}
       
  1759 
       
  1760 /**
       
  1761  * Requests a product string descriptor of connected device.
       
  1762  *
       
  1763  * @internalComponent
       
  1764  * @param	aMessage	Message received from the client
       
  1765  * @return	Any error that occurred or KErrNone
       
  1766  */
       
  1767 TInt CUsbSession::GetProductStringDescriptor(const RMessage2& aMessage)
       
  1768 	{
       
  1769 	LOG_FUNC
       
  1770 
       
  1771 	const TUint deviceId = aMessage.Int0();
       
  1772 	const TUint langId = aMessage.Int1();
       
  1773 	LOGTEXT3(_L8("\tdeviceId = %d, langId = %d"), deviceId, langId);
       
  1774 
       
  1775 	TName string;
       
  1776 	TInt ret = iUsbServer->Host().GetProductStringDescriptor(deviceId,langId,string);
       
  1777 	if (ret == KErrNone)
       
  1778 		{
       
  1779 		LOGTEXT2(_L("\tstring = \"%S\""), &string);
       
  1780 		ret = aMessage.Write(2, string);
       
  1781 		}
       
  1782 
       
  1783 	return ret;
       
  1784 	}
       
  1785 
       
  1786 /**
       
  1787  * Requests a OTG descriptor of connected device.
       
  1788  *
       
  1789  * @internalComponent
       
  1790  * @param	aMessage	Message received from the client
       
  1791  * @return	Any error that occurred or KErrNone
       
  1792  */
       
  1793 TInt CUsbSession::GetOtgDescriptor(const RMessage2& aMessage)
       
  1794 	{
       
  1795 	LOG_FUNC
       
  1796 
       
  1797 	const TUint deviceId = aMessage.Int0();
       
  1798 	LOGTEXT2(_L8("\tdeviceId = %d"), deviceId);
       
  1799 
       
  1800     TOtgDescriptor otgDescriptor;
       
  1801 	TInt ret = iUsbServer->Host().GetOtgDescriptor(deviceId, otgDescriptor);
       
  1802 	if (ret == KErrNone)
       
  1803 		{
       
  1804 		TPckg<TOtgDescriptor> buf(otgDescriptor);
       
  1805 		ret = aMessage.Write(1, buf);
       
  1806 		}
       
  1807 
       
  1808 	return ret;
       
  1809 	}
       
  1810 
       
  1811 /**
       
  1812  * Client request to observe the host (for state changes).
       
  1813  * Asks the host to register the session as an observer.
       
  1814  * Assures initialisation/dequeueing of Event queue.
       
  1815  * No events are queued until the first observer is registered
       
  1816  *
       
  1817  * @internalComponent
       
  1818  * @param	aMessage	Message received from the client
       
  1819  * @param	aComplete	set to true to complete the request
       
  1820  *
       
  1821  * @return	Any error that occurred or KErrNone
       
  1822  */
       
  1823 TInt CUsbSession::RegisterHostObserver(const RMessage2& aMessage, TBool& aComplete)
       
  1824 	{
       
  1825 	LOG_FUNC
       
  1826 
       
  1827 	if (iHostEventObserverOutstanding)
       
  1828 		{
       
  1829 		return KErrInUse;
       
  1830 		}
       
  1831 
       
  1832 	iHostEventObserverMessage = aMessage;
       
  1833 	iHostEventObserverOutstanding = ETrue;
       
  1834 	aComplete = EFalse;
       
  1835 
       
  1836  	if (iHostEventObserverQueueEvents == EFalse)
       
  1837 	 	{
       
  1838  		// This is the first observer after c'tor or DeregisterObserver(),
       
  1839  		// so zap the device event queue.
       
  1840  		LOGTEXT(_L8("    Reset OTG Host State Queue"));
       
  1841  		iHostEventQueueHead = 0;
       
  1842  		iHostEventQueueTail = 0;
       
  1843  		iHostEventObserverQueueEvents = ETrue;
       
  1844 	 	}
       
  1845  	else if (iHostEventQueueHead != iHostEventQueueTail)
       
  1846 	 	{
       
  1847  		// event(s) queued, we can de-queue one now
       
  1848  		UsbHostEventDequeue();
       
  1849 	 	}
       
  1850 
       
  1851 	return KErrNone;
       
  1852 	}
       
  1853 
       
  1854 /**
       
  1855  * Deregister the client as an observer of host state changes.
       
  1856  *
       
  1857  * @internalComponent
       
  1858  * @return Always KErrNone
       
  1859  */
       
  1860 TInt CUsbSession::DeRegisterHostObserver()
       
  1861 	{
       
  1862 	LOG_FUNC
       
  1863 
       
  1864 
       
  1865 	if (!iHostEventObserverOutstanding)
       
  1866 		{
       
  1867 		return KErrNone;
       
  1868 		}
       
  1869 
       
  1870 	iHostEventObserverOutstanding = EFalse;
       
  1871 	iHostEventObserverMessage.Complete(KErrCancel);
       
  1872 
       
  1873 	// client doesn't need events queuing any more
       
  1874  	iHostEventObserverQueueEvents = EFalse;
       
  1875 
       
  1876 	return KErrNone;
       
  1877 	}
       
  1878 
       
  1879 /**
       
  1880  * Client request to observe both OTG and HOST (for events and errors).
       
  1881  * Asks HOST and OTGDI components to register the session as an observer.
       
  1882  * Assures initialisation/dequeueing of Event queue.
       
  1883  * No events are queued until the first observer is registered
       
  1884  *
       
  1885  * @internalComponent
       
  1886  * @param	aMessage	Message received from the client
       
  1887  * @param	aComplete	set to true to complete the request
       
  1888  *
       
  1889  * @return	Any error that occurred or KErrNone
       
  1890  */
       
  1891 TInt CUsbSession::RegisterMsgObserver(const RMessage2& aMessage, TBool& aComplete)
       
  1892 	{
       
  1893 	LOG_FUNC
       
  1894 
       
  1895 	if (iMsgObserverOutstanding)
       
  1896 		{
       
  1897 		return KErrInUse;
       
  1898 		}
       
  1899 
       
  1900 	iMsgObserverMessage = aMessage;
       
  1901 	iMsgObserverOutstanding = ETrue;
       
  1902 	aComplete = EFalse;
       
  1903 
       
  1904  	if (iMsgObserverQueueEvents == EFalse)
       
  1905 	 	{
       
  1906  		// This is the first observer after c'tor or DeregisterObserver(),
       
  1907  		// so zap the device event queue.
       
  1908  		LOGTEXT(_L8("    Reset OTG Message Queue"));
       
  1909  		iMsgQueueHead = 0;
       
  1910  		iMsgQueueTail = 0;
       
  1911  		iMsgObserverQueueEvents = ETrue;
       
  1912 	 	}
       
  1913  	else if (iMsgQueueHead != iMsgQueueTail)
       
  1914 	 	{
       
  1915  		// event(s) queued, we can de-queue one now
       
  1916  		UsbMsgDequeue();
       
  1917 	 	}
       
  1918 
       
  1919 	return KErrNone;
       
  1920 	}
       
  1921 
       
  1922 /**
       
  1923  * Deregister the client as an observer of OTG/HOST events and errors.
       
  1924  *
       
  1925  * @internalComponent
       
  1926  * @return Always KErrNone
       
  1927  */
       
  1928 TInt CUsbSession::DeRegisterMsgObserver()
       
  1929 	{
       
  1930 	LOG_FUNC
       
  1931 
       
  1932 	if (!iMsgObserverOutstanding)
       
  1933 		{
       
  1934 		return KErrNone;
       
  1935 		}
       
  1936 
       
  1937 	iMsgObserverOutstanding = EFalse;
       
  1938 	iMsgObserverMessage.Complete(KErrCancel);
       
  1939 
       
  1940 	// client doesn't need events queuing any more
       
  1941  	iMsgObserverQueueEvents = EFalse;
       
  1942 
       
  1943 	return KErrNone;
       
  1944 	}
       
  1945 
       
  1946 
       
  1947 
       
  1948 /**
       
  1949  * Called by CUsbOtg or CUsbHost when the USB OTG/HOST message has arrived
       
  1950  *
       
  1951  * @internalComponent
       
  1952  * @param aMessage The new OTG Message
       
  1953  */
       
  1954 void CUsbSession::UsbOtgHostMessage(TInt aMessage)
       
  1955 	{
       
  1956 	LOG_FUNC
       
  1957 
       
  1958 	// can we bypass the queue?
       
  1959  	if ((iMsgObserverOutstanding) && (iMsgQueueHead == iMsgQueueTail))
       
  1960 		{
       
  1961 		TPckg<TInt> pckg(aMessage);
       
  1962 
       
  1963 		iNotifiedMsg = aMessage;
       
  1964 
       
  1965 		iMsgObserverOutstanding = EFalse;
       
  1966 		const TInt err = iMsgObserverMessage.Write(0, pckg);
       
  1967 		iMsgObserverMessage.Complete(err);
       
  1968 		}
       
  1969 	else if (iMsgObserverQueueEvents)
       
  1970 		{
       
  1971 		// add event to head of queue
       
  1972 		iMsgQueue[iMsgQueueHead] = aMessage;
       
  1973 		iMsgQueueHead = (iMsgQueueHead + 1) % KOtgHostMessageQueueSize;
       
  1974 		LOGTEXT3(_L8("+++ CUsbSession::UsbOtgMessage() addqueue (%d, %d)"), iMsgQueueHead,
       
  1975 			iMsgQueueTail);
       
  1976 
       
  1977  		// UsbMsgDequeueEvent() will read from queue when RegisterMsgObserver()
       
  1978 		// is next called.
       
  1979 		}
       
  1980 	}
       
  1981 
       
  1982 /**
       
  1983  * Called by CUsbHost when it state change. CUsbSession is an observer of
       
  1984  * the device. If the client has an Observer outstanding then complete it,
       
  1985  * otherwise put it in a circular queue.
       
  1986  *
       
  1987  * @internalComponent
       
  1988  * @param	aDevInfo	The information about the device being attached or detached
       
  1989  * 						along with the status of Function Driver loading
       
  1990  */
       
  1991 void CUsbSession::UsbHostEvent(TDeviceEventInformation& aDevInfo)
       
  1992 	{
       
  1993 	LOG_FUNC
       
  1994 
       
  1995 	// can we bypass the queue?
       
  1996  	if ((iHostEventObserverOutstanding) && (iHostEventQueueHead == iHostEventQueueTail))
       
  1997 		{
       
  1998 		iNotifiedHostState = aDevInfo;
       
  1999 		iHostEventObserverOutstanding = EFalse;
       
  2000 
       
  2001 		LOGTEXT(_L8("CUsbSession::UsbHostEvent() detected outstanding request"));
       
  2002 
       
  2003 		TPckg<TDeviceEventInformation> info(aDevInfo);
       
  2004 		const TInt err = iHostEventObserverMessage.Write(0, info);
       
  2005 		iHostEventObserverMessage.Complete(err);
       
  2006 		LOGTEXT2(_L8("CUsbSession::UsbHostEvent() detects outstanding request: request is compeleted with %d"), err);
       
  2007 		}
       
  2008 	else if (iHostEventObserverQueueEvents)
       
  2009 		{
       
  2010 		// add dev info to head of queue
       
  2011 		iHostStateQueue[iHostEventQueueHead] = aDevInfo;
       
  2012 		iHostEventQueueHead = (iHostEventQueueHead + 1) % KDeviceStatesQueueSize;
       
  2013 		LOGTEXT3(_L8("+++ CUsbSession::UsbHostEvent() addqueue (%d, %d)"), iHostEventQueueHead,
       
  2014 			iHostEventQueueTail);
       
  2015 
       
  2016  		// UsbHostStateDequeueEvent() will read from queue when RegisterHostObserver()
       
  2017 		// is next called.
       
  2018 		}
       
  2019 	}
       
  2020 
       
  2021 /**
       
  2022  * Dequeues an event and completes the observer's request with it.
       
  2023  */
       
  2024 void CUsbSession::UsbMsgDequeue()
       
  2025  	{
       
  2026 	LOG_FUNC
       
  2027 
       
  2028 	// Work our way through the queue, until we reach the end
       
  2029  	// OR we find an event the current observer wants.
       
  2030  	if ((iMsgObserverOutstanding) && (iMsgQueueHead != iMsgQueueTail))
       
  2031  		{
       
  2032  		TInt newMsg = iMsgQueue[iMsgQueueTail];
       
  2033 
       
  2034  		// advance tail towards the head
       
  2035  		iMsgQueueTail = (iMsgQueueTail + 1) % KOtgHostMessageQueueSize;
       
  2036 
       
  2037  		TPckg<TUint32> pckg(newMsg);
       
  2038  		iNotifiedMsg = newMsg;
       
  2039 
       
  2040  		LOGTEXT3(_L8(">>> dequeued event #%d (0x%x)"), iMsgQueueTail, newMsg);
       
  2041 
       
  2042 		iMsgObserverOutstanding = EFalse;
       
  2043 		const TInt err = iMsgObserverMessage.Write(0, pckg);
       
  2044 		iMsgObserverMessage.Complete(err);
       
  2045    		}
       
  2046   	}
       
  2047 
       
  2048 /**
       
  2049  * Dequeues an event and completes the observer's request with it.
       
  2050  */
       
  2051 void CUsbSession::UsbHostEventDequeue()
       
  2052  	{
       
  2053 	LOG_FUNC
       
  2054 
       
  2055 	// Work our way through the queue, until we reach the end
       
  2056  	// OR we find an event the current observer wants.
       
  2057  	if ((iHostEventObserverOutstanding) && (iHostEventQueueHead != iHostEventQueueTail))
       
  2058  		{
       
  2059  		// inform the observer of state changes they are interested in AND
       
  2060  		// if the cable is pulled out (EUsbDeviceStateUndefined)
       
  2061  		TDeviceEventInformation newDevInfo = iHostStateQueue[iHostEventQueueTail];
       
  2062 		iNotifiedHostState = newDevInfo;
       
  2063 
       
  2064  		// advance tail towards the head
       
  2065  		iHostEventQueueTail = (iHostEventQueueTail + 1) % KDeviceStatesQueueSize;
       
  2066 
       
  2067 		LOGTEXT3(_L8(">>> CUsbSession::UsbHostStateDequeueEvent() dequeued event #%d (0x%x)"), iHostEventQueueTail, newDevInfo.iEventType);
       
  2068 
       
  2069 		TPckg<TDeviceEventInformation> info(newDevInfo);
       
  2070 		iHostEventObserverOutstanding = EFalse;
       
  2071 		const TInt err = iHostEventObserverMessage.Write(0, info);
       
  2072 		iHostEventObserverMessage.Complete(err);
       
  2073 
       
  2074 		LOGTEXT2(_L8("CUsbSession::UsbHostStateDequeueEvent() detects outstanding request: request is compeleted with %d"), err);
       
  2075    		}
       
  2076    	}
       
  2077 
       
  2078 TInt CUsbSession::RequestSession()
       
  2079 	{
       
  2080 	return DoRequestSession();
       
  2081 	}
       
  2082 
       
  2083 TInt CUsbSession::DoRequestSession()
       
  2084 	{
       
  2085 	if ( iCtlSession )
       
  2086 		{
       
  2087 		if ( iCtlSession == this )
       
  2088 			{
       
  2089 	 		if (iMsgObserverQueueEvents)
       
  2090 	 			{
       
  2091 	 			UsbOtgHostMessage(KUsbMessageRequestSession);
       
  2092 	 			return KErrNone;
       
  2093 	 			}
       
  2094 		 	else
       
  2095 		 		{
       
  2096 		 		return KErrNotFound;
       
  2097 		 		}
       
  2098 			}
       
  2099 		else
       
  2100 			{
       
  2101 			return iCtlSession->DoRequestSession();
       
  2102 			}
       
  2103 		}
       
  2104  	return KErrNotFound;
       
  2105 	}
       
  2106 
       
  2107 #endif // SYMBIAN_ENABLE_USB_OTG_HOST_PRIV
       
  2108