os/kernelhwsrv/kernel/eka/drivers/camerasc/cameraldd.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/camerasc/cameraldd.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,2223 @@
     1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32/drivers/camerasc/cameraldd.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <drivers/camerasc.h>
    1.22 +#include <kernel/kern_priv.h>
    1.23 +#include <kernel/cache.h>
    1.24 +
    1.25 +//#define __KTRACE_CAM(s) s;
    1.26 +#define __KTRACE_CAM(s)
    1.27 +
    1.28 +#define DISCARD_COMPLETED_TO_AVOID_OVERFLOW
    1.29 +
    1.30 +static const char KCameraLddPanic[]="CameraSc LDD";
    1.31 +
    1.32 +/**
    1.33 +Standard export function for LDDs. This creates a DLogicalDevice derived object,
    1.34 +in this case, DSoundScLddFactory.
    1.35 +*/
    1.36 +DECLARE_STANDARD_LDD()
    1.37 +	{
    1.38 +	return new DCameraScLddFactory;
    1.39 +	}
    1.40 +
    1.41 +/**
    1.42 +Constructor for the camera driver factory class.
    1.43 +*/
    1.44 +DCameraScLddFactory::DCameraScLddFactory()
    1.45 +	{
    1.46 +//	iUnitsOpenMask=0;
    1.47 +
    1.48 +	__KTRACE_CAM(Kern::Printf(">DCameraScLddFactory::DCameraScLddFactory"));
    1.49 +
    1.50 +	// Set version number for this device.
    1.51 +	iVersion=RDevCameraSc::VersionRequired();
    1.52 +
    1.53 +	// Indicate that units / PDD are supported.
    1.54 +	iParseMask=KDeviceAllowUnit|KDeviceAllowPhysicalDevice;
    1.55 +
    1.56 +	// Leave the units decision to the PDD
    1.57 +	iUnitsMask=0xffffffff;
    1.58 +	}
    1.59 +
    1.60 +/**
    1.61 +Second stage constructor for the camera driver factory class.
    1.62 +This must at least set a name for the driver object.
    1.63 +@return KErrNone if successful, otherwise one of the other system wide error codes.
    1.64 +*/
    1.65 +TInt DCameraScLddFactory::Install()
    1.66 +	{
    1.67 +	return(SetName(&KDevCameraScName));
    1.68 +	}
    1.69 +
    1.70 +/**
    1.71 +Return the 'capabilities' of the camera driver in general.
    1.72 +Called in the response to an RDevice::GetCaps() request.
    1.73 +@param aDes A user-side descriptor to write the capabilities information into.
    1.74 +*/
    1.75 +void DCameraScLddFactory::GetCaps(TDes8 &aDes) const
    1.76 +	{
    1.77 +	// Create a capabilities object
    1.78 +	TCapsDevCameraV01 caps;
    1.79 +	caps.iVersion=iVersion;
    1.80 +
    1.81 +	// Write it back to user memory
    1.82 +	Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
    1.83 +	}
    1.84 +
    1.85 +/**
    1.86 +Called by the kernel's device driver framework to create a logical channel.
    1.87 +This is called in the context of the client thread which requested the creation of a logical
    1.88 +channel - through a call to RBusLogicalChannel::DoCreate().
    1.89 +The thread is in a critical section.
    1.90 +@param aChannel Set by this function to point to the created logical channel.
    1.91 +@return KErrNone if successful, otherwise one of the other system wide error codes.
    1.92 +*/
    1.93 +TInt DCameraScLddFactory::Create(DLogicalChannelBase*& aChannel)
    1.94 +	{
    1.95 +	__KTRACE_CAM(Kern::Printf(">DCameraScLddFactory::Create"));
    1.96 +
    1.97 +	aChannel=new DCameraScLdd;
    1.98 +	if (!aChannel)
    1.99 +		return(KErrNoMemory);
   1.100 +
   1.101 +	return(KErrNone);
   1.102 +	}
   1.103 +
   1.104 +/**
   1.105 +Check whether a channel has is currently open on the specified unit.
   1.106 +@param aUnit The number of the unit to be checked.
   1.107 +@return ETrue if a channel is open on the specified channel, EFalse otherwise.
   1.108 +@pre The unit info. mutex must be held.
   1.109 +*/
   1.110 +TBool DCameraScLddFactory::IsUnitOpen(TInt aUnit)
   1.111 +	{
   1.112 +	return(iUnitsOpenMask&(1<<aUnit));
   1.113 +	}
   1.114 +
   1.115 +/**
   1.116 +Attempt to change the state of the channel open status for a particular channel.
   1.117 +@param aUnit The number of the unit to be updated.
   1.118 +@param aIsOpenSetting	The required new state for the channel open status: either ETrue to set the status to open or
   1.119 +						EFalse to set the status to closed.
   1.120 +@return KErrNone if the status was updated successfully;
   1.121 +		KErrInUse if an attempt has been made to set the channnel status to open while it is already open.
   1.122 +*/
   1.123 +TInt DCameraScLddFactory::SetUnitOpen(TInt aUnit,TBool aIsOpenSetting)
   1.124 +	{
   1.125 +	NKern::FMWait(&iUnitInfoMutex); // Acquire the unit info. mutex.
   1.126 +
   1.127 +	// Fail a request to open an channel that is already open
   1.128 +	if (aIsOpenSetting && IsUnitOpen(aUnit))
   1.129 +		{
   1.130 +		NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.
   1.131 +		return(KErrInUse);
   1.132 +		}
   1.133 +
   1.134 +	// Update the open status as requested
   1.135 +	if (aIsOpenSetting)
   1.136 +		iUnitsOpenMask|=(1<<aUnit);
   1.137 +	else
   1.138 +		iUnitsOpenMask&=~(1<<aUnit);
   1.139 +
   1.140 +	NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.
   1.141 +	return(KErrNone);
   1.142 +	}
   1.143 +
   1.144 +/**
   1.145 +Constructor for the camera driver logical channel.
   1.146 +*/
   1.147 +DCameraScLdd::DCameraScLdd()
   1.148 +	:	iRequestQueue(&iMutex),
   1.149 +		iRestartDfc(DCameraScLdd::RestartDfc,this,5),
   1.150 +		iPowerDownDfc(DCameraScLdd::PowerDownDfc,this,3),
   1.151 +		iPowerUpDfc(DCameraScLdd::PowerUpDfc,this,3)
   1.152 +	{
   1.153 +	iState=EOpen;
   1.154 +//	iCaptureMode=ECaptureModeImage;
   1.155 +//	iFrameHeight=0;
   1.156 +//	iFrameWidth=0;
   1.157 +//	iBufManager=NULL;
   1.158 +//	iPowerHandler=NULL;
   1.159 +//	iImageGatherCount=0;
   1.160 +
   1.161 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DCameraScLdd"));
   1.162 +
   1.163 +	iUnit=-1;	// Invalid unit number
   1.164 +
   1.165 +	// Get pointer to client thread's DThread object
   1.166 +	iOwningThread=&Kern::CurrentThread();
   1.167 +
   1.168 +	// Open a reference on client thread so it's control block can't dissapear until
   1.169 +	// this driver has finished with it. Note, this call to Open() can't fail since
   1.170 +	// it is the thread we are currently running in
   1.171 +	iOwningThread->Open();
   1.172 +	}
   1.173 +
   1.174 +/**
   1.175 +Destructor for the camera driver logical channel.
   1.176 +This is called in the context of the client thread once a 'ECloseMsg' message has been
   1.177 +sent to the device driver DFC thread.
   1.178 +*/
   1.179 +DCameraScLdd::~DCameraScLdd()
   1.180 +	{
   1.181 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::~DCameraScLdd"));
   1.182 +
   1.183 +	TInt captureMode;
   1.184 +
   1.185 +	// Remove and delete the power handler.
   1.186 +	if (iPowerHandler)
   1.187 +		{
   1.188 +		iPowerHandler->Remove();
   1.189 +		delete iPowerHandler;
   1.190 +		}
   1.191 +
   1.192 +	if (iCaptureModeConfig)
   1.193 +		{
   1.194 +		// Delete any buffers and shared chunk we created.
   1.195 +		for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
   1.196 +			{
   1.197 +			if (iCaptureModeConfig[captureMode].iBufManager)
   1.198 +				delete iCaptureModeConfig[captureMode].iBufManager;
   1.199 +			}
   1.200 +
   1.201 +		// Delete the buffer config. info. structure.
   1.202 +		for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
   1.203 +			{
   1.204 +			if (iCaptureModeConfig[captureMode].iBufConfig)
   1.205 +				Kern::Free(iCaptureModeConfig[captureMode].iBufConfig);
   1.206 +			}
   1.207 +
   1.208 +			if (iCaptureModeConfig)
   1.209 +				delete[] iCaptureModeConfig;
   1.210 +		}
   1.211 +	// Close our reference on the client thread
   1.212 +	Kern::SafeClose((DObject*&)iOwningThread,NULL);
   1.213 +
   1.214 +	// Clear the 'units open mask' in the LDD factory.
   1.215 +	if (iUnit>=0)
   1.216 +		((DCameraScLddFactory*)iDevice)->SetUnitOpen(iUnit,EFalse);
   1.217 +	}
   1.218 +
   1.219 +/**
   1.220 +Second stage constructor for the camera driver - called by the kernel's device driver framework.
   1.221 +This is called in the context of the client thread which requested the creation of a logical channel
   1.222 +(e.g. through a call to RBusLogicalChannel::DoCreate()).
   1.223 +The thread is in a critical section.
   1.224 +@param aUnit The unit argument supplied by the client. This is checked by the PDD and not used here.
   1.225 +@param aInfo The info argument supplied by the client. Always NULL in this case.
   1.226 +@param aVer The version argument supplied by the client.
   1.227 +@return KErrNone if successful, otherwise one of the other system wide error codes.
   1.228 +*/
   1.229 +TInt DCameraScLdd::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
   1.230 +	{
   1.231 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoCreate"));
   1.232 +
   1.233 +	// Check the client has EMultimediaDD capability.
   1.234 +	if (!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ECAMERA.LDD (Camera driver)")))
   1.235 +		return(KErrPermissionDenied);
   1.236 +
   1.237 +	// Check that the camera driver version specified by the client is compatible.
   1.238 +	if (!Kern::QueryVersionSupported(RDevCameraSc::VersionRequired(),aVer))
   1.239 +		return(KErrNotSupported);
   1.240 +
   1.241 +	// Check that a channel hasn't already been opened on this unit.
   1.242 +	TInt r=((DCameraScLddFactory*)iDevice)->SetUnitOpen(aUnit,ETrue); // Try to update 'units open mask' in the LDD factory.
   1.243 +	if (r!=KErrNone)
   1.244 +		return(r);
   1.245 +	iUnit=aUnit;
   1.246 +
   1.247 +	// Create the power handler
   1.248 +	iPowerHandler=new DCameraScPowerHandler(this);
   1.249 +	if (!iPowerHandler)
   1.250 +		return(KErrNoMemory);
   1.251 +	iPowerHandler->Add();
   1.252 +
   1.253 +	// Create the pending capture request list
   1.254 +	r=iRequestQueue.Create(iOwningThread);
   1.255 +	if (r!=KErrNone)
   1.256 +		return(r);
   1.257 +
   1.258 +	// Initialise the PDD
   1.259 +	((DCameraScPdd*)iPdd)->iLdd=this;
   1.260 +
   1.261 +	// Setup the default camera config
   1.262 +	iCaptureMode=ECamCaptureModeImage;
   1.263 +
   1.264 +	iCaptureModeConfig = new TCaptureModeConfig[ECamCaptureModeMax];
   1.265 +	if(!iCaptureModeConfig)
   1.266 +		return KErrNoMemory;
   1.267 +	TInt capsSize = Pdd()->CapsSize();
   1.268 +	TInt captureMode;
   1.269 +	TAny* capsBuf;
   1.270 +	capsBuf = Kern::Alloc(capsSize);
   1.271 +	if(!capsBuf)
   1.272 +		return KErrNoMemory;
   1.273 +
   1.274 +	// Query the driver for its capabilities and set a default pixel format
   1.275 +	// and frame size for each available capture mode.
   1.276 +	TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
   1.277 +	Pdd()->Caps(capsPtr);
   1.278 +
   1.279 +	TCameraCapsV02* caps = (TCameraCapsV02*) capsPtr.Ptr();
   1.280 +	SDevCamPixelFormat* pixelFormat = (SDevCamPixelFormat*) (caps + 1);
   1.281 +	SDevCamFrameSize* frameSize;
   1.282 +	TAny* frameSizeCapsBuf=0;
   1.283 +	TPtr8 frameSizeCapsPtr(0,0,0);
   1.284 +
   1.285 +	// Set the cache to hold the default dynamic attribute values.
   1.286 +	iBrightnessValue = caps->iDynamicRange[ECamAttributeBrightness].iDefault;
   1.287 +	iContrastValue = caps->iDynamicRange[ECamAttributeContrast].iDefault;
   1.288 +	iColorEffectValue = caps->iDynamicRange[ECamAttributeColorEffect].iDefault;
   1.289 +	
   1.290 +	for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
   1.291 +		{
   1.292 +		if ((captureMode==ECamCaptureModeImage) && (caps->iNumImagePixelFormats==0))
   1.293 +			continue;
   1.294 +
   1.295 +		if ((captureMode==ECamCaptureModeVideo) && (caps->iNumVideoPixelFormats==0))
   1.296 +			continue;
   1.297 +
   1.298 +		if ((captureMode==ECamCaptureModeViewFinder) && (caps->iNumViewFinderPixelFormats==0))
   1.299 +			continue;
   1.300 +
   1.301 +		iCaptureModeConfig[captureMode].iCamConfig.iPixelFormat=*pixelFormat;
   1.302 +		frameSizeCapsBuf = Kern::Alloc(pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize));
   1.303 +		new (&frameSizeCapsPtr) TPtr8((TUint8*)frameSizeCapsBuf, pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize), pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize));
   1.304 +		r=Pdd()->FrameSizeCaps((TDevCamCaptureMode)captureMode, pixelFormat->iPixelFormat, frameSizeCapsPtr);
   1.305 +		if(r!=KErrNone)
   1.306 +			{
   1.307 +			Kern::Free(frameSizeCapsBuf);
   1.308 +			return r;
   1.309 +			}
   1.310 +		frameSize=(SDevCamFrameSize*) frameSizeCapsPtr.Ptr();
   1.311 +		iCaptureModeConfig[captureMode].iCamConfig.iFrameSize = *frameSize;
   1.312 +		iCaptureModeConfig[captureMode].iCamConfig.iFrameRate = frameSize->iMinFrameRate;
   1.313 +		Kern::Free(frameSizeCapsBuf);
   1.314 +
   1.315 +		iCaptureModeConfig[captureMode].iCamConfig.iFlashMode = ECamFlashNone;
   1.316 +		iCaptureModeConfig[captureMode].iCamConfig.iExposureMode = ECamExposureAuto;
   1.317 +		iCaptureModeConfig[captureMode].iCamConfig.iWhiteBalanceMode = ECamWBAuto;
   1.318 +		iCaptureModeConfig[captureMode].iCamConfig.iZoom = 0;
   1.319 +		iCaptureModeConfig[captureMode].iCamConfig.iPixelWidthInBytes = 0;
   1.320 +		}
   1.321 +	Kern::Free(capsBuf);
   1.322 +	// Setup the default buffer config.
   1.323 +	r=ReAllocBufferConfigInfo(0);	// Zeros the structure
   1.324 +	if (r!=KErrNone)
   1.325 +		return(r);
   1.326 +	for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
   1.327 +		{
   1.328 +		iCaptureModeConfig[captureMode].iBufConfig->iNumBuffers=KDefaultNumClientBuffers;
   1.329 +		}
   1.330 +
   1.331 +	// Set up the correct DFC queue and enable the reception of client messages.
   1.332 +	TDfcQue* dfcq=((DCameraScPdd*)iPdd)->DfcQ(aUnit);
   1.333 +	SetDfcQ(dfcq);
   1.334 +	iRestartDfc.SetDfcQ(dfcq);
   1.335 +	iPowerDownDfc.SetDfcQ(dfcq);
   1.336 +	iPowerUpDfc.SetDfcQ(dfcq);
   1.337 +	iMsgQ.Receive();
   1.338 +
   1.339 +	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoCreate"));
   1.340 +
   1.341 +	return(KErrNone);
   1.342 +	}
   1.343 +
   1.344 +/**
   1.345 +Shutdown the camera device.
   1.346 +Terminate all device activity and power down the hardware.
   1.347 +*/
   1.348 +void DCameraScLdd::Shutdown()
   1.349 +	{
   1.350 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Shutdown"));
   1.351 +
   1.352 +	iState=EOpen;
   1.353 +
   1.354 +	// Power down the hardware
   1.355 +	Pdd()->PowerDown();
   1.356 +
   1.357 +	// Cancel any requests that we may be handling
   1.358 +	DoCancel(RDevCameraSc::EAllRequests);
   1.359 +
   1.360 +	// Make sure DFCs are not queued.
   1.361 +	iRestartDfc.Cancel();
   1.362 +	iPowerDownDfc.Cancel();
   1.363 +	iPowerUpDfc.Cancel();
   1.364 +	}
   1.365 +
   1.366 +/**
   1.367 +Notification to the driver that a handle to it has been requested by a user thread.
   1.368 +The use of a camera driver channel is restricted here to a single thread (that has
   1.369 +EMultimediaDD capability).
   1.370 +@param aThread A pointer to thread which is requesting the handle.
   1.371 +@param aType Whether the requested handle is thread or process relative.
   1.372 +@return	KErrNone, if the request is for a thread relative handle - originating from
   1.373 +		the same the thread that created the channel object;
   1.374 +		KErrAccessDenied, otherwise.
   1.375 +*/
   1.376 +TInt DCameraScLdd::RequestUserHandle(DThread* aThread, TOwnerType aType)
   1.377 +	{
   1.378 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::RequestUserHandle"));
   1.379 +
   1.380 +	// Ensure that each channel can only be used by a single thread.
   1.381 +	if (aType!=EOwnerThread || aThread!=iOwningThread)
   1.382 +		return(KErrAccessDenied);
   1.383 +	return(KErrNone);
   1.384 +	}
   1.385 +
   1.386 +/**
   1.387 +Process a request on this logical channel
   1.388 +Called in the context of the client thread.
   1.389 +@param aReqNo	The request number:
   1.390 +				==KMaxTInt: a 'DoCancel' message;
   1.391 +				>=0: a 'DoControl' message with function number equal to value.
   1.392 +				<0: a 'DoRequest' message with function number equal to ~value.
   1.393 +@param a1 The first request argument. For DoRequest(), this is a pointer to the TRequestStatus.
   1.394 +@param a2 The second request argument. For DoRequest(), this is a pointer to the 2 actual TAny* arguments.
   1.395 +@return The result of the request. This is ignored by device driver framework for DoRequest().
   1.396 +*/
   1.397 +TInt DCameraScLdd::Request(TInt aReqNo, TAny* a1, TAny* a2)
   1.398 +	{
   1.399 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Request(%d)",aReqNo));
   1.400 +	TInt r;
   1.401 +	if (aReqNo<RDevCameraSc::EMsgControlMax && aReqNo>(~RDevCameraSc::EMsgRequestMax))
   1.402 +		{
   1.403 +		// Implement in the context of the kernel thread - prepare and issue a kernel message.
   1.404 +		r=DLogicalChannel::Request(aReqNo,a1,a2);
   1.405 +		}
   1.406 +	else
   1.407 +		{
   1.408 +		// Implement in the context of the client thread.
   1.409 +		// Decode the message type and dispatch it to the relevent handler function.
   1.410 +		if ((TUint)aReqNo<(TUint)KMaxTInt)
   1.411 +			r=DoControl(aReqNo,a1,a2);		// DoControl - process the request.
   1.412 +
   1.413 +		else if (aReqNo==KMaxTInt)
   1.414 +			{
   1.415 +			r=DoCancel((TInt)a1);			// DoCancel - cancel the request.
   1.416 +			}
   1.417 +
   1.418 +		else
   1.419 +			{
   1.420 +			// DoRequest
   1.421 +			TInt func=~aReqNo;
   1.422 +
   1.423 +			// NotifyNewImage() during image capture mode is another case which must be handled in the kernel thread.
   1.424 +			if (iCaptureMode==ECamCaptureModeImage && func==RDevCameraSc::ERequestNotifyNewImage)
   1.425 +				r=DLogicalChannel::Request(aReqNo,a1,a2);
   1.426 +			else
   1.427 +				{
   1.428 +				// Read the arguments from the client thread and process the request.
   1.429 +				TAny* a[2];
   1.430 +				kumemget32(a,a2,sizeof(a));
   1.431 +				TRequestStatus* status=(TRequestStatus*)a1;
   1.432 +				r=DoRequest(func,status,a[0],a[1]);
   1.433 +
   1.434 +				// Complete request if there was an error
   1.435 +				if (r!=KErrNone)
   1.436 +					Kern::RequestComplete(iOwningThread,status,r);
   1.437 +				r=KErrNone;
   1.438 +				}
   1.439 +			}
   1.440 +		}
   1.441 +	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::Request - %d",r));
   1.442 +	return(r);
   1.443 +	}
   1.444 +
   1.445 +/**
   1.446 +Process a message for this logical channel.
   1.447 +This function is called in the context of the DFC thread.
   1.448 +@param aMsg The message to process.
   1.449 +			The iValue member of this distinguishes the message type:
   1.450 +			iValue==ECloseMsg, channel close message.
   1.451 +			iValue==KMaxTInt, a 'DoCancel' message.
   1.452 +			iValue>=0, a 'DoControl' message with function number equal to iValue.
   1.453 +			iValue<0, a 'DoRequest' message with function number equal to ~iValue.
   1.454 +*/
   1.455 +void DCameraScLdd::HandleMsg(TMessageBase* aMsg)
   1.456 +	{
   1.457 +	TThreadMessage& m=*(TThreadMessage*)aMsg;
   1.458 +	TInt id=m.iValue;
   1.459 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::HandleMsg(%d)",id));
   1.460 +
   1.461 +	// Decode the message type and dispatch it to the relevent handler function.
   1.462 +	if (id==(TInt)ECloseMsg)
   1.463 +		{
   1.464 +		// Channel close.
   1.465 +		Shutdown();
   1.466 +		m.Complete(KErrNone,EFalse);
   1.467 +		return;
   1.468 +		}
   1.469 +	else if (id<0)	// The only DoRequest handled in the kernel thread is NotifyNewImage(ECamCaptureModeImage).
   1.470 +		{
   1.471 +		// DoRequest
   1.472 +		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
   1.473 +		TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
   1.474 +		if (r!=KErrNone)
   1.475 +			Kern::RequestComplete(iOwningThread,pS,r);
   1.476 +		m.Complete(KErrNone,ETrue);
   1.477 +		}
   1.478 +	else
   1.479 +		{
   1.480 +		// Must be DoControl (Cancel is handled in the client thread).
   1.481 +		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
   1.482 +		m.Complete(r,ETrue);
   1.483 +		}
   1.484 +	}
   1.485 +
   1.486 +/**
   1.487 +Process a synchronous 'DoControl' request.
   1.488 +This function is called in the context of the DFC thread.
   1.489 +@param aFunction The request number.
   1.490 +@param a1 The first request argument.
   1.491 +@param a2 The second request argument.
   1.492 +@return KErrNone if successful, otherwise one of the other system wide error codes.
   1.493 +*/
   1.494 +TInt DCameraScLdd::DoControl(TInt aFunction, TAny* a1, TAny* a2)
   1.495 +	{
   1.496 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoControl(%d)",aFunction));
   1.497 +
   1.498 +	TInt r=KErrNotSupported;
   1.499 +	switch (aFunction)
   1.500 +		{
   1.501 +		case RDevCameraSc::EControlCaps:
   1.502 +			{
   1.503 +			r = GetSensorCaps(a1);
   1.504 +			break;
   1.505 +			}
   1.506 +		case RDevCameraSc::EControlSetCaptureMode:
   1.507 +			{
   1.508 +			// Change the capture mode.
   1.509 +			r=SetCaptureMode((TInt)a1);
   1.510 +			break;
   1.511 +			}
   1.512 +		case RDevCameraSc::EControlSetCamConfig:
   1.513 +			{
   1.514 +			// Set the new camera configuration.
   1.515 +			NKern::ThreadEnterCS();
   1.516 +			r=SetCamConfig((TInt)a1, (const TDesC8*)a2);
   1.517 +			NKern::ThreadLeaveCS();
   1.518 +			break;
   1.519 +			}
   1.520 +		case RDevCameraSc::EControlGetCamConfig:
   1.521 +			{
   1.522 +			// Write the config to the client.
   1.523 +			TPtrC8 ptr((const TUint8*)&iCaptureModeConfig[(TInt)a1].iCamConfig,sizeof(iCaptureModeConfig[(TInt)a1].iCamConfig));
   1.524 +			Kern::InfoCopy(*((TDes8*)a2),ptr);
   1.525 +			r=KErrNone;
   1.526 +			break;
   1.527 +			}
   1.528 +		case RDevCameraSc::EControlGetBufferConfig:
   1.529 +			if (iCaptureModeConfig[(TInt)a1].iBufConfig)
   1.530 +				{
   1.531 +				// Write the buffer config to the client.
   1.532 +				TPtrC8 ptr((const TUint8*)&(*iCaptureModeConfig[(TInt)a1].iBufConfig),iCaptureModeConfig[(TInt)a1].iBufConfigSize);
   1.533 +				Kern::InfoCopy(*((TDes8*)a2),ptr);
   1.534 +				r=KErrNone;
   1.535 +				}
   1.536 +			break;
   1.537 +		case RDevCameraSc::EControlSetBufConfigChunkCreate:
   1.538 +			// Need to be in critical section while deleting an exisiting config and creating a new one
   1.539 +			NKern::ThreadEnterCS();
   1.540 +			r=SetBufConfig((TInt)a1,(TInt)a2);
   1.541 +			NKern::ThreadLeaveCS();
   1.542 +			break;
   1.543 +		case RDevCameraSc::EControlSetBufConfigChunkOpen:
   1.544 +			SSetBufConfigChunkOpenInfo info;
   1.545 +			r=Kern::ThreadRawRead(iOwningThread,a2,&info,sizeof(info));
   1.546 +			if (r==KErrNone)
   1.547 +				{
   1.548 +				// Need to be in critical section while deleting an exisiting config and creating a new one
   1.549 +				NKern::ThreadEnterCS();
   1.550 +				r=SetBufConfig((TInt)a1,info.iBufferConfigBuf,info.iChunkHandle);
   1.551 +				NKern::ThreadLeaveCS();
   1.552 +				}
   1.553 +			break;
   1.554 +		case RDevCameraSc::EControlChunkClose:
   1.555 +			r=ChunkClose((TInt)a1);
   1.556 +			break;
   1.557 +		case RDevCameraSc::EControlStart:
   1.558 +			r=Start();
   1.559 +			break;
   1.560 +		case RDevCameraSc::EControlStop:
   1.561 +			if (iState==ECapturing)
   1.562 +				{
   1.563 +				r=Pdd()->Stop();
   1.564 +				DoCancel(1<<RDevCameraSc::ERequestNotifyNewImage);
   1.565 +				if (r==KErrNone)
   1.566 +					iState=EConfigured;
   1.567 +				}
   1.568 +			else
   1.569 +				{
   1.570 +				r=KErrGeneral;
   1.571 +				}
   1.572 +			break;
   1.573 +		case RDevCameraSc::EControlReleaseBuffer:
   1.574 +			r=ReleaseBuffer((TInt)a1);
   1.575 +			break;
   1.576 +		case RDevCameraSc::EControlNotifyNewImageSpecificCancel:
   1.577 +			{
   1.578 +			NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
   1.579 +			iRequestQueue.Cancel((TRequestStatus*)a1);
   1.580 +			NKern::FMSignal(&iMutex); 		// Release the buffer/request list mutex.
   1.581 +			r=KErrNone;
   1.582 +			break;
   1.583 +			}
   1.584 +			
   1.585 +		case RDevCameraSc::EControlBufferIdToOffset:
   1.586 +			{
   1.587 +			// a1 has pointer to buffer for search criteria
   1.588 +			// a2 has pointer to offset for result
   1.589 +			TDevCamBufferModeAndId info;
   1.590 +			TPtr8 inDesc((TUint8*)(&info), sizeof(info));
   1.591 +
   1.592 +			r = Kern::ThreadDesRead(iOwningThread,a1,inDesc,0);
   1.593 +			if (r == KErrNone)
   1.594 +				{
   1.595 +				TInt id = info.iId;
   1.596 +				TDevCamCaptureMode captureMode = info.iCaptureMode;
   1.597 +
   1.598 +				r = KErrNotFound;
   1.599 +				DBufferManager* mgr = iCaptureModeConfig[captureMode].iBufManager;
   1.600 +				if (mgr)
   1.601 +					{
   1.602 +					if (mgr->iImageBuffer[id].iId == id)
   1.603 +						{
   1.604 +						kumemput32(a2, &mgr->iImageBuffer[id].iChunkOffset, sizeof(TInt));
   1.605 +						r = KErrNone;
   1.606 +						}
   1.607 +					}
   1.608 +				}
   1.609 +			
   1.610 +			break;
   1.611 +			}
   1.612 +		case RDevCameraSc::EControlCapsSize:
   1.613 +			{
   1.614 +			r = Pdd()->CapsSize();
   1.615 +			break;
   1.616 +			}
   1.617 +		case RDevCameraSc::EControlFrameSizeCaps:
   1.618 +			{
   1.619 +			r = GetFrameSizeCaps(a1, a2);
   1.620 +			break;
   1.621 +			}
   1.622 +			
   1.623 +		case RDevCameraSc::EControlSetDynamicAttribute:
   1.624 +			{
   1.625 +			NKern::ThreadEnterCS();
   1.626 +			r = SetDynamicAttribute((TInt)a1, (TUint)a2);
   1.627 +			NKern::ThreadLeaveCS();
   1.628 +			break;
   1.629 +			}
   1.630 +			
   1.631 +		case RDevCameraSc::EControlGetDynamicAttribute:
   1.632 +			{
   1.633 +			TInt attribute = (TInt)(a1);
   1.634 +			TUint value = 0;
   1.635 +			
   1.636 +			r = GetDynamicAttribute(attribute, value);
   1.637 +			if (r == KErrNone)
   1.638 +				{
   1.639 +				kumemput32(a2, &value, sizeof(TUint));
   1.640 +				}
   1.641 +				
   1.642 +			break;
   1.643 +			}
   1.644 +			
   1.645 +		}
   1.646 +	return(r);
   1.647 +	}
   1.648 +
   1.649 +/**
   1.650 +Process an asynchronous 'DoRequest' request.
   1.651 +This function is called in the context of the DFC thread.
   1.652 +@param aFunction The request number.
   1.653 +@param aStatus A pointer to the TRequestStatus.
   1.654 +@param a1 The first request argument.
   1.655 +@param a2 The second request argument.
   1.656 +@return KErrNone if successful, otherwise one of the other system wide error codes.
   1.657 +*/
   1.658 +TInt DCameraScLdd::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* /*a1*/, TAny* /*a2*/)
   1.659 +	{
   1.660 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoRequest(%d)",aFunction));
   1.661 +
   1.662 +	TInt r=KErrNotSupported;
   1.663 +	switch (aFunction)
   1.664 +		{
   1.665 +		case RDevCameraSc::ERequestNotifyNewImage:
   1.666 +			r=NotifyNewImage(aStatus);
   1.667 +			break;
   1.668 +		}
   1.669 +
   1.670 +	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoRequest - %d",r));
   1.671 +	return(r);
   1.672 +	}
   1.673 +
   1.674 +/**
   1.675 +Process the cancelling of asynchronous requests.
   1.676 +This function is called in the context of the DFC thread.
   1.677 +@param aMask A mask indicating which requests need to be cancelled.
   1.678 +@return The result of the cancel. Either KErrNone if successful, otherwise one of the other
   1.679 +	system wide error codes.
   1.680 +*/
   1.681 +TInt DCameraScLdd::DoCancel(TUint aMask)
   1.682 +	{
   1.683 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoCancel(%08x)",aMask));
   1.684 +
   1.685 +	if (aMask&(1<<RDevCameraSc::ERequestNotifyNewImage))
   1.686 +		{
   1.687 +		NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
   1.688 +		iRequestQueue.CancelAll();
   1.689 +		NKern::FMSignal(&iMutex); 		// Release the buffer/request list mutex.
   1.690 +		}
   1.691 +	return(KErrNone);
   1.692 +	}
   1.693 +
   1.694 +/**
   1.695 +@pre The thread must be in a critical section.
   1.696 +*/
   1.697 +TInt DCameraScLdd::ReAllocBufferConfigInfo(TInt aNumBuffers)
   1.698 +	{
   1.699 +	for (TInt captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
   1.700 +		{
   1.701 +		if (iCaptureModeConfig[captureMode].iBufConfig)
   1.702 +			{
   1.703 +			Kern::Free(iCaptureModeConfig[captureMode].iBufConfig);
   1.704 +			iCaptureModeConfig[captureMode].iBufConfig=NULL;
   1.705 +			}
   1.706 +
   1.707 +		iCaptureModeConfig[captureMode].iBufConfigSize=aNumBuffers*(sizeof(SBufSpecList)); // Size of the three integers that hold the offset to the start of each buffer and the buffer id.
   1.708 +		iCaptureModeConfig[captureMode].iBufConfigSize+=sizeof(TSharedChunkBufConfigBase);
   1.709 +		iCaptureModeConfig[captureMode].iBufConfig=(TCameraSharedChunkBufConfig*)Kern::AllocZ(iCaptureModeConfig[captureMode].iBufConfigSize);
   1.710 +		if (!iCaptureModeConfig[captureMode].iBufConfig)
   1.711 +			return(KErrNoMemory);
   1.712 +		}
   1.713 +	return(KErrNone);
   1.714 +	}
   1.715 +
   1.716 +/**
   1.717 +Reallocate memory for the new buffer configuration.
   1.718 +@param aNumBuffers The number of buffers.
   1.719 +@pre The thread must be in a critical section.
   1.720 +*/
   1.721 +TInt DCameraScLdd::ReAllocBufferConfigInfo(TInt aCaptureMode, TInt aNumBuffers)
   1.722 +	{
   1.723 +	if (iCaptureModeConfig[aCaptureMode].iBufConfig)
   1.724 +		{
   1.725 +		Kern::Free(iCaptureModeConfig[aCaptureMode].iBufConfig);
   1.726 +		iCaptureModeConfig[aCaptureMode].iBufConfig=NULL;
   1.727 +		}
   1.728 +
   1.729 +	iCaptureModeConfig[aCaptureMode].iBufConfigSize=aNumBuffers*(sizeof(SBufSpecList)); // Size of the three integers that hold the offset to the start of each buffer and the buffer id.
   1.730 +	iCaptureModeConfig[aCaptureMode].iBufConfigSize+=sizeof(TSharedChunkBufConfigBase);
   1.731 +	iCaptureModeConfig[aCaptureMode].iBufConfig=(TCameraSharedChunkBufConfig*)Kern::AllocZ(iCaptureModeConfig[aCaptureMode].iBufConfigSize);
   1.732 +	if (!iCaptureModeConfig[aCaptureMode].iBufConfig)
   1.733 +		return(KErrNoMemory);
   1.734 +
   1.735 +	return(KErrNone);
   1.736 +	}
   1.737 +
   1.738 +/**
   1.739 +@return	A handle to the shared chunk for the owning thread (a value >0), if successful;
   1.740 +		otherwise one of the other system wide error codes, (a value <0).
   1.741 +@param aCamConfigBuf The supplied camera configuration.
   1.742 +@pre The thread must be in a critical section.
   1.743 +*/
   1.744 +TInt DCameraScLdd::SetCamConfig(TInt aCaptureMode, const TDesC8* aCamConfigBuf)
   1.745 +	{
   1.746 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetCamConfig()"));
   1.747 +
   1.748 +	// Set the configuration of the sensor
   1.749 +	TInt r=DoSetConfig(aCaptureMode, aCamConfigBuf);
   1.750 +	return(r);
   1.751 +	}
   1.752 +
   1.753 +/**
   1.754 +Allows changing of the dynamic settings.
   1.755 +Checks locally the validity of the arguments passed so as to increase performance by not
   1.756 +forcing a context switch.
   1.757 +
   1.758 +If the setting has been accepted by the sensor the new value is cached by the LDD so further
   1.759 +querying does not involve another context switch.
   1.760 +
   1.761 +@param aAttribute An enum identifying the dynamic attribute to change.
   1.762 +@param aValue The attributes value.
   1.763 +@return KErrNone if successful, KErrNotSupported if not supported, KErrArgument if aValue out of range.
   1.764 +		Otherwise, one of the system wide error codes.
   1.765 +@pre The thread must be in a critical section.
   1.766 +*/
   1.767 +TInt DCameraScLdd::SetDynamicAttribute(TInt aAttribute, TUint aValue)
   1.768 +	{
   1.769 +	TUint* attrCachePtr = NULL;
   1.770 +	TInt err = KErrNotSupported;
   1.771 +	
   1.772 +	switch (aAttribute)
   1.773 +		{
   1.774 +		case ECamAttributeBrightness:
   1.775 +			err = Pdd()->SetBrightness(aValue);
   1.776 +			attrCachePtr = &iBrightnessValue;
   1.777 +			break;
   1.778 +			
   1.779 +		case ECamAttributeContrast:
   1.780 +			err = Pdd()->SetContrast(aValue);
   1.781 +			attrCachePtr = &iContrastValue;
   1.782 +			break;
   1.783 +			
   1.784 +		case ECamAttributeColorEffect:
   1.785 +			err = Pdd()->SetColorEffect(aValue);
   1.786 +			attrCachePtr = &iColorEffectValue;
   1.787 +			break;
   1.788 +			
   1.789 +		default:
   1.790 +			return err;
   1.791 +		}
   1.792 +	
   1.793 +	if (err == KErrNone)
   1.794 +		{
   1.795 +		// Cache the set value.
   1.796 +		__ASSERT_DEBUG(attrCachePtr, Kern::Fault(KCameraLddPanic, __LINE__));
   1.797 +		*attrCachePtr = aValue;
   1.798 +		}
   1.799 +		
   1.800 +	return err;
   1.801 +	}
   1.802 +
   1.803 +
   1.804 +/**
   1.805 +Allows querying of a dynamic setting.
   1.806 +The value is read from the cached LDD values.
   1.807 +
   1.808 +@param aAttribute An enum identifying the dynamic attribute to change.
   1.809 +@param aValue A reference to a variable that will receive the attribute value.
   1.810 +@return KErrNone if successful, KErrNotFound if aAttribute is an unsupported
   1.811 +        setting. The parameter aValue is not changed if this function fails.
   1.812 +*/
   1.813 +TInt DCameraScLdd::GetDynamicAttribute(TInt aAttribute, TUint& aValue)
   1.814 +	{
   1.815 +	switch (aAttribute)
   1.816 +		{
   1.817 +		case ECamAttributeBrightness:
   1.818 +			aValue = iBrightnessValue;
   1.819 +			break;
   1.820 +			
   1.821 +		case ECamAttributeContrast:
   1.822 +			aValue = iContrastValue;
   1.823 +			break;
   1.824 +			
   1.825 +		case ECamAttributeColorEffect:
   1.826 +			aValue = iColorEffectValue;
   1.827 +			break;
   1.828 +			
   1.829 +		default:
   1.830 +			return KErrNotFound;
   1.831 +		}
   1.832 +		
   1.833 +	return KErrNone;
   1.834 +	}
   1.835 +
   1.836 +
   1.837 +/**
   1.838 +Updates the buffer configuration of the camera for the specified capture mode.
   1.839 +@return	A handle to the shared chunk for the owning thread (a value >0), if successful;
   1.840 +		otherwise one of the other system wide error codes, (a value <0).
   1.841 +*/
   1.842 +TInt DCameraScLdd::SetBufConfig(TInt aCaptureMode, TInt aNumBuffers)
   1.843 +	{
   1.844 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetBufConfig(CaptureMode=%d,NumBuffers=%d)",aCaptureMode,aNumBuffers));
   1.845 +
   1.846 +	// Free any memory and chunk already allocated
   1.847 +	TInt r=ChunkClose(aCaptureMode);
   1.848 +	if (r!=KErrNone)
   1.849 +		return(r);
   1.850 +
   1.851 +	// Allocate a new shared chunk and create the specified number of buffers within it.
   1.852 +	TInt buffersize=((iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iWidth*iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iHeight) * iCaptureModeConfig[aCaptureMode].iCamConfig.iPixelWidthInBytes);
   1.853 +	__KTRACE_CAM(Kern::Printf(">>DCameraScLdd::SetBufConfig - iFrameSize:%d, iPixelWidthInBytes:%d => bufferSize:%d",(iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iWidth*iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iHeight),iCaptureModeConfig[aCaptureMode].iCamConfig.iPixelWidthInBytes,buffersize));
   1.854 +	iCaptureModeConfig[aCaptureMode].iBufManager=new DBufferManager(this);
   1.855 +	if (!iCaptureModeConfig[aCaptureMode].iBufManager)
   1.856 +		return(KErrNoMemory);
   1.857 +	r=iCaptureModeConfig[aCaptureMode].iBufManager->Create(aNumBuffers,buffersize);
   1.858 +	if (r!=KErrNone)
   1.859 +		return(r);
   1.860 +
   1.861 +	// Update the LDD's chunk/buffer geometry info.
   1.862 +	r=ReAllocBufferConfigInfo(aCaptureMode, aNumBuffers);
   1.863 +	if (r!=KErrNone)
   1.864 +		return(r);
   1.865 +	iCaptureModeConfig[aCaptureMode].iBufManager->GetBufConfig(*iCaptureModeConfig[aCaptureMode].iBufConfig);
   1.866 +
   1.867 +	// Create handle to the shared chunk for the owning thread.
   1.868 +	r=Kern::MakeHandleAndOpen(iOwningThread,iCaptureModeConfig[aCaptureMode].iBufManager->iChunk);
   1.869 +	if (r>0)
   1.870 +		{
   1.871 +		// And save the the chunk and handle for later.  Normally the chunk handle will be closed when the chunk
   1.872 +		// is closed, but if the chunk is re-allocated then it will need to be closed before re-allocation.
   1.873 +		iCaptureModeConfig[aCaptureMode].iChunkHandle=r;
   1.874 +		}
   1.875 +
   1.876 +	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::SetBufConfig - %d",r));
   1.877 +	return(r);
   1.878 +	}
   1.879 +
   1.880 +/**
   1.881 +Updates the buffer configuration of the camera, which has been supplied by the user, for the specified capture mode.
   1.882 +@param aCaptureMode		The capture mode for which the setting of the buffer configuration is made.
   1.883 +@param aBufferConfigBuf	A buffer that holds the buffer configuration for the camera.
   1.884 +@param aChunkHandle		A handle for the shared chunk supplied by the client.
   1.885 +@return KErrNone if successful, otherwise one of the other system wide error codes.
   1.886 +@pre The thread must be in a critical section.
   1.887 +*/
   1.888 +TInt DCameraScLdd::SetBufConfig(TInt aCaptureMode,const TDesC8* aBufferConfigBuf,TInt aChunkHandle)
   1.889 +	{
   1.890 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetConfig(Handle-%d)",aChunkHandle));
   1.891 +
   1.892 +	// Read the buffer config structure from the client.
   1.893 +	TInt numBuffers;
   1.894 +	TPtr8 ptr((TUint8*)&numBuffers,sizeof(numBuffers));
   1.895 +	TInt r=Kern::ThreadDesRead(iOwningThread,aBufferConfigBuf,ptr,0);
   1.896 +	if (r!=KErrNone)
   1.897 +		return(r);
   1.898 +	// Calculate the minimum length of the descriptor.
   1.899 +	TInt minDesLen=(numBuffers*sizeof(SBufSpecList))+sizeof(TSharedChunkBufConfigBase);
   1.900 +	r=Kern::ThreadGetDesLength(iOwningThread,aBufferConfigBuf);
   1.901 +	if (r<minDesLen)
   1.902 +		return(KErrArgument);
   1.903 +	r=ReAllocBufferConfigInfo(aCaptureMode, numBuffers);
   1.904 +	if (r!=KErrNone)
   1.905 +		return(r);
   1.906 +	ptr.Set((TUint8*)iCaptureModeConfig[aCaptureMode].iBufConfig,0,iCaptureModeConfig[aCaptureMode].iBufConfigSize);
   1.907 +	r=Kern::ThreadDesRead(iOwningThread,aBufferConfigBuf,ptr,0);
   1.908 +	if (r!=KErrNone)
   1.909 +		return(r);
   1.910 +
   1.911 +	// Free any memory and chunk already allocated
   1.912 +	r=ChunkClose(aCaptureMode);
   1.913 +	if (r!=KErrNone)
   1.914 +		return(r);
   1.915 +
   1.916 +	// Open the shared chunk supplied and create buffer objects for the committed buffers within it.
   1.917 +	iCaptureModeConfig[aCaptureMode].iBufManager=new DBufferManager(this);
   1.918 +	if (!iCaptureModeConfig[aCaptureMode].iBufManager)
   1.919 +		return(KErrNoMemory);
   1.920 +	r=iCaptureModeConfig[aCaptureMode].iBufManager->Create(*iCaptureModeConfig[aCaptureMode].iBufConfig,aChunkHandle,iOwningThread);
   1.921 +	if (r!=KErrNone)
   1.922 +		return(r);
   1.923 +
   1.924 +	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::SetConfig - %d",KErrNone));
   1.925 +	return(r);
   1.926 +	}
   1.927 +
   1.928 +/**
   1.929 +Frees the buffer manager associated with a chunk, and closes the chunk itself.  The chunk being closed,
   1.930 +and its associated DBufferManager instance should have been allocated by the device driver.  However,
   1.931 +this is not a requirement.
   1.932 +@param aCaptureMode The capture mode for which to free the buffer manager and chunk.
   1.933 +@return	KErrNone if successful.
   1.934 +		KErrInUse if an attempt has been made to free the memory and chunk while they are in use.
   1.935 +		Otherwise one of the other system-wide error codes.
   1.936 +*/
   1.937 +TInt DCameraScLdd::ChunkClose(TInt aCaptureMode)
   1.938 +	{
   1.939 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ChunkClose(Capture Mode-%d)",aCaptureMode));
   1.940 +
   1.941 +	if(iCaptureMode == aCaptureMode)
   1.942 +        {
   1.943 +        if (iState==ECapturing)
   1.944 +            return(KErrInUse);
   1.945 +        }
   1.946 +
   1.947 +	// Delete any existing buffers
   1.948 +	if (iCaptureModeConfig[aCaptureMode].iBufManager)
   1.949 +		{
   1.950 +		delete iCaptureModeConfig[aCaptureMode].iBufManager;
   1.951 +		iCaptureModeConfig[aCaptureMode].iBufManager=NULL;
   1.952 +		}
   1.953 +
   1.954 +	// If a handle to the shared chunk was created, close it, using the handle of the thread on which
   1.955 +	// it was created, in case a different thread is now calling us
   1.956 +	if (iCaptureModeConfig[aCaptureMode].iChunkHandle>0)
   1.957 +		{
   1.958 +		Kern::CloseHandle(iOwningThread,iCaptureModeConfig[aCaptureMode].iChunkHandle);
   1.959 +		iCaptureModeConfig[aCaptureMode].iChunkHandle=0;
   1.960 +		}
   1.961 +
   1.962 +	return(KErrNone);
   1.963 +	}
   1.964 +
   1.965 +/**
   1.966 +Set the current capture mode and submits the camera configuration to the PDD, passing it as a descriptor
   1.967 +to support future changes to the config structure.
   1.968 +
   1.969 +@param aCaptureMode	The capture mode that the camera switches to.
   1.970 +@return KErrNone if successful;
   1.971 +		otherwise one of the other system-wide error codes.
   1.972 +*/
   1.973 +TInt DCameraScLdd::SetCaptureMode(TInt aCaptureMode)
   1.974 +	{
   1.975 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetCaptureMode(Mode-%d)",aCaptureMode));
   1.976 +
   1.977 +	TInt r=KErrNone;
   1.978 +	if(aCaptureMode >= ECamCaptureModeMax || aCaptureMode < 0)
   1.979 +		{
   1.980 +		r=KErrNotFound;
   1.981 +		return(r);
   1.982 +		}
   1.983 +
   1.984 +	if (!iCaptureModeConfig[aCaptureMode].iBufManager)
   1.985 +		{
   1.986 +		r=KErrNotReady;
   1.987 +		return(r);
   1.988 +		}
   1.989 +
   1.990 +	iCaptureMode=(TDevCamCaptureMode)aCaptureMode;	// The capture mode has already been checked for its validity.
   1.991 +
   1.992 +	__KTRACE_CAM(Kern::Printf("DCameraScLdd::SetCaptureMode: iFrameSize:%dx%d)",iCaptureModeConfig[iCaptureMode].iCamConfig.iFrameSize.iWidth, iCaptureModeConfig[iCaptureMode].iCamConfig.iFrameSize.iHeight));
   1.993 +
   1.994 +	// Call the PDD to change the hardware configuration according to the new capture mode.
   1.995 +	// Pass it as a descriptor - to support future changes to the config structure.
   1.996 +	TPtr8 ptr((TUint8*)&iCaptureModeConfig[iCaptureMode].iCamConfig,sizeof(iCaptureModeConfig[iCaptureMode].iCamConfig),sizeof(iCaptureModeConfig[iCaptureMode].iCamConfig));
   1.997 +	r=Pdd()->SetConfig(ptr);
   1.998 +	if (r!=KErrNone)
   1.999 +		return(r);
  1.1000 +	return KErrNone;
  1.1001 +	}
  1.1002 +
  1.1003 +
  1.1004 +/**
  1.1005 +Process a start image capture request from the client - in the capture mode supplied.
  1.1006 +If this is a free running mode then the PDD is called straight away to commence capturing frames. In one shot mode the driver postpones the capturing
  1.1007 +of frames until a NotifyNewImage() request is received.
  1.1008 +@return KErrNone if successful; whether capture mode was actually started or deferred until NotifyNewImage();
  1.1009 +		KErrNotReady if SetConfig() has not been previously called;
  1.1010 +		otherwise one of the other system-wide error codes.
  1.1011 +*/
  1.1012 +TInt DCameraScLdd::Start()
  1.1013 +	{
  1.1014 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Start(Current Mode-%d)",iCaptureMode));
  1.1015 +
  1.1016 +	if (iState==ECapturing)
  1.1017 +		return(KErrInUse);
  1.1018 +	TInt r=KErrNone;
  1.1019 +
  1.1020 +	// Only continue if the mode being started has been configured
  1.1021 +	if (iCaptureModeConfig[iCaptureMode].iBufManager)
  1.1022 +		iState=EConfigured;
  1.1023 +
  1.1024 +	if (iState==EOpen)
  1.1025 +		r=KErrNotReady;
  1.1026 +	else if (iState==EConfigured)
  1.1027 +		{
  1.1028 +		iCaptureModeConfig[iCaptureMode].iBufManager->Reset();
  1.1029 +		if (iCaptureMode!=ECamCaptureModeImage)
  1.1030 +			r=DoStart();
  1.1031 +		if (r==KErrNone)
  1.1032 +			iState=ECapturing;
  1.1033 +		}
  1.1034 +	else
  1.1035 +		r=KErrGeneral;
  1.1036 +	return(r);
  1.1037 +	}
  1.1038 +
  1.1039 +/**
  1.1040 +Start the PDD capturing images.
  1.1041 +@return KErrNone if successful, otherwise one of the other system wide error codes.
  1.1042 +*/
  1.1043 +TInt DCameraScLdd::DoStart()
  1.1044 +	{
  1.1045 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoStart()"));
  1.1046 +
  1.1047 +	DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
  1.1048 +	TLinAddr linAddr=(bufManager->iChunkBase)+(bufManager->iCurrentBuffer->iChunkOffset);
  1.1049 +	TPhysAddr physAddr=bufManager->iCurrentBuffer->iPhysicalAddress;
  1.1050 +	TInt r=Pdd()->Start(iCaptureMode,linAddr,physAddr);
  1.1051 +
  1.1052 +/*
  1.1053 + * 	James Cooper: Uncommenting this code will cause the ASSERT_DEBUG in SetImageCaptured() to fail
  1.1054 + * 	if (r==KErrNone && bufManager->iNextBuffer)
  1.1055 +		{
  1.1056 +		linAddr=(bufManager->iChunkBase)+(bufManager->iNextBuffer->iChunkOffset);
  1.1057 +		physAddr=bufManager->iNextBuffer->iPhysicalAddress;
  1.1058 +		r=Pdd()->CaptureNextImage(linAddr,physAddr);
  1.1059 +		}
  1.1060 +*/	
  1.1061 +	return(r);
  1.1062 +	}
  1.1063 +
  1.1064 +/**
  1.1065 +Process a notify a new image request from the client.
  1.1066 +If there is an image already available then the request is completed straight away, otherwise it is added to the capture request queue.
  1.1067 +@param aStatus	The request status to be signalled when the request is complete. If the request is successful then this is set
  1.1068 +				to the offset within the shared chunk where the record data resides. Alternatively, if an error occurs,
  1.1069 +				it will be set to one of the system wide error values.
  1.1070 +@return KErrNone if successful - whether the request was completed or simply queued;
  1.1071 +		KErrNotReady if Start() hasn't been previousely called;
  1.1072 +		KErrInUse: if the client needs to free up buffers before further requests can be accepted;
  1.1073 +		KErrGeneral: if the client has more requests queued than there are buffers;
  1.1074 +		otherwise one of the other system wide error codes.
  1.1075 +*/
  1.1076 +TInt DCameraScLdd::NotifyNewImage(TRequestStatus* aStatus)
  1.1077 +	{
  1.1078 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage(%x) - iState(%d)",aStatus,iState));
  1.1079 +	DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
  1.1080 +	TInt r;
  1.1081 +	if (iState!=ECapturing || !bufManager)
  1.1082 +		return(KErrNotReady);
  1.1083 +
  1.1084 +	NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
  1.1085 +	if (iCaptureMode!=ECamCaptureModeImage)
  1.1086 +		{
  1.1087 +		// We're operating in one of the free running modes, see if an image is already available.
  1.1088 +		__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage - Getting image for client"));
  1.1089 +		TImageBuffer* buf=bufManager->GetImageForClient(EFalse);
  1.1090 +		if (buf)
  1.1091 +			{
  1.1092 +			__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage - There is an image available already"));
  1.1093 +			// There is an image available already - complete the request.
  1.1094 +			r=buf->iResult;
  1.1095 +			NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
  1.1096 +			if (r==KErrNone)
  1.1097 +				{
  1.1098 +				// Only complete if successful here. Errors will be completed on returning from this method.
  1.1099 +				__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage(iId:%d)",buf->iId));
  1.1100 +				Kern::RequestComplete(iOwningThread,aStatus,(buf->iId));
  1.1101 +				}
  1.1102 +			return(r);
  1.1103 +			}
  1.1104 +
  1.1105 +		// The buffer 'completed' list is empty. If the 'in-use' list contains all the buffers apart from the one being filled
  1.1106 +		// then let the client know they need to free some buffers.
  1.1107 +		if (bufManager->iFreeBufferQ.IsEmpty() && !bufManager->iNextBuffer)
  1.1108 +			{
  1.1109 +			NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
  1.1110 +			return(KErrInUse);
  1.1111 +			}
  1.1112 +		}
  1.1113 +	else
  1.1114 +		{
  1.1115 +		// We're operating in one shot image capture mode. Check if the client needs to free up some buffers
  1.1116 +		// before we can accept the request.
  1.1117 +		if (bufManager->iCompletedBufferQ.IsEmpty() && bufManager->iFreeBufferQ.IsEmpty() && !bufManager->iNextBuffer)
  1.1118 +			{
  1.1119 +			NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
  1.1120 +			return(KErrInUse);
  1.1121 +			}
  1.1122 +
  1.1123 +		// Enough buffers are available so we can start capturing data. First
  1.1124 +		// check that there isn't already a capture request in progress.
  1.1125 +		if (iRequestQueue.IsEmpty())
  1.1126 +			{
  1.1127 +			// No previous request in progress so start the PDD.
  1.1128 +			NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
  1.1129 +			r=DoStart();
  1.1130 +			if (r!=KErrNone)
  1.1131 +				return(r);
  1.1132 +			NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex again.
  1.1133 +			}
  1.1134 +		}
  1.1135 +
  1.1136 +	// Save the request in the pending queue and return. The request will be completed from the PDD and the DFC thread when
  1.1137 +	// an image is available.
  1.1138 +	r=iRequestQueue.Add(aStatus);
  1.1139 +	NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
  1.1140 +	return(r);
  1.1141 +	}
  1.1142 +
  1.1143 +/**
  1.1144 +Process a release buffer request from the client.
  1.1145 +@param aChunkOffset The chunk offset corresponding to the buffer to be freed.
  1.1146 +@return KErrNone if successful;
  1.1147 +		KErrNotFound if no 'in use' buffer had the specified chunk offset;
  1.1148 +		KErrNotReady if the driver hasn't been configured for the current capture mode.
  1.1149 +*/
  1.1150 +TInt DCameraScLdd::ReleaseBuffer(TInt aBufferId)
  1.1151 +	{
  1.1152 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ReleaseBuffer(%d)",aBufferId));
  1.1153 +	if(!iCaptureModeConfig[iCaptureMode].iBufManager)
  1.1154 +		return KErrNotReady;
  1.1155 +	DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
  1.1156 +	TInt chunkOffset = 0;
  1.1157 +
  1.1158 +	TInt r=KErrNone;
  1.1159 +	/*	The driver is left in an ECapturing state after capturing frames. However, it can be left in an
  1.1160 +		EConfigured state as a result of Stop() being called. Stop() cancels all pending capture requests and
  1.1161 +		leaves the driver in a state in which it can be restarted without needing reconfiguring.	*/
  1.1162 +	if (iState!=EOpen && bufManager)
  1.1163 +		{
  1.1164 +		chunkOffset = bufManager->iImageBuffer[aBufferId].iChunkOffset;
  1.1165 +		TImageBuffer* buf=NULL;
  1.1166 +		NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
  1.1167 +		buf=bufManager->FindInUseImage(chunkOffset);
  1.1168 +		NKern::FMSignal(&iMutex); 		// Release the buffer/request list mutex.
  1.1169 +		if (buf)
  1.1170 +			{
  1.1171 +			// The buffer specified by the client has been found in the 'in-use' list.
  1.1172 +			bufManager->Purge(buf);
  1.1173 +			}
  1.1174 +		else
  1.1175 +			r=KErrNotFound;
  1.1176 +
  1.1177 +		if (r==KErrNone)
  1.1178 +			{
  1.1179 +			NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
  1.1180 +			// Release it from the 'in-use list into the 'free' list.
  1.1181 +			r=bufManager->ReleaseImage(chunkOffset);
  1.1182 +			if (r>0)
  1.1183 +				{
  1.1184 +				// The buffer needs to be queued straight away - so signal this to the PDD
  1.1185 +				TLinAddr linAddr=(bufManager->iChunkBase)+(bufManager->iNextBuffer->iChunkOffset);
  1.1186 +				TPhysAddr physAddr=bufManager->iNextBuffer->iPhysicalAddress;
  1.1187 +				buf=bufManager->iNextBuffer;
  1.1188 +				NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
  1.1189 +				r=Pdd()->CaptureNextImage(linAddr,physAddr);
  1.1190 +				if (r==KErrNotReady)
  1.1191 +					r=KErrNone;
  1.1192 +				}
  1.1193 +			else
  1.1194 +				NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
  1.1195 +			}
  1.1196 +		}
  1.1197 +	else
  1.1198 +		r=KErrNotReady;
  1.1199 +	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::ReleaseBuffer() - r(%d)",r));
  1.1200 +	return(r);
  1.1201 +	}
  1.1202 +
  1.1203 +/**
  1.1204 +Called from the PDD in the DFC thread each time it finishes capturing an image frame.
  1.1205 +This will complete a pending capture request and update buffer lists.
  1.1206 +@param aCaptureMode The capture mode of the image captured. @see TDevCamCaptureMode.
  1.1207 +@param aResult The result of the image capture request being completed.
  1.1208 +@param aLinAddr	If this function returns KErrNone then on return, this holds the linear address of the start of the next buffer
  1.1209 +				to use for image capture.
  1.1210 +@param aPhysAddr If this function returns KErrNone then on return, this holds the physical address that corresponds to the
  1.1211 +				 linear address: aLinAddr.
  1.1212 +@return KErrNone if capturing should continue - with holding information on the next buffer to use for image capture.
  1.1213 +		KErrNotReady if capturing should continue - but with no further buffer available for image capture just yet.
  1.1214 +		KErrAbort if image capturing should now be terminated.
  1.1215 +*/
  1.1216 +TInt DCameraScLdd::ImageCaptureCallback(TDevCamCaptureMode /*aCaptureMode*/,TInt aResult,TLinAddr* aLinAddr,TPhysAddr* aPhysAddr)
  1.1217 +	{
  1.1218 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ImageCaptureCallback"));
  1.1219 +
  1.1220 +	DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
  1.1221 +	// Update the buffer list and get the next buffer for capture.
  1.1222 +	NKern::FMWait(&iMutex); 				// Acquire the buffer/request list mutex.
  1.1223 +	TImageBuffer* nextBuffer=bufManager->SetImageCaptured(aResult);	// Puts the captured image's buffer in the completed buffer queue.
  1.1224 +
  1.1225 +	// Check if there is a capture request pending.
  1.1226 +	if (!iRequestQueue.IsEmpty())
  1.1227 +		{
  1.1228 +		// A capture request is pending.
  1.1229 +		TBool removeLast=((iCaptureMode==ECamCaptureModeImage) ? (TBool) ETrue : (TBool) EFalse);
  1.1230 +		TImageBuffer* buf=bufManager->GetImageForClient(removeLast);	// Retrieved the captured image from the buffer in the completed buffer queue.
  1.1231 +		if (buf)
  1.1232 +			{
  1.1233 +			// Update the request pending list and complete the request.
  1.1234 +			TRequestStatus* rs=iRequestQueue.Remove();
  1.1235 +			TInt reason=(buf->iResult==KErrNone) ? buf->iId : buf->iResult;
  1.1236 +			NKern::FMSignal(&iMutex); 													// Release the buffer/request list mutex.
  1.1237 +			buf->SyncMemoryAfterDmaRead();
  1.1238 +			Kern::RequestComplete(iOwningThread,rs,reason);								// Complete the request.
  1.1239 +			}
  1.1240 +		else
  1.1241 +			NKern::FMSignal(&iMutex); 													// Release the buffer/request list mutex.
  1.1242 +		}
  1.1243 +	else
  1.1244 +		NKern::FMSignal(&iMutex); 														// Release the buffer/request list mutex.
  1.1245 +
  1.1246 +	// Now work out what instruction to give to the PDD
  1.1247 +	TInt r=KErrNone;
  1.1248 +	if (iCaptureMode==ECamCaptureModeImage)
  1.1249 +		{
  1.1250 +		// Image capture mode. If we've just completed a one shot request, see if there is yet another one pending.
  1.1251 +		if (!iRequestQueue.IsEmpty())
  1.1252 +			{
  1.1253 +			// Another request is pending so let the PDD carry on.
  1.1254 +			// If an error occured we need to first stop and re-start image capture
  1.1255 +			if (aResult!=KErrNone)
  1.1256 +				{
  1.1257 +				iRestartDfc.Enque();	// Queue a DFC to re-start the PDD later.
  1.1258 +				r=KErrAbort;
  1.1259 +				}
  1.1260 +			}
  1.1261 +		else
  1.1262 +			{
  1.1263 +			r=KErrAbort;	// End of image gather mode so stop the PDD.
  1.1264 +			}
  1.1265 +		}
  1.1266 +	else
  1.1267 +		{
  1.1268 +		// One of the free running modes. If an error occured we need to first stop and re-start image capture
  1.1269 +		if (aResult!=KErrNone)
  1.1270 +			{
  1.1271 +			iRestartDfc.Enque();	// Queue a DFC to re-start the PDD later.
  1.1272 +			r=KErrAbort;
  1.1273 +			}
  1.1274 +		}
  1.1275 +
  1.1276 +	// If capture should continue, check if there is a further buffer available to use for image capture.
  1.1277 +	if (r==KErrNone)
  1.1278 +		{
  1.1279 +		if (nextBuffer)
  1.1280 +			{
  1.1281 +			*aLinAddr=(bufManager->iChunkBase)+(nextBuffer->iChunkOffset);
  1.1282 +			*aPhysAddr=nextBuffer->iPhysicalAddress;
  1.1283 +			}
  1.1284 +		else
  1.1285 +			r=KErrNotReady;
  1.1286 +		}
  1.1287 +	return(r);
  1.1288 +	}
  1.1289 +
  1.1290 +/**
  1.1291 +Stores the camera configuration passed in from the user after checking and validating it.
  1.1292 +@param	aCaptureMode	The capture mode for which the setting of the camera configuration is made.
  1.1293 +@param	aCamConfigBuf	A buffer that contains the camera configuration.
  1.1294 +@return	KErrNone if successful
  1.1295 +		KErrInUse if the camera is capturing an image
  1.1296 +		KErrArgument if the camera configuration passed in is invalid
  1.1297 +		otherwise a system wide error code.
  1.1298 +*/
  1.1299 +TInt DCameraScLdd::DoSetConfig(TInt aCaptureMode, const TDesC8* aCamConfigBuf)
  1.1300 +	{
  1.1301 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoSetConfig(CaptureMode=%d)",aCaptureMode));
  1.1302 +	
  1.1303 +    if(iCaptureMode == aCaptureMode)
  1.1304 +        {
  1.1305 +        if (iState==ECapturing)
  1.1306 +            return(KErrInUse);
  1.1307 +        }
  1.1308 +
  1.1309 +	// Read the config structure from the client
  1.1310 +	TCameraConfigV02 config;
  1.1311 +	TPtr8 ptr((TUint8*)&config,sizeof(config));
  1.1312 +	TInt r=Kern::ThreadDesRead(iOwningThread,aCamConfigBuf,ptr,0);
  1.1313 +	if (r!=KErrNone)
  1.1314 +		return(r);
  1.1315 +
  1.1316 +	// Check that it is compatible with this camera device
  1.1317 +	r=ValidateConfig(aCaptureMode, config);
  1.1318 +	if (r!=KErrNone)
  1.1319 +		{
  1.1320 +		if (r == KErrNotFound)
  1.1321 +			r = KErrArgument;
  1.1322 +		return(r);
  1.1323 +		}
  1.1324 +
  1.1325 +	// We're about to replace any previous configuration - so set the
  1.1326 +	// status back to un-configured. A new buffer configuration must be calculated as a result of that.
  1.1327 +	//iState=EOpen;
  1.1328 +
  1.1329 +	// Save the new configuration.
  1.1330 +	iCaptureModeConfig[aCaptureMode].iCamConfig=config;
  1.1331 +	iCaptureModeConfig[aCaptureMode].iFrameHeight=iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iHeight;
  1.1332 +	iCaptureModeConfig[aCaptureMode].iFrameWidth=iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iWidth;
  1.1333 +
  1.1334 +	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoSetConfig - %d",KErrNone));
  1.1335 +	return(r);
  1.1336 +	}
  1.1337 +
  1.1338 +/**
  1.1339 +Validates the configuration that is about to be used with the driver.
  1.1340 +@param aCaptureMode	The capture mode that the configuration is for.
  1.1341 +@param aConfig 		The buffer that contains the camera configuration, as passed in from the user.
  1.1342 +@return	KErrNotFound if the configuration is not supported by the camera sensor.
  1.1343 +		KErrNotSupported if the driver does not support aCaptureMode
  1.1344 +		KErrNone if successful.
  1.1345 +*/
  1.1346 +TInt DCameraScLdd::ValidateConfig(TInt aCaptureMode, TCameraConfigV02& aConfig)
  1.1347 +	{
  1.1348 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ValidateConfig"));
  1.1349 +
  1.1350 +	TInt capsSize = Pdd()->CapsSize();
  1.1351 +	NKern::ThreadEnterCS();
  1.1352 +	TAny* capsBuf = Kern::Alloc(capsSize);
  1.1353 +	if(!capsBuf)
  1.1354 +		{
  1.1355 +		NKern::ThreadLeaveCS();
  1.1356 +		return KErrNoMemory;
  1.1357 +		}
  1.1358 +
  1.1359 +	TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
  1.1360 +	Pdd()->Caps(capsPtr);
  1.1361 +	NKern::ThreadLeaveCS();
  1.1362 +
  1.1363 +	TCameraCapsV02* camCaps = (TCameraCapsV02*) capsPtr.Ptr();
  1.1364 +
  1.1365 +	TInt r;
  1.1366 +	if(aCaptureMode==ECamCaptureModeImage && camCaps->iNumImagePixelFormats)
  1.1367 +		{
  1.1368 +		r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
  1.1369 +		}
  1.1370 +	else if(aCaptureMode==ECamCaptureModeVideo && camCaps->iNumVideoPixelFormats)
  1.1371 +		{
  1.1372 +		r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
  1.1373 +		}
  1.1374 +	else if(aCaptureMode==ECamCaptureModeViewFinder && camCaps->iNumViewFinderPixelFormats)
  1.1375 +		{
  1.1376 +		r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
  1.1377 +		}
  1.1378 +	else
  1.1379 +		r=KErrNotSupported;
  1.1380 +
  1.1381 +	if(r==KErrNone)
  1.1382 +		{
  1.1383 +		// Calculate the pixel width (in bytes) for the format specified
  1.1384 +		aConfig.iPixelWidthInBytes=aConfig.iPixelFormat.iPixelWidthInBytes;
  1.1385 +		}
  1.1386 +
  1.1387 +	NKern::ThreadEnterCS();
  1.1388 +	Kern::Free(capsBuf);
  1.1389 +	NKern::ThreadLeaveCS();
  1.1390 +
  1.1391 +	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::ValidateConfig - %d",r));
  1.1392 +	return(r);
  1.1393 +	}
  1.1394 +
  1.1395 +/**
  1.1396 +Validates the configuration that is about to be used with the driver by checking it against what the camera sensor supports.
  1.1397 +@param aCamCaps		The buffer that contains the capabilities of the camera driver.
  1.1398 +@param aCaptureMode	The capture mode that the configuration is for.
  1.1399 +@param aConfig 		The buffer that contains the camera configuration, as passed in from the user.
  1.1400 +@return	KErrNotFound if the configuration is not supported by the camera sensor
  1.1401 +		KErrNone if successful
  1.1402 +		or one of the system wide error values.
  1.1403 +*/
  1.1404 +TInt DCameraScLdd::DoValidateConfig(TCameraCapsV02* aCamCaps, TInt& aCaptureMode, TCameraConfigV02& aConfig)
  1.1405 +	{
  1.1406 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoValidateConfig"));
  1.1407 +	TAny* frameSizeCapsBuf;
  1.1408 +	TInt frameSizeCapsSize;
  1.1409 +	SFrameSizeCapsInfo info;
  1.1410 +	SDevCamFrameSize* frameSize;
  1.1411 +	TUint i;
  1.1412 +	TUint l;
  1.1413 +	SDevCamPixelFormat* pixelFormat;
  1.1414 +	TUint start;
  1.1415 +	TUint end;
  1.1416 +	TInt r;
  1.1417 +	pixelFormat = (SDevCamPixelFormat*) (aCamCaps + 1);
  1.1418 +	if(aCaptureMode==ECamCaptureModeImage)
  1.1419 +		{
  1.1420 +		start=0;
  1.1421 +		end=aCamCaps->iNumImagePixelFormats;
  1.1422 +		}
  1.1423 +	else if(aCaptureMode==ECamCaptureModeVideo)
  1.1424 +		{
  1.1425 +		start=aCamCaps->iNumImagePixelFormats;
  1.1426 +		end=aCamCaps->iNumImagePixelFormats + aCamCaps->iNumVideoPixelFormats;
  1.1427 +		pixelFormat += aCamCaps->iNumImagePixelFormats;
  1.1428 +		}
  1.1429 +	else if(aCaptureMode==ECamCaptureModeViewFinder)
  1.1430 +		{
  1.1431 +		start=aCamCaps->iNumImagePixelFormats+aCamCaps->iNumVideoPixelFormats;
  1.1432 +		end=aCamCaps->iNumImagePixelFormats + aCamCaps->iNumVideoPixelFormats + aCamCaps->iNumViewFinderPixelFormats;
  1.1433 +		pixelFormat += aCamCaps->iNumImagePixelFormats;
  1.1434 +		pixelFormat += aCamCaps->iNumVideoPixelFormats;
  1.1435 +		}
  1.1436 +	else
  1.1437 +		return KErrNotSupported;
  1.1438 +
  1.1439 +	for (i=start; i<end; i++)
  1.1440 +		{
  1.1441 +		if(aConfig.iPixelFormat.iPixelFormat==pixelFormat->iPixelFormat)
  1.1442 +			{
  1.1443 +			info.iUidPixelFormat = pixelFormat->iPixelFormat;
  1.1444 +			info.iCaptureMode = (TDevCamCaptureMode) aCaptureMode;
  1.1445 +			frameSizeCapsSize = pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize);
  1.1446 +			NKern::ThreadEnterCS();
  1.1447 +			frameSizeCapsBuf = Kern::Alloc(frameSizeCapsSize);
  1.1448 +			NKern::ThreadLeaveCS();
  1.1449 +			if (!frameSizeCapsBuf)
  1.1450 +				{
  1.1451 +				return KErrNoMemory;
  1.1452 +				}
  1.1453 +			TPtr8 frameSizeCapsPtr( (TUint8*)frameSizeCapsBuf, frameSizeCapsSize, frameSizeCapsSize );
  1.1454 +			if ((r = Pdd()->FrameSizeCaps(info.iCaptureMode, info.iUidPixelFormat, frameSizeCapsPtr)) == KErrNone)
  1.1455 +				{
  1.1456 +				frameSize = (SDevCamFrameSize*) frameSizeCapsPtr.Ptr();
  1.1457 +				for(l=0; l<pixelFormat->iNumFrameSizes; l++ )
  1.1458 +					{
  1.1459 +					if (aConfig.iFrameSize.iWidth == frameSize->iWidth &&
  1.1460 +						aConfig.iFrameSize.iHeight == frameSize->iHeight &&
  1.1461 +						aConfig.iFrameRate >= frameSize->iMinFrameRate &&
  1.1462 +						aConfig.iFrameRate <= frameSize->iMaxFrameRate)
  1.1463 +						{
  1.1464 +						NKern::ThreadEnterCS();
  1.1465 +						Kern::Free(frameSizeCapsBuf);
  1.1466 +						NKern::ThreadLeaveCS();
  1.1467 +						__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoValidateConfig"));
  1.1468 +						return KErrNone;
  1.1469 +						}
  1.1470 +					frameSize++;
  1.1471 +					}
  1.1472 +				NKern::ThreadEnterCS();
  1.1473 +				Kern::Free(frameSizeCapsBuf);
  1.1474 +				NKern::ThreadLeaveCS();
  1.1475 +				return KErrNotFound;
  1.1476 +				}
  1.1477 +			else
  1.1478 +				{
  1.1479 +				NKern::ThreadEnterCS();
  1.1480 +				Kern::Free(frameSizeCapsBuf);
  1.1481 +				NKern::ThreadLeaveCS();
  1.1482 +				return r;
  1.1483 +				}
  1.1484 +			}
  1.1485 +		pixelFormat++;
  1.1486 +		}
  1.1487 +	return KErrNotFound;
  1.1488 +	}
  1.1489 +
  1.1490 +/**
  1.1491 +The DFC used to re-start the PDD following a data capture error.
  1.1492 +@param aChannel A pointer to the camera driver logical channel object.
  1.1493 +*/
  1.1494 +void DCameraScLdd::RestartDfc(TAny* aChannel)
  1.1495 +	{
  1.1496 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::RestartDfc"));
  1.1497 +
  1.1498 +	DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
  1.1499 +
  1.1500 +	if (!drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer)
  1.1501 +		drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer=drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->NextAvailableForCapture();
  1.1502 +	__ASSERT_ALWAYS(drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer,Kern::Fault(KCameraLddPanic,__LINE__));
  1.1503 +
  1.1504 +	if (!drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iNextBuffer)
  1.1505 +		drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iNextBuffer=drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->NextAvailableForCapture();
  1.1506 +
  1.1507 +	drv.DoStart();
  1.1508 +	}
  1.1509 +
  1.1510 +/**
  1.1511 +The DFC used to handle power down requests from the power manager before a transition into system
  1.1512 +shutdown/standby.
  1.1513 +@param aChannel A pointer to the camera driver logical channel object.
  1.1514 +*/
  1.1515 +void DCameraScLdd::PowerDownDfc(TAny* aChannel)
  1.1516 +	{
  1.1517 +	DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
  1.1518 +	drv.Shutdown();
  1.1519 +	drv.iPowerHandler->PowerDownDone();
  1.1520 +	}
  1.1521 +
  1.1522 +/**
  1.1523 +The DFC used to handle power up requests from the power manager following a transition out of system standby.
  1.1524 +@param aChannel A pointer to the camera driver logical channel object.
  1.1525 +*/
  1.1526 +void DCameraScLdd::PowerUpDfc(TAny* aChannel)
  1.1527 +	{
  1.1528 +	DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
  1.1529 +	drv.iPowerHandler->PowerUpDone();
  1.1530 +	}
  1.1531 +
  1.1532 +void DCameraScLdd::PanicClientThread(TInt aReason)
  1.1533 +	{
  1.1534 +	Kern::ThreadKill(iOwningThread, EExitPanic, aReason, KDevCameraScName);
  1.1535 +	}
  1.1536 +
  1.1537 +/**
  1.1538 +Retrieves the capabilities of the camera sensor.
  1.1539 +@param aBuffer	A pointer to a descriptor passed in by the user.
  1.1540 +*/
  1.1541 +TInt DCameraScLdd::GetSensorCaps(TAny* aBuffer)
  1.1542 +	{
  1.1543 +	// Return the capabilities for this device. Read this from the PDD and
  1.1544 +	// then write it to the client
  1.1545 +	TInt capsSize = Pdd()->CapsSize();
  1.1546 +	TInt bufferSize;
  1.1547 +	TInt maxBufferSize;
  1.1548 +	Kern::KUDesInfo(*((TDes8*)aBuffer), bufferSize, maxBufferSize);
  1.1549 +	if(capsSize>maxBufferSize)
  1.1550 +		{
  1.1551 +		return KErrArgument;
  1.1552 +		}
  1.1553 +	NKern::ThreadEnterCS();
  1.1554 +	TAny* capsBuf = Kern::Alloc(capsSize);
  1.1555 +	if(!capsBuf)
  1.1556 +		{
  1.1557 +		NKern::ThreadLeaveCS();
  1.1558 +		return KErrNoMemory;
  1.1559 +		}
  1.1560 +
  1.1561 +	TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
  1.1562 +	Pdd()->Caps(capsPtr);
  1.1563 +	NKern::ThreadLeaveCS();
  1.1564 +	Kern::InfoCopy(*((TDes8*)aBuffer), capsPtr.Ptr(), capsSize);
  1.1565 +	NKern::ThreadEnterCS();
  1.1566 +	Kern::Free((TAny*)capsBuf);
  1.1567 +	NKern::ThreadLeaveCS();
  1.1568 +	return KErrNone;
  1.1569 +	}
  1.1570 +
  1.1571 +/**
  1.1572 +Retrieves the frame sizes supported for a given pixel format.
  1.1573 +@param aBuffer	A pointer to descriptor passed in by the user.
  1.1574 +@param aFrameSizeCapsInfo A structure that holds information regarding the requested capabilities.
  1.1575 +*/
  1.1576 +TInt DCameraScLdd::GetFrameSizeCaps(TAny* aBuffer, TAny* aFrameSizeCapsInfo)
  1.1577 +	{
  1.1578 +	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::GetFrameSizeCaps()"));
  1.1579 +	TInt frameSizeCapsMaxSize;
  1.1580 +	TInt frameSizeCapsSize;
  1.1581 +	Kern::KUDesInfo(*((TDes8*)aBuffer),frameSizeCapsSize,frameSizeCapsMaxSize);
  1.1582 +	SFrameSizeCapsInfo info;
  1.1583 +	kumemget((TAny*)&info,aFrameSizeCapsInfo,sizeof(info));
  1.1584 +	NKern::ThreadEnterCS();
  1.1585 +	// Allocate memory on the heap for the frame size structure.
  1.1586 +	TAny* frameSizeCapsBuf = Kern::Alloc(frameSizeCapsMaxSize);
  1.1587 +	if (!frameSizeCapsBuf)
  1.1588 +		{
  1.1589 +		NKern::ThreadLeaveCS();
  1.1590 +		return KErrNoMemory;
  1.1591 +		}
  1.1592 +	TPtr8 frameSizeCapsPtr( (TUint8*)frameSizeCapsBuf, frameSizeCapsMaxSize, frameSizeCapsMaxSize );
  1.1593 +	// Request the frame sizes from the Pdd.
  1.1594 +	TInt r=Pdd()->FrameSizeCaps(info.iCaptureMode, info.iUidPixelFormat, frameSizeCapsPtr);
  1.1595 +	NKern::ThreadLeaveCS();
  1.1596 +	if (r!=KErrNone)
  1.1597 +		{
  1.1598 +		NKern::ThreadEnterCS();
  1.1599 +		Kern::Free((TAny*)frameSizeCapsBuf);
  1.1600 +		NKern::ThreadLeaveCS();
  1.1601 +		return r;
  1.1602 +		}
  1.1603 +	Kern::InfoCopy(*((TDes8*)aBuffer),frameSizeCapsPtr.Ptr(), frameSizeCapsMaxSize);
  1.1604 +	NKern::ThreadEnterCS();
  1.1605 +	Kern::Free((TAny*)frameSizeCapsBuf);
  1.1606 +	NKern::ThreadLeaveCS();
  1.1607 +	return KErrNone;
  1.1608 +	}
  1.1609 +
  1.1610 +
  1.1611 +/**
  1.1612 +Constructor for the buffer manager.
  1.1613 +*/
  1.1614 +DBufferManager::DBufferManager(DCameraScLdd* aLdd)
  1.1615 +	: iLdd(aLdd)
  1.1616 +	{
  1.1617 +//	iChunk=NULL;
  1.1618 +//	iNumBuffers=0;
  1.1619 +//	iImageBuffer=NULL;
  1.1620 +	}
  1.1621 +
  1.1622 +/**
  1.1623 +Destructor for the buffer manager.
  1.1624 +@pre The thread must be in a critical section.
  1.1625 +*/
  1.1626 +DBufferManager::~DBufferManager()
  1.1627 +	{
  1.1628 +	if (iChunk)
  1.1629 +		Kern::ChunkClose(iChunk);
  1.1630 +	delete[] iImageBuffer;
  1.1631 +	}
  1.1632 +
  1.1633 +/**
  1.1634 +Second stage constructor for the buffer manager. This version creates a shared chunk and a buffer object for each
  1.1635 +buffer specified within this. Then it commits memory within the chunk for each of these buffers. This also involves the
  1.1636 +creation of a set of buffer lists to manage the buffers.
  1.1637 +@param aNumBuffers The number of buffers required in the shared chunk.
  1.1638 +@param aBufferSize The size of each buffer required in the shared chunk.
  1.1639 +@return KErrNone if successful, otherwise one of the other system wide error codes.
  1.1640 +@pre The thread must be in a critical section.
  1.1641 +*/
  1.1642 +TInt DBufferManager::Create(TInt aNumBuffers,TInt aBufferSize)
  1.1643 +	{
  1.1644 +	__KTRACE_CAM(Kern::Printf(">DBufferManager::Create(Bufs-%d,Sz-%d)",aNumBuffers,aBufferSize));
  1.1645 +
  1.1646 +	TInt r=CreateBufferLists(aNumBuffers);
  1.1647 +	if (r!=KErrNone)
  1.1648 +		return(r);
  1.1649 +
  1.1650 +	// Calculate the size of the chunk required for the buffer configuration specified.
  1.1651 +	aBufferSize=Kern::RoundToPageSize(aBufferSize);
  1.1652 +	TInt pageSize=Kern::RoundToPageSize(1);
  1.1653 +	// Leave space for guard pages around each buffer.  There is a guard page in between each buffer but
  1.1654 +	// NO guard page before the first buffer or after the last buffer
  1.1655 +	TUint64 chunkSize=TUint64(aBufferSize+pageSize)*aNumBuffers-pageSize;
  1.1656 +	if (chunkSize>(TUint64)KMaxTInt)
  1.1657 +		return(KErrNoMemory); // Need more than 2GB of memory!
  1.1658 +
  1.1659 +	// Create the shared chunk. The PDD supplies most of the chunk create info - but not the maximum size.
  1.1660 +	TChunkCreateInfo info;
  1.1661 +	info.iMaxSize=(TInt)chunkSize;
  1.1662 +	iLdd->Pdd()->GetChunkCreateInfo(info);		// Call down to the PDD for the rest.
  1.1663 +
  1.1664 +	r = Kern::ChunkCreate(info,iChunk,iChunkBase,iChunkMapAttr);
  1.1665 +	if (r!=KErrNone)
  1.1666 +		return(r);
  1.1667 +
  1.1668 +	// Commit memory in the chunk for each buffer.
  1.1669 +	TInt offset=0;
  1.1670 +	TBool isContiguous;
  1.1671 +	for (TInt i=0; i<aNumBuffers ; i++)
  1.1672 +		{
  1.1673 +		r=CommitMemoryForBuffer(offset,aBufferSize,isContiguous);
  1.1674 +		if (r!=KErrNone)
  1.1675 +			return(r);
  1.1676 +		r=iImageBuffer[i].Create(iChunk,offset,aBufferSize,i,isContiguous);
  1.1677 +		iImageBuffer[i].iId=i;
  1.1678 +		if (r!=KErrNone)
  1.1679 +			return(r);
  1.1680 +		offset += (aBufferSize+pageSize);
  1.1681 +		}
  1.1682 +
  1.1683 +	return(KErrNone);
  1.1684 +	}
  1.1685 +
  1.1686 +/**
  1.1687 +Second stage constructor for the buffer manager. This version opens an existing shared chunk using a client supplied
  1.1688 +handle. It then creates a buffer object for each buffer that exists within the chunk as well as creating a set of buffer
  1.1689 +lists to manage the buffers.
  1.1690 +@param aBufConfig The shared chunk buffer configuration object - specifying the geometry of the buffer configuration
  1.1691 +within the shared chunk supplied.
  1.1692 +@param aChunkHandle A handle for the shared chunk supplied by the client.
  1.1693 +@param anOwningThread The thread in which the given handle is valid.
  1.1694 +@return KErrNone if successful, otherwise one of the other system wide error codes.
  1.1695 +@pre The thread must be in a critical section.
  1.1696 +*/
  1.1697 +TInt DBufferManager::Create(TCameraSharedChunkBufConfig& aBufConfig,TInt aChunkHandle,DThread* anOwningThread)
  1.1698 +	{
  1.1699 +	__KTRACE_CAM(Kern::Printf(">DBufferManager::Create(Handle-%d)",aChunkHandle));
  1.1700 +
  1.1701 +	// Validate the buffer configuration information
  1.1702 +	if (!aBufConfig.iFlags&KScFlagBufOffsetListInUse)
  1.1703 +		return(KErrArgument);
  1.1704 +
  1.1705 +	TInt numBuffers=aBufConfig.iNumBuffers;
  1.1706 +	TInt r=CreateBufferLists(numBuffers);
  1.1707 +	if (r!=KErrNone)
  1.1708 +		return(r);
  1.1709 +
  1.1710 +	DChunk* chunk;
  1.1711 +	chunk=Kern::OpenSharedChunk(anOwningThread,aChunkHandle,ETrue);
  1.1712 +	if (!chunk)
  1.1713 +		return(KErrBadHandle);
  1.1714 +	iChunk=chunk;
  1.1715 +
  1.1716 +	// Read the physical address for the 1st buffer in order to determine the kernel address and the map attributes.
  1.1717 +	TInt bufferSizeInBytes=aBufConfig.iBufferSizeInBytes;
  1.1718 +
  1.1719 +	SBufSpecList* bufferSpec=&aBufConfig.iSpec;
  1.1720 +
  1.1721 +	TInt offset=bufferSpec[0].iBufferOffset;
  1.1722 +
  1.1723 +	TPhysAddr physAddr;
  1.1724 +	r=Kern::ChunkPhysicalAddress(iChunk,offset,bufferSizeInBytes,iChunkBase,iChunkMapAttr,physAddr,NULL);
  1.1725 +	if (r!=KErrNone)
  1.1726 +		return(r);
  1.1727 +
  1.1728 +	// Store the supplied buffer info. into each buffer object.
  1.1729 +
  1.1730 +	for (TInt i=0; i<numBuffers; i++)
  1.1731 +		{
  1.1732 +		offset=bufferSpec[i].iBufferOffset;
  1.1733 +		// Assume it isn't contiguous here - Create() will detect and do the right thing if it is contiguous.
  1.1734 +		r=iImageBuffer[i].Create(iChunk,offset,bufferSizeInBytes,i,EFalse);
  1.1735 +		iImageBuffer[i].iId=i;
  1.1736 +		if (r!=KErrNone)
  1.1737 +			return(r);
  1.1738 +		}
  1.1739 +	__KTRACE_CAM(Kern::Printf("<DBufferManager::Create - %d",KErrNone));
  1.1740 +	return(KErrNone);
  1.1741 +	}
  1.1742 +
  1.1743 +/**
  1.1744 +Copies the contents of the Buffer Manager's configuration into aBufConfig
  1.1745 +@param aBufConfig The buffer that the data is copied into.
  1.1746 +*/
  1.1747 +void DBufferManager::GetBufConfig(TCameraSharedChunkBufConfig& aBufConfig)
  1.1748 +	{
  1.1749 +	__KTRACE_CAM(Kern::Printf(">DBufferManager::GetBufConfig"));
  1.1750 +	TInt numBuffers=iNumBuffers;
  1.1751 +	if (numBuffers<=0)
  1.1752 +		return;
  1.1753 +
  1.1754 +	SBufSpecList* bufferSpec=&aBufConfig.iSpec;
  1.1755 +
  1.1756 +	while (numBuffers--)
  1.1757 +		{
  1.1758 +		bufferSpec[numBuffers].iBufferOffset=iImageBuffer[numBuffers].iChunkOffset;
  1.1759 +		bufferSpec[numBuffers].iBufferId=iImageBuffer[numBuffers].iId;
  1.1760 +		}
  1.1761 +
  1.1762 +	aBufConfig.iNumBuffers=iNumBuffers;
  1.1763 +	aBufConfig.iBufferSizeInBytes=iImageBuffer[0].iSize;	// They're all the same size - so read from the 1st one.
  1.1764 +	aBufConfig.iFlags|=KScFlagBufOffsetListInUse;
  1.1765 +	return;
  1.1766 +	}
  1.1767 +
  1.1768 +/**
  1.1769 +Allocate an array of buffer objects, - one for each buffer contained within the shared chunk.
  1.1770 +@param aNumBuffers The number of buffer objects required.
  1.1771 +@return KErrNone if successful, otherwise one of the other system wide error codes.
  1.1772 +@pre The thread must be in a critical section.
  1.1773 +*/
  1.1774 +TInt DBufferManager::CreateBufferLists(TInt aNumBuffers)
  1.1775 +	{
  1.1776 +	__KTRACE_CAM(Kern::Printf(">DBufferManager::CreateBufferLists(Bufs-%d)",aNumBuffers));
  1.1777 +
  1.1778 +	// Construct the array of buffers.
  1.1779 +	iNumBuffers=aNumBuffers;
  1.1780 +	iImageBuffer=new TImageBuffer[aNumBuffers];
  1.1781 +	if (!iImageBuffer)
  1.1782 +		return(KErrNoMemory);
  1.1783 +	return(KErrNone);
  1.1784 +	}
  1.1785 +
  1.1786 +TInt DBufferManager::CommitMemoryForBuffer(TInt aChunkOffset,TInt aSize,TBool& aIsContiguous)
  1.1787 +	{
  1.1788 +	__KTRACE_CAM(Kern::Printf(">DBufferManager::CommitMemoryForBuffer(Offset-%x,Sz-%d)",aChunkOffset,aSize));
  1.1789 +
  1.1790 +	// Try for physically contiguous memory first.
  1.1791 +	TPhysAddr physicalAddress;
  1.1792 +	TInt r=Kern::ChunkCommitContiguous(iChunk,aChunkOffset,aSize,physicalAddress);
  1.1793 +	if (r==KErrNone)
  1.1794 +		{
  1.1795 +		aIsContiguous=ETrue;
  1.1796 +		return(r);
  1.1797 +		}
  1.1798 +
  1.1799 +	// Commit memory that isn't contiguous instead.
  1.1800 +	aIsContiguous=EFalse;
  1.1801 +	r=Kern::ChunkCommit(iChunk,aChunkOffset,aSize);
  1.1802 +	return(r);
  1.1803 +	}
  1.1804 +
  1.1805 +/**
  1.1806 +Reset all image buffer lists to reflect the state at the start of the image capture process.
  1.1807 +@pre The buffer/request queue mutex must be held.
  1.1808 +*/
  1.1809 +void DBufferManager::Reset()
  1.1810 +	{
  1.1811 +	__KTRACE_CAM(Kern::Printf(">DBufferManager::Reset"));
  1.1812 +
  1.1813 +	TImageBuffer* pBuf;
  1.1814 +
  1.1815 +	// Before reseting buffer lists, purge the cache for all cached buffers currently in use by client.
  1.1816 +	pBuf=(TImageBuffer*)iInUseBufferQ.First();
  1.1817 +	SDblQueLink* anchor=&iInUseBufferQ.iA;
  1.1818 +	while (pBuf!=anchor)
  1.1819 +		{
  1.1820 +		Purge(pBuf);
  1.1821 +		pBuf=(TImageBuffer*)pBuf->iNext;
  1.1822 +		}
  1.1823 +
  1.1824 +	// Start by reseting all the lists.
  1.1825 +	iFreeBufferQ.iA.iNext=iFreeBufferQ.iA.iPrev=&iFreeBufferQ.iA;
  1.1826 +	iCompletedBufferQ.iA.iNext=iCompletedBufferQ.iA.iPrev=&iCompletedBufferQ.iA;
  1.1827 +	iInUseBufferQ.iA.iNext=iInUseBufferQ.iA.iPrev=&iInUseBufferQ.iA;
  1.1828 +
  1.1829 +	// Set the pointers to the current and the next record buffers.
  1.1830 +	pBuf=iImageBuffer; 		// This is the first buffer
  1.1831 +	iCurrentBuffer=pBuf++;
  1.1832 +	iNextBuffer = pBuf++;
  1.1833 +
  1.1834 +	// Add all other buffers to the free list.
  1.1835 +	TImageBuffer* bufferLimit=iImageBuffer+iNumBuffers;
  1.1836 +	while(pBuf<bufferLimit)
  1.1837 +		iFreeBufferQ.Add(pBuf++);
  1.1838 +	}
  1.1839 +
  1.1840 +/**
  1.1841 +Purge the cache for a cached image buffer.
  1.1842 +@param aBuffer The buffer to be purged.
  1.1843 +*/
  1.1844 +void DBufferManager::Purge(TImageBuffer* aBuffer)
  1.1845 +	{
  1.1846 +	aBuffer->SyncMemoryBeforeDmaRead();
  1.1847 +	}
  1.1848 +
  1.1849 +/**
  1.1850 +Update buffer lists after an image has been captured.
  1.1851 +@param aResult The result of the image capture operation that has just completed.
  1.1852 +@return A pointer to the next image buffer for capture - or NULL if none are available.
  1.1853 +@pre The buffer/request queue mutex must be held.
  1.1854 +*/
  1.1855 +TImageBuffer* DBufferManager::SetImageCaptured(TInt aResult)
  1.1856 +	{
  1.1857 +	// Take a copy of the buffer with the image just captured.
  1.1858 +	__ASSERT_DEBUG(iCurrentBuffer,Kern::Fault(KCameraLddPanic,__LINE__));
  1.1859 +	TImageBuffer* cur=iCurrentBuffer;
  1.1860 +
  1.1861 +	// Make the queued buffer the current one.
  1.1862 +	iCurrentBuffer=iNextBuffer;
  1.1863 +
  1.1864 +	// Now we need to identify the next image buffer to queue.
  1.1865 +	iNextBuffer=NextAvailableForCapture();
  1.1866 +
  1.1867 +	// Now add the buffer with the image just captured to the 'completed' list.
  1.1868 +	if (cur)
  1.1869 +		{
  1.1870 +		cur->iResult=aResult;						// Store the result of the capture operation in the image buffer object.
  1.1871 +		iCompletedBufferQ.Add(cur);
  1.1872 +		}
  1.1873 +
  1.1874 +	__KTRACE_CAM(Kern::Printf("<DBufferManager::SetImageCaptured(buf=%08x)-%d",cur->iChunkOffset,aResult));
  1.1875 +	return(iNextBuffer);
  1.1876 +	}
  1.1877 +
  1.1878 +/**
  1.1879 +Remove from the buffer lists the next buffer that is available to queue for transfer.
  1.1880 +@return A pointer to the next image buffer for capture - or NULL if none are available.
  1.1881 +@pre The buffer/request queue mutex must be held.
  1.1882 +*/
  1.1883 +TImageBuffer* DBufferManager::NextAvailableForCapture()
  1.1884 +	{
  1.1885 +	// We need to identify the next image buffer to queue. Try to get one from the 'free' list.
  1.1886 +	TImageBuffer* buffer=(TImageBuffer*)iFreeBufferQ.GetFirst();
  1.1887 +#ifdef DISCARD_COMPLETED_TO_AVOID_OVERFLOW
  1.1888 +	// If there are none left on the 'free' list then take one from the completed list.
  1.1889 +	if (!buffer)
  1.1890 +		buffer=(TImageBuffer*)iCompletedBufferQ.GetFirst();
  1.1891 +#endif
  1.1892 +	return(buffer);
  1.1893 +	}
  1.1894 +
  1.1895 +/**
  1.1896 +Get the next image from the 'completed' capture list. If there is no error associated with the buffer,
  1.1897 +make it 'in use' by the client. Otherwise, return the buffer to the free list.
  1.1898 +@param aRemoveLast	If true, the buffer is removed from the tail of the completed capture list, otherwise
  1.1899 +					it is removed from the head of this list.
  1.1900 +@return A pointer to the next completed image buffer - or NULL if there is no buffer available.
  1.1901 +@pre The buffer/request queue mutex must be held.
  1.1902 +*/
  1.1903 +TImageBuffer* DBufferManager::GetImageForClient(TBool aRemoveLast)
  1.1904 +	{
  1.1905 +	__KTRACE_CAM(Kern::Printf("<DBufferManager::GetImageForClient"));
  1.1906 +	TImageBuffer* buffer=NULL;
  1.1907 +	if (!iCompletedBufferQ.IsEmpty())
  1.1908 +		{
  1.1909 +		buffer = (aRemoveLast) ? (TImageBuffer*)iCompletedBufferQ.Last() : (TImageBuffer*)iCompletedBufferQ.First();
  1.1910 +		buffer->Deque();
  1.1911 +
  1.1912 +		if (buffer->iResult==KErrNone)
  1.1913 +			iInUseBufferQ.Add(buffer);
  1.1914 +		else
  1.1915 +			iFreeBufferQ.Add(buffer);
  1.1916 +		}
  1.1917 +	return(buffer);
  1.1918 +	}
  1.1919 +
  1.1920 +/**
  1.1921 +Release (move to free list) the 'in use' image specified by the given chunk offset.
  1.1922 +@param aChunkOffset The chunk offset corresponding to the buffer to be freed.
  1.1923 +@return The freed image buffer, or NULL if no 'in use' buffer had the specified chunk offset.
  1.1924 +@return KErrNone if buffer moved to the free list;
  1.1925 +		1 if the buffer needs to be queued straight away
  1.1926 +		KErrArgument if no 'in use' buffer had the specified chunk offset;
  1.1927 +@pre The buffer/request queue mutex must be held.
  1.1928 +*/
  1.1929 +TInt DBufferManager::ReleaseImage(TInt aChunkOffset)
  1.1930 +	{
  1.1931 +	__KTRACE_CAM(Kern::Printf(">DBufferManager::ReleaseImage(chunkOffset=%08x)",aChunkOffset));
  1.1932 +	TInt r=KErrArgument;
  1.1933 +
  1.1934 +	// Scan 'in use' list for the image buffer
  1.1935 +	TImageBuffer* pBuf;
  1.1936 +	pBuf=(TImageBuffer*)iInUseBufferQ.First();
  1.1937 +	SDblQueLink* anchor=&iInUseBufferQ.iA;
  1.1938 +	while (pBuf!=anchor && pBuf->iChunkOffset!=aChunkOffset)
  1.1939 +		pBuf=(TImageBuffer*)pBuf->iNext;
  1.1940 +
  1.1941 +	if (pBuf!=anchor)
  1.1942 +		{
  1.1943 +		// Buffer found in 'in-use' list.
  1.1944 +		if (!iNextBuffer)
  1.1945 +			{
  1.1946 +			// We need to signal the pdd to queue this buffer straight away.
  1.1947 +			iNextBuffer=(TImageBuffer*)pBuf->Deque();
  1.1948 +			r=1;
  1.1949 +			}
  1.1950 +		else
  1.1951 +			{
  1.1952 +			// Move buffer to the free list.
  1.1953 +			iFreeBufferQ.Add(pBuf->Deque());
  1.1954 +			r=KErrNone;
  1.1955 +			}
  1.1956 +		}
  1.1957 +
  1.1958 +	__KTRACE_CAM(Kern::Printf("<DBufferManager::ReleaseImage(buf=%08x)",((pBuf!=anchor) ? pBuf->iChunkOffset : -1)));
  1.1959 +	return(r);
  1.1960 +	}
  1.1961 +
  1.1962 +/**
  1.1963 +Find the 'in use' image specified by the given chunk offset
  1.1964 +@param aChunkOffset The chunk offset corresponding to the buffer to be freed
  1.1965 +@return The image buffer, or NULL if no 'in use' buffer had the specified chunk offset
  1.1966 +@pre The buffer/request queue mutex must be held.
  1.1967 +*/
  1.1968 +TImageBuffer* DBufferManager::FindInUseImage(TInt aChunkOffset)
  1.1969 +	{
  1.1970 +	// Scan 'in use' list for the image buffer
  1.1971 +	TImageBuffer* pBuf;
  1.1972 +	pBuf=(TImageBuffer*)iInUseBufferQ.First();
  1.1973 +	SDblQueLink* anchor=&iInUseBufferQ.iA;
  1.1974 +	while (pBuf!=anchor && pBuf->iChunkOffset!=aChunkOffset)
  1.1975 +		pBuf=(TImageBuffer*)pBuf->iNext;
  1.1976 +
  1.1977 +	return((pBuf!=anchor)?pBuf:NULL);
  1.1978 +	}
  1.1979 +
  1.1980 +/**
  1.1981 +Constructor for the image buffer class.
  1.1982 +Clears all member data
  1.1983 +*/
  1.1984 +TImageBuffer::TImageBuffer()
  1.1985 +	{
  1.1986 +	memclr(this,sizeof(*this));
  1.1987 +	}
  1.1988 +
  1.1989 +/**
  1.1990 +Destructor for the image buffer class.
  1.1991 +*/
  1.1992 +TImageBuffer::~TImageBuffer()
  1.1993 +	{
  1.1994 +	delete[] iPhysicalPages;
  1.1995 +	}
  1.1996 +
  1.1997 +/**
  1.1998 +Second stage constructor for the image buffer class - get information on the memory
  1.1999 +allocated to this buffer.
  1.2000 +@param aChunk	The chunk into which the memory is to be commited
  1.2001 +@param aOffset	The offset within aChunk for the start of the comitted memory.
  1.2002 +				Must be a multiple of the MMU page size.
  1.2003 +@param aSize	The number of bytes of memory commited.
  1.2004 +				Must be a multiple of the MMU page size.
  1.2005 +@return KErrNone if successful, otherwise one of the other system wide error codes.
  1.2006 +@pre The thread must be in a critical section.
  1.2007 +*/
  1.2008 +TInt TImageBuffer::Create(DChunk* aChunk,TInt aOffset,TInt aSize, TInt aId, TBool aIsContiguous)
  1.2009 +	{
  1.2010 +	__KTRACE_CAM(Kern::Printf(">TImageBuffer::Create(Off-%x,Sz-%d,Contig-%d)",aOffset,aSize,aIsContiguous));
  1.2011 +
  1.2012 +	// Save info. on the chunk the buffer is in, and the offset and size of the buffer.
  1.2013 +	iChunk=aChunk;
  1.2014 +	iChunkOffset=aOffset;
  1.2015 +	iId=aId;
  1.2016 +	iSize=aSize;
  1.2017 +
  1.2018 +	TInt r=KErrNone;
  1.2019 +	iPhysicalPages=NULL;
  1.2020 +	if (!aIsContiguous)
  1.2021 +		{
  1.2022 +		// Allocate an array for a list of the physical pages.
  1.2023 +		iPhysicalPages = new TPhysAddr[aSize/Kern::RoundToPageSize(1)+2];
  1.2024 +		if (!iPhysicalPages)
  1.2025 +			r=KErrNoMemory;
  1.2026 +		}
  1.2027 +
  1.2028 +	if (r==KErrNone)
  1.2029 +		{
  1.2030 +		// Get the physical addresses of the pages in the buffer.
  1.2031 +		TUint32 mapAttr;
  1.2032 +		r=Kern::ChunkPhysicalAddress(aChunk,aOffset,aSize,iLinearAddress,mapAttr,iPhysicalAddress,iPhysicalPages);
  1.2033 +		// r = 0 or 1 on success. (1 meaning the physical pages are not contiguous).
  1.2034 +		if (r==1)
  1.2035 +			{
  1.2036 +			// The physical pages are not contiguous.
  1.2037 +			iPhysicalAddress=KPhysAddrInvalid;	// Mark the physical address as invalid.
  1.2038 +			r=(aIsContiguous) ? KErrGeneral : KErrNone;
  1.2039 +			}
  1.2040 +		if (r==0)
  1.2041 +			{
  1.2042 +			delete[] iPhysicalPages;	// We shouldn't retain this info. if the physical pages are contiguous.
  1.2043 +			iPhysicalPages=NULL;
  1.2044 +			}
  1.2045 +		}
  1.2046 +	__KTRACE_CAM(Kern::Printf("<TImageBuffer::Create - %d",r));
  1.2047 +	return(r);
  1.2048 +	}
  1.2049 +
  1.2050 +/**
  1.2051 +Prepares a cacheable buffer for use by the DMA engine, before an image capture.
  1.2052 +*/
  1.2053 +void TImageBuffer::SyncMemoryBeforeDmaRead()
  1.2054 +	{
  1.2055 +#ifndef __WINS__
  1.2056 +	if (iChunk->iMapAttr&EMapAttrCachedMax)
  1.2057 +		{
  1.2058 +		Cache::SyncMemoryBeforeDmaRead(iLinearAddress,iSize);
  1.2059 +		}
  1.2060 +#endif
  1.2061 +	}
  1.2062 +
  1.2063 +/**
  1.2064 +Prepare a cacheable buffer for use by the CPU, after an image capture using DMA.
  1.2065 +*/
  1.2066 +void TImageBuffer::SyncMemoryAfterDmaRead()
  1.2067 +	{
  1.2068 +#ifndef __WINS__
  1.2069 +	if (iChunk->iMapAttr&EMapAttrCachedMax)
  1.2070 +		{
  1.2071 +		Cache::SyncMemoryAfterDmaRead(iLinearAddress,iSize);
  1.2072 +		}
  1.2073 +#endif
  1.2074 +	}
  1.2075 +
  1.2076 +/**
  1.2077 +Constructor for the capture request queue.
  1.2078 +*/
  1.2079 +TCameraScRequestQueue::TCameraScRequestQueue(NFastMutex* aMutexPtr)
  1.2080 +	: iMutexPtr(aMutexPtr)
  1.2081 +	{
  1.2082 +	iOwningThread=NULL;
  1.2083 +	memclr(&iRequest[0],sizeof(TCameraScRequest*)*KMaxCamScRequestsPending);
  1.2084 +	}
  1.2085 +
  1.2086 +/**
  1.2087 +Destructor for the capture request queue.
  1.2088 +*/
  1.2089 +TCameraScRequestQueue::~TCameraScRequestQueue()
  1.2090 +	{
  1.2091 +	for (TInt i=0 ; i<KMaxCamScRequestsPending ; i++)
  1.2092 +		delete iRequest[i];
  1.2093 +	}
  1.2094 +
  1.2095 +/**
  1.2096 +Second stage constructor for the capture request queue.
  1.2097 +@param anOwningThread A pointer to the owning client thread.
  1.2098 +@return KErrNone if successful;
  1.2099 +		KErrNoMemory if unable to allocate memory for the capture request queue.
  1.2100 +@pre The thread must be in a critical section.
  1.2101 +*/
  1.2102 +TInt TCameraScRequestQueue::Create(DThread* anOwningThread)
  1.2103 +	{
  1.2104 +	iOwningThread=anOwningThread;
  1.2105 +
  1.2106 +	// Create the set of available request objects and add them to the unused request queue.
  1.2107 +	for (TInt i=0 ; i<KMaxCamScRequestsPending ; i++)
  1.2108 +		{
  1.2109 +		iRequest[i]=new TCameraScRequest;
  1.2110 +		if (!iRequest[i])
  1.2111 +			return(KErrNoMemory);
  1.2112 +		iUnusedRequestQ.Add(iRequest[i]);
  1.2113 +		}
  1.2114 +
  1.2115 +	return(KErrNone);
  1.2116 +	}
  1.2117 +
  1.2118 +/**
  1.2119 +Store a request status pointer onto the tail of the capture request queue.
  1.2120 +@param aStatus The request status pointer to be stored.
  1.2121 +@return KErrNone if successful;
  1.2122 +		KErrGeneral if the limit on the number of pending capture request (KMaxCamScRequestsPending) would be exceeded.
  1.2123 +@pre The buffer/request queue mutex must be held.
  1.2124 +*/
  1.2125 +TInt TCameraScRequestQueue::Add(TRequestStatus* aStatus)
  1.2126 +	{
  1.2127 +	TCameraScRequest* req=(TCameraScRequest*)iUnusedRequestQ.GetFirst();
  1.2128 +	if (!req)
  1.2129 +		return(KErrGeneral);								// Must have exceeded KMaxCamScRequestsPending
  1.2130 +
  1.2131 +	req->iStatus=aStatus;
  1.2132 +	iPendRequestQ.Add(req);
  1.2133 +	return(KErrNone);
  1.2134 +	}
  1.2135 +
  1.2136 +/**
  1.2137 +Retrieve the next request status pointer from the head of the capture request queue.
  1.2138 +@return The request status pointer removed or NULL if the list is empty.
  1.2139 +@pre The buffer/request queue mutex must be held.
  1.2140 +*/
  1.2141 +TRequestStatus* TCameraScRequestQueue::Remove()
  1.2142 +	{
  1.2143 +	TRequestStatus* status=NULL;
  1.2144 +	TCameraScRequest* req=(TCameraScRequest*)iPendRequestQ.GetFirst();
  1.2145 +	if (req)
  1.2146 +		{
  1.2147 +		status=req->iStatus;
  1.2148 +		iUnusedRequestQ.Add(req);
  1.2149 +		}
  1.2150 +	return(status);
  1.2151 +	}
  1.2152 +
  1.2153 +/**
  1.2154 +Remove a specifc request status pointer from the the capture request queue, completing it with a 'KErrCancel' completion reason.
  1.2155 +@param aStatus The request status pointer to be completed.
  1.2156 +@pre The buffer/request queue mutex must be held.
  1.2157 +*/
  1.2158 +void TCameraScRequestQueue::Cancel(TRequestStatus* aStatus)
  1.2159 +	{
  1.2160 +	// Find the entry concerned
  1.2161 +	TCameraScRequest* req=(TCameraScRequest*)iPendRequestQ.First();
  1.2162 +	SDblQueLink* anchor=&iPendRequestQ.iA;
  1.2163 +	while (req!=anchor && req->iStatus!=aStatus)
  1.2164 +		req=(TCameraScRequest*)req->iNext;
  1.2165 +	if (req==anchor)
  1.2166 +		return;
  1.2167 +
  1.2168 +	// Remove and cancel it.
  1.2169 +	req->Deque();
  1.2170 +	iUnusedRequestQ.Add(req);
  1.2171 +	NKern::FMSignal(iMutexPtr); 	// Release the request list mutex while we complete the request. This is safe.
  1.2172 +	Kern::RequestComplete(iOwningThread,req->iStatus,KErrCancel);
  1.2173 +	NKern::FMWait(iMutexPtr); 		// Re-acquire the request list mutex.
  1.2174 +	}
  1.2175 +
  1.2176 +/**
  1.2177 +Remove each request status pointer from the the capture request queue, completing each with a 'KErrCancel' completion reason.
  1.2178 +@pre The buffer/request queue mutex must be held.
  1.2179 +*/
  1.2180 +void TCameraScRequestQueue::CancelAll()
  1.2181 +	{
  1.2182 +
  1.2183 +	TRequestStatus* status;
  1.2184 +	while ((status=Remove())!=NULL)
  1.2185 +		{
  1.2186 +		NKern::FMSignal(iMutexPtr); 	// Release the request list mutex while we complete the request. This is safe.
  1.2187 +		Kern::RequestComplete(iOwningThread,status,KErrCancel);
  1.2188 +		NKern::FMWait(iMutexPtr); 		// Re-acquire the request list mutex.
  1.2189 +		}
  1.2190 +	}
  1.2191 +
  1.2192 +/**
  1.2193 +Constructor for the camera driver power handler class.
  1.2194 +@param aChannel A pointer to the camera driver logical channel which owns this power handler.
  1.2195 +*/
  1.2196 +DCameraScPowerHandler::DCameraScPowerHandler(DCameraScLdd* aChannel)
  1.2197 +:	DPowerHandler(KDevCameraScName),
  1.2198 +	iChannel(aChannel)
  1.2199 +	{
  1.2200 +	}
  1.2201 +
  1.2202 +/**
  1.2203 +A request from the power manager for the power down of the camera device.
  1.2204 +This is called during a transition of the phone into standby or power off.
  1.2205 +@param aState The target power state; can be EPwStandby or EPwOff only.
  1.2206 +*/
  1.2207 +void DCameraScPowerHandler::PowerDown(TPowerState aPowerState)
  1.2208 +	{
  1.2209 +	(void)aPowerState;
  1.2210 +	__KTRACE_CAM(Kern::Printf(">DCameraScPowerHandler::PowerDown(State-%d)",aPowerState));
  1.2211 +
  1.2212 +	// Power-down involves hardware access so queue a DFC to perform this from the driver thread.
  1.2213 +	iChannel->iPowerDownDfc.Enque();
  1.2214 +	}
  1.2215 +
  1.2216 +/**
  1.2217 +A request from the power manager for the power up of the camera device.
  1.2218 +This is called during a transition of the phone out of standby.
  1.2219 +*/
  1.2220 +void DCameraScPowerHandler::PowerUp()
  1.2221 +	{
  1.2222 +	__KTRACE_CAM(Kern::Printf(">DCameraScPowerHandler::PowerUp"));
  1.2223 +
  1.2224 +	// Power-up involves hardware access so queue a DFC to perform this from the driver thread.
  1.2225 +	iChannel->iPowerUpDfc.Enque();
  1.2226 +	}