examples/Base/IPC/AdvancedClientServerExample/driver/driver1_pdd.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 Physical Device Driver
00015 //
00016 
00017 
00018 
00023 #include <kern_priv.h>
00024 #include "driver1.h"
00025 #include "driver1_dev.h"
00026 
00030 class DDevice1PddFactory : public DPhysicalDevice
00031         {
00032 public:
00033         DDevice1PddFactory();
00034         
00035         // Inherited from DPhysicalDevice
00036         virtual TInt Install();
00037         virtual void GetCaps(TDes8& aDes) const;
00038         virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
00039         virtual TInt Validate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
00040 public:
00041         TInt iHardwareInUse;
00042 private:
00046         enum TMinimumLDDVersion
00047                 {
00048                 EMinimumLddMajorVersion=1,
00049                 EMinimumLddMinorVersion=0,
00050                 EMinimumLddBuild=0 //Not used
00051                 };
00052         };
00053 
00054 // Name for PDD, must match LDD name with a '.' and distinguishing name appended
00055 _LIT(KDriver1PddName,"DRIVER1.template");
00056 
00060 class DDriver1Device : public DDriver1
00061         {
00062 public:
00063         DDriver1Device(DDevice1PddFactory* aFactory);
00064         ~DDriver1Device();
00065         TInt DoCreate();
00066         
00067         // Inherited from DDriver1. These functions are called by the LDD.
00068         virtual TInt BufferSize() const;
00069         virtual TInt Speed() const;
00070         virtual TInt SetSpeed(TInt aSpeed);
00071         virtual TInt SendData(const TDesC8& aData);
00072         virtual void SendDataCancel();
00073         virtual TInt ReceiveData(TDes8& aBuffer);
00074         virtual void ReceiveDataCancel();
00075 private:
00076         static void SendDataTimerCallback(TAny* aPtr);
00077         void SendDataCallback();
00078         static void ReceiveDataTimerCallback(TAny* aPtr);
00079         void ReceiveDataCallback();
00080 private:
00081         DDevice1PddFactory* iFactory;
00082         TInt iSpeed;
00083         NTimer iSendDataTimer;
00084         NTimer iReceiveDataTimer;
00085         TBuf8<256> iBuffer;
00086         TDes8* iReceiveBuffer;
00087         };
00088 //
00089 // DDevice1PddFactory
00090 //
00091 
00096 DECLARE_STANDARD_PDD()
00097         {
00098         return new DDevice1PddFactory;
00099         }
00100 
00101 DDevice1PddFactory::DDevice1PddFactory()
00102         {
00103         // Sets version number for this device
00104         iVersion=RDriver1::VersionRequired();
00105         }
00106 
00112 TInt DDevice1PddFactory::Install()
00113         {
00114         return SetName(&KDriver1PddName);
00115         }
00116 
00122 void DDevice1PddFactory::GetCaps(TDes8& aDes) const
00123         {
00124         // Create a capabilities object
00125         DDriver1::TCaps caps;
00126         caps.iVersion = iVersion;
00127         // Zero the buffer
00128         TInt maxLen = aDes.MaxLength();
00129         aDes.FillZ(maxLen);
00130         // Copy capabilities
00131         TInt size=sizeof(caps);
00132         if(size>maxLen)
00133                 size=maxLen;
00134         aDes.Copy((TUint8*)&caps,size);
00135         }
00136 
00148 TInt DDevice1PddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
00149         {
00150         // Ignore the parameters we aren't interested in...
00151         (void)aUnit;
00152         (void)aInfo;
00153         (void)aVer;
00154 
00155         // Create a new physical channel
00156         DDriver1Device* device=new DDriver1Device(this);
00157         aChannel=device;
00158         if (!device)
00159                 return KErrNoMemory;
00160         return device->DoCreate();
00161         }
00162 
00173 TInt DDevice1PddFactory::Validate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
00174         {
00175         // Check version numbers
00176         if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(EMinimumLddMajorVersion,EMinimumLddMinorVersion,EMinimumLddBuild))))
00177                 return KErrNotSupported;
00178 
00179         // We don't support units
00180     if (aUnit != -1)
00181         return KErrNotSupported;
00182 
00183         // Ignore extra info, (this could be used for validation purposes).
00184         // Note, aInfo is a pointer to a descriptor in user memory, therefore safe methods should
00185         // be used for reading its contents e.g. using Kern::KUDesGet()
00186         (void)aInfo;
00187 
00188         // OK
00189         return KErrNone;
00190         }
00191 
00195 DDriver1Device::DDriver1Device(DDevice1PddFactory* aFactory)
00196         :       iFactory(aFactory),
00197                 iSpeed(100000),  // 100000us (100ms) per byte
00198                 iSendDataTimer(SendDataTimerCallback,this),
00199                 iReceiveDataTimer(ReceiveDataTimerCallback,this)
00200         {
00201         }
00202 
00206 DDriver1Device::~DDriver1Device()
00207         {
00208         // Driver no longer using hardware resources
00209         NKern::LockedDec(iFactory->iHardwareInUse);
00210         }
00211 
00212 TInt DDriver1Device::DoCreate()
00213         {
00214         // Claim the hardware resources by incrementing iHardwareInUse.
00215         // Must do this before any other failure can happen in this function so that
00216         // the destructor can safely decrement iHardwareInUse.
00217         //
00218         // This method of ensuring hardware is only in use by one driver at a time
00219         // wouldn't be needed if the driver claimed real hardware resources which
00220         // could only be used once. E.g. binding to an interrupt.
00221         if(NKern::LockedInc(iFactory->iHardwareInUse))
00222                 return KErrInUse;
00223 
00224         // Other setup goes here
00225         return KErrNone;
00226         }
00230 TInt DDriver1Device::BufferSize() const
00231         {
00232         return iBuffer.MaxSize();
00233         }
00234         
00238 TInt DDriver1Device::Speed() const
00239         {
00240         return iSpeed;
00241         }
00242 
00247 TInt DDriver1Device::SetSpeed(TInt aSpeed)
00248         {
00249         if(aSpeed<=0)
00250                 return KErrArgument;
00251         iSpeed = aSpeed;
00252         return KErrNone;
00253         }
00254 
00255 // Methods for processing 'SendData'
00256 //
00260 TInt DDriver1Device::SendData(const TDesC8& aData)
00261         {
00262         // Save the last part of the data to 'send', we will pretend to 'receive' this later
00263         iBuffer=aData.Right(iBuffer.MaxSize());
00264         // Pretend to send the data by waiting for iSpeed micro-seconds per byte...
00265         iSendDataTimer.OneShot(aData.Size()*iSpeed/NKern::TickPeriod());
00266         return KErrNone;
00267         }
00268 
00272 void DDriver1Device::SendDataCancel()
00273         {
00274         // Stop the timer we were using to pretend we were processing the send.
00275         iSendDataTimer.Cancel();
00276         }
00277 
00282 void DDriver1Device::SendDataTimerCallback(TAny* aPtr)
00283         {
00284         // Just forward callback to non-static callback function
00285         ((DDriver1Device*)aPtr)->SendDataCallback();
00286         }
00287 
00291 void DDriver1Device::SendDataCallback()
00292         {
00293         // Tell LDD we've finished
00294         iLdd->SendDataComplete(KErrNone);
00295         }
00296         
00297 //
00298 // Methods for processing 'ReceiveData'
00299 //
00303 TInt DDriver1Device::ReceiveData(TDes8& aBuffer)
00304         {
00305         // Save a pointer to the buffer we need to put the 'received' data in
00306         iReceiveBuffer=&aBuffer;
00307         // Pretend to receive the data by waiting for iSpeed micro-seconds per byte...
00308         iReceiveDataTimer.OneShot(iBuffer.Size()*iSpeed/NKern::TickPeriod());
00309         return KErrNone;
00310         }
00314 void DDriver1Device::ReceiveDataCancel()
00315         {
00316         // Stop the timer we were using to pretend we were processing the receive
00317         iReceiveDataTimer.Cancel();
00318         }
00323 void DDriver1Device::ReceiveDataTimerCallback(TAny* aPtr)
00324         {
00325         // Just forward callback to non-static callback function
00326         ((DDriver1Device*)aPtr)->ReceiveDataCallback();
00327         }
00331 void DDriver1Device::ReceiveDataCallback()
00332         {
00333         // Pretend the data we have received is that saved in iBuffer when we last did a send
00334         *iReceiveBuffer=iBuffer;
00335         // Tell LDD we've finished
00336         iLdd->ReceiveDataComplete(KErrNone);
00337         }

Generated by  doxygen 1.6.2