diff -r 89d6a7a84779 -r 25a17d01db0c Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/driver1__ldd_8cpp-source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/driver1__ldd_8cpp-source.html Fri Jan 22 18:26:19 2010 +0000 @@ -0,0 +1,433 @@ + +
+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 +