accessoryservices/remotecontrolfw/client/inner/src/session.cpp
changeset 0 4e1aa6a622a0
child 70 653a8b91b95e
equal deleted inserted replaced
-1:000000000000 0:4e1aa6a622a0
       
     1 // Copyright (c) 2004-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 #include <bluetooth/logger.h>
       
    22 #include <e32base.h>
       
    23 #include "remconserver.h"
       
    24 #include <remconaddress.h>
       
    25 #include "remconclient.h"
       
    26 
       
    27 #ifdef __FLOG_ACTIVE
       
    28 _LIT8(KLogComponent, LOG_COMPONENT_REMCON_INNER);
       
    29 #endif
       
    30 
       
    31 /** 
       
    32 Starts the server process.
       
    33 */
       
    34 static TInt StartServer()
       
    35 	{
       
    36 	LOG_STATIC_FUNC
       
    37 	const TUidType serverUid(KNullUid, KNullUid, KRemConSrvUid);
       
    38 
       
    39 	//
       
    40 	// EPOC and EKA2 is easy, we just create a new server process. Simultaneous
       
    41 	// launching of two such processes should be detected when the second one
       
    42 	// attempts to create the server object, failing with KErrAlreadyExists.
       
    43 	//
       
    44 	RProcess server;
       
    45 	TInt err = server.Create(KRemConServerImg, KNullDesC, serverUid);
       
    46 	
       
    47 	if ( err != KErrNone )
       
    48 		{
       
    49 		return err;
       
    50 		}
       
    51 
       
    52 	TRequestStatus stat;
       
    53 	server.Rendezvous(stat);
       
    54 	
       
    55 	if ( stat != KRequestPending )
       
    56 		{
       
    57 		server.Kill(0); 	// abort startup
       
    58 		}
       
    59 	else
       
    60 		{
       
    61 		server.Resume();	// logon OK - start the server
       
    62 		}
       
    63 
       
    64 	User::WaitForRequest(stat); 	// wait for start or death
       
    65 
       
    66 	// we can't use the 'exit reason' if the server panicked as this
       
    67 	// is the panic 'reason' and may be '0' which cannot be distinguished
       
    68 	// from KErrNone
       
    69 	err = (server.ExitType() == EExitPanic) ? KErrServerTerminated : stat.Int();
       
    70 
       
    71 	server.Close();
       
    72 
       
    73 	return err;
       
    74 	}
       
    75 
       
    76 RRemCon::RRemCon(TRemConClientType aClientType) 
       
    77 :	iClientType(aClientType),
       
    78 	iNumRemotesPckg(0),
       
    79 	iReceivePckg(TRemConClientReceivePackage())
       
    80 	{
       
    81 	LOG_FUNC
       
    82 	}
       
    83 
       
    84 EXPORT_C TVersion RRemCon::Version() const
       
    85 	{
       
    86 	LOG_FUNC
       
    87 	return(TVersion(	KRemConSrvMajorVersionNumber,
       
    88 						KRemConSrvMinorVersionNumber,
       
    89 						KRemConSrvBuildNumber
       
    90 					)
       
    91 			);
       
    92 	}
       
    93 
       
    94 EXPORT_C TInt RRemCon::Connect()
       
    95 	{
       
    96 	LOG_FUNC
       
    97 
       
    98 	TInt err = DoConnect();
       
    99 	if ( err == KErrNone )
       
   100 		{
       
   101 		err = SetClientType();
       
   102 		if ( err != KErrNone )
       
   103 			{
       
   104 			// For this API to be clean, we must clean up the session handle 
       
   105 			// already successfully created.
       
   106 			Close();
       
   107 			}
       
   108 		}
       
   109 	return err;
       
   110 	}
       
   111 
       
   112 EXPORT_C TInt RRemCon::Connect(const TPlayerType& aClientType, const TPlayerSubType& aClientSubType, const TDesC8& aName)
       
   113 	{
       
   114 	LOG_FUNC
       
   115 
       
   116 	TInt err = DoConnect();
       
   117 	if ( err == KErrNone )	
       
   118 		{
       
   119 		err = SetClientType(aClientType,aClientSubType,aName);
       
   120 		if ( err != KErrNone )
       
   121 			{
       
   122 			// For this API to be clean, we must clean up the session handle 
       
   123 			// already successfully created.
       
   124 			Close();
       
   125 			}
       
   126 		}
       
   127 	return err;
       
   128 	}
       
   129 /**
       
   130 Connects the session, starting the server if necessary. This involves two IPC 
       
   131 calls, the first to connect the session to the server, the second to set the 
       
   132 server-side session's type correctly (controller or target).
       
   133 @return Error.
       
   134 */
       
   135 TInt RRemCon::DoConnect()
       
   136 	{
       
   137 	LOG_FUNC
       
   138 	TInt retry = 2;
       
   139 	
       
   140 	FOREVER
       
   141 		{
       
   142 		// 4 is the number of asynchronous APIs which may be outstanding 
       
   143 		// simultaneously.
       
   144 		TInt err = CreateSession(KRemConServerName, Version(), 4);
       
   145 
       
   146 		if ((err != KErrNotFound) && (err != KErrServerTerminated))
       
   147 			{
       
   148 			return err;
       
   149 			}
       
   150 
       
   151 		if (--retry == 0)
       
   152 			{
       
   153 			return err;
       
   154 			}
       
   155 
       
   156 		err = StartServer();
       
   157 
       
   158 		if ((err != KErrNone) && (err != KErrAlreadyExists))
       
   159 			{
       
   160 			return err;
       
   161 			}
       
   162 		}
       
   163 	}
       
   164 
       
   165 /**
       
   166 Does IPC with the server to set the type of the session from our member (set 
       
   167 at construction time).
       
   168 @return Error.
       
   169 */
       
   170 TInt RRemCon::SetClientType()
       
   171 	{
       
   172 	LOG_FUNC
       
   173 	return SendReceive(ERemConSetClientType, TIpcArgs(iClientType));
       
   174 	}
       
   175 
       
   176 TInt RRemCon::SetClientType(const TPlayerType& aClientType, const TPlayerSubType& aClientSubType, const TDesC8& aName)
       
   177 	{
       
   178 	LOG_FUNC
       
   179 	TIpcArgs args;
       
   180 	args.Set(0,iClientType);
       
   181 	iPlayerTypePckg().iPlayerType = aClientType;
       
   182 	iPlayerTypePckg().iPlayerSubType = aClientSubType;
       
   183 	args.Set(1,&iPlayerTypePckg);
       
   184 	args.Set(2,aName.Length());
       
   185 	args.Set(3, &aName);
       
   186 	return SendReceive(ERemConSetClientType, args);
       
   187 	}
       
   188 
       
   189 EXPORT_C TInt RRemCon::SendUnreliable(TUid aInterfaceUid, 
       
   190 		TUint aOperationId, 
       
   191 		TRemConMessageSubType aSubType,
       
   192 		const TDesC8& aData)
       
   193 	{
       
   194 	LOG_FUNC
       
   195 	TIpcArgs args;
       
   196 	iOpInfoPckg().iOperationId = aOperationId;
       
   197 	iOpInfoPckg().iMessageSubType = aSubType;
       
   198 	
       
   199 	args.Set(0, aInterfaceUid.iUid);
       
   200 	args.Set(1, &iOpInfoPckg);
       
   201 	args.Set(2, &aData);
       
   202 	TInt err = SendReceive(ERemConSendUnreliable, args); 
       
   203 	return err;
       
   204 	}
       
   205 
       
   206 
       
   207 EXPORT_C void RRemCon::Send(TRequestStatus& aStatus, 
       
   208 		TUid aInterfaceUid, 
       
   209 		TUint aOperationId, 
       
   210 		TUint& aNumRemotes,
       
   211 		TRemConMessageSubType aSubType,
       
   212 		const TDesC8& aData)
       
   213 	{
       
   214 	LOG_FUNC
       
   215 
       
   216 	TIpcArgs args;
       
   217 	iOpInfoPckg().iOperationId = aOperationId;
       
   218 	iOpInfoPckg().iMessageSubType = aSubType;
       
   219 	args.Set(0, aInterfaceUid.iUid);
       
   220 	args.Set(1, &iOpInfoPckg);
       
   221 	iNumRemotesPckg.Set((TUint8*)&aNumRemotes, sizeof(TUint), sizeof(TUint));
       
   222 	args.Set(2, &iNumRemotesPckg);
       
   223 	args.Set(3, &aData);
       
   224 
       
   225 	SendReceive(ERemConSend,
       
   226 		args,
       
   227 		aStatus
       
   228 		);
       
   229 	}
       
   230 
       
   231 /**
       
   232 Sends a notify command to the remote device.
       
   233 
       
   234 @see RRemCon::Send()
       
   235 */
       
   236 EXPORT_C void RRemCon::SendNotify(TRequestStatus& aStatus, 
       
   237 		TUid aInterfaceUid, 
       
   238 		TUint aOperationId, 
       
   239 		TRemConMessageSubType aSubType,
       
   240 		const TDesC8& aData)
       
   241 	{
       
   242 	LOG_FUNC
       
   243 
       
   244 	TIpcArgs args;
       
   245 	iOpInfoPckg().iOperationId = aOperationId;
       
   246 	iOpInfoPckg().iMessageSubType = aSubType;
       
   247 	args.Set(0, aInterfaceUid.iUid);
       
   248 	args.Set(1, &iOpInfoPckg);
       
   249 	args.Set(2, &aData);
       
   250 		
       
   251 	SendReceive(ERemConSendNotify,
       
   252 		args,
       
   253 		aStatus
       
   254 		);
       
   255 	}
       
   256 	
       
   257 EXPORT_C TInt RRemCon::SendCancel()
       
   258 	{
       
   259 	LOG_FUNC
       
   260 	
       
   261 	//Ignore Return code because
       
   262 	// a) It'll mostly be other than KErrNone because the server has terminated, in which
       
   263 	//    case the original async request will have completed with the error anyway!
       
   264 	// b) It's meaningless to the client whatever the return code is.
       
   265 	(void)SendReceive(ERemConSendCancel);
       
   266 	
       
   267 	return KErrNone; 
       
   268 	}
       
   269 
       
   270 EXPORT_C void RRemCon::Receive(TRequestStatus& aStatus, 
       
   271 							   TRemConClientReceivePackage& aReceivePackage,
       
   272 							   TDes8& aData)
       
   273 	{
       
   274 	LOG_FUNC
       
   275 
       
   276 	TIpcArgs args;
       
   277 	iReceivePckg.Set(reinterpret_cast<TUint8*>(&aReceivePackage), sizeof(TRemConClientReceivePackage), sizeof(TRemConClientReceivePackage));
       
   278 	args.Set(0, &iReceivePckg);
       
   279 	args.Set(1, &aData);
       
   280 
       
   281 	SendReceive(ERemConReceive, 
       
   282 		args,
       
   283 		aStatus);
       
   284 	}
       
   285 
       
   286 EXPORT_C TInt RRemCon::ReceiveCancel()
       
   287 	{
       
   288 	LOG_FUNC
       
   289 
       
   290 	// See RRemCon::SendCancel() for comment
       
   291 	(void)SendReceive(ERemConReceiveCancel);
       
   292 	
       
   293 	return KErrNone;
       
   294 	}
       
   295 
       
   296 EXPORT_C TInt RRemCon::GetConnections(TSglQue<TRemConAddress>& aConnections)
       
   297 	{
       
   298 	LOG_FUNC
       
   299 
       
   300 	// Plan: 
       
   301 	// 1/ Empty the given queue (in case of any subsequent error).
       
   302 	// 2/ First IPC call: get the current number of connections from the 
       
   303 	// server and allocate a buffer to read their statuses into. 
       
   304 	// 3/ Second IPC call: read the connections into that buffer, and translate 
       
   305 	// them into the client's queue.
       
   306 	// What if the set of connections changes between these 2 IPC calls? The 
       
   307 	// server-side session needs to remember the set of connection statuses at 
       
   308 	// the point in time of the 1st IPC call, to correctly answer the 2nd IPC 
       
   309 	// call. This means the server-side session has to queue connection state 
       
   310 	// changes that occur in the meantime, which can fail due to memory 
       
   311 	// allocation. This is OK because (a) they can fail a new connection 
       
   312 	// indication back to the bearer, and (b) they can make sure they can 
       
   313 	// handle a disconnection indication by pre-allocating (at connection 
       
   314 	// establishment time) enough memory to be able to remember its future 
       
   315 	// disconnection.
       
   316 
       
   317 	// 1/
       
   318 	aConnections.Reset();
       
   319 
       
   320 	// 2/
       
   321 	TUint connCount = 0;
       
   322 	TPckg<TUint> countBuf(connCount);
       
   323 	TInt err = SendReceive(ERemConGetConnectionCount, TIpcArgs(&countBuf));
       
   324 	// Only bother to get the statuses if there are some to get- otherwise 
       
   325 	// just give the client back their empty queue and KErrNone.
       
   326 	if ( err == KErrNone && connCount != 0 )
       
   327 		{
       
   328 		RBuf8 buf;
       
   329 		err = buf.Create(connCount * sizeof(TRemConAddress));
       
   330 		if ( err == KErrNone )
       
   331 			{
       
   332 			// 3/
       
   333 			err = SendReceive(ERemConGetConnections, TIpcArgs(&buf));
       
   334 			if ( err == KErrNone )
       
   335 				{
       
   336 				// Read the statuses into the client's array.
       
   337 				for ( TUint ii = 0 ; ii < connCount ; ii++ )
       
   338 					{
       
   339 					// Divide the data in to TRemConAddress portions
       
   340 					TRemConAddress* tempAddr = new TRemConAddress();
       
   341 					if (tempAddr)
       
   342 						{
       
   343 						Mem::Copy((TAny*)(tempAddr),(TAny*)(buf.Ptr()+(ii*sizeof(TRemConAddress))) , sizeof(TRemConAddress));	
       
   344 						aConnections.AddLast(*tempAddr);			
       
   345 						}
       
   346 					else
       
   347 						{
       
   348 						// Perform the cleanup in case of error
       
   349 						TSglQueIter<TRemConAddress> iter(aConnections);
       
   350 						iter.SetToFirst();
       
   351 						TRemConAddress* addr;
       
   352 						while (( addr = iter++ )  != NULL )
       
   353 							{
       
   354 							aConnections.Remove(*addr);
       
   355 							delete addr;	
       
   356 							};
       
   357 							
       
   358 						err = KErrNoMemory;
       
   359 						break;				
       
   360 						}
       
   361 					}
       
   362 				}
       
   363 			// The data that was in buf is passed into small appBuf's 
       
   364 			// and it is now owned by the client (via their TSglQue).
       
   365 			}
       
   366 		// Cleanup the allocated buffer for statuses info
       
   367 		buf.Close();
       
   368 		}
       
   369 	return err;
       
   370 	}
       
   371 
       
   372 EXPORT_C void RRemCon::NotifyConnectionsChange(TRequestStatus& aStatus)
       
   373 	{
       
   374 	LOG_FUNC
       
   375 
       
   376 	SendReceive(ERemConNotifyConnectionsChange, 
       
   377 		aStatus);
       
   378 	}
       
   379 
       
   380 EXPORT_C TInt RRemCon::NotifyConnectionsChangeCancel()
       
   381 	{
       
   382 	LOG_FUNC
       
   383 
       
   384 	// See RRemCon::SendCancel() for comment
       
   385 	(void)SendReceive(ERemConNotifyConnectionsChangeCancel);
       
   386 
       
   387 	return KErrNone;
       
   388 	}
       
   389 
       
   390 EXPORT_C TInt RRemCon::RegisterInterestedAPIs(const TDesC8& aAPIs)
       
   391 	{
       
   392 	LOG_FUNC
       
   393 	return SendReceive(ERemConRegisterInterestedAPIs, TIpcArgs(&aAPIs));
       
   394 	}
       
   395 
       
   396 EXPORT_C TInt RRemCon::__DbgMarkHeap()
       
   397 	{
       
   398 	LOG_FUNC
       
   399 #ifdef _DEBUG
       
   400 	return SendReceive(ERemConDbgMarkHeap);
       
   401 #else
       
   402 	return KErrNone;
       
   403 #endif
       
   404 	}
       
   405 
       
   406 EXPORT_C TInt RRemCon::__DbgCheckHeap(TInt aCount)
       
   407 	{
       
   408 	LOG_FUNC
       
   409 #ifdef _DEBUG
       
   410 	return SendReceive(ERemConDbgCheckHeap, TIpcArgs(aCount));
       
   411 #else
       
   412 	(void)aCount;
       
   413 	return KErrNone;
       
   414 #endif
       
   415 	}
       
   416 
       
   417 EXPORT_C TInt RRemCon::__DbgMarkEnd(TInt aCount)
       
   418 	{
       
   419 	LOG_FUNC
       
   420 #ifdef _DEBUG
       
   421 	return SendReceive(ERemConDbgMarkEnd, TIpcArgs(aCount));
       
   422 #else
       
   423 	(void)aCount;
       
   424 	return KErrNone;
       
   425 #endif
       
   426 	}
       
   427 
       
   428 EXPORT_C TInt RRemCon::__DbgFailNext(TInt aCount)
       
   429 	{
       
   430 	LOG_FUNC
       
   431 #ifdef _DEBUG
       
   432 	return SendReceive(ERemConDbgFailNext, TIpcArgs(aCount));
       
   433 #else
       
   434 	(void)aCount;
       
   435 	return KErrNone;
       
   436 #endif
       
   437 	}
       
   438 
       
   439 EXPORT_C RRemConController::RRemConController()
       
   440 :	RRemCon(ERemConClientTypeController)
       
   441 	{
       
   442 	LOG_FUNC
       
   443 	}
       
   444 
       
   445 EXPORT_C TInt RRemConController::GoConnectionOriented(const TRemConAddress& aConnection)
       
   446 	{
       
   447 	LOG_FUNC
       
   448 
       
   449 	return SendReceive(ERemConGoConnectionOriented,
       
   450 			TIpcArgs(aConnection.BearerUid().iUid, 
       
   451 					&aConnection.Addr())
       
   452 		);
       
   453 	}
       
   454 
       
   455 EXPORT_C TInt RRemConController::GoConnectionless()
       
   456 	{
       
   457 	LOG_FUNC
       
   458 
       
   459 	return SendReceive(ERemConGoConnectionless);
       
   460 	}
       
   461 
       
   462 EXPORT_C void RRemConController::ConnectBearer(TRequestStatus& aStatus)
       
   463 	{
       
   464 	LOG_FUNC
       
   465 
       
   466 	SendReceive(ERemConConnectBearer, 
       
   467 		aStatus);
       
   468 	}
       
   469 
       
   470 EXPORT_C TInt RRemConController::ConnectBearerCancel()
       
   471 	{
       
   472 	LOG_FUNC
       
   473 
       
   474 	// See RRemCon::SendCancel() for comment
       
   475 	(void)SendReceive(ERemConConnectBearerCancel);
       
   476 	
       
   477 	return KErrNone;
       
   478 	}
       
   479 
       
   480 EXPORT_C void RRemConController::DisconnectBearer(TRequestStatus& aStatus)
       
   481 	{
       
   482 	LOG_FUNC
       
   483 
       
   484 	SendReceive(ERemConDisconnectBearer, 
       
   485 		aStatus);
       
   486 	}
       
   487 
       
   488 EXPORT_C TInt RRemConController::DisconnectBearerCancel()
       
   489 	{
       
   490 	LOG_FUNC
       
   491 
       
   492 	// See RRemCon::SendCancel() for comment
       
   493 	(void)SendReceive(ERemConDisconnectBearerCancel);
       
   494 
       
   495 	return KErrNone;
       
   496 	}
       
   497 
       
   498 EXPORT_C RRemConTarget::RRemConTarget()
       
   499 :	RRemCon(ERemConClientTypeTarget)
       
   500 	{
       
   501 	LOG_FUNC
       
   502 	}
       
   503