kerneltest/e32test/examples/driver1/driver1_ldd.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 2003-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 the License "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 Example Logical Device Driver
       
    18  @publishedPartner
       
    19  @released
       
    20 */
       
    21 
       
    22 #include <kernel/kern_priv.h>
       
    23 #include "driver1.h"
       
    24 #include "driver1_dev.h"
       
    25 
       
    26 _LIT(KDriver1PanicCategory,"Driver1");
       
    27 
       
    28 
       
    29 //
       
    30 // DDriver1Factory
       
    31 //
       
    32 
       
    33 /**
       
    34   Standard export function for LDDs. This creates a DLogicalDevice derived object,
       
    35   in this case, our DDriver1Factory
       
    36 */
       
    37 DECLARE_STANDARD_LDD()
       
    38 	{
       
    39 	return new DDriver1Factory;
       
    40 	}
       
    41 
       
    42 /**
       
    43   Constructor
       
    44 */
       
    45 DDriver1Factory::DDriver1Factory()
       
    46 	{
       
    47 	// Set version number for this device
       
    48 	iVersion=RDriver1::VersionRequired();
       
    49 	// Indicate that we work with a PDD
       
    50 	iParseMask=KDeviceAllowPhysicalDevice;
       
    51 	}
       
    52 
       
    53 
       
    54 /**
       
    55   Second stage constructor for DDriver1Factory.
       
    56   This must at least set a name for the driver object.
       
    57 
       
    58   @return KErrNone if successful, otherwise one of the other system wide error codes.
       
    59 */
       
    60 TInt DDriver1Factory::Install()
       
    61 	{
       
    62 	return SetName(&RDriver1::Name());
       
    63 	}
       
    64 
       
    65 
       
    66 /**
       
    67      Destructor
       
    68    */
       
    69 DDriver1Factory::~DDriver1Factory()
       
    70    	{
       
    71    	}
       
    72 
       
    73 
       
    74 /**
       
    75   Return the drivers capabilities.
       
    76   Called in the response to an RDevice::GetCaps() request.
       
    77 
       
    78   @param aDes User-side descriptor to write capabilities information into
       
    79 */
       
    80 void DDriver1Factory::GetCaps(TDes8& aDes) const
       
    81 	{
       
    82 	// Create a capabilities object
       
    83 	RDriver1::TCaps caps;
       
    84 	caps.iVersion = iVersion;
       
    85 	// Write it back to user memory
       
    86 	Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
       
    87 	}
       
    88 
       
    89 /**
       
    90   Called by the kernel's device driver framework to create a Logical Channel.
       
    91   This is called in the context of the user thread (client) which requested the creation of a Logical Channel
       
    92   (E.g. through a call to RBusLogicalChannel::DoCreate)
       
    93   The thread is in a critical section.
       
    94 
       
    95   @param aChannel Set to point to the created Logical Channel
       
    96 
       
    97   @return KErrNone if successful, otherwise one of the other system wide error codes.
       
    98 */
       
    99 TInt DDriver1Factory::Create(DLogicalChannelBase*& aChannel)
       
   100 	{
       
   101 	aChannel=new DDriver1Channel;
       
   102 	if(!aChannel)
       
   103 		return KErrNoMemory;
       
   104 
       
   105 	return KErrNone;
       
   106 	}
       
   107 
       
   108 //
       
   109 // Logical Channel
       
   110 //
       
   111 
       
   112 /**
       
   113   Constructor
       
   114 */
       
   115 DDriver1Channel::DDriver1Channel()
       
   116 	:	iSendDataDfc(SendDataDfc, this, 1),        // DFC is priority '1'
       
   117 		iReceiveDataDfc(ReceiveDataDfc, this, 1)   // DFC is priority '1'
       
   118 	{
       
   119 	// Get pointer to client threads DThread object
       
   120 	iClient=&Kern::CurrentThread();
       
   121 
       
   122 	// Open a reference on client thread so it's control block can't dissapear until
       
   123 	// this driver has finished with it.
       
   124 	// Note, this call to Open can't fail since its the thread we are currently running in
       
   125 	iClient->Open();
       
   126 	}
       
   127 
       
   128 /**
       
   129   Second stage constructor called by the kernel's device driver framework.
       
   130   This is called in the context of the user thread (client) which requested the creation of a Logical Channel
       
   131   (E.g. through a call to RBusLogicalChannel::DoCreate)
       
   132   The thread is in a critical section.
       
   133 
       
   134   @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
       
   135   @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
       
   136   @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate
       
   137 
       
   138   @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   139 */
       
   140 TInt DDriver1Channel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
       
   141 	{
       
   142 	// Check Platform Security capabilities of client thread (if required).
       
   143 	//
       
   144 	// Here we handle the simple case where:
       
   145 	// 1. The device driver can only have one client thread
       
   146 	// 2. The security policy is the binary all-or-nothing policy.
       
   147 	//    E.g. "If you have the right capability you can do anything with the driver
       
   148 	//    and if you don't have the capability you can't do anything"
       
   149 	// 
       
   150 	// If only some functionality of the driver is restricted, then the security check should
       
   151 	// go elsewhere. E.g. in DoRequest/DoControl. In that case Kern::CurrentThreadHasCapability
       
   152 	// shouldn't be used because the 'current thread' isn't the client.
       
   153 	//
       
   154 	// In this example we do a check here for ECapability_None (which always passes)...
       
   155 	if(!Kern::CurrentThreadHasCapability(ECapability_None,__PLATSEC_DIAGNOSTIC_STRING("Checked by DRIVER1")))
       
   156 		return KErrPermissionDenied;
       
   157 
       
   158 	// Check version
       
   159 	if (!Kern::QueryVersionSupported(RDriver1::VersionRequired(),aVer))
       
   160 		return KErrNotSupported;
       
   161 
       
   162 	// Setup LDD for receiving client messages
       
   163 	SetDfcQ(((DDevice1PddFactory*)iPhysicalDevice)->iDfcQ);
       
   164 	iMsgQ.Receive();
       
   165 
       
   166 	// Associate DFCs with the same queue we set above to receive client messages on
       
   167 	iSendDataDfc.SetDfcQ(iDfcQ);
       
   168 	iReceiveDataDfc.SetDfcQ(iDfcQ);
       
   169 
       
   170 	// Give PDD a pointer to this channel
       
   171 	Pdd()->iLdd=this;
       
   172 
       
   173 	// Done
       
   174 	return KErrNone;
       
   175 	}
       
   176 
       
   177 /**
       
   178   Destructor
       
   179 */
       
   180 DDriver1Channel::~DDriver1Channel()
       
   181 	{
       
   182 	// Cancel all processing that we may be doing
       
   183 	DoCancel(RDriver1::EAllRequests);
       
   184 	// Close our reference on the client thread
       
   185 	Kern::SafeClose((DObject*&)iClient,NULL);
       
   186 	}
       
   187 
       
   188 /**
       
   189   Called when a user thread requests a handle to this channel.
       
   190 */
       
   191 TInt DDriver1Channel::RequestUserHandle(DThread* aThread, TOwnerType aType)
       
   192 	{
       
   193 	// Make sure that only our client can get a handle
       
   194 	if (aType!=EOwnerThread || aThread!=iClient)
       
   195 		return KErrAccessDenied;
       
   196 	return KErrNone;
       
   197 	}
       
   198 
       
   199 /**
       
   200   Process a message for this logical channel.
       
   201   This function is called in the context of a DFC thread.
       
   202 
       
   203   @param aMessage The message to process.
       
   204 	              The iValue member of this distinguishes the message type:
       
   205 	              iValue==ECloseMsg, channel close message
       
   206 	              iValue==KMaxTInt, a 'DoCancel' message
       
   207 	              iValue>=0, a 'DoControl' message with function number equal to iValue
       
   208 	              iValue<0, a 'DoRequest' message with function number equal to ~iValue
       
   209 */
       
   210 void DDriver1Channel::HandleMsg(TMessageBase* aMsg)
       
   211 	{
       
   212 	TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   213 
       
   214 	// Get message type
       
   215 	TInt id=m.iValue;
       
   216 
       
   217 	// Decode the message type and dispatch it to the relevent handler function...
       
   218 
       
   219 	if (id==(TInt)ECloseMsg)
       
   220 		{
       
   221 		// Channel Close
       
   222 		DoCancel(RDriver1::EAllRequests);
       
   223 		m.Complete(KErrNone, EFalse);
       
   224 		return;
       
   225 		}
       
   226 
       
   227 	if (id==KMaxTInt)
       
   228 		{
       
   229 		// DoCancel
       
   230 		DoCancel(m.Int0());
       
   231 		m.Complete(KErrNone,ETrue);
       
   232 		return;
       
   233 		}
       
   234 
       
   235 	if (id<0)
       
   236 		{
       
   237 		// DoRequest
       
   238 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   239 		TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
       
   240 		if (r!=KErrNone)
       
   241 			Kern::RequestComplete(iClient,pS,r);
       
   242 		m.Complete(KErrNone,ETrue);
       
   243 		}
       
   244 	else
       
   245 		{
       
   246 		// DoControl
       
   247 		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
   248 		m.Complete(r,ETrue);
       
   249 		}
       
   250 	}
       
   251 
       
   252 /**
       
   253   Process synchronous 'control' requests
       
   254 */
       
   255 TInt DDriver1Channel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
       
   256 	{
       
   257 	(void)a2;   // a2 not used in this example
       
   258 
       
   259 	TInt r;
       
   260 
       
   261 	switch (aFunction)
       
   262 		{
       
   263 		case RDriver1::EGetConfig:
       
   264 			r = GetConfig((TDes8*)a1);
       
   265 			break;
       
   266 
       
   267 		case RDriver1::ESetConfig:
       
   268 			r = SetConfig((const TDesC8*)a1);
       
   269 			break;
       
   270 
       
   271 		default:
       
   272 			r = KErrNotSupported;
       
   273 			break;
       
   274 		}
       
   275 
       
   276 	return r;
       
   277 	}
       
   278 
       
   279 /**
       
   280   Process asynchronous requests.
       
   281 */
       
   282 TInt DDriver1Channel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
   283 	{
       
   284 	(void)a2;   // a2 not used in this example
       
   285 
       
   286 	TInt r;
       
   287 
       
   288 	switch(aReqNo)
       
   289 		{
       
   290 		case RDriver1::ESendData:
       
   291 			r=SendData(aStatus,(const TDesC8*)a1);
       
   292 			break;
       
   293 
       
   294 		case RDriver1::EReceiveData:
       
   295 			// Example Platform Security capability check which tests the
       
   296 			// client for ECapability_None (which always passes)...
       
   297 			if(iClient->HasCapability(ECapability_None,__PLATSEC_DIAGNOSTIC_STRING("Checked by DRIVER1")))
       
   298 				r=ReceiveData(aStatus,(TDes8*)a1);
       
   299 			else
       
   300 				r=KErrPermissionDenied;
       
   301 			break;
       
   302 
       
   303 		default:
       
   304 			r = KErrNotSupported;
       
   305 			break;
       
   306 		}
       
   307 
       
   308 	return r;
       
   309 	}
       
   310 
       
   311 /**
       
   312   Process cancelling of asynchronous requests.
       
   313 */
       
   314 void DDriver1Channel::DoCancel(TUint aMask)
       
   315 	{
       
   316 	if(aMask&(1<<RDriver1::ESendData))
       
   317 		SendDataCancel();
       
   318 	if(aMask&(1<<RDriver1::EReceiveData))
       
   319 		ReceiveDataCancel();
       
   320 	}
       
   321 
       
   322 //
       
   323 // Methods for processing configuration control messages
       
   324 //
       
   325 
       
   326 /**
       
   327   Process a GetConfig control message. This writes the current driver configuration to a
       
   328   RDriver1::TConfigBuf supplied by the client.
       
   329 */
       
   330 TInt DDriver1Channel::GetConfig(TDes8* aConfigBuf)
       
   331 	{
       
   332 	// Create a structure giving the current configuration
       
   333 	RDriver1::TConfig config;
       
   334 	CurrentConfig(config);
       
   335 
       
   336 	// Write the config to the client
       
   337 	TPtrC8 ptr((const TUint8*)&config,sizeof(config));
       
   338 	return Kern::ThreadDesWrite(iClient,aConfigBuf,ptr,0,KTruncateToMaxLength,NULL);
       
   339 	}
       
   340 
       
   341 /**
       
   342   Process a SetConfig control message. This sets the driver configuration using a
       
   343   RDriver1::TConfigBuf supplied by the client.
       
   344 */
       
   345 TInt DDriver1Channel::SetConfig(const TDesC8* aConfigBuf)
       
   346 	{
       
   347 	// Don't allow configuration changes whilst we're busy
       
   348 	if(iSendDataStatus || iReceiveDataStatus)
       
   349 		return KErrInUse;
       
   350 
       
   351 	// Create a config structure.
       
   352 	RDriver1::TConfig config;
       
   353 	CurrentConfig(config);
       
   354 
       
   355 	// Note: We have filled config with the current settings, this is to allow
       
   356 	// backwards compatibility when a client gives us an old (and shorter) version
       
   357 	// of the config structure.
       
   358 
       
   359 	// Read the config structure from client
       
   360 	TPtr8 ptr((TUint8*)&config,sizeof(config));
       
   361 	TInt r=Kern::ThreadDesRead(iClient,aConfigBuf,ptr,0);
       
   362 	if(r!=KErrNone)
       
   363 		return r;
       
   364 
       
   365 	// Use config data to setup the driver. Checking that parameters which aren't settable
       
   366 	// either contain the correct values or are zero (meaning 'default')
       
   367 	if(config.iPddBufferSize && config.iPddBufferSize!=Pdd()->BufferSize())
       
   368 		return KErrArgument;
       
   369 
       
   370 	if(config.iMaxSendDataSize && config.iMaxSendDataSize!=iSendDataBuffer.MaxSize())
       
   371 		return KErrArgument;
       
   372 
       
   373 	if(config.iMaxReceiveDataSize && config.iMaxReceiveDataSize!=iReceiveDataBuffer.MaxSize())
       
   374 		return KErrArgument;
       
   375 
       
   376 	r=Pdd()->SetSpeed(config.iSpeed);
       
   377 	if(r!=KErrNone)
       
   378 		return r;
       
   379 
       
   380 	return r;
       
   381 	}
       
   382 
       
   383 /**
       
   384   Fill a TConfig with the drivers current configuration.
       
   385 */
       
   386 void DDriver1Channel::CurrentConfig(RDriver1::TConfig& aConfig)
       
   387 	{
       
   388 	aConfig.iSpeed = Pdd()->Speed();
       
   389 	aConfig.iPddBufferSize = Pdd()->BufferSize();
       
   390 	aConfig.iMaxSendDataSize = iSendDataBuffer.MaxSize();
       
   391 	aConfig.iMaxReceiveDataSize = iReceiveDataBuffer.MaxSize();
       
   392 	}
       
   393 
       
   394 //
       
   395 // Methods for processing 'SendData'
       
   396 //
       
   397 
       
   398 /**
       
   399   Start processing a SendData request.
       
   400 */
       
   401 TInt DDriver1Channel::SendData(TRequestStatus* aStatus,const TDesC8* aData)
       
   402 	{
       
   403 	// Check that a 'SendData' isn't already in progress
       
   404 	if(iSendDataStatus)
       
   405 		{
       
   406 		Kern::ThreadKill(iClient,EExitPanic,ERequestAlreadyPending,KDriver1PanicCategory);
       
   407 		return KErrInUse;
       
   408 		}
       
   409 
       
   410 	// Read data from client into our buffer
       
   411 	TInt r=Kern::ThreadDesRead(iClient,aData,iSendDataBuffer,0);
       
   412 	if(r!=KErrNone)
       
   413 		return r;
       
   414 
       
   415 	// Give data to PDD so that it can do the work
       
   416 	r=Pdd()->SendData(iSendDataBuffer);
       
   417 	if(r!=KErrNone)
       
   418 		return r;
       
   419 
       
   420 	// Save the client request status and return
       
   421 	iSendDataStatus = aStatus;
       
   422 	return KErrNone;
       
   423 	}
       
   424 
       
   425 /**
       
   426   Cancel a SendData request.
       
   427 */
       
   428 void DDriver1Channel::SendDataCancel()
       
   429 	{
       
   430 	if(iSendDataStatus)
       
   431 		{
       
   432 		// Tell PDD to stop processing the request
       
   433 		Pdd()->SendDataCancel();
       
   434 		// Cancel DFC
       
   435 		iSendDataDfc.Cancel();
       
   436 		// Complete clients request
       
   437 		Kern::RequestComplete(iClient,iSendDataStatus,KErrCancel);
       
   438 		}
       
   439 	}
       
   440 
       
   441 /**
       
   442   Called by PDD from ISR to indicate that a SendData operation has completed.
       
   443 */
       
   444 void DDriver1Channel::SendDataComplete(TInt aResult)
       
   445 	{
       
   446 	// Save result code
       
   447 	iSendDataResult = aResult;
       
   448 	// Queue DFC
       
   449 	iSendDataDfc.Add();
       
   450 	}
       
   451 
       
   452 /**
       
   453   DFC callback which gets triggered after the PDD has signalled that SendData completed.
       
   454   This just casts aPtr and calls DoSendDataComplete().
       
   455 */
       
   456 void DDriver1Channel::SendDataDfc(TAny* aPtr)
       
   457 	{
       
   458 	((DDriver1Channel*)aPtr)->DoSendDataComplete();
       
   459 	}
       
   460 
       
   461 /**
       
   462   Called from a DFC after the PDD has signalled that SendData completed.
       
   463 */
       
   464 void DDriver1Channel::DoSendDataComplete()
       
   465 	{
       
   466 	TInt result = iSendDataResult;
       
   467 	// Complete clients request
       
   468 	Kern::RequestComplete(iClient,iSendDataStatus,result);
       
   469 	}
       
   470 
       
   471 //
       
   472 // Methods for processing 'ReceiveData'
       
   473 //
       
   474 
       
   475 /**
       
   476   Start processing a ReceiveData request.
       
   477 */
       
   478 TInt DDriver1Channel::ReceiveData(TRequestStatus* aStatus,TDes8* aPtr)
       
   479 	{
       
   480 	// Check that a 'ReceiveData' isn't already in progress
       
   481 	if(iReceiveDataStatus)
       
   482 		{
       
   483 		Kern::ThreadKill(iClient,EExitPanic,ERequestAlreadyPending,KDriver1PanicCategory);
       
   484 		return KErrInUse;
       
   485 		}
       
   486 
       
   487 	// Ask PDD for data
       
   488 	TInt r=Pdd()->ReceiveData(iReceiveDataBuffer);
       
   489 	if(r!=KErrNone)
       
   490 		return r;
       
   491 
       
   492 	// Save the client request status and descriptor before returning
       
   493 	iReceiveDataStatus = aStatus;
       
   494 	iReceiveDataDescriptor = aPtr;
       
   495 	return KErrNone;
       
   496 	}
       
   497 
       
   498 /**
       
   499   Cancel a ReceiveData request.
       
   500 */
       
   501 void DDriver1Channel::ReceiveDataCancel()
       
   502 	{
       
   503 	if(iReceiveDataStatus)
       
   504 		{
       
   505 		// Tell PDD to stop processing the request
       
   506 		Pdd()->ReceiveDataCancel();
       
   507 		// Cancel DFC
       
   508 		iReceiveDataDfc.Cancel();
       
   509 		// Finished with client descriptor, so NULL it to help detect coding errors
       
   510 		iReceiveDataDescriptor = NULL;
       
   511 		// Complete clients request
       
   512 		Kern::RequestComplete(iClient,iReceiveDataStatus,KErrCancel);
       
   513 		}
       
   514 	}
       
   515 
       
   516 /**
       
   517   Called by PDD from ISR to indicate that a ReceiveData operation has completed.
       
   518 */
       
   519 void DDriver1Channel::ReceiveDataComplete(TInt aResult)
       
   520 	{
       
   521 	// Save result code
       
   522 	iReceiveDataResult = aResult;
       
   523 	// Queue DFC
       
   524 	iReceiveDataDfc.Add();
       
   525 	}
       
   526 
       
   527 /**
       
   528   DFC Callback which gets triggered after the PDD has signalled that ReceiveData completed.
       
   529   This just casts aPtr and calls DoReceiveDataComplete().
       
   530 */
       
   531 void DDriver1Channel::ReceiveDataDfc(TAny* aPtr)
       
   532 	{
       
   533 	((DDriver1Channel*)aPtr)->DoReceiveDataComplete();
       
   534 	}
       
   535 
       
   536 /**
       
   537   Called from a DFC after the PDD has signalled that ReceiveData completed.
       
   538 */
       
   539 void DDriver1Channel::DoReceiveDataComplete()
       
   540 	{
       
   541 	// Write data to client from our buffer
       
   542 	TInt result=Kern::ThreadDesWrite(iClient,iReceiveDataDescriptor,iReceiveDataBuffer,0);
       
   543 
       
   544 	// Finished with client descriptor, so NULL it to help detect coding errors
       
   545 	iReceiveDataDescriptor = NULL;
       
   546 
       
   547 	// Use result code from PDD if it was an error
       
   548 	if(iReceiveDataResult!=KErrNone)
       
   549 		result = iReceiveDataResult;
       
   550 
       
   551 	// Complete clients request
       
   552 	Kern::RequestComplete(iClient,iReceiveDataStatus,result);
       
   553 	}
       
   554