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 }
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.