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

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010   this list of conditions and the following disclaimer in the documentation
00011   and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013   may be used to endorse or promote products derived from this software
00014   without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description: Example Logical Device Driver 
00028 */
00029 
00034 #include <kern_priv.h>
00035 #include "driver1.h"
00036 #include "driver1_dev.h"
00037 
00038 _LIT(KDriver1PanicCategory,"Driver1");
00039 
00040 //
00041 // DDriver1Factory
00042 //
00043 
00048 DECLARE_STANDARD_LDD()
00049         {
00050         return new DDriver1Factory;
00051         }
00052 
00056 DDriver1Factory::DDriver1Factory()
00057         {
00058         // Sets the version number for this device.
00059         iVersion=RDriver1::VersionRequired();
00060         // Indicate that we work with a PDD
00061         iParseMask=KDeviceAllowPhysicalDevice;
00062         }
00063 
00070 TInt DDriver1Factory::Install()
00071         {
00072         return SetName(&RDriver1::Name());
00073         }
00074 
00078 DDriver1Factory::~DDriver1Factory()
00079         {
00080         }
00081 
00087 void DDriver1Factory::GetCaps(TDes8& aDes) const
00088         {
00089         // Create a capabilities object
00090         RDriver1::TCaps caps;
00091         caps.iVersion = iVersion;
00092         // Write it back to user memory
00093         Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
00094         }
00095 
00104 TInt DDriver1Factory::Create(DLogicalChannelBase*& aChannel)
00105         {
00106         aChannel=new DDriver1Channel;
00107         if(!aChannel)
00108                 return KErrNoMemory;
00109 
00110         return KErrNone;
00111         }
00112 
00116 DDriver1Channel::DDriver1Channel()
00117         :       iSendDataDfc(SendDataDfc, this, 1),        // DFC is priority '1'
00118                 iReceiveDataDfc(ReceiveDataDfc, this, 1)   // DFC is priority '1'
00119         {
00120         // Get pointer to client thread's DThread object
00121         iClient=&Kern::CurrentThread();
00122 
00123         // Open a reference on client thread so its control block can't disappear until
00124         // this driver has finished with it.
00125         // Note, this call to Open can't fail since it's the thread we are currently running in.
00126         iClient->Open();
00127         }
00128 
00139 TInt DDriver1Channel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
00140         {
00141         // Check Platform Security capabilities of client thread (if required).
00142         //
00143         // Here we handle the simple case where:
00144         // 1. The device driver can only have one client thread
00145         // 2. The security policy is the binary all-or-nothing policy.
00146         //    E.g. "If you have the right capability you can do anything with the driver
00147         //    and if you don't have the capability you can't do anything"
00148         // 
00149         // If only some functionality of the driver is restricted, then the security check should
00150         // go elsewhere, e.g. in DoRequest/DoControl. In that case Kern::CurrentThreadHasCapability()
00151         // shouldn't be used because the 'current thread' isn't the client.
00152         //
00153         // In this example we do a check here for ECapabilityMultimediaDD...
00154         if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by DRIVER1")))
00155                 return KErrPermissionDenied;
00156 
00157         // Check version
00158         if (!Kern::QueryVersionSupported(RDriver1::VersionRequired(),aVer))
00159                 return KErrNotSupported;
00160 
00161         // Setup LDD for receiving client messages
00162         SetDfcQ(Kern::DfcQue0());
00163         iMsgQ.Receive();
00164 
00165         // To receive client messages, associate the DFCs with the queue created above.
00166         iSendDataDfc.SetDfcQ(iDfcQ);
00167         iReceiveDataDfc.SetDfcQ(iDfcQ);
00168 
00169         // Give PDD a pointer to this channel
00170         Pdd()->iLdd=this;
00171 
00172         // Done
00173         return KErrNone;
00174         }
00175 
00179 DDriver1Channel::~DDriver1Channel()
00180         {
00181         // Cancel all processing that we may be doing
00182         DoCancel(RDriver1::EAllRequests);
00183         // Close our reference on the client thread
00184         Kern::SafeClose((DObject*&)iClient,NULL);
00185         }
00186 
00194 TInt DDriver1Channel::RequestUserHandle(DThread* aThread, TOwnerType aType)
00195         {
00196         // Make sure that only our client can get a handle
00197         if (aType!=EOwnerThread || aThread!=iClient)
00198                 return KErrAccessDenied;
00199         return KErrNone;
00200         }
00201 
00213 void DDriver1Channel::HandleMsg(TMessageBase* aMsg)
00214         {
00215         TThreadMessage& m=*(TThreadMessage*)aMsg;
00216 
00217         // Get message type
00218         TInt id=m.iValue;
00219 
00220         // Decode the message type and dispatch it to the relevent handler function...
00221         if (id==(TInt)ECloseMsg)
00222                 {
00223                 // Channel Close
00224                 DoCancel(RDriver1::EAllRequests);
00225                 m.Complete(KErrNone, EFalse);
00226                 return;
00227                 }
00228 
00229         if (id==KMaxTInt)
00230                 {
00231                 // DoCancel
00232                 DoCancel(m.Int0());
00233                 m.Complete(KErrNone,ETrue);
00234                 return;
00235                 }
00236 
00237         if (id<0)
00238                 {
00239                 // DoRequest
00240                 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
00241                 TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
00242                 if (r!=KErrNone)
00243                         Kern::RequestComplete(iClient,pS,r);
00244                 m.Complete(KErrNone,ETrue);
00245                 }
00246         else
00247                 {
00248                 // DoControl
00249                 TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
00250                 m.Complete(r,ETrue);
00251                 }
00252         }
00253 
00261 TInt DDriver1Channel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
00262         {
00263         (void)a2;   // a2 not used in this example
00264 
00265         TInt r;
00266 
00267         switch (aFunction)
00268                 {
00269                 case RDriver1::EGetConfig:
00270                         r = GetConfig((TDes8*)a1);
00271                         break;
00272 
00273                 case RDriver1::ESetConfig:
00274                         r = SetConfig((const TDesC8*)a1);
00275                         break;
00276 
00277                 default:
00278                         r = KErrNotSupported;
00279                         break;
00280                 }
00281 
00282         return r;
00283         }
00284 
00293 TInt DDriver1Channel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
00294         {
00295         (void)a2;   // a2 not used in this example
00296 
00297         TInt r;
00298 
00299         switch(aReqNo)
00300                 {
00301                 case RDriver1::ESendData:
00302                         r=SendData(aStatus,(const TDesC8*)a1);
00303                         break;
00304 
00305                 case RDriver1::EReceiveData:
00306                         r=ReceiveData(aStatus,(TDes8*)a1);
00307                         break;
00308 
00309                 default:
00310                         r = KErrNotSupported;
00311                         break;
00312                 }
00313 
00314         return r;
00315         }
00316 
00321 void DDriver1Channel::DoCancel(TUint aMask)
00322         {
00323         if(aMask&(1<<RDriver1::ESendData))
00324                 SendDataCancel();
00325         if(aMask&(1<<RDriver1::EReceiveData))
00326                 ReceiveDataCancel();
00327         }
00328 
00329 //
00330 // Methods for processing configuration control messages
00331 //
00332 
00337 TInt DDriver1Channel::GetConfig(TDes8* aConfigBuf)
00338         {
00339         // Create a structure giving the current configuration
00340         RDriver1::TConfig config;
00341         CurrentConfig(config);
00342 
00343         // Write the config to the client
00344         TPtrC8 ptr((const TUint8*)&config,sizeof(config));
00345         return Kern::ThreadDesWrite(iClient,aConfigBuf,ptr,0,KTruncateToMaxLength,NULL);
00346         }
00347 
00352 TInt DDriver1Channel::SetConfig(const TDesC8* aConfigBuf)
00353         {
00354         // Don't allow configuration changes whilst we're busy
00355         if(iSendDataStatus || iReceiveDataStatus)
00356                 return KErrInUse;
00357 
00358         // Create a config structure.
00359         RDriver1::TConfig config;
00360         CurrentConfig(config);
00361 
00362         // Note: We have filled config with the current settings, this is to allow
00363         // backwards compatibility when a client gives us an old (and shorter) version
00364         // of the config structure.
00365 
00366         // Read the config structure from client
00367         TPtr8 ptr((TUint8*)&config,sizeof(config));
00368         TInt r=Kern::ThreadDesRead(iClient,aConfigBuf,ptr,0);
00369         if(r!=KErrNone)
00370                 return r;
00371 
00372         // Use config data to setup the driver. Checking that parameters which aren't settable
00373         // either contain the correct values or are zero (meaning 'default')
00374         if(config.iPddBufferSize && config.iPddBufferSize!=Pdd()->BufferSize())
00375                 return KErrArgument;
00376 
00377         if(config.iMaxSendDataSize && config.iMaxSendDataSize!=iSendDataBuffer.MaxSize())
00378                 return KErrArgument;
00379 
00380         if(config.iMaxReceiveDataSize && config.iMaxReceiveDataSize!=iReceiveDataBuffer.MaxSize())
00381                 return KErrArgument;
00382 
00383         r=Pdd()->SetSpeed(config.iSpeed);
00384         if(r!=KErrNone)
00385                 return r;
00386 
00387         return r;
00388         }
00389 
00394 void DDriver1Channel::CurrentConfig(RDriver1::TConfig& aConfig)
00395         {
00396         aConfig.iSpeed = Pdd()->Speed();
00397         aConfig.iPddBufferSize = Pdd()->BufferSize();
00398         aConfig.iMaxSendDataSize = iSendDataBuffer.MaxSize();
00399         aConfig.iMaxReceiveDataSize = iReceiveDataBuffer.MaxSize();
00400         }
00401 
00402 //
00403 // Methods for processing 'SendData'
00404 //
00405 
00413 TInt DDriver1Channel::SendData(TRequestStatus* aStatus,const TDesC8* aData)
00414         {
00415         // Check that a 'SendData' isn't already in progress
00416         if(iSendDataStatus)
00417                 {
00418                 Kern::ThreadKill(iClient,EExitPanic,ERequestAlreadyPending,KDriver1PanicCategory);
00419                 return KErrInUse;
00420                 }
00421 
00422         // Read data from client into our buffer
00423         TInt r=Kern::ThreadDesRead(iClient,aData,iSendDataBuffer,0);
00424         if(r!=KErrNone)
00425                 return r;
00426 
00427         // Give data to PDD so that it can do the work
00428         r=Pdd()->SendData(iSendDataBuffer);
00429         if(r!=KErrNone)
00430                 return r;
00431 
00432         // Save the client request status and return
00433         iSendDataStatus = aStatus;
00434         return KErrNone;
00435         }
00436 
00440 void DDriver1Channel::SendDataCancel()
00441         {
00442         if(iSendDataStatus)
00443                 {
00444                 // Tell PDD to stop processing the request
00445                 Pdd()->SendDataCancel();
00446                 // Cancel DFC
00447                 iSendDataDfc.Cancel();
00448                 // Complete client's request
00449                 Kern::RequestComplete(iClient,iSendDataStatus,KErrCancel);
00450                 }
00451         }
00452 
00456 void DDriver1Channel::SendDataComplete(TInt aResult)
00457         {
00458         // Save result code
00459         iSendDataResult = aResult;
00460         // Queue DFC
00461         iSendDataDfc.Add();
00462         }
00463 
00468 void DDriver1Channel::SendDataDfc(TAny* aPtr)
00469         {
00470         ((DDriver1Channel*)aPtr)->DoSendDataComplete();
00471         }
00472 
00476 void DDriver1Channel::DoSendDataComplete()
00477         {
00478         TInt result = iSendDataResult;
00479         // Complete clients request
00480         Kern::RequestComplete(iClient,iSendDataStatus,result);
00481         }
00482 
00483 //
00484 // Methods for processing 'ReceiveData'
00485 //
00486 
00493 TInt DDriver1Channel::ReceiveData(TRequestStatus* aStatus,TDes8* aPtr)
00494         {
00495         // Check that a 'ReceiveData' isn't already in progress
00496         if(iReceiveDataStatus)
00497                 {
00498                 Kern::ThreadKill(iClient,EExitPanic,ERequestAlreadyPending,KDriver1PanicCategory);
00499                 return KErrInUse;
00500                 }
00501 
00502         // Ask PDD for data
00503         TInt r=Pdd()->ReceiveData(iReceiveDataBuffer);
00504         if(r!=KErrNone)
00505                 return r;
00506 
00507         // Save the client request status and descriptor before returning
00508         iReceiveDataStatus = aStatus;
00509         iReceiveDataDescriptor = aPtr;
00510         return KErrNone;
00511         }
00512 
00516 void DDriver1Channel::ReceiveDataCancel()
00517         {
00518         if(iReceiveDataStatus)
00519                 {
00520                 // Tell PDD to stop processing the request
00521                 Pdd()->ReceiveDataCancel();
00522                 // Cancel DFC
00523                 iReceiveDataDfc.Cancel();
00524                 // Finished with client descriptor, so NULL it to help detect coding errors
00525                 iReceiveDataDescriptor = NULL;
00526                 // Complete clients request
00527                 Kern::RequestComplete(iClient,iReceiveDataStatus,KErrCancel);
00528                 }
00529         }
00530 
00534 void DDriver1Channel::ReceiveDataComplete(TInt aResult)
00535         {
00536         // Save result code
00537         iReceiveDataResult = aResult;
00538         // Queue DFC
00539         iReceiveDataDfc.Add();
00540         }
00541 
00546 void DDriver1Channel::ReceiveDataDfc(TAny* aPtr)
00547         {
00548         ((DDriver1Channel*)aPtr)->DoReceiveDataComplete();
00549         }
00550 
00554 void DDriver1Channel::DoReceiveDataComplete()
00555         {
00556         // Write data to client from our buffer
00557         TInt result=Kern::ThreadDesWrite(iClient,iReceiveDataDescriptor,iReceiveDataBuffer,0);
00558 
00559         // Finished with client descriptor, so NULL it to help detect coding errors
00560         iReceiveDataDescriptor = NULL;
00561 
00562         // Use result code from PDD if it was an error
00563         if(iReceiveDataResult!=KErrNone)
00564                 result = iReceiveDataResult;
00565 
00566         // Complete client's request
00567         Kern::RequestComplete(iClient,iReceiveDataStatus,result);
00568         }
00569 

Generated by  doxygen 1.6.2