examples/Base/IPC/AdvancedClientServerExample/driver/driver1_ldd.cpp

Go to the documentation of this file.
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 

Generated by  doxygen 1.6.2