week 10 bug fix submission (SF PDK version): Bug 1892, Bug 1897, Bug 1319. Also 3 or 4 documents were found to contain code blocks with SFL, which has been fixed. Partial fix for broken links, links to Forum Nokia, and the 'Symbian platform' terminology issues.
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License
"Eclipse Public License v1.0" which accompanies this distribution,
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
Nokia Corporation - initial contribution.
Contributors:
-->
<!DOCTYPE concept
PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept xml:lang="en" id="GUID-3F1E303E-2946-5D71-9D9B-9F4F5B1BC424"><title>driver1_pdd.cpp</title><prolog><metadata><keywords/></metadata></prolog><conbody><codeblock id="GUID-CC1D2B20-43E4-5605-9DA6-AB74D96D1F98" xml:space="preserve">// driver1_pdd.cpp
//
// Copyright (c) 2009 Nokia Ltd. All rights reserved.
//
/**
@file Example Pysical Device Driver
@publishedPartner
@released
*/
#include <kern_priv.h>
#include "driver1.h"
#include "driver1_dev.h"
// Name for PDD, must match LDD name with a '.' and distinguishing name appended
_LIT(KDriver1PddName,"DRIVER1.template");
class DDriver1Device : public DDriver1
{
public:
DDriver1Device(DDevice1PddFactory* aFactory);
~DDriver1Device();
TInt DoCreate();
// Inherited from DDriver1. These called by the LDD.
virtual TInt BufferSize() const;
virtual TInt Speed() const;
virtual TInt SetSpeed(TInt aSpeed);
virtual TInt SendData(const TDesC8& aData);
virtual void SendDataCancel();
virtual TInt ReceiveData(TDes8& aBuffer);
virtual void ReceiveDataCancel();
private:
static void SendDataTimerCallback(TAny* aPtr);
void SendDataCallback();
static void ReceiveDataTimerCallback(TAny* aPtr);
void ReceiveDataCallback();
private:
DDevice1PddFactory* iFactory;
TInt iSpeed;
NTimer iSendDataTimer;
NTimer iReceiveDataTimer;
TBuf8<256> iBuffer;
TDes8* iReceiveBuffer;
};
//
// DDevice1PddFactory
//
const TInt KDriver1ThreadPriority = 27;
_LIT(KDriver1Thread,"Driver1Thread");
/**
Standard export function for PDDs. This creates a DPhysicalDevice derived object,
in this case, our DDevice1PddFactory
*/
DECLARE_STANDARD_PDD()
{
DDevice1PddFactory* p = new DDevice1PddFactory;
if (p)
{
// Allocate a kernel thread to run the DFC
TInt r = Kern::DynamicDfcQCreate(p->iDfcQ, KDriver1ThreadPriority, KDriver1Thread);
if (r != KErrNone)
{
delete p;
return NULL;
}
}
return p;
}
DDevice1PddFactory::DDevice1PddFactory()
{
// Set version number for this device
iVersion=RDriver1::VersionRequired();
}
/**
Second stage constructor for DPhysicalDevice derived objects.
This must at least set a name for the driver object.
@return KErrNone or standard error code.
*/
TInt DDevice1PddFactory::Install()
{
return SetName(&KDriver1PddName);
}
/**
Returns the drivers capabilities. This is not used by the Symbian OS device driver framework
but may be useful for the LDD to use.
@param aDes Descriptor to write capabilities information into
*/
void DDevice1PddFactory::GetCaps(TDes8& aDes) const
{
// Create a capabilities object
DDriver1::TCaps caps;
caps.iVersion = iVersion;
// Zero the buffer
TInt maxLen = aDes.MaxLength();
aDes.FillZ(maxLen);
// Copy cpabilities
TInt size=sizeof(caps);
if(size>maxLen)
size=maxLen;
aDes.Copy((TUint8*)&caps,size);
}
/**
Called by the kernel's device driver framework to create a Physical Channel.
This is called in the context of the user thread (client) which requested the creation of a Logical Channel
(E.g. through a call to RBusLogicalChannel::DoCreate)
The thread is in a critical section.
@param aChannel Set to point to the created Physical Channel
@param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
@param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
@param aVer The version number of the Logical Channel which will use this Physical Channel
@return KErrNone or standard error code.
*/
TInt DDevice1PddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
{
// Ignore the parameters we aren't interested in...
(void)aUnit;
(void)aInfo;
(void)aVer;
// Create a new physical channel
DDriver1Device* device=new DDriver1Device(this);
aChannel=device;
if (!device)
return KErrNoMemory;
return device->DoCreate();
}
/**
Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel.
This is called in the context of the user thread (client) which requested the creation of a Logical Channel
(E.g. through a call to RBusLogicalChannel::DoCreate)
The thread is in a critical section.
@param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
@param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
@param aVer The version number of the Logical Channel which will use this Physical Channel
@return KErrNone or standard error code.
*/
TInt DDevice1PddFactory::Validate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
{
// Check version numbers
if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(EMinimumLddMajorVersion,EMinimumLddMinorVersion,EMinimumLddBuild))))
return KErrNotSupported;
// We don't support units
if (aUnit != -1)
return KErrNotSupported;
// Ignore extra info, (this could be used for validation purposes)
// Note, aInof is a pointer to a descriptor in user memory, therefore safe methods should
// be used for reading its contents. E.g. using Kern::KUDesGet()
(void)aInfo;
// OK
return KErrNone;
}
/**
Destructor
*/
DDevice1PddFactory::~DDevice1PddFactory()
{
if (iDfcQ)
iDfcQ->Destroy();
}
//
// DDriver1Device
//
DDriver1Device::DDriver1Device(DDevice1PddFactory* aFactory)
: iFactory(aFactory),
iSpeed(100000), // 100000us (100ms) per byte
iSendDataTimer(SendDataTimerCallback,this),
iReceiveDataTimer(ReceiveDataTimerCallback,this)
{
}
DDriver1Device::~DDriver1Device()
{
// Driver no longer using hardware resources
NKern::LockedDec(iFactory->iHardwareInUse);
}
TInt DDriver1Device::DoCreate()
{
// Claim the hardware resources by incrementing iHardwareInUse.
// Must do this before any other failure can happen in this function so that
// the destructor can safely decrement iHardwareInUse.
//
// This method of ensuring hardware is only in use by one driver at a time
// wouldn't be needed if the driver claimed real hardware resources which
// could only be used once. E.g. binding to an interrupt.
if(NKern::LockedInc(iFactory->iHardwareInUse))
return KErrInUse;
// Other setup goes here
return KErrNone;
}
TInt DDriver1Device::BufferSize() const
{
return iBuffer.MaxSize();
}
TInt DDriver1Device::Speed() const
{
return iSpeed;
}
TInt DDriver1Device::SetSpeed(TInt aSpeed)
{
if(aSpeed<=0)
return KErrArgument;
iSpeed = aSpeed;
return KErrNone;
}
TInt DDriver1Device::SendData(const TDesC8& aData)
{
// Save the last part of the data to 'send', we will pretend to 'receive' this later
iBuffer=aData.Right(iBuffer.MaxSize());
// Pretend to send the data by waiting for iSpeed micro-seconds per byte...
iSendDataTimer.OneShot(aData.Size()*iSpeed/NKern::TickPeriod());
return KErrNone;
}
void DDriver1Device::SendDataCancel()
{
// Stop the timer we were using to pretend we were processing the send
iSendDataTimer.Cancel();
}
void DDriver1Device::SendDataTimerCallback(TAny* aPtr)
{
// Just forward callback to non-static callback function
((DDriver1Device*)aPtr)->SendDataCallback();
}
void DDriver1Device::SendDataCallback()
{
// Tell LDD we've done
iLdd->SendDataComplete(KErrNone);
}
TInt DDriver1Device::ReceiveData(TDes8& aBuffer)
{
// Save a pointer to the buffer we need to put the 'recevied' data in
iReceiveBuffer=&aBuffer;
// Pretend to receive the data by waiting for iSpeed micro-seconds per byte...
iReceiveDataTimer.OneShot(iBuffer.Size()*iSpeed/NKern::TickPeriod());
return KErrNone;
}
void DDriver1Device::ReceiveDataCancel()
{
// Stop the timer we were using to pretend we were processing the receive
iReceiveDataTimer.Cancel();
}
void DDriver1Device::ReceiveDataTimerCallback(TAny* aPtr)
{
// Just forward callback to non-static callback function
((DDriver1Device*)aPtr)->ReceiveDataCallback();
}
void DDriver1Device::ReceiveDataCallback()
{
// Pretend the data we have received is that saved in iBuffer when we last did a send
*iReceiveBuffer=iBuffer;
// Tell LDD we've done
iLdd->ReceiveDataComplete(KErrNone);
}
</codeblock> </conbody></concept>