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