00001 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). 00002 // All rights reserved. 00003 // This component and the accompanying materials are made available 00004 // under the terms of "Eclipse Public License v1.0" 00005 // which accompanies this distribution, and is available 00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html". 00007 // 00008 // Initial Contributors: 00009 // Nokia Corporation - initial contribution. 00010 // 00011 // Contributors: 00012 // 00013 // Description: 00014 // Example Logical Device Driver 00015 // 00016 00017 00018 00023 #include <kern_priv.h> 00024 #include "driver1.h" 00025 #include "driver1_dev.h" 00026 00027 _LIT(KDriver1PanicCategory,"Driver1"); 00028 00029 // 00030 // DDriver1Factory 00031 // 00032 00037 DECLARE_STANDARD_LDD() 00038 { 00039 return new DDriver1Factory; 00040 } 00041 00045 DDriver1Factory::DDriver1Factory() 00046 { 00047 // Sets the version number for this device. 00048 iVersion=RDriver1::VersionRequired(); 00049 // Indicate that we work with a PDD 00050 iParseMask=KDeviceAllowPhysicalDevice; 00051 } 00052 00059 TInt DDriver1Factory::Install() 00060 { 00061 return SetName(&RDriver1::Name()); 00062 } 00063 00067 DDriver1Factory::~DDriver1Factory() 00068 { 00069 } 00070 00076 void DDriver1Factory::GetCaps(TDes8& aDes) const 00077 { 00078 // Create a capabilities object 00079 RDriver1::TCaps caps; 00080 caps.iVersion = iVersion; 00081 // Write it back to user memory 00082 Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps)); 00083 } 00084 00093 TInt DDriver1Factory::Create(DLogicalChannelBase*& aChannel) 00094 { 00095 aChannel=new DDriver1Channel; 00096 if(!aChannel) 00097 return KErrNoMemory; 00098 00099 return KErrNone; 00100 } 00101 00105 DDriver1Channel::DDriver1Channel() 00106 : iSendDataDfc(SendDataDfc, this, 1), // DFC is priority '1' 00107 iReceiveDataDfc(ReceiveDataDfc, this, 1) // DFC is priority '1' 00108 { 00109 // Get pointer to client thread's DThread object 00110 iClient=&Kern::CurrentThread(); 00111 00112 // Open a reference on client thread so its control block can't disappear until 00113 // this driver has finished with it. 00114 // Note, this call to Open can't fail since it's the thread we are currently running in. 00115 iClient->Open(); 00116 } 00117 00128 TInt DDriver1Channel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer) 00129 { 00130 // Check Platform Security capabilities of client thread (if required). 00131 // 00132 // Here we handle the simple case where: 00133 // 1. The device driver can only have one client thread 00134 // 2. The security policy is the binary all-or-nothing policy. 00135 // E.g. "If you have the right capability you can do anything with the driver 00136 // and if you don't have the capability you can't do anything" 00137 // 00138 // If only some functionality of the driver is restricted, then the security check should 00139 // go elsewhere, e.g. in DoRequest/DoControl. In that case Kern::CurrentThreadHasCapability() 00140 // shouldn't be used because the 'current thread' isn't the client. 00141 // 00142 // In this example we do a check here for ECapabilityMultimediaDD... 00143 if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by DRIVER1"))) 00144 return KErrPermissionDenied; 00145 00146 // Check version 00147 if (!Kern::QueryVersionSupported(RDriver1::VersionRequired(),aVer)) 00148 return KErrNotSupported; 00149 00150 // Setup LDD for receiving client messages 00151 SetDfcQ(Kern::DfcQue0()); 00152 iMsgQ.Receive(); 00153 00154 // To receive client messages, associate the DFCs with the queue created above. 00155 iSendDataDfc.SetDfcQ(iDfcQ); 00156 iReceiveDataDfc.SetDfcQ(iDfcQ); 00157 00158 // Give PDD a pointer to this channel 00159 Pdd()->iLdd=this; 00160 00161 // Done 00162 return KErrNone; 00163 } 00164 00168 DDriver1Channel::~DDriver1Channel() 00169 { 00170 // Cancel all processing that we may be doing 00171 DoCancel(RDriver1::EAllRequests); 00172 // Close our reference on the client thread 00173 Kern::SafeClose((DObject*&)iClient,NULL); 00174 } 00175 00183 TInt DDriver1Channel::RequestUserHandle(DThread* aThread, TOwnerType aType) 00184 { 00185 // Make sure that only our client can get a handle 00186 if (aType!=EOwnerThread || aThread!=iClient) 00187 return KErrAccessDenied; 00188 return KErrNone; 00189 } 00190 00202 void DDriver1Channel::HandleMsg(TMessageBase* aMsg) 00203 { 00204 TThreadMessage& m=*(TThreadMessage*)aMsg; 00205 00206 // Get message type 00207 TInt id=m.iValue; 00208 00209 // Decode the message type and dispatch it to the relevent handler function... 00210 if (id==(TInt)ECloseMsg) 00211 { 00212 // Channel Close 00213 DoCancel(RDriver1::EAllRequests); 00214 m.Complete(KErrNone, EFalse); 00215 return; 00216 } 00217 00218 if (id==KMaxTInt) 00219 { 00220 // DoCancel 00221 DoCancel(m.Int0()); 00222 m.Complete(KErrNone,ETrue); 00223 return; 00224 } 00225 00226 if (id<0) 00227 { 00228 // DoRequest 00229 TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); 00230 TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2()); 00231 if (r!=KErrNone) 00232 Kern::RequestComplete(iClient,pS,r); 00233 m.Complete(KErrNone,ETrue); 00234 } 00235 else 00236 { 00237 // DoControl 00238 TInt r=DoControl(id,m.Ptr0(),m.Ptr1()); 00239 m.Complete(r,ETrue); 00240 } 00241 } 00242 00250 TInt DDriver1Channel::DoControl(TInt aFunction, TAny* a1, TAny* a2) 00251 { 00252 (void)a2; // a2 not used in this example 00253 00254 TInt r; 00255 00256 switch (aFunction) 00257 { 00258 case RDriver1::EGetConfig: 00259 r = GetConfig((TDes8*)a1); 00260 break; 00261 00262 case RDriver1::ESetConfig: 00263 r = SetConfig((const TDesC8*)a1); 00264 break; 00265 00266 default: 00267 r = KErrNotSupported; 00268 break; 00269 } 00270 00271 return r; 00272 } 00273 00282 TInt DDriver1Channel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2) 00283 { 00284 (void)a2; // a2 not used in this example 00285 00286 TInt r; 00287 00288 switch(aReqNo) 00289 { 00290 case RDriver1::ESendData: 00291 r=SendData(aStatus,(const TDesC8*)a1); 00292 break; 00293 00294 case RDriver1::EReceiveData: 00295 r=ReceiveData(aStatus,(TDes8*)a1); 00296 break; 00297 00298 default: 00299 r = KErrNotSupported; 00300 break; 00301 } 00302 00303 return r; 00304 } 00305 00310 void DDriver1Channel::DoCancel(TUint aMask) 00311 { 00312 if(aMask&(1<<RDriver1::ESendData)) 00313 SendDataCancel(); 00314 if(aMask&(1<<RDriver1::EReceiveData)) 00315 ReceiveDataCancel(); 00316 } 00317 00318 // 00319 // Methods for processing configuration control messages 00320 // 00321 00326 TInt DDriver1Channel::GetConfig(TDes8* aConfigBuf) 00327 { 00328 // Create a structure giving the current configuration 00329 RDriver1::TConfig config; 00330 CurrentConfig(config); 00331 00332 // Write the config to the client 00333 TPtrC8 ptr((const TUint8*)&config,sizeof(config)); 00334 return Kern::ThreadDesWrite(iClient,aConfigBuf,ptr,0,KTruncateToMaxLength,NULL); 00335 } 00336 00341 TInt DDriver1Channel::SetConfig(const TDesC8* aConfigBuf) 00342 { 00343 // Don't allow configuration changes whilst we're busy 00344 if(iSendDataStatus || iReceiveDataStatus) 00345 return KErrInUse; 00346 00347 // Create a config structure. 00348 RDriver1::TConfig config; 00349 CurrentConfig(config); 00350 00351 // Note: We have filled config with the current settings, this is to allow 00352 // backwards compatibility when a client gives us an old (and shorter) version 00353 // of the config structure. 00354 00355 // Read the config structure from client 00356 TPtr8 ptr((TUint8*)&config,sizeof(config)); 00357 TInt r=Kern::ThreadDesRead(iClient,aConfigBuf,ptr,0); 00358 if(r!=KErrNone) 00359 return r; 00360 00361 // Use config data to setup the driver. Checking that parameters which aren't settable 00362 // either contain the correct values or are zero (meaning 'default') 00363 if(config.iPddBufferSize && config.iPddBufferSize!=Pdd()->BufferSize()) 00364 return KErrArgument; 00365 00366 if(config.iMaxSendDataSize && config.iMaxSendDataSize!=iSendDataBuffer.MaxSize()) 00367 return KErrArgument; 00368 00369 if(config.iMaxReceiveDataSize && config.iMaxReceiveDataSize!=iReceiveDataBuffer.MaxSize()) 00370 return KErrArgument; 00371 00372 r=Pdd()->SetSpeed(config.iSpeed); 00373 if(r!=KErrNone) 00374 return r; 00375 00376 return r; 00377 } 00378 00383 void DDriver1Channel::CurrentConfig(RDriver1::TConfig& aConfig) 00384 { 00385 aConfig.iSpeed = Pdd()->Speed(); 00386 aConfig.iPddBufferSize = Pdd()->BufferSize(); 00387 aConfig.iMaxSendDataSize = iSendDataBuffer.MaxSize(); 00388 aConfig.iMaxReceiveDataSize = iReceiveDataBuffer.MaxSize(); 00389 } 00390 00391 // 00392 // Methods for processing 'SendData' 00393 // 00394 00402 TInt DDriver1Channel::SendData(TRequestStatus* aStatus,const TDesC8* aData) 00403 { 00404 // Check that a 'SendData' isn't already in progress 00405 if(iSendDataStatus) 00406 { 00407 Kern::ThreadKill(iClient,EExitPanic,ERequestAlreadyPending,KDriver1PanicCategory); 00408 return KErrInUse; 00409 } 00410 00411 // Read data from client into our buffer 00412 TInt r=Kern::ThreadDesRead(iClient,aData,iSendDataBuffer,0); 00413 if(r!=KErrNone) 00414 return r; 00415 00416 // Give data to PDD so that it can do the work 00417 r=Pdd()->SendData(iSendDataBuffer); 00418 if(r!=KErrNone) 00419 return r; 00420 00421 // Save the client request status and return 00422 iSendDataStatus = aStatus; 00423 return KErrNone; 00424 } 00425 00429 void DDriver1Channel::SendDataCancel() 00430 { 00431 if(iSendDataStatus) 00432 { 00433 // Tell PDD to stop processing the request 00434 Pdd()->SendDataCancel(); 00435 // Cancel DFC 00436 iSendDataDfc.Cancel(); 00437 // Complete client's request 00438 Kern::RequestComplete(iClient,iSendDataStatus,KErrCancel); 00439 } 00440 } 00441 00445 void DDriver1Channel::SendDataComplete(TInt aResult) 00446 { 00447 // Save result code 00448 iSendDataResult = aResult; 00449 // Queue DFC 00450 iSendDataDfc.Add(); 00451 } 00452 00457 void DDriver1Channel::SendDataDfc(TAny* aPtr) 00458 { 00459 ((DDriver1Channel*)aPtr)->DoSendDataComplete(); 00460 } 00461 00465 void DDriver1Channel::DoSendDataComplete() 00466 { 00467 TInt result = iSendDataResult; 00468 // Complete clients request 00469 Kern::RequestComplete(iClient,iSendDataStatus,result); 00470 } 00471 00472 // 00473 // Methods for processing 'ReceiveData' 00474 // 00475 00482 TInt DDriver1Channel::ReceiveData(TRequestStatus* aStatus,TDes8* aPtr) 00483 { 00484 // Check that a 'ReceiveData' isn't already in progress 00485 if(iReceiveDataStatus) 00486 { 00487 Kern::ThreadKill(iClient,EExitPanic,ERequestAlreadyPending,KDriver1PanicCategory); 00488 return KErrInUse; 00489 } 00490 00491 // Ask PDD for data 00492 TInt r=Pdd()->ReceiveData(iReceiveDataBuffer); 00493 if(r!=KErrNone) 00494 return r; 00495 00496 // Save the client request status and descriptor before returning 00497 iReceiveDataStatus = aStatus; 00498 iReceiveDataDescriptor = aPtr; 00499 return KErrNone; 00500 } 00501 00505 void DDriver1Channel::ReceiveDataCancel() 00506 { 00507 if(iReceiveDataStatus) 00508 { 00509 // Tell PDD to stop processing the request 00510 Pdd()->ReceiveDataCancel(); 00511 // Cancel DFC 00512 iReceiveDataDfc.Cancel(); 00513 // Finished with client descriptor, so NULL it to help detect coding errors 00514 iReceiveDataDescriptor = NULL; 00515 // Complete clients request 00516 Kern::RequestComplete(iClient,iReceiveDataStatus,KErrCancel); 00517 } 00518 } 00519 00523 void DDriver1Channel::ReceiveDataComplete(TInt aResult) 00524 { 00525 // Save result code 00526 iReceiveDataResult = aResult; 00527 // Queue DFC 00528 iReceiveDataDfc.Add(); 00529 } 00530 00535 void DDriver1Channel::ReceiveDataDfc(TAny* aPtr) 00536 { 00537 ((DDriver1Channel*)aPtr)->DoReceiveDataComplete(); 00538 } 00539 00543 void DDriver1Channel::DoReceiveDataComplete() 00544 { 00545 // Write data to client from our buffer 00546 TInt result=Kern::ThreadDesWrite(iClient,iReceiveDataDescriptor,iReceiveDataBuffer,0); 00547 00548 // Finished with client descriptor, so NULL it to help detect coding errors 00549 iReceiveDataDescriptor = NULL; 00550 00551 // Use result code from PDD if it was an error 00552 if(iReceiveDataResult!=KErrNone) 00553 result = iReceiveDataResult; 00554 00555 // Complete client's request 00556 Kern::RequestComplete(iClient,iReceiveDataStatus,result); 00557 } 00558
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.