remotecontrol/remotecontrolfw/reference/serialbearer/src/remconserialbearer.cpp
changeset 51 20ac952a623c
equal deleted inserted replaced
48:22de2e391156 51:20ac952a623c
       
     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 <remcon/remconbearerobserver.h>
       
    23 #include <remcon/remconconverterplugin.h>
       
    24 #include <remconaddress.h>
       
    25 #include "remconserialbearer.h"
       
    26 #include "sender.h"
       
    27 #include "receiver.h"
       
    28 #include "utils.h"
       
    29 
       
    30 #ifdef __FLOG_ACTIVE
       
    31 _LIT8(KLogComponent, LOG_COMPONENT_REMCON_REF_SER_BEARER);
       
    32 #endif
       
    33 
       
    34 PANICCATEGORY("SerialBear");
       
    35 
       
    36 /**
       
    37 Factory function.
       
    38 @return Ownership of a new CRemConSerialBearer.
       
    39 */
       
    40 CRemConSerialBearer* CRemConSerialBearer::NewL(TBearerParams& aParams)
       
    41 	{
       
    42 	LOG_STATIC_FUNC
       
    43 	CRemConSerialBearer* self = new(ELeave) CRemConSerialBearer(aParams);
       
    44 	CleanupStack::PushL(self);
       
    45 	self->ConstructL();
       
    46 	CLEANUPSTACK_POP1(self);
       
    47 	return self;
       
    48 	}
       
    49 
       
    50 /**
       
    51 Destructor.
       
    52 */
       
    53 CRemConSerialBearer::~CRemConSerialBearer()
       
    54 	{
       
    55 	LOG_LINE
       
    56 	LOG_FUNC
       
    57 
       
    58 	delete iSender;
       
    59 	delete iReceiver;
       
    60 
       
    61 	iComm.Close();
       
    62 	iCommServ.Close();
       
    63 
       
    64 /*#ifndef __WINS__
       
    65 	if ( iUsb.Handle() )
       
    66 		{
       
    67 		// Can't do anything with error here.
       
    68 		(void)iUsb.Stop();
       
    69 		}
       
    70 	iUsb.Close();
       
    71 #endif
       
    72 */
       
    73 	}
       
    74 
       
    75 /**
       
    76 Constructor.
       
    77 */
       
    78 CRemConSerialBearer::CRemConSerialBearer(TBearerParams& aParams)
       
    79 :	CRemConBearerPlugin(aParams)
       
    80 	{
       
    81 	LOG_FUNC
       
    82 	}
       
    83 
       
    84 /**
       
    85 2nd-phase construction.
       
    86 */
       
    87 void CRemConSerialBearer::ConstructL()
       
    88 	{
       
    89 	// NB The sender and receiver have references to our RComm. We protect our 
       
    90 	// down-calls in case the port subsession is not open.
       
    91 	iSender = CSender::NewL(iComm, *this);
       
    92 	iReceiver = CReceiver::NewL(iComm, *this);
       
    93 
       
    94 /*#ifndef __WINS__
       
    95 	// Connect and Start USB to begin with. 
       
    96 	LEAVEIFERRORL(iUsb.Connect());
       
    97 	TRequestStatus stat;
       
    98 	iUsb.Start(stat);
       
    99 	User::WaitForRequest(stat);
       
   100 	LEAVEIFERRORL(stat.Int());
       
   101 #endif
       
   102 */
       
   103 	// We trap and discard errors from this 'connection' attempt. We don't 
       
   104 	// want to fail RemCon server initialisation because the port is being 
       
   105 	// used by someone else. When RemCon wants to send a command, it will 
       
   106 	// expect the bearer to reconnect.
       
   107 	// In any case a controller client is allowed to request a 
       
   108 	// connection-oriented channel over this bearer- this will result in 
       
   109 	// another 'connection' attempt.
       
   110 	TRAPD(err, ConnectL());
       
   111 	// If we 'connected' OK, throw an indication up to RemCon.
       
   112 	if ( err == KErrNone )
       
   113 		{
       
   114 		TRemConAddress addr;
       
   115 		addr.BearerUid() = Uid();
       
   116 		err = Observer().ConnectIndicate(addr);
       
   117 		if ( err != KErrNone )
       
   118 			{
       
   119 			// We couldn't successfully tell RemCon about our connection, so 
       
   120 			// tear it down.
       
   121 			ClosePort();
       
   122 			}
       
   123 		}
       
   124 		
       
   125 	if ( iComm.SubSessionHandle() )
       
   126 		{
       
   127 		Receive();
       
   128 		}
       
   129 
       
   130 //	TRemConAddress addr;
       
   131 //	addr.BearerUid() = Uid();
       
   132 //	addr.Addr() = _L8("different");
       
   133 //	Observer().ConnectIndicate(addr);
       
   134 
       
   135 	LOG(_L("<<CRemConSerialBearer::ConstructL"));
       
   136 	}
       
   137 
       
   138 TAny* CRemConSerialBearer::GetInterface(TUid aUid)
       
   139 	{
       
   140 	LOG_FUNC;
       
   141 	LOG1(_L("\taUid = 0x%08x"), aUid);
       
   142 
       
   143 	TAny* ret = NULL;
       
   144 	if ( aUid == TUid::Uid(KRemConBearerInterface1) )
       
   145 		{
       
   146 		ret = reinterpret_cast<TAny*>(
       
   147 			static_cast<MRemConBearerInterface*>(this)
       
   148 			);
       
   149 		}
       
   150 
       
   151 	LOG1(_L("\tret = [0x%08x]"), ret);
       
   152 	return ret;
       
   153 	}
       
   154 
       
   155 void CRemConSerialBearer::ConnectRequest(const TRemConAddress& aAddr)
       
   156 	{
       
   157 	LOG(KNullDesC8);
       
   158 	LOG_FUNC;
       
   159 	// This bearer does not use client-specified connection data. The 
       
   160 	// connection data gives the *remote* address to connect to. This is not a 
       
   161 	// valid concept in the wired case. 
       
   162 
       
   163 	// This ASSERTS if we already have the port open!!!!
       
   164 	TRAPD(connectErr, ConnectL());
       
   165 	
       
   166 	TInt err = Observer().ConnectConfirm(aAddr, connectErr);
       
   167 	// If there was an error in RemCon we should drop the connection otherwise 
       
   168 	// RemCon might get surprised by later incoming messages on a connection 
       
   169 	// it doesn't know exists. Otherwise, start listening for incoming data.
       
   170 	// Of course, don't start listening unless the port opened OK 
       
   171 	// (connectErr).
       
   172 	if ( err != KErrNone || connectErr != KErrNone )
       
   173 		{
       
   174 		ClosePort();
       
   175 		}
       
   176 	else
       
   177 		{
       
   178 		Receive();
       
   179 		}
       
   180 	}
       
   181 
       
   182 void CRemConSerialBearer::DisconnectRequest(const TRemConAddress& aAddr)
       
   183 	{
       
   184 	LOG(KNullDesC8);
       
   185 	LOG_FUNC;
       
   186 
       
   187 	// make sure we are connected before disconnect
       
   188 	ASSERT_ALWAYS(iCommServ.Handle());
       
   189 	
       
   190 	// Undo everything done in Connect (without assuming that Connect 
       
   191 	// completed successfully). Must cancel any outstanding requests for this 
       
   192 	// to be safe.
       
   193 	ClosePort();
       
   194 	Observer().DisconnectConfirm(aAddr, KErrNone);
       
   195 	}
       
   196 
       
   197 void CRemConSerialBearer::ConnectL()
       
   198 	{
       
   199 	LOG_FUNC;
       
   200 
       
   201 #if defined (__WINS__)
       
   202 #define PDD_NAME _L("ECDRV")
       
   203 #define LDD_NAME _L("ECOMM")
       
   204 #else  // __GCC32__
       
   205 #define PDD_NAME _L("EUART1")
       
   206 #define LDD_NAME _L("ECOMM")
       
   207 #endif
       
   208 
       
   209 	// make sure we aren't connected
       
   210 	ASSERT_ALWAYS(!iCommServ.Handle());
       
   211 	
       
   212 	TInt r=User::LoadPhysicalDevice(PDD_NAME);
       
   213 	if (r!=KErrNone && r!=KErrAlreadyExists)
       
   214 		{
       
   215 		LEAVEIFERRORL(r);
       
   216 		}
       
   217 	r=User::LoadLogicalDevice(LDD_NAME);
       
   218 	if (r!=KErrNone && r!=KErrAlreadyExists)
       
   219 		{
       
   220 		LEAVEIFERRORL(r);
       
   221 		}
       
   222 
       
   223 	_LIT(KModule, "ECUART");
       
   224 #if defined (__WINS__)
       
   225 	_LIT(KPort, "COMM::1");
       
   226 #else
       
   227 //	_LIT(KPort, "COMM::2");  // On H2 and H4 this is the IR port
       
   228 							 // use COMM::2 for Lubbock.
       
   229 	_LIT(KPort, "COMM::3");  // need this for H2 and H4 board
       
   230 #endif
       
   231 
       
   232 	LEAVEIFERRORL(iCommServ.Connect());
       
   233 	
       
   234  	// if appropriate close will unloadcommmodule internally
       
   235  	CleanupClosePushL(iCommServ);
       
   236 
       
   237 	LEAVEIFERRORL(iCommServ.LoadCommModule(KModule));
       
   238 	
       
   239 	// as above if not connected this should be NULL
       
   240 	ASSERT_ALWAYS(!iComm.SubSessionHandle());
       
   241 	
       
   242 	LEAVEIFERRORL(iComm.Open(iCommServ, KPort, ECommExclusive));
       
   243 
       
   244 	// put these on clean up stack - will call close if we leave
       
   245 	CleanupClosePushL(iComm);
       
   246 
       
   247 	// Put the port's config into a known state.
       
   248 	TCommConfig portSettings;
       
   249 	LEAVEIFERRORL(iComm.Config(portSettings));
       
   250 	portSettings().iRate = EBps115200;
       
   251 	portSettings().iDataBits = EData8;
       
   252 	portSettings().iStopBits = EStop1;
       
   253 	LEAVEIFERRORL(iComm.SetConfig(portSettings));
       
   254 
       
   255 	CleanupStack::Pop(2,&iCommServ);// pop iComm then iCommServ
       
   256 
       
   257 	/* clear out the serial port so we know we start from fresh...
       
   258 	 simple expedient (that hopefully will work), try and receive 20 bytes,
       
   259 	 then cancel the receive. Given the current behaviour of the read cancel this
       
   260 	 will return any characters that are currently in the serial port buffers 
       
   261 	*/
       
   262 	ASSERT_DEBUG(iReceiver);
       
   263 	Receive();
       
   264 	iReceiver->Cancel();
       
   265 	}
       
   266 
       
   267 void CRemConSerialBearer::ClosePort()
       
   268 	{
       
   269 	LOG_FUNC;
       
   270 
       
   271 	ASSERT_DEBUG(iSender);
       
   272 	iSender->Cancel();
       
   273 	ASSERT_DEBUG(iReceiver);
       
   274 	iReceiver->Cancel();
       
   275 	iComm.Close();
       
   276 	iCommServ.Close();
       
   277 	}
       
   278 
       
   279 TInt CRemConSerialBearer::SendResponse(TUid aInterfaceUid, 
       
   280 		TUint aOperationId, 
       
   281 		TUint /*aTransactionId*/, // we don't care about this transaction ID
       
   282 		RBuf8& aData, 
       
   283 		const TRemConAddress& /*aAddr*/)
       
   284 	{
       
   285 	LOG(KNullDesC8);
       
   286 	LOG_FUNC;
       
   287 	LOG1(_L("\taOperationId = 0x%02x"), aOperationId);
       
   288 	
       
   289 	TInt ret = DoSend(aInterfaceUid, aOperationId, aData, ERemConResponse);
       
   290 
       
   291 	LOG1(_L("\tret = %d"), ret);
       
   292 	return ret;
       
   293 	}
       
   294 
       
   295 TInt CRemConSerialBearer::SendCommand(TUid aInterfaceUid, 
       
   296 		TUint aOperationId, 
       
   297 		TUint aTransactionId,  
       
   298 		RBuf8& aData, 
       
   299 		const TRemConAddress& /*aAddr*/)
       
   300 	{
       
   301 	LOG(KNullDesC8());
       
   302 	LOG_FUNC;
       
   303 	LOG1(_L("\taOperationId = 0x%02x"), aOperationId);
       
   304 	
       
   305 	iTransactionId = aTransactionId;
       
   306 	TInt ret = DoSend(aInterfaceUid, aOperationId, aData, ERemConCommand);
       
   307 
       
   308 	LOG1(_L("\tret = %d"), ret);
       
   309 	return ret;
       
   310 	}
       
   311 
       
   312 TInt CRemConSerialBearer::DoSend(TUid aInterfaceUid, 
       
   313 		TUint aOperationId, 
       
   314 		RBuf8& aData, 
       
   315 		TRemConMessageType aMsgType)
       
   316 	{
       
   317 	LOG_FUNC;
       
   318 	
       
   319 	TInt ret = KErrInUse;
       
   320 
       
   321 	// make sure we are connected
       
   322 	ASSERT_ALWAYS(iComm.SubSessionHandle());
       
   323 
       
   324 	// Check we're not already busy sending.
       
   325 	ASSERT_DEBUG(iSender);
       
   326 	if ( iSender->IsActive() )
       
   327 		{
       
   328 		ret = KErrInUse;
       
   329 		}
       
   330 	else
       
   331 		{
       
   332 		ret = Observer().InterfaceToBearer(Uid(), aInterfaceUid, aOperationId, aData, aMsgType, iOutMsg);
       
   333 		if ( ret == KErrNone )
       
   334 			{
       
   335 			LOG1(_L("\tsending text \"%S\""), &iOutMsg);
       
   336 			iSender->Send(iOutMsg);
       
   337 			}
       
   338 		}
       
   339 
       
   340 	// If no error, we took ownership of aData- we've finished with it now.
       
   341 	if ( ret == KErrNone )
       
   342 		{
       
   343 		aData.Close();
       
   344 		}
       
   345 
       
   346 	LOG1(_L("\tret = %d"), ret);
       
   347 	return ret;
       
   348 	}
       
   349 
       
   350 void CRemConSerialBearer::MsoSendComplete(TInt aError)
       
   351 	{
       
   352 	LOG(KNullDesC8);
       
   353 	LOG_FUNC;
       
   354 	LOG1(_L("\taError = %d"), aError);
       
   355 	(void)aError;
       
   356 
       
   357 	// We don't do anything. How does RemCon get to know of this? Does it 
       
   358 	// care? No. A command which never gets a response is standard remote 
       
   359 	// control behaviour. The user will retry, and doesn't need an InfoMsg to 
       
   360 	// tell them anything about it.
       
   361 	}
       
   362 
       
   363 TInt CRemConSerialBearer::GetResponse(TUid& aInterfaceUid, 
       
   364 		TUint& aTransactionId, 
       
   365 		TUint& aOperationId, 
       
   366 		RBuf8& aData, 
       
   367 		TRemConAddress& aAddr)
       
   368 	{
       
   369 	LOG_FUNC;
       
   370 
       
   371 	ASSERT_DEBUG(iReceiver);
       
   372 	// RemCon shouldn't call use unless we prompted them to with NewResponse.
       
   373 	ASSERT_DEBUG(!iReceiver->IsActive()); 
       
   374 	// The message should be a response, unless RemCon is being buggy and 
       
   375 	// calling GetResponse at bad times.
       
   376 	ASSERT_DEBUG(iMsgType == ERemConResponse);
       
   377 
       
   378 	TRAPD(err, DoGetResponseL(aInterfaceUid, aOperationId, aData, aAddr));
       
   379 	LOG3(_L("\taInterfaceUid = 0x%08x, aOperationId = 0x%02x, msgType = %d"), 
       
   380 		aInterfaceUid, aOperationId, iMsgType);
       
   381 
       
   382 	// The serial bearer only has one incoming message in it at once, so we 
       
   383 	// don't need any queueing or anything fancy to get the transaction ID- 
       
   384 	// it's just the last one RemCon told us.
       
   385 	aTransactionId = iTransactionId;
       
   386 
       
   387 	// Repost read request on port.
       
   388 	Receive();
       
   389 
       
   390 	LOG1(_L("\terr = %d"), err);
       
   391 	return err;
       
   392 	}
       
   393 
       
   394 void CRemConSerialBearer::DoGetResponseL(TUid& aInterfaceUid, 
       
   395 		TUint& aOperationId, 
       
   396 		RBuf8& aData, 
       
   397 		TRemConAddress& aAddr)
       
   398 	{
       
   399 	LOG_FUNC;
       
   400 
       
   401 	aInterfaceUid = iInterfaceUid;
       
   402 	aOperationId = iOperationId;
       
   403 	ASSERT_DEBUG(aData.MaxLength() == 0);
       
   404 	// Pass ownership of this to RemCon.
       
   405 	aData.CreateL(iData);
       
   406 
       
   407 	aAddr.BearerUid() = Uid();
       
   408 	aAddr.Addr() = KNullDesC8();
       
   409 	}
       
   410 
       
   411 TInt CRemConSerialBearer::GetCommand(TUid& aInterfaceUid, 
       
   412 		TUint& aTransactionId, 
       
   413 		TUint& aOperationId, 
       
   414 		RBuf8& aData, 
       
   415 		TRemConAddress& aAddr)
       
   416 	{
       
   417 	LOG_FUNC;
       
   418 
       
   419 	ASSERT_DEBUG(iReceiver);
       
   420 	// RemCon shouldn't call use unless we prompted them to with NewCommand.
       
   421 	ASSERT_DEBUG(!iReceiver->IsActive()); 
       
   422 	// The message should be a command, unless RemCon is being buggy and 
       
   423 	// calling GetCommand at bad times.
       
   424 	ASSERT_DEBUG(iMsgType == ERemConCommand);
       
   425 
       
   426 	TRAPD(err, DoGetCommandL(aInterfaceUid, aOperationId, aData, aAddr));
       
   427 	LOG3(_L("\taInterfaceUid = 0x%08x, aOperationId = 0x%02x, msgType = %d"), 
       
   428 		aInterfaceUid, aOperationId, iMsgType);
       
   429 
       
   430 	// The serial bearer only has one incoming message in it at once, so we 
       
   431 	// don't need any queueing or anything fancy to get the transaction ID- 
       
   432 	// it's just the last one RemCon told us.
       
   433 	aTransactionId = iTransactionId;
       
   434 	
       
   435 	// Repost read request on port.
       
   436 	Receive();
       
   437 
       
   438 	LOG1(_L("\terr = %d"), err);
       
   439 	return err;
       
   440 	}
       
   441 
       
   442 void CRemConSerialBearer::DoGetCommandL(TUid& aInterfaceUid,
       
   443 		TUint& aOperationId, 
       
   444 		RBuf8& aData, 
       
   445 		TRemConAddress& aAddr)
       
   446 	{
       
   447 	LOG_FUNC;
       
   448 
       
   449 	aInterfaceUid = iInterfaceUid;
       
   450 	aOperationId = iOperationId;
       
   451 	// Pass ownership of this to RemCon.
       
   452 	aData.CreateL(iData);
       
   453 	
       
   454 	aAddr.BearerUid() = Uid();
       
   455 	aAddr.Addr() = KNullDesC8();
       
   456 	}
       
   457 
       
   458 // Utility to repost a read on the port.
       
   459 void CRemConSerialBearer::Receive()
       
   460 	{
       
   461 	LOG_FUNC;
       
   462 
       
   463 	ASSERT_DEBUG(iComm.SubSessionHandle());
       
   464 	ASSERT_DEBUG(iReceiver);
       
   465 	/* we should check we aren't currently trying to receive. 
       
   466 	   In this design we only kick off a receive when we aren't already trying to read something already.
       
   467 	   If we get this wrong the SetActive in iReceiver->Receive will blow up, so we'll assert here so we know.
       
   468 	   This configuration is for test code not real life so there is no 'real' problem anyway.
       
   469 	*/
       
   470 	ASSERT_DEBUG(!iReceiver->IsActive());
       
   471 	/* you might expect to see an iReceiver->Cancel() here BUT there are problems with doing this
       
   472 	   a) The underlying RComm::Read may just decide to put the 5 bytes of message it currently has in 
       
   473 	       the buffer (if we happen to call this half way through an incoming message). In this case this
       
   474 	       bearer will NEVER recover as it assumes it will only receive the proper complete 30 byte message
       
   475 	       and makes no attempt to get back in step (it will have 5 bytes from one message + 25 from another for ever).
       
   476 	   b) We are pretty confident we don't need to (see above).
       
   477 	*/
       
   478 	iReceiver->Receive(iInMsg);
       
   479 	}
       
   480 
       
   481 void CRemConSerialBearer::MroReceiveComplete(TInt aError)
       
   482 	{
       
   483 	LOG(KNullDesC8);
       
   484 	LOG_FUNC;
       
   485 	LOG2(_L("\taError = %d, iInMsg = \"%S\""), aError, &iInMsg);
       
   486 
       
   487 	// If any error occurred either getting or decoding the message, we need 
       
   488 	// to re-post now. Otherwise, we wait until after RemCon has picked up the 
       
   489 	// message until we re-post a read. 
       
   490 	if ( aError == KErrNone )
       
   491 		{
       
   492 		TRemConAddress addr;
       
   493 		addr.BearerUid() = Uid();
       
   494 		addr.Addr() = KNullDesC8();
       
   495 
       
   496 		aError = Observer().BearerToInterface(Uid(), 
       
   497 			iInMsg,
       
   498 			iInMsg, 
       
   499 			iInterfaceUid, 
       
   500 			iOperationId,
       
   501 			iMsgType, 
       
   502 			iData);
       
   503 
       
   504 		if ( aError == KErrNone )
       
   505 			{
       
   506 			if ( iMsgType == ERemConCommand )
       
   507 				{
       
   508 				iTransactionId = Observer().NewTransactionId();
       
   509 				aError = Observer().NewCommand(addr);
       
   510 				}
       
   511 			else if ( iMsgType == ERemConResponse )
       
   512 				{
       
   513 				aError = Observer().NewResponse(addr);
       
   514 				}
       
   515 			else
       
   516 				{
       
   517 				// drop the message (malformed- not apparently a command or response)
       
   518 				aError = KErrNotSupported;
       
   519 				}
       
   520 			}
       
   521 		// else drop the message (either no converter for that interface UID or it couldn't convert the message)
       
   522 		}
       
   523 	// else just drop the message (error receiving it)
       
   524 	
       
   525 	// If we successfully told RemCon there was a new message to pick up, 
       
   526 	// don't repost our port read until RemCon has come back and picked up the 
       
   527 	// message. If there was any error, then RemCon isn't going to come back 
       
   528 	// for this message- it's effectively dropped- and we should re-post our 
       
   529 	// request now.
       
   530 	if ( aError != KErrNone )
       
   531 		{
       
   532 		Receive();
       
   533 		}
       
   534 	}
       
   535 
       
   536 TSecurityPolicy CRemConSerialBearer::SecurityPolicy() const
       
   537 	{
       
   538 	return TSecurityPolicy(ECapabilityLocalServices);
       
   539 	}
       
   540 
       
   541 void CRemConSerialBearer::ClientStatus(TBool aControllerPresent, TBool aTargetPresent)
       
   542 	{
       
   543 	LOG2(_L("CRemConSerialBearer::ClientStatus aControllerPresent = %d, aTargetPresent = %d"), 
       
   544 		aControllerPresent, aTargetPresent);
       
   545 	(void)aControllerPresent;
       
   546 	(void)aTargetPresent;
       
   547 
       
   548 	// I don't care.
       
   549 	}