kerneltest/e32test/examples/driver1/driver1_pdd.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file Example Pysical Device Driver
       
    18  @publishedPartner
       
    19  @released
       
    20 */
       
    21 
       
    22 #include <kernel/kern_priv.h>
       
    23 #include "driver1.h"
       
    24 #include "driver1_dev.h"
       
    25 
       
    26 // Name for PDD, must match LDD name with a '.' and distinguishing name appended
       
    27 _LIT(KDriver1PddName,"DRIVER1.template");
       
    28 
       
    29 
       
    30 class DDriver1Device : public DDriver1
       
    31 	{
       
    32 public:
       
    33 	DDriver1Device(DDevice1PddFactory* aFactory);
       
    34 	~DDriver1Device();
       
    35 	TInt DoCreate();
       
    36 	// Inherited from DDriver1. These called by the LDD.
       
    37 	virtual TInt BufferSize() const;
       
    38 	virtual TInt Speed() const;
       
    39 	virtual TInt SetSpeed(TInt aSpeed);
       
    40 	virtual TInt SendData(const TDesC8& aData);
       
    41 	virtual void SendDataCancel();
       
    42 	virtual TInt ReceiveData(TDes8& aBuffer);
       
    43 	virtual void ReceiveDataCancel();
       
    44 private:
       
    45 	static void SendDataTimerCallback(TAny* aPtr);
       
    46 	void SendDataCallback();
       
    47 	static void ReceiveDataTimerCallback(TAny* aPtr);
       
    48 	void ReceiveDataCallback();
       
    49 private:
       
    50 	DDevice1PddFactory* iFactory;
       
    51 	TInt iSpeed;
       
    52 	NTimer iSendDataTimer;
       
    53 	NTimer iReceiveDataTimer;
       
    54 	TBuf8<256> iBuffer;
       
    55 	TDes8* iReceiveBuffer;
       
    56 	};
       
    57 
       
    58 
       
    59 
       
    60 //
       
    61 // DDevice1PddFactory
       
    62 //
       
    63 
       
    64 const TInt KDriver1ThreadPriority = 27;
       
    65 _LIT(KDriver1Thread,"Driver1Thread");
       
    66 
       
    67 /**
       
    68   Standard export function for PDDs. This creates a DPhysicalDevice derived object,
       
    69   in this case, our DDevice1PddFactory
       
    70 */
       
    71 DECLARE_STANDARD_PDD()
       
    72 	{
       
    73 	return new DDevice1PddFactory;
       
    74 	}
       
    75 
       
    76 DDevice1PddFactory::DDevice1PddFactory()
       
    77 	{
       
    78 	// Set version number for this device
       
    79 	iVersion=RDriver1::VersionRequired();
       
    80 	}
       
    81 
       
    82 /**
       
    83   Second stage constructor for DPhysicalDevice derived objects.
       
    84   This must at least set a name for the driver object.
       
    85 
       
    86   @return KErrNone or standard error code.
       
    87 */
       
    88 TInt DDevice1PddFactory::Install()
       
    89 	{
       
    90 	// Allocate a kernel thread to run the DFC 
       
    91 	TInt r = Kern::DynamicDfcQCreate(iDfcQ, KDriver1ThreadPriority, KDriver1Thread);
       
    92 	if (r == KErrNone)
       
    93 		{ 
       
    94 		r = SetName(&KDriver1PddName);
       
    95 		} 	
       
    96 	return r;
       
    97 	}
       
    98 
       
    99 /**
       
   100   Returns the drivers capabilities. This is not used by the Symbian OS device driver framework
       
   101   but may be useful for the LDD to use.
       
   102 
       
   103   @param aDes Descriptor to write capabilities information into
       
   104 */
       
   105 void DDevice1PddFactory::GetCaps(TDes8& aDes) const
       
   106 	{
       
   107 	// Create a capabilities object
       
   108 	DDriver1::TCaps caps;
       
   109 	caps.iVersion = iVersion;
       
   110 	// Zero the buffer
       
   111 	TInt maxLen = aDes.MaxLength();
       
   112 	aDes.FillZ(maxLen);
       
   113 	// Copy cpabilities
       
   114 	TInt size=sizeof(caps);
       
   115 	if(size>maxLen)
       
   116 		size=maxLen;
       
   117 	aDes.Copy((TUint8*)&caps,size);
       
   118 	}
       
   119 
       
   120 /**
       
   121   Called by the kernel's device driver framework to create a Physical Channel.
       
   122   This is called in the context of the user thread (client) which requested the creation of a Logical Channel
       
   123   (E.g. through a call to RBusLogicalChannel::DoCreate)
       
   124   The thread is in a critical section.
       
   125 
       
   126   @param aChannel Set to point to the created Physical Channel
       
   127   @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
       
   128   @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
       
   129   @param aVer The version number of the Logical Channel which will use this Physical Channel 
       
   130 
       
   131   @return KErrNone or standard error code.
       
   132 */
       
   133 TInt DDevice1PddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
       
   134 	{
       
   135 	// Ignore the parameters we aren't interested in...
       
   136 	(void)aUnit;
       
   137 	(void)aInfo;
       
   138 	(void)aVer;
       
   139 
       
   140 	// Create a new physical channel
       
   141 	DDriver1Device* device=new DDriver1Device(this);
       
   142 	aChannel=device;
       
   143 	if (!device)
       
   144 		return KErrNoMemory;
       
   145 	return device->DoCreate();
       
   146 	}
       
   147 
       
   148 /**
       
   149   Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.
       
   150   This is called in the context of the user thread (client) which requested the creation of a Logical Channel
       
   151   (E.g. through a call to RBusLogicalChannel::DoCreate)
       
   152   The thread is in a critical section.
       
   153 
       
   154   @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
       
   155   @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
       
   156   @param aVer The version number of the Logical Channel which will use this Physical Channel 
       
   157 
       
   158   @return KErrNone or standard error code.
       
   159 */
       
   160 TInt DDevice1PddFactory::Validate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
       
   161 	{
       
   162 	// Check version numbers
       
   163 	if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(EMinimumLddMajorVersion,EMinimumLddMinorVersion,EMinimumLddBuild))))
       
   164 		return KErrNotSupported;
       
   165 
       
   166 	// We don't support units
       
   167     if (aUnit != -1)
       
   168         return KErrNotSupported;
       
   169 
       
   170 	// Ignore extra info, (this could be used for validation purposes)
       
   171 	// Note, aInof is a pointer to a descriptor in user memory, therefore safe methods should
       
   172 	// be used for reading its contents. E.g. using Kern::KUDesGet()
       
   173 	(void)aInfo;
       
   174 
       
   175 	// OK
       
   176 	return KErrNone;
       
   177 	}
       
   178 
       
   179 /**
       
   180   Destructor
       
   181 */
       
   182 DDevice1PddFactory::~DDevice1PddFactory()
       
   183 	{
       
   184 	if (iDfcQ)
       
   185 		iDfcQ->Destroy();
       
   186 	}
       
   187 
       
   188 //
       
   189 // DDriver1Device
       
   190 //
       
   191 
       
   192 DDriver1Device::DDriver1Device(DDevice1PddFactory* aFactory)
       
   193 	:	iFactory(aFactory),
       
   194 		iSpeed(100000),  // 100000us (100ms) per byte
       
   195 		iSendDataTimer(SendDataTimerCallback,this),
       
   196 		iReceiveDataTimer(ReceiveDataTimerCallback,this)
       
   197 	{
       
   198 	}
       
   199 
       
   200 DDriver1Device::~DDriver1Device()
       
   201 	{
       
   202 	// Driver no longer using hardware resources
       
   203 	__e32_atomic_add_ord32(&iFactory->iHardwareInUse, TUint32(-1));
       
   204 	}
       
   205 
       
   206 TInt DDriver1Device::DoCreate()
       
   207 	{
       
   208 	// Claim the hardware resources by incrementing iHardwareInUse.
       
   209 	// Must do this before any other failure can happen in this function so that
       
   210 	// the destructor can safely decrement iHardwareInUse.
       
   211 	//
       
   212 	// This method of ensuring hardware is only in use by one driver at a time
       
   213 	// wouldn't be needed if the driver claimed real hardware resources which
       
   214 	// could only be used once. E.g. binding to an interrupt.
       
   215 	if (__e32_atomic_add_ord32(&iFactory->iHardwareInUse, 1))
       
   216 		return KErrInUse;
       
   217 
       
   218 	// Other setup goes here
       
   219 
       
   220 	return KErrNone;
       
   221 	}
       
   222 
       
   223 TInt DDriver1Device::BufferSize() const
       
   224 	{
       
   225 	return iBuffer.MaxSize();
       
   226 	}
       
   227 
       
   228 TInt DDriver1Device::Speed() const
       
   229 	{
       
   230 	return iSpeed;
       
   231 	}
       
   232 
       
   233 TInt DDriver1Device::SetSpeed(TInt aSpeed)
       
   234 	{
       
   235 	if(aSpeed<=0)
       
   236 		return KErrArgument;
       
   237 	iSpeed = aSpeed;
       
   238 	return KErrNone;
       
   239 	}
       
   240 
       
   241 TInt DDriver1Device::SendData(const TDesC8& aData)
       
   242 	{
       
   243 	// Save the last part of the data to 'send', we will pretend to 'receive' this later
       
   244 	iBuffer=aData.Right(iBuffer.MaxSize());
       
   245 	// Pretend to send the data by waiting for iSpeed micro-seconds per byte...
       
   246 	iSendDataTimer.OneShot(aData.Size()*iSpeed/NKern::TickPeriod());
       
   247 
       
   248 	return KErrNone;
       
   249 	}
       
   250 
       
   251 void DDriver1Device::SendDataCancel()
       
   252 	{
       
   253 	// Stop the timer we were using to pretend we were processing the send
       
   254 	iSendDataTimer.Cancel();
       
   255 	}
       
   256 
       
   257 void DDriver1Device::SendDataTimerCallback(TAny* aPtr)
       
   258 	{
       
   259 	// Just forward callback to non-static callback function
       
   260 	((DDriver1Device*)aPtr)->SendDataCallback();
       
   261 	}
       
   262 
       
   263 void DDriver1Device::SendDataCallback()
       
   264 	{
       
   265 	// Tell LDD we've done
       
   266 	iLdd->SendDataComplete(KErrNone);
       
   267 	}
       
   268 
       
   269 TInt DDriver1Device::ReceiveData(TDes8& aBuffer)
       
   270 	{
       
   271 	// Save a pointer to the buffer we need to put the 'recevied' data in
       
   272 	iReceiveBuffer=&aBuffer;
       
   273 	// Pretend to receive the data by waiting for iSpeed micro-seconds per byte...
       
   274 	iReceiveDataTimer.OneShot(iBuffer.Size()*iSpeed/NKern::TickPeriod());
       
   275 
       
   276 	return KErrNone;
       
   277 	}
       
   278 
       
   279 void DDriver1Device::ReceiveDataCancel()
       
   280 	{
       
   281 	// Stop the timer we were using to pretend we were processing the receive
       
   282 	iReceiveDataTimer.Cancel();
       
   283 	}
       
   284 
       
   285 void DDriver1Device::ReceiveDataTimerCallback(TAny* aPtr)
       
   286 	{
       
   287 	// Just forward callback to non-static callback function
       
   288 	((DDriver1Device*)aPtr)->ReceiveDataCallback();
       
   289 	}
       
   290 
       
   291 void DDriver1Device::ReceiveDataCallback()
       
   292 	{
       
   293 	// Pretend the data we have received is that saved in iBuffer when we last did a send
       
   294 	*iReceiveBuffer=iBuffer;
       
   295 	// Tell LDD we've done
       
   296 	iLdd->ReceiveDataComplete(KErrNone);
       
   297 	}