diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/driver1__ldd_8cpp-source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/driver1__ldd_8cpp-source.html Tue Mar 30 11:56:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,433 +0,0 @@ - -
-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 -