kernel/eka/drivers/camerasc/cameraldd.cpp
changeset 0 a41df078684a
child 31 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32/drivers/camerasc/cameraldd.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <drivers/camerasc.h>
       
    19 #include <kernel/kern_priv.h>
       
    20 #include <kernel/cache.h>
       
    21 
       
    22 //#define __KTRACE_CAM(s) s;
       
    23 #define __KTRACE_CAM(s)
       
    24 
       
    25 #define DISCARD_COMPLETED_TO_AVOID_OVERFLOW
       
    26 
       
    27 static const char KCameraLddPanic[]="CameraSc LDD";
       
    28 
       
    29 /**
       
    30 Standard export function for LDDs. This creates a DLogicalDevice derived object,
       
    31 in this case, DSoundScLddFactory.
       
    32 */
       
    33 DECLARE_STANDARD_LDD()
       
    34 	{
       
    35 	return new DCameraScLddFactory;
       
    36 	}
       
    37 
       
    38 /**
       
    39 Constructor for the camera driver factory class.
       
    40 */
       
    41 DCameraScLddFactory::DCameraScLddFactory()
       
    42 	{
       
    43 //	iUnitsOpenMask=0;
       
    44 
       
    45 	__KTRACE_CAM(Kern::Printf(">DCameraScLddFactory::DCameraScLddFactory"));
       
    46 
       
    47 	// Set version number for this device.
       
    48 	iVersion=RDevCameraSc::VersionRequired();
       
    49 
       
    50 	// Indicate that units / PDD are supported.
       
    51 	iParseMask=KDeviceAllowUnit|KDeviceAllowPhysicalDevice;
       
    52 
       
    53 	// Leave the units decision to the PDD
       
    54 	iUnitsMask=0xffffffff;
       
    55 	}
       
    56 
       
    57 /**
       
    58 Second stage constructor for the camera driver factory class.
       
    59 This must at least set a name for the driver object.
       
    60 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
    61 */
       
    62 TInt DCameraScLddFactory::Install()
       
    63 	{
       
    64 	return(SetName(&KDevCameraScName));
       
    65 	}
       
    66 
       
    67 /**
       
    68 Return the 'capabilities' of the camera driver in general.
       
    69 Called in the response to an RDevice::GetCaps() request.
       
    70 @param aDes A user-side descriptor to write the capabilities information into.
       
    71 */
       
    72 void DCameraScLddFactory::GetCaps(TDes8 &aDes) const
       
    73 	{
       
    74 	// Create a capabilities object
       
    75 	TCapsDevCameraV01 caps;
       
    76 	caps.iVersion=iVersion;
       
    77 
       
    78 	// Write it back to user memory
       
    79 	Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
       
    80 	}
       
    81 
       
    82 /**
       
    83 Called by the kernel's device driver framework to create a logical channel.
       
    84 This is called in the context of the client thread which requested the creation of a logical
       
    85 channel - through a call to RBusLogicalChannel::DoCreate().
       
    86 The thread is in a critical section.
       
    87 @param aChannel Set by this function to point to the created logical channel.
       
    88 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
    89 */
       
    90 TInt DCameraScLddFactory::Create(DLogicalChannelBase*& aChannel)
       
    91 	{
       
    92 	__KTRACE_CAM(Kern::Printf(">DCameraScLddFactory::Create"));
       
    93 
       
    94 	aChannel=new DCameraScLdd;
       
    95 	if (!aChannel)
       
    96 		return(KErrNoMemory);
       
    97 
       
    98 	return(KErrNone);
       
    99 	}
       
   100 
       
   101 /**
       
   102 Check whether a channel has is currently open on the specified unit.
       
   103 @param aUnit The number of the unit to be checked.
       
   104 @return ETrue if a channel is open on the specified channel, EFalse otherwise.
       
   105 @pre The unit info. mutex must be held.
       
   106 */
       
   107 TBool DCameraScLddFactory::IsUnitOpen(TInt aUnit)
       
   108 	{
       
   109 	return(iUnitsOpenMask&(1<<aUnit));
       
   110 	}
       
   111 
       
   112 /**
       
   113 Attempt to change the state of the channel open status for a particular channel.
       
   114 @param aUnit The number of the unit to be updated.
       
   115 @param aIsOpenSetting	The required new state for the channel open status: either ETrue to set the status to open or
       
   116 						EFalse to set the status to closed.
       
   117 @return KErrNone if the status was updated successfully;
       
   118 		KErrInUse if an attempt has been made to set the channnel status to open while it is already open.
       
   119 */
       
   120 TInt DCameraScLddFactory::SetUnitOpen(TInt aUnit,TBool aIsOpenSetting)
       
   121 	{
       
   122 	NKern::FMWait(&iUnitInfoMutex); // Acquire the unit info. mutex.
       
   123 
       
   124 	// Fail a request to open an channel that is already open
       
   125 	if (aIsOpenSetting && IsUnitOpen(aUnit))
       
   126 		{
       
   127 		NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.
       
   128 		return(KErrInUse);
       
   129 		}
       
   130 
       
   131 	// Update the open status as requested
       
   132 	if (aIsOpenSetting)
       
   133 		iUnitsOpenMask|=(1<<aUnit);
       
   134 	else
       
   135 		iUnitsOpenMask&=~(1<<aUnit);
       
   136 
       
   137 	NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.
       
   138 	return(KErrNone);
       
   139 	}
       
   140 
       
   141 /**
       
   142 Constructor for the camera driver logical channel.
       
   143 */
       
   144 DCameraScLdd::DCameraScLdd()
       
   145 	:	iRequestQueue(&iMutex),
       
   146 		iRestartDfc(DCameraScLdd::RestartDfc,this,5),
       
   147 		iPowerDownDfc(DCameraScLdd::PowerDownDfc,this,3),
       
   148 		iPowerUpDfc(DCameraScLdd::PowerUpDfc,this,3)
       
   149 	{
       
   150 //	iState=EOpen;
       
   151 //	iCaptureMode=ECaptureModeImage;
       
   152 //	iFrameHeight=0;
       
   153 //	iFrameWidth=0;
       
   154 //	iBufManager=NULL;
       
   155 //	iPowerHandler=NULL;
       
   156 //	iImageGatherCount=0;
       
   157 
       
   158 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DCameraScLdd"));
       
   159 
       
   160 	iUnit=-1;	// Invalid unit number
       
   161 
       
   162 	// Get pointer to client thread's DThread object
       
   163 	iOwningThread=&Kern::CurrentThread();
       
   164 
       
   165 	// Open a reference on client thread so it's control block can't dissapear until
       
   166 	// this driver has finished with it. Note, this call to Open() can't fail since
       
   167 	// it is the thread we are currently running in
       
   168 	iOwningThread->Open();
       
   169 	}
       
   170 
       
   171 /**
       
   172 Destructor for the camera driver logical channel.
       
   173 This is called in the context of the client thread once a 'ECloseMsg' message has been
       
   174 sent to the device driver DFC thread.
       
   175 */
       
   176 DCameraScLdd::~DCameraScLdd()
       
   177 	{
       
   178 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::~DCameraScLdd"));
       
   179 
       
   180 	TInt captureMode;
       
   181 
       
   182 	// Remove and delete the power handler.
       
   183 	if (iPowerHandler)
       
   184 		{
       
   185 		iPowerHandler->Remove();
       
   186 		delete iPowerHandler;
       
   187 		iPowerHandler=NULL;
       
   188 		}
       
   189 
       
   190 	if (iCaptureModeConfig)
       
   191 		{
       
   192 		// Delete any buffers, the shared chunk we created, and the buffer config struct.
       
   193 		for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
       
   194 			{
       
   195 			if (iCaptureModeConfig[captureMode].iBufManager)
       
   196 				{
       
   197 				delete iCaptureModeConfig[captureMode].iBufManager;
       
   198 				iCaptureModeConfig[captureMode].iBufManager=NULL;
       
   199 				}
       
   200 
       
   201 			if (iCaptureModeConfig[captureMode].iBufConfig)
       
   202 				{
       
   203 				Kern::Free(iCaptureModeConfig[captureMode].iBufConfig);
       
   204 				iCaptureModeConfig[captureMode].iBufConfig=NULL;
       
   205 				}
       
   206 			}
       
   207 
       
   208 		delete[] iCaptureModeConfig;
       
   209 		iCaptureModeConfig=NULL;
       
   210 		}
       
   211 
       
   212 	// Close our reference on the client thread
       
   213 	Kern::SafeClose((DObject*&)iOwningThread,NULL);
       
   214 
       
   215 	// Clear the 'units open mask' in the LDD factory.
       
   216 	if (iUnit>=0)
       
   217 		((DCameraScLddFactory*)iDevice)->SetUnitOpen(iUnit,EFalse);
       
   218 	}
       
   219 
       
   220 /**
       
   221 Second stage constructor for the camera driver - called by the kernel's device driver framework.
       
   222 This is called in the context of the client thread which requested the creation of a logical channel
       
   223 (e.g. through a call to RBusLogicalChannel::DoCreate()).
       
   224 The thread is in a critical section.
       
   225 @param aUnit The unit argument supplied by the client. This is checked by the PDD and not used here.
       
   226 @param aInfo The info argument supplied by the client. Always NULL in this case.
       
   227 @param aVer The version argument supplied by the client.
       
   228 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   229 */
       
   230 TInt DCameraScLdd::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
       
   231 	{
       
   232 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoCreate"));
       
   233 
       
   234 	// Check the client has EMultimediaDD capability.
       
   235 	if (!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ECAMERA.LDD (Camera driver)")))
       
   236 		return(KErrPermissionDenied);
       
   237 
       
   238 	// Check that the camera driver version specified by the client is compatible.
       
   239 	if (!Kern::QueryVersionSupported(RDevCameraSc::VersionRequired(),aVer))
       
   240 		return(KErrNotSupported);
       
   241 
       
   242 	// Check that a channel hasn't already been opened on this unit.
       
   243 	TInt r=((DCameraScLddFactory*)iDevice)->SetUnitOpen(aUnit,ETrue); // Try to update 'units open mask' in the LDD factory.
       
   244 	if (r!=KErrNone)
       
   245 		return(r);
       
   246 	iUnit=aUnit;
       
   247 
       
   248 	// Create the power handler
       
   249 	iPowerHandler=new DCameraScPowerHandler(this);
       
   250 	if (!iPowerHandler)
       
   251 		return(KErrNoMemory);
       
   252 	iPowerHandler->Add();
       
   253 
       
   254 	// Create the pending capture request list
       
   255 	r=iRequestQueue.Create(iOwningThread);
       
   256 	if (r!=KErrNone)
       
   257 		return(r);
       
   258 
       
   259 	// Initialise the PDD
       
   260 	((DCameraScPdd*)iPdd)->iLdd=this;
       
   261 
       
   262 	// Setup the default camera config
       
   263 	iCaptureMode=ECamCaptureModeImage;
       
   264 
       
   265 	iCaptureModeConfig = new TCaptureModeConfig[ECamCaptureModeMax];
       
   266 	if(!iCaptureModeConfig)
       
   267 		return KErrNoMemory;
       
   268 	TInt capsSize = Pdd()->CapsSize();
       
   269 	TInt captureMode;
       
   270 	TAny* capsBuf;
       
   271 	capsBuf = Kern::Alloc(capsSize);
       
   272 	if(!capsBuf)
       
   273 		return KErrNoMemory;
       
   274 
       
   275 	// Query the driver for its capabilities and set a default pixel format
       
   276 	// and frame size for each available capture mode.
       
   277 	TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
       
   278 	Pdd()->Caps(capsPtr);
       
   279 
       
   280 	TCameraCapsV02* caps = (TCameraCapsV02*) capsPtr.Ptr();
       
   281 	SDevCamPixelFormat* pixelFormat = (SDevCamPixelFormat*) (caps + 1);
       
   282 	SDevCamFrameSize* frameSize;
       
   283 	TAny* frameSizeCapsBuf=0;
       
   284 	TPtr8 frameSizeCapsPtr(0,0,0);
       
   285 
       
   286 	for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
       
   287 		{
       
   288 		if ((captureMode==ECamCaptureModeImage) && (caps->iNumImagePixelFormats==0))
       
   289 			continue;
       
   290 
       
   291 		if ((captureMode==ECamCaptureModeVideo) && (caps->iNumVideoPixelFormats==0))
       
   292 			continue;
       
   293 
       
   294 		if ((captureMode==ECamCaptureModeViewFinder) && (caps->iNumViewFinderPixelFormats==0))
       
   295 			continue;
       
   296 
       
   297 		iCaptureModeConfig[captureMode].iCamConfig.iPixelFormat=*pixelFormat;
       
   298 		frameSizeCapsBuf = Kern::Alloc(pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize));
       
   299 		new (&frameSizeCapsPtr) TPtr8((TUint8*)frameSizeCapsBuf, pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize), pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize));
       
   300 		r=Pdd()->FrameSizeCaps((TDevCamCaptureMode)captureMode, pixelFormat->iPixelFormat, frameSizeCapsPtr);
       
   301 		if(r!=KErrNone)
       
   302 			{
       
   303 			Kern::Free(frameSizeCapsBuf);
       
   304 			return r;
       
   305 			}
       
   306 		frameSize=(SDevCamFrameSize*) frameSizeCapsPtr.Ptr();
       
   307 		iCaptureModeConfig[captureMode].iCamConfig.iFrameSize=*frameSize;
       
   308 		Kern::Free(frameSizeCapsBuf);
       
   309 
       
   310 		iCaptureModeConfig[captureMode].iCamConfig.iFlashMode=ECamFlashNone;
       
   311 		iCaptureModeConfig[captureMode].iCamConfig.iExposureMode=ECamExposureAuto;
       
   312 		iCaptureModeConfig[captureMode].iCamConfig.iWhiteBalanceMode=ECamWBAuto;
       
   313 		iCaptureModeConfig[captureMode].iCamConfig.iZoom=0;
       
   314 		iCaptureModeConfig[captureMode].iCamConfig.iPixelWidthInBytes=0;
       
   315 		iCaptureModeConfig[captureMode].iCamConfig.iFrameRate = 0;
       
   316 		}
       
   317 	Kern::Free(capsBuf);
       
   318 	// Setup the default buffer config.
       
   319 	r=ReAllocBufferConfigInfo(0);	// Zeros the structure
       
   320 	if (r!=KErrNone)
       
   321 		return(r);
       
   322 	for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
       
   323 		{
       
   324 		iCaptureModeConfig[captureMode].iBufConfig->iNumBuffers=KDefaultNumClientBuffers;
       
   325 		}
       
   326 
       
   327 	// Set up the correct DFC queue and enable the reception of client messages.
       
   328 	TDfcQue* dfcq=((DCameraScPdd*)iPdd)->DfcQ(aUnit);
       
   329 	SetDfcQ(dfcq);
       
   330 	iRestartDfc.SetDfcQ(dfcq);
       
   331 	iPowerDownDfc.SetDfcQ(dfcq);
       
   332 	iPowerUpDfc.SetDfcQ(dfcq);
       
   333 	iMsgQ.Receive();
       
   334 
       
   335 	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoCreate"));
       
   336 
       
   337 	return(KErrNone);
       
   338 	}
       
   339 
       
   340 /**
       
   341 Shutdown the camera device.
       
   342 Terminate all device activity and power down the hardware.
       
   343 */
       
   344 void DCameraScLdd::Shutdown()
       
   345 	{
       
   346 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Shutdown"));
       
   347 
       
   348 	iState=EOpen;
       
   349 
       
   350 	// Power down the hardware
       
   351 	Pdd()->PowerDown();
       
   352 
       
   353 	// Cancel any requests that we may be handling
       
   354 	DoCancel(RDevCameraSc::EAllRequests);
       
   355 
       
   356 	// Make sure DFCs are not queued.
       
   357 	iRestartDfc.Cancel();
       
   358 	iPowerDownDfc.Cancel();
       
   359 	iPowerUpDfc.Cancel();
       
   360 	}
       
   361 
       
   362 /**
       
   363 Notification to the driver that a handle to it has been requested by a user thread.
       
   364 The use of a camera driver channel is restricted here to a single thread (that has
       
   365 EMultimediaDD capability).
       
   366 @param aThread A pointer to thread which is requesting the handle.
       
   367 @param aType Whether the requested handle is thread or process relative.
       
   368 @return	KErrNone, if the request is for a thread relative handle - originating from
       
   369 		the same the thread that created the channel object;
       
   370 		KErrAccessDenied, otherwise.
       
   371 */
       
   372 TInt DCameraScLdd::RequestUserHandle(DThread* aThread, TOwnerType aType)
       
   373 	{
       
   374 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::RequestUserHandle"));
       
   375 
       
   376 	// Ensure that each channel can only be used by a single thread.
       
   377 	if (aType!=EOwnerThread || aThread!=iOwningThread)
       
   378 		return(KErrAccessDenied);
       
   379 	return(KErrNone);
       
   380 	}
       
   381 
       
   382 /**
       
   383 Process a request on this logical channel
       
   384 Called in the context of the client thread.
       
   385 @param aReqNo	The request number:
       
   386 				==KMaxTInt: a 'DoCancel' message;
       
   387 				>=0: a 'DoControl' message with function number equal to value.
       
   388 				<0: a 'DoRequest' message with function number equal to ~value.
       
   389 @param a1 The first request argument. For DoRequest(), this is a pointer to the TRequestStatus.
       
   390 @param a2 The second request argument. For DoRequest(), this is a pointer to the 2 actual TAny* arguments.
       
   391 @return The result of the request. This is ignored by device driver framework for DoRequest().
       
   392 */
       
   393 TInt DCameraScLdd::Request(TInt aReqNo, TAny* a1, TAny* a2)
       
   394 	{
       
   395 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Request(%d)",aReqNo));
       
   396 	TInt r;
       
   397 	if (aReqNo<RDevCameraSc::EMsgControlMax && aReqNo>(~RDevCameraSc::EMsgRequestMax))
       
   398 		{
       
   399 		// Implement in the context of the kernel thread - prepare and issue a kernel message.
       
   400 		r=DLogicalChannel::Request(aReqNo,a1,a2);
       
   401 		}
       
   402 	else
       
   403 		{
       
   404 		// Implement in the context of the client thread.
       
   405 		// Decode the message type and dispatch it to the relevent handler function.
       
   406 		if ((TUint)aReqNo<(TUint)KMaxTInt)
       
   407 			r=DoControl(aReqNo,a1,a2);		// DoControl - process the request.
       
   408 
       
   409 		else if (aReqNo==KMaxTInt)
       
   410 			{
       
   411 			r=DoCancel((TInt)a1);			// DoCancel - cancel the request.
       
   412 			}
       
   413 
       
   414 		else
       
   415 			{
       
   416 			// DoRequest
       
   417 			TInt func=~aReqNo;
       
   418 
       
   419 			// NotifyNewImage() during image capture mode is another case which must be handled in the kernel thread.
       
   420 			if (iCaptureMode==ECamCaptureModeImage && func==RDevCameraSc::ERequestNotifyNewImage)
       
   421 				r=DLogicalChannel::Request(aReqNo,a1,a2);
       
   422 			else
       
   423 				{
       
   424 				// Read the arguments from the client thread and process the request.
       
   425 				TAny* a[2];
       
   426 				kumemget32(a,a2,sizeof(a));
       
   427 				TRequestStatus* status=(TRequestStatus*)a1;
       
   428 				r=DoRequest(func,status,a[0],a[1]);
       
   429 
       
   430 				// Complete request if there was an error
       
   431 				if (r!=KErrNone)
       
   432 					Kern::RequestComplete(iOwningThread,status,r);
       
   433 				r=KErrNone;
       
   434 				}
       
   435 			}
       
   436 		}
       
   437 	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::Request - %d",r));
       
   438 	return(r);
       
   439 	}
       
   440 
       
   441 /**
       
   442 Process a message for this logical channel.
       
   443 This function is called in the context of the DFC thread.
       
   444 @param aMsg The message to process.
       
   445 			The iValue member of this distinguishes the message type:
       
   446 			iValue==ECloseMsg, channel close message.
       
   447 			iValue==KMaxTInt, a 'DoCancel' message.
       
   448 			iValue>=0, a 'DoControl' message with function number equal to iValue.
       
   449 			iValue<0, a 'DoRequest' message with function number equal to ~iValue.
       
   450 */
       
   451 void DCameraScLdd::HandleMsg(TMessageBase* aMsg)
       
   452 	{
       
   453 	TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   454 	TInt id=m.iValue;
       
   455 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::HandleMsg(%d)",id));
       
   456 
       
   457 	// Decode the message type and dispatch it to the relevent handler function.
       
   458 	if (id==(TInt)ECloseMsg)
       
   459 		{
       
   460 		// Channel close.
       
   461 		Shutdown();
       
   462 		m.Complete(KErrNone,EFalse);
       
   463 		return;
       
   464 		}
       
   465 	else if (id<0)	// The only DoRequest handled in the kernel thread is NotifyNewImage(ECamCaptureModeImage).
       
   466 		{
       
   467 		// DoRequest
       
   468 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   469 		TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
       
   470 		if (r!=KErrNone)
       
   471 			Kern::RequestComplete(iOwningThread,pS,r);
       
   472 		m.Complete(KErrNone,ETrue);
       
   473 		}
       
   474 	else
       
   475 		{
       
   476 		// Must be DoControl (Cancel is handled in the client thread).
       
   477 		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
   478 		m.Complete(r,ETrue);
       
   479 		}
       
   480 	}
       
   481 
       
   482 /**
       
   483 Process a synchronous 'DoControl' request.
       
   484 This function is called in the context of the DFC thread.
       
   485 @param aFunction The request number.
       
   486 @param a1 The first request argument.
       
   487 @param a2 The second request argument.
       
   488 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   489 */
       
   490 TInt DCameraScLdd::DoControl(TInt aFunction, TAny* a1, TAny* a2)
       
   491 	{
       
   492 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoControl(%d)",aFunction));
       
   493 
       
   494 	TInt r=KErrNotSupported;
       
   495 	switch (aFunction)
       
   496 		{
       
   497 		case RDevCameraSc::EControlCaps:
       
   498 			{
       
   499 			r = GetSensorCaps(a1);
       
   500 			break;
       
   501 			}
       
   502 		case RDevCameraSc::EControlSetCaptureMode:
       
   503 			{
       
   504 			// Change the capture mode.
       
   505 			r=SetCaptureMode((TInt)a1);
       
   506 			break;
       
   507 			}
       
   508 		case RDevCameraSc::EControlSetCamConfig:
       
   509 			{
       
   510 			// Set the new camera configuration.
       
   511 			NKern::ThreadEnterCS();
       
   512 			r=SetCamConfig((TInt)a1, (const TDesC8*)a2);
       
   513 			NKern::ThreadLeaveCS();
       
   514 			break;
       
   515 			}
       
   516 		case RDevCameraSc::EControlGetCamConfig:
       
   517 			{
       
   518 			// Write the config to the client.
       
   519 			TPtrC8 ptr((const TUint8*)&iCaptureModeConfig[(TInt)a1].iCamConfig,sizeof(iCaptureModeConfig[(TInt)a1].iCamConfig));
       
   520 			Kern::InfoCopy(*((TDes8*)a2),ptr);
       
   521 			r=KErrNone;
       
   522 			break;
       
   523 			}
       
   524 		case RDevCameraSc::EControlGetBufferConfig:
       
   525 			if (iCaptureModeConfig[(TInt)a1].iBufConfig)
       
   526 				{
       
   527 				// Write the buffer config to the client.
       
   528 				TPtrC8 ptr((const TUint8*)&(*iCaptureModeConfig[(TInt)a1].iBufConfig),iCaptureModeConfig[(TInt)a1].iBufConfigSize);
       
   529 				Kern::InfoCopy(*((TDes8*)a2),ptr);
       
   530 				r=KErrNone;
       
   531 				}
       
   532 			break;
       
   533 		case RDevCameraSc::EControlSetBufConfigChunkCreate:
       
   534 			// Need to be in critical section while deleting an exisiting config and creating a new one
       
   535 			NKern::ThreadEnterCS();
       
   536 			r=SetBufConfig((TInt)a1,(TInt)a2);
       
   537 			NKern::ThreadLeaveCS();
       
   538 			break;
       
   539 		case RDevCameraSc::EControlSetBufConfigChunkOpen:
       
   540 			SSetBufConfigChunkOpenInfo info;
       
   541 			r=Kern::ThreadRawRead(iOwningThread,a2,&info,sizeof(info));
       
   542 			if (r==KErrNone)
       
   543 				{
       
   544 				// Need to be in critical section while deleting an exisiting config and creating a new one
       
   545 				NKern::ThreadEnterCS();
       
   546 				r=SetBufConfig((TInt)a1,info.iBufferConfigBuf,info.iChunkHandle);
       
   547 				NKern::ThreadLeaveCS();
       
   548 				}
       
   549 			break;
       
   550 		case RDevCameraSc::EControlChunkClose:
       
   551 			r=ChunkClose((TInt)a1);
       
   552 			break;
       
   553 		case RDevCameraSc::EControlStart:
       
   554 			r=Start();
       
   555 			break;
       
   556 		case RDevCameraSc::EControlStop:
       
   557 			if (iState==ECapturing)
       
   558 				{
       
   559 				r=Pdd()->Stop();
       
   560 				DoCancel(1<<RDevCameraSc::ERequestNotifyNewImage);
       
   561 				if (r==KErrNone)
       
   562 					iState=EConfigured;
       
   563 				}
       
   564 			else
       
   565 				{
       
   566 				r=KErrGeneral;
       
   567 				}
       
   568 			break;
       
   569 		case RDevCameraSc::EControlReleaseBuffer:
       
   570 			r=ReleaseBuffer((TInt)a1);
       
   571 			break;
       
   572 		case RDevCameraSc::EControlNotifyNewImageSpecificCancel:
       
   573 			{
       
   574 			NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
       
   575 			iRequestQueue.Cancel((TRequestStatus*)a1);
       
   576 			NKern::FMSignal(&iMutex); 		// Release the buffer/request list mutex.
       
   577 			r=KErrNone;
       
   578 			break;
       
   579 			}
       
   580 		case RDevCameraSc::EControlBufferIdToOffset:
       
   581 			{
       
   582 			// a1 has pointer to buffer for search criteria
       
   583 			// a2 has pointer to offset for result
       
   584 			TDevCamBufferModeAndId info;
       
   585 			TPtr8 indesc((TUint8*)&info,sizeof(info));
       
   586 
       
   587 			r = Kern::ThreadDesRead(iOwningThread,a1,indesc,0);
       
   588 			if (KErrNone==r)
       
   589 				{
       
   590 				TInt id = info.iId;
       
   591 				TDevCamCaptureMode captureMode = info.iCaptureMode;
       
   592 				DBufferManager* mgr = iCaptureModeConfig[captureMode].iBufManager;
       
   593 				
       
   594 				if (mgr)
       
   595 					{
       
   596 					if (mgr->iImageBuffer[id].iId == id)
       
   597 						{
       
   598 						kumemput32(a2, &mgr->iImageBuffer[id].iChunkOffset, sizeof(TInt));
       
   599 						r = KErrNone;
       
   600 						}
       
   601 					else
       
   602 						{
       
   603 						r = KErrNotFound;
       
   604 						}
       
   605 					}
       
   606 				}
       
   607 			break;
       
   608 			}
       
   609 		case RDevCameraSc::EControlCapsSize:
       
   610 			{
       
   611 			r = Pdd()->CapsSize();
       
   612 			break;
       
   613 			}
       
   614 		case RDevCameraSc::EControlFrameSizeCaps:
       
   615 			{
       
   616 			r = GetFrameSizeCaps(a1, a2);
       
   617 			break;
       
   618 			}
       
   619 		case RDevCameraSc::EControlSetDynamicAttribute:
       
   620 			{
       
   621 			// Set the new camera configuration.
       
   622 			NKern::ThreadEnterCS();
       
   623 			r=SetDynamicAttribute((TInt)a1, (TUint)a2);
       
   624 			NKern::ThreadLeaveCS();
       
   625 			break;
       
   626 			}
       
   627 		}
       
   628 	return(r);
       
   629 	}
       
   630 
       
   631 /**
       
   632 Process an asynchronous 'DoRequest' request.
       
   633 This function is called in the context of the DFC thread.
       
   634 @param aFunction The request number.
       
   635 @param aStatus A pointer to the TRequestStatus.
       
   636 @param a1 The first request argument.
       
   637 @param a2 The second request argument.
       
   638 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   639 */
       
   640 TInt DCameraScLdd::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* /*a1*/, TAny* /*a2*/)
       
   641 	{
       
   642 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoRequest(%d)",aFunction));
       
   643 
       
   644 	TInt r=KErrNotSupported;
       
   645 	switch (aFunction)
       
   646 		{
       
   647 		case RDevCameraSc::ERequestNotifyNewImage:
       
   648 			r=NotifyNewImage(aStatus);
       
   649 			break;
       
   650 		}
       
   651 
       
   652 	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoRequest - %d",r));
       
   653 	return(r);
       
   654 	}
       
   655 
       
   656 /**
       
   657 Process the cancelling of asynchronous requests.
       
   658 This function is called in the context of the DFC thread.
       
   659 @param aMask A mask indicating which requests need to be cancelled.
       
   660 @return The result of the cancel. Either KErrNone if successful, otherwise one of the other
       
   661 	system wide error codes.
       
   662 */
       
   663 TInt DCameraScLdd::DoCancel(TUint aMask)
       
   664 	{
       
   665 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoCancel(%08x)",aMask));
       
   666 
       
   667 	if (aMask&(1<<RDevCameraSc::ERequestNotifyNewImage))
       
   668 		{
       
   669 		NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
       
   670 		iRequestQueue.CancelAll();
       
   671 		NKern::FMSignal(&iMutex); 		// Release the buffer/request list mutex.
       
   672 		}
       
   673 	return(KErrNone);
       
   674 	}
       
   675 
       
   676 /**
       
   677 @pre The thread must be in a critical section.
       
   678 */
       
   679 TInt DCameraScLdd::ReAllocBufferConfigInfo(TInt aNumBuffers)
       
   680 	{
       
   681 	for (TInt captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
       
   682 		{
       
   683 		if (iCaptureModeConfig[captureMode].iBufConfig)
       
   684 			{
       
   685 			Kern::Free(iCaptureModeConfig[captureMode].iBufConfig);
       
   686 			iCaptureModeConfig[captureMode].iBufConfig=NULL;
       
   687 			}
       
   688 
       
   689 		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.
       
   690 		iCaptureModeConfig[captureMode].iBufConfigSize+=sizeof(TSharedChunkBufConfigBase);
       
   691 		iCaptureModeConfig[captureMode].iBufConfig=(TCameraSharedChunkBufConfig*)Kern::AllocZ(iCaptureModeConfig[captureMode].iBufConfigSize);
       
   692 		if (!iCaptureModeConfig[captureMode].iBufConfig)
       
   693 			return(KErrNoMemory);
       
   694 		}
       
   695 	return(KErrNone);
       
   696 	}
       
   697 
       
   698 /**
       
   699 Reallocate memory for the new buffer configuration.
       
   700 @param aNumBuffers The number of buffers.
       
   701 @pre The thread must be in a critical section.
       
   702 */
       
   703 TInt DCameraScLdd::ReAllocBufferConfigInfo(TInt aCaptureMode, TInt aNumBuffers)
       
   704 	{
       
   705 	if (iCaptureModeConfig[aCaptureMode].iBufConfig)
       
   706 		{
       
   707 		Kern::Free(iCaptureModeConfig[aCaptureMode].iBufConfig);
       
   708 		iCaptureModeConfig[aCaptureMode].iBufConfig=NULL;
       
   709 		}
       
   710 
       
   711 	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.
       
   712 	iCaptureModeConfig[aCaptureMode].iBufConfigSize+=sizeof(TSharedChunkBufConfigBase);
       
   713 	iCaptureModeConfig[aCaptureMode].iBufConfig=(TCameraSharedChunkBufConfig*)Kern::AllocZ(iCaptureModeConfig[aCaptureMode].iBufConfigSize);
       
   714 	if (!iCaptureModeConfig[aCaptureMode].iBufConfig)
       
   715 		return(KErrNoMemory);
       
   716 
       
   717 	return(KErrNone);
       
   718 	}
       
   719 
       
   720 /**
       
   721 @return	A handle to the shared chunk for the owning thread (a value >0), if successful;
       
   722 		otherwise one of the other system wide error codes, (a value <0).
       
   723 @param aCamConfigBuf The supplied camera configuration.
       
   724 @pre The thread must be in a critical section.
       
   725 */
       
   726 TInt DCameraScLdd::SetCamConfig(TInt aCaptureMode, const TDesC8* aCamConfigBuf)
       
   727 	{
       
   728 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetCamConfig()"));
       
   729 
       
   730 	// Set the configuration of the sensor
       
   731 	TInt r=DoSetConfig(aCaptureMode, aCamConfigBuf);
       
   732 	return(r);
       
   733 	}
       
   734 
       
   735 /**
       
   736 Allows changing of the dynamic settings.
       
   737 Checks locally the validity of the arguments passed so as to increase performance by not
       
   738 forcing a context switch.
       
   739 
       
   740 @param aAttribute An enum identifying the dynamic attribute to change.
       
   741 @param aValue The attributes value.
       
   742 @return KErrNone if successful, KErrNotSupported if not supported, KErrArgument if aValue out of range.
       
   743 		Otherwise, one of the system wide error codes.
       
   744 @pre The thread must be in a critical section.
       
   745 */
       
   746 TInt DCameraScLdd::SetDynamicAttribute(TInt aAttribute, TUint aValue)
       
   747 	{
       
   748 	Kern::Printf(">DCameraScLdd::SetDynamicAttribute()");
       
   749 	switch(aAttribute)
       
   750 		{
       
   751 		case ECamAttributeBrightness:
       
   752 			return Pdd()->SetBrightness(aValue);
       
   753 		case ECamAttributeContrast:
       
   754 			return Pdd()->SetContrast(aValue);
       
   755 		case ECamAttributeColorEffect:
       
   756 			return Pdd()->SetColorEffect(aValue);
       
   757 		default:
       
   758 			return KErrNotFound;
       
   759 		}
       
   760 	}
       
   761 
       
   762 /**
       
   763 Updates the buffer configuration of the camera for the specified capture mode.
       
   764 @return	A handle to the shared chunk for the owning thread (a value >0), if successful;
       
   765 		otherwise one of the other system wide error codes, (a value <0).
       
   766 */
       
   767 TInt DCameraScLdd::SetBufConfig(TInt aCaptureMode, TInt aNumBuffers)
       
   768 	{
       
   769 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetBufConfig(CaptureMode=%d,NumBuffers=%d)",aCaptureMode,aNumBuffers));
       
   770 
       
   771 	// Free any memory and chunk already allocated
       
   772 	TInt r=ChunkClose(aCaptureMode);
       
   773 	if (r!=KErrNone)
       
   774 		return(r);
       
   775 
       
   776 	// Allocate a new shared chunk and create the specified number of buffers within it.
       
   777 	TInt buffersize=((iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iWidth*iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iHeight) * iCaptureModeConfig[aCaptureMode].iCamConfig.iPixelWidthInBytes);
       
   778 	__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));
       
   779 	iCaptureModeConfig[aCaptureMode].iBufManager=new DBufferManager(this);
       
   780 	if (!iCaptureModeConfig[aCaptureMode].iBufManager)
       
   781 		return(KErrNoMemory);
       
   782 	r=iCaptureModeConfig[aCaptureMode].iBufManager->Create(aNumBuffers,buffersize);
       
   783 	if (r!=KErrNone)
       
   784 		return(r);
       
   785 
       
   786 	// Update the LDD's chunk/buffer geometry info.
       
   787 	r=ReAllocBufferConfigInfo(aCaptureMode, aNumBuffers);
       
   788 	if (r!=KErrNone)
       
   789 		return(r);
       
   790 	iCaptureModeConfig[aCaptureMode].iBufManager->GetBufConfig(*iCaptureModeConfig[aCaptureMode].iBufConfig);
       
   791 
       
   792 	// Create handle to the shared chunk for the owning thread.
       
   793 	r=Kern::MakeHandleAndOpen(iOwningThread,iCaptureModeConfig[aCaptureMode].iBufManager->iChunk);
       
   794 	if (r>0)
       
   795 		{
       
   796 		// And save the the chunk and handle for later.  Normally the chunk handle will be closed when the chunk
       
   797 		// is closed, but if the chunk is re-allocated then it will need to be closed before re-allocation.
       
   798 		iCaptureModeConfig[aCaptureMode].iChunkHandle=r;
       
   799 		}
       
   800 
       
   801 	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::SetBufConfig - %d",r));
       
   802 	return(r);
       
   803 	}
       
   804 
       
   805 /**
       
   806 Updates the buffer configuration of the camera, which has been supplied by the user, for the specified capture mode.
       
   807 @param aCaptureMode		The capture mode for which the setting of the buffer configuration is made.
       
   808 @param aBufferConfigBuf	A buffer that holds the buffer configuration for the camera.
       
   809 @param aChunkHandle		A handle for the shared chunk supplied by the client.
       
   810 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   811 @pre The thread must be in a critical section.
       
   812 */
       
   813 TInt DCameraScLdd::SetBufConfig(TInt aCaptureMode,const TDesC8* aBufferConfigBuf,TInt aChunkHandle)
       
   814 	{
       
   815 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetConfig(Handle-%d)",aChunkHandle));
       
   816 
       
   817 	// Read the buffer config structure from the client.
       
   818 	TInt numBuffers;
       
   819 	TPtr8 ptr((TUint8*)&numBuffers,sizeof(numBuffers));
       
   820 	TInt r=Kern::ThreadDesRead(iOwningThread,aBufferConfigBuf,ptr,0);
       
   821 	if (r!=KErrNone)
       
   822 		return(r);
       
   823 	// Calculate the minimum length of the descriptor.
       
   824 	TInt minDesLen=(numBuffers*sizeof(SBufSpecList))+sizeof(TSharedChunkBufConfigBase);
       
   825 	r=Kern::ThreadGetDesLength(iOwningThread,aBufferConfigBuf);
       
   826 	if (r<minDesLen)
       
   827 		return(KErrArgument);
       
   828 	r=ReAllocBufferConfigInfo(aCaptureMode, numBuffers);
       
   829 	if (r!=KErrNone)
       
   830 		return(r);
       
   831 	ptr.Set((TUint8*)iCaptureModeConfig[aCaptureMode].iBufConfig,0,iCaptureModeConfig[aCaptureMode].iBufConfigSize);
       
   832 	r=Kern::ThreadDesRead(iOwningThread,aBufferConfigBuf,ptr,0);
       
   833 	if (r!=KErrNone)
       
   834 		return(r);
       
   835 
       
   836 	// Free any memory and chunk already allocated
       
   837 	r=ChunkClose(aCaptureMode);
       
   838 	if (r!=KErrNone)
       
   839 		return(r);
       
   840 
       
   841 	// Open the shared chunk supplied and create buffer objects for the committed buffers within it.
       
   842 	iCaptureModeConfig[aCaptureMode].iBufManager=new DBufferManager(this);
       
   843 	if (!iCaptureModeConfig[aCaptureMode].iBufManager)
       
   844 		return(KErrNoMemory);
       
   845 	r=iCaptureModeConfig[aCaptureMode].iBufManager->Create(*iCaptureModeConfig[aCaptureMode].iBufConfig,aChunkHandle,iOwningThread);
       
   846 	if (r!=KErrNone)
       
   847 		return(r);
       
   848 
       
   849 	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::SetConfig - %d",KErrNone));
       
   850 	return(r);
       
   851 	}
       
   852 
       
   853 /**
       
   854 Frees the buffer manager associated with a chunk, and closes the chunk itself.  The chunk being closed,
       
   855 and its associated DBufferManager instance should have been allocated by the device driver.  However,
       
   856 this is not a requirement.
       
   857 @param aCaptureMode The capture mode for which to free the buffer manager and chunk.
       
   858 @return	KErrNone if successful.
       
   859 		KErrInUse if an attempt has been made to free the memory and chunk while they are in use.
       
   860 		Otherwise one of the other system-wide error codes.
       
   861 */
       
   862 TInt DCameraScLdd::ChunkClose(TInt aCaptureMode)
       
   863 	{
       
   864 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ChunkClose(Capture Mode-%d)",aCaptureMode));
       
   865 
       
   866 	// For the active mode we need to perform extra checks.
       
   867 	if(iCaptureMode == aCaptureMode)
       
   868 		{
       
   869 		if (iState==ECapturing)
       
   870 			{
       
   871 			return(KErrInUse);
       
   872 			}
       
   873 		}
       
   874 
       
   875 	// Delete any existing buffers
       
   876 	if (iCaptureModeConfig[aCaptureMode].iBufManager)
       
   877 		{
       
   878 		delete iCaptureModeConfig[aCaptureMode].iBufManager;
       
   879 		iCaptureModeConfig[aCaptureMode].iBufManager=NULL;
       
   880 		}
       
   881 
       
   882 	// If a handle to the shared chunk was created, close it, using the handle of the thread on which
       
   883 	// it was created, in case a different thread is now calling us
       
   884 	if (iCaptureModeConfig[aCaptureMode].iChunkHandle>0)
       
   885 		{
       
   886 		Kern::CloseHandle(iOwningThread,iCaptureModeConfig[aCaptureMode].iChunkHandle);
       
   887 		iCaptureModeConfig[aCaptureMode].iChunkHandle=0;
       
   888 		}
       
   889 
       
   890 	return(KErrNone);
       
   891 	}
       
   892 
       
   893 /**
       
   894 Set the current capture mode and submits the camera configuration to the PDD, passing it as a descriptor
       
   895 to support future changes to the config structure.
       
   896 
       
   897 @param aCaptureMode	The capture mode that the camera switches to.
       
   898 @return KErrNone if successful;
       
   899 		otherwise one of the other system-wide error codes.
       
   900 */
       
   901 TInt DCameraScLdd::SetCaptureMode(TInt aCaptureMode)
       
   902 	{
       
   903 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetCaptureMode(Mode-%d)",aCaptureMode));
       
   904 
       
   905 	TInt r=KErrNone;
       
   906 	if(aCaptureMode >= ECamCaptureModeMax || aCaptureMode < 0)
       
   907 		{
       
   908 		r=KErrNotFound;
       
   909 		return(r);
       
   910 		}
       
   911 
       
   912 	if (!iCaptureModeConfig[aCaptureMode].iBufManager)
       
   913 		{
       
   914 		r=KErrNotReady;
       
   915 		return(r);
       
   916 		}
       
   917 
       
   918 	iCaptureMode=(TDevCamCaptureMode)aCaptureMode;	// The capture mode has already been checked for its validity.
       
   919 
       
   920 	__KTRACE_CAM(Kern::Printf("DCameraScLdd::SetCaptureMode: iFrameSize:%dx%d)",iCaptureModeConfig[iCaptureMode].iCamConfig.iFrameSize.iWidth, iCaptureModeConfig[iCaptureMode].iCamConfig.iFrameSize.iHeight));
       
   921 
       
   922 	// Call the PDD to change the hardware configuration according to the new capture mode.
       
   923 	// Pass it as a descriptor - to support future changes to the config structure.
       
   924 	TPtr8 ptr((TUint8*)&iCaptureModeConfig[iCaptureMode].iCamConfig,sizeof(iCaptureModeConfig[iCaptureMode].iCamConfig),sizeof(iCaptureModeConfig[iCaptureMode].iCamConfig));
       
   925 	r=Pdd()->SetConfig(ptr);
       
   926 	if (r!=KErrNone)
       
   927 		return(r);
       
   928 	return KErrNone;
       
   929 	}
       
   930 
       
   931 
       
   932 /**
       
   933 Process a start image capture request from the client - in the capture mode supplied.
       
   934 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
       
   935 of frames until a NotifyNewImage() request is received.
       
   936 @return KErrNone if successful; whether capture mode was actually started or deferred until NotifyNewImage();
       
   937 		KErrNotReady if SetConfig() has not been previously called;
       
   938 		otherwise one of the other system-wide error codes.
       
   939 */
       
   940 TInt DCameraScLdd::Start()
       
   941 	{
       
   942 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Start(Current Mode-%d)",iCaptureMode));
       
   943 
       
   944 	// We should only be able to do this for the active mode.
       
   945 	if (iState==ECapturing)
       
   946 		return(KErrInUse);
       
   947 
       
   948 	TInt r=KErrNone;
       
   949 
       
   950 	// Only continue if the mode being started has been configured
       
   951 	if (iCaptureModeConfig[iCaptureMode].iBufManager)
       
   952 		iState=EConfigured;
       
   953 
       
   954 	if (iState==EOpen)
       
   955 		r=KErrNotReady;
       
   956 	else if (iState==EConfigured)
       
   957 		{
       
   958 		iCaptureModeConfig[iCaptureMode].iBufManager->Reset();
       
   959 		if (iCaptureMode!=ECamCaptureModeImage)
       
   960 			r=DoStart();
       
   961 		if (r==KErrNone)
       
   962 			iState=ECapturing;
       
   963 		}
       
   964 	else
       
   965 		r=KErrGeneral;
       
   966 	return(r);
       
   967 	}
       
   968 
       
   969 /**
       
   970 Start the PDD capturing images.
       
   971 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   972 */
       
   973 TInt DCameraScLdd::DoStart()
       
   974 	{
       
   975 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoStart()"));
       
   976 
       
   977 	DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
       
   978 	TLinAddr linAddr=(bufManager->iChunkBase)+(bufManager->iCurrentBuffer->iChunkOffset);
       
   979 	TPhysAddr physAddr=bufManager->iCurrentBuffer->iPhysicalAddress;
       
   980 	TInt r=Pdd()->Start(iCaptureMode,linAddr,physAddr);
       
   981 
       
   982 	if (r==KErrNone && bufManager->iNextBuffer)
       
   983 		{
       
   984 		linAddr=(bufManager->iChunkBase)+(bufManager->iNextBuffer->iChunkOffset);
       
   985 		physAddr=bufManager->iNextBuffer->iPhysicalAddress;
       
   986 		r=Pdd()->CaptureNextImage(linAddr,physAddr);
       
   987 		}
       
   988 	return(r);
       
   989 	}
       
   990 
       
   991 /**
       
   992 Process a notify a new image request from the client.
       
   993 If there is an image already available then the request is completed straight away, otherwise it is added to the capture request queue.
       
   994 @param aStatus	The request status to be signalled when the request is complete. If the request is successful then this is set
       
   995 				to the offset within the shared chunk where the record data resides. Alternatively, if an error occurs,
       
   996 				it will be set to one of the system wide error values.
       
   997 @return KErrNone if successful - whether the request was completed or simply queued;
       
   998 		KErrNotReady if Start() hasn't been previousely called;
       
   999 		KErrInUse: if the client needs to free up buffers before further requests can be accepted;
       
  1000 		KErrGeneral: if the client has more requests queued than there are buffers;
       
  1001 		otherwise one of the other system wide error codes.
       
  1002 */
       
  1003 TInt DCameraScLdd::NotifyNewImage(TRequestStatus* aStatus)
       
  1004 	{
       
  1005 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage(%x) - iState(%d)",aStatus,iState));
       
  1006 	DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
       
  1007 	TInt r;
       
  1008 	if (iState!=ECapturing || !bufManager)
       
  1009 		return(KErrNotReady);
       
  1010 
       
  1011 	NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
       
  1012 	if (iCaptureMode!=ECamCaptureModeImage)
       
  1013 		{
       
  1014 		// We're operating in one of the free running modes, see if an image is already available.
       
  1015 		__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage - Getting image for client"));
       
  1016 		TImageBuffer* buf=bufManager->GetImageForClient(EFalse);
       
  1017 		if (buf)
       
  1018 			{
       
  1019 			__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage - There is an image available already"));
       
  1020 			// There is an image available already - complete the request.
       
  1021 			r=buf->iResult;
       
  1022 			NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
       
  1023 			if (r==KErrNone)
       
  1024 				{
       
  1025 				// Only complete if successful here. Errors will be completed on returning from this method.
       
  1026 				__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage(iId:%d)",buf->iId));
       
  1027 				Kern::RequestComplete(iOwningThread,aStatus,(buf->iId));
       
  1028 				}
       
  1029 			return(r);
       
  1030 			}
       
  1031 
       
  1032 		// The buffer 'completed' list is empty. If the 'in-use' list contains all the buffers apart from the one being filled
       
  1033 		// then let the client know they need to free some buffers.
       
  1034 		if (bufManager->iFreeBufferQ.IsEmpty() && !bufManager->iNextBuffer)
       
  1035 			{
       
  1036 			NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
       
  1037 			return(KErrInUse);
       
  1038 			}
       
  1039 		}
       
  1040 	else
       
  1041 		{
       
  1042 		// We're operating in one shot image capture mode. Check if the client needs to free up some buffers
       
  1043 		// before we can accept the request.
       
  1044 		if (bufManager->iCompletedBufferQ.IsEmpty() && bufManager->iFreeBufferQ.IsEmpty() && !bufManager->iNextBuffer)
       
  1045 			{
       
  1046 			NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
       
  1047 			return(KErrInUse);
       
  1048 			}
       
  1049 
       
  1050 		// Enough buffers are available so we can start capturing data. First
       
  1051 		// check that there isn't already a capture request in progress.
       
  1052 		if (iRequestQueue.IsEmpty())
       
  1053 			{
       
  1054 			// No previous request in progress so start the PDD.
       
  1055 			NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
       
  1056 			r=DoStart();
       
  1057 			if (r!=KErrNone)
       
  1058 				return(r);
       
  1059 			NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex again.
       
  1060 			}
       
  1061 		}
       
  1062 
       
  1063 	// Save the request in the pending queue and return. The request will be completed from the PDD and the DFC thread when
       
  1064 	// an image is available.
       
  1065 	r=iRequestQueue.Add(aStatus);
       
  1066 	NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
       
  1067 	return(r);
       
  1068 	}
       
  1069 
       
  1070 /**
       
  1071 Process a release buffer request from the client.
       
  1072 @param aChunkOffset The chunk offset corresponding to the buffer to be freed.
       
  1073 @return KErrNone if successful;
       
  1074 		KErrNotFound if no 'in use' buffer had the specified chunk offset;
       
  1075 		KErrNotReady if the driver hasn't been configured for the current capture mode.
       
  1076 */
       
  1077 TInt DCameraScLdd::ReleaseBuffer(TInt aBufferId)
       
  1078 	{
       
  1079 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ReleaseBuffer(%d)",aBufferId));
       
  1080 	if(!iCaptureModeConfig[iCaptureMode].iBufManager)
       
  1081 		return KErrNotReady;
       
  1082 	DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
       
  1083 	TInt chunkOffset = 0;
       
  1084 
       
  1085 	TInt r=KErrNone;
       
  1086 	/*	The driver is left in an ECapturing state after capturing frames. However, it can be left in an
       
  1087 		EConfigured state as a result of Stop() being called. Stop() cancels all pending capture requests and
       
  1088 		leaves the driver in a state in which it can be restarted without needing reconfiguring.	*/
       
  1089 	if (iState!=EOpen && bufManager)
       
  1090 		{
       
  1091 		chunkOffset = bufManager->iImageBuffer[aBufferId].iChunkOffset;
       
  1092 		TImageBuffer* buf=NULL;
       
  1093 		NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
       
  1094 		buf=bufManager->FindInUseImage(chunkOffset);
       
  1095 		NKern::FMSignal(&iMutex); 		// Release the buffer/request list mutex.
       
  1096 		if (buf)
       
  1097 			{
       
  1098 			// The buffer specified by the client has been found in the 'in-use' list.
       
  1099 			bufManager->Purge(buf);
       
  1100 			}
       
  1101 		else
       
  1102 			r=KErrNotFound;
       
  1103 
       
  1104 		if (r==KErrNone)
       
  1105 			{
       
  1106 			NKern::FMWait(&iMutex); 		// Acquire the buffer/request list mutex.
       
  1107 			// Release it from the 'in-use list into the 'free' list.
       
  1108 			r=bufManager->ReleaseImage(chunkOffset);
       
  1109 			if (r>0)
       
  1110 				{
       
  1111 				// The buffer needs to be queued straight away - so signal this to the PDD
       
  1112 				TLinAddr linAddr=(bufManager->iChunkBase)+(bufManager->iNextBuffer->iChunkOffset);
       
  1113 				TPhysAddr physAddr=bufManager->iNextBuffer->iPhysicalAddress;
       
  1114 				buf=bufManager->iNextBuffer;
       
  1115 				NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
       
  1116 				r=Pdd()->CaptureNextImage(linAddr,physAddr);
       
  1117 				if (r==KErrNotReady)
       
  1118 					r=KErrNone;
       
  1119 				}
       
  1120 			else
       
  1121 				NKern::FMSignal(&iMutex); 	// Release the buffer/request list mutex.
       
  1122 			}
       
  1123 		}
       
  1124 	else
       
  1125 		r=KErrNotReady;
       
  1126 	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::ReleaseBuffer() - r(%d)",r));
       
  1127 	return(r);
       
  1128 	}
       
  1129 
       
  1130 /**
       
  1131 Called from the PDD in the DFC thread each time it finishes capturing an image frame.
       
  1132 This will complete a pending capture request and update buffer lists.
       
  1133 @param aCaptureMode The capture mode of the image captured. @see TDevCamCaptureMode.
       
  1134 @param aResult The result of the image capture request being completed.
       
  1135 @param aLinAddr	If this function returns KErrNone then on return, this holds the linear address of the start of the next buffer
       
  1136 				to use for image capture.
       
  1137 @param aPhysAddr If this function returns KErrNone then on return, this holds the physical address that corresponds to the
       
  1138 				 linear address: aLinAddr.
       
  1139 @return KErrNone if capturing should continue - with holding information on the next buffer to use for image capture.
       
  1140 		KErrNotReady if capturing should continue - but with no further buffer available for image capture just yet.
       
  1141 		KErrAbort if image capturing should now be terminated.
       
  1142 */
       
  1143 TInt DCameraScLdd::ImageCaptureCallback(TDevCamCaptureMode /*aCaptureMode*/,TInt aResult,TLinAddr* aLinAddr,TPhysAddr* aPhysAddr)
       
  1144 	{
       
  1145 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ImageCaptureCallback"));
       
  1146 
       
  1147 	DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
       
  1148 	// Update the buffer list and get the next buffer for capture.
       
  1149 	NKern::FMWait(&iMutex); 				// Acquire the buffer/request list mutex.
       
  1150 	TImageBuffer* nextBuffer=bufManager->SetImageCaptured(aResult);	// Puts the captured image's buffer in the completed buffer queue.
       
  1151 
       
  1152 	// Check if there is a capture request pending.
       
  1153 	if (!iRequestQueue.IsEmpty())
       
  1154 		{
       
  1155 		// A capture request is pending.
       
  1156 		TBool removeLast=((iCaptureMode==ECamCaptureModeImage) ? (TBool) ETrue : (TBool) EFalse);
       
  1157 		TImageBuffer* buf=bufManager->GetImageForClient(removeLast);	// Retrieved the captured image from the buffer in the completed buffer queue.
       
  1158 		if (buf)
       
  1159 			{
       
  1160 			// Update the request pending list and complete the request.
       
  1161 			TRequestStatus* rs=iRequestQueue.Remove();
       
  1162 			TInt reason=(buf->iResult==KErrNone) ? buf->iId : buf->iResult;
       
  1163 			NKern::FMSignal(&iMutex); 													// Release the buffer/request list mutex.
       
  1164 			buf->SyncMemoryAfterDmaRead();
       
  1165 			Kern::RequestComplete(iOwningThread,rs,reason);								// Complete the request.
       
  1166 			}
       
  1167 		else
       
  1168 			NKern::FMSignal(&iMutex); 													// Release the buffer/request list mutex.
       
  1169 		}
       
  1170 	else
       
  1171 		NKern::FMSignal(&iMutex); 														// Release the buffer/request list mutex.
       
  1172 
       
  1173 	// Now work out what instruction to give to the PDD
       
  1174 	TInt r=KErrNone;
       
  1175 	if (iCaptureMode==ECamCaptureModeImage)
       
  1176 		{
       
  1177 		// Image capture mode. If we've just completed a one shot request, see if there is yet another one pending.
       
  1178 		if (!iRequestQueue.IsEmpty())
       
  1179 			{
       
  1180 			// Another request is pending so let the PDD carry on.
       
  1181 			// If an error occured we need to first stop and re-start image capture
       
  1182 			if (aResult!=KErrNone)
       
  1183 				{
       
  1184 				iRestartDfc.Enque();	// Queue a DFC to re-start the PDD later.
       
  1185 				r=KErrAbort;
       
  1186 				}
       
  1187 			}
       
  1188 		else
       
  1189 			{
       
  1190 			r=KErrAbort;	// End of image gather mode so stop the PDD.
       
  1191 			}
       
  1192 		}
       
  1193 	else
       
  1194 		{
       
  1195 		// One of the free running modes. If an error occured we need to first stop and re-start image capture
       
  1196 		if (aResult!=KErrNone)
       
  1197 			{
       
  1198 			iRestartDfc.Enque();	// Queue a DFC to re-start the PDD later.
       
  1199 			r=KErrAbort;
       
  1200 			}
       
  1201 		}
       
  1202 
       
  1203 	// If capture should continue, check if there is a further buffer available to use for image capture.
       
  1204 	if (r==KErrNone)
       
  1205 		{
       
  1206 		if (nextBuffer)
       
  1207 			{
       
  1208 			*aLinAddr=(bufManager->iChunkBase)+(nextBuffer->iChunkOffset);
       
  1209 			*aPhysAddr=nextBuffer->iPhysicalAddress;
       
  1210 			}
       
  1211 		else
       
  1212 			r=KErrNotReady;
       
  1213 		}
       
  1214 	return(r);
       
  1215 	}
       
  1216 
       
  1217 /**
       
  1218 Stores the camera configuration passed in from the user after checking and validating it.
       
  1219 @param	aCaptureMode	The capture mode for which the setting of the camera configuration is made.
       
  1220 @param	aCamConfigBuf	A buffer that contains the camera configuration.
       
  1221 @return	KErrNone if successful
       
  1222 		KErrInUse if the camera is capturing an image
       
  1223 		KErrArgument if the camera configuration passed in is invalid
       
  1224 		otherwise a system wide error code.
       
  1225 */
       
  1226 TInt DCameraScLdd::DoSetConfig(TInt aCaptureMode, const TDesC8* aCamConfigBuf)
       
  1227 	{
       
  1228 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoSetConfig(CaptureMode=%d)",aCaptureMode));
       
  1229 
       
  1230 	// For the active mode we need to perform extra checks.
       
  1231 	if(iCaptureMode == aCaptureMode)
       
  1232 		{
       
  1233 		if (iState==ECapturing)
       
  1234 			{
       
  1235 			return(KErrInUse);
       
  1236 			}
       
  1237 		}
       
  1238 
       
  1239 	// Read the config structure from the client
       
  1240 	TCameraConfigV02 config;
       
  1241 	TPtr8 ptr((TUint8*)&config,sizeof(config));
       
  1242 	TInt r=Kern::ThreadDesRead(iOwningThread,aCamConfigBuf,ptr,0);
       
  1243 	if (r!=KErrNone)
       
  1244 		return(r);
       
  1245 
       
  1246 	// Check that it is compatible with this camera device
       
  1247 	r=ValidateConfig(aCaptureMode, config);
       
  1248 	if (r!=KErrNone)
       
  1249 		{
       
  1250 		if (r == KErrNotFound)
       
  1251 			r = KErrArgument;
       
  1252 		return(r);
       
  1253 		}
       
  1254 
       
  1255 	// For the active mode we need to perform extra tasks.
       
  1256 	// We're about to replace any previous configuration - so set the
       
  1257 	// status back to un-configured. A new buffer configuration must be calculated as a result of that.
       
  1258 	if(iCaptureMode == aCaptureMode)
       
  1259 		{
       
  1260 		iState=EOpen;
       
  1261 		}
       
  1262 
       
  1263 	// Save the new configuration.
       
  1264 	iCaptureModeConfig[aCaptureMode].iCamConfig=config;
       
  1265 	iCaptureModeConfig[aCaptureMode].iFrameHeight=iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iHeight;
       
  1266 	iCaptureModeConfig[aCaptureMode].iFrameWidth=iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iWidth;
       
  1267 
       
  1268 	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoSetConfig - %d",KErrNone));
       
  1269 	return(r);
       
  1270 	}
       
  1271 
       
  1272 /**
       
  1273 Validates the configuration that is about to be used with the driver.
       
  1274 @param aCaptureMode	The capture mode that the configuration is for.
       
  1275 @param aConfig 		The buffer that contains the camera configuration, as passed in from the user.
       
  1276 @return	KErrNotFound if the configuration is not supported by the camera sensor.
       
  1277 		KErrNotSupported if the driver does not support aCaptureMode
       
  1278 		KErrNone if successful.
       
  1279 */
       
  1280 TInt DCameraScLdd::ValidateConfig(TInt aCaptureMode, TCameraConfigV02& aConfig)
       
  1281 	{
       
  1282 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ValidateConfig"));
       
  1283 
       
  1284 	TInt capsSize = Pdd()->CapsSize();
       
  1285 	NKern::ThreadEnterCS();
       
  1286 	TAny* capsBuf = Kern::Alloc(capsSize);
       
  1287 	if(!capsBuf)
       
  1288 		{
       
  1289 		NKern::ThreadLeaveCS();
       
  1290 		return KErrNoMemory;
       
  1291 		}
       
  1292 
       
  1293 	TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
       
  1294 	Pdd()->Caps(capsPtr);
       
  1295 	NKern::ThreadLeaveCS();
       
  1296 
       
  1297 	TCameraCapsV02* camCaps = (TCameraCapsV02*) capsPtr.Ptr();
       
  1298 
       
  1299 	TInt r;
       
  1300 	if(aCaptureMode==ECamCaptureModeImage && camCaps->iNumImagePixelFormats)
       
  1301 		{
       
  1302 		r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
       
  1303 		}
       
  1304 	else if(aCaptureMode==ECamCaptureModeVideo && camCaps->iNumVideoPixelFormats)
       
  1305 		{
       
  1306 		r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
       
  1307 		}
       
  1308 	else if(aCaptureMode==ECamCaptureModeViewFinder && camCaps->iNumViewFinderPixelFormats)
       
  1309 		{
       
  1310 		r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
       
  1311 		}
       
  1312 	else
       
  1313 		r=KErrNotSupported;
       
  1314 
       
  1315 	if(r==KErrNone)
       
  1316 		{
       
  1317 		// Calculate the pixel width (in bytes) for the format specified
       
  1318 		aConfig.iPixelWidthInBytes=aConfig.iPixelFormat.iPixelWidthInBytes;
       
  1319 		}
       
  1320 
       
  1321 	NKern::ThreadEnterCS();
       
  1322 	Kern::Free(capsBuf);
       
  1323 	NKern::ThreadLeaveCS();
       
  1324 
       
  1325 	__KTRACE_CAM(Kern::Printf("<DCameraScLdd::ValidateConfig - %d",r));
       
  1326 	return(r);
       
  1327 	}
       
  1328 
       
  1329 /**
       
  1330 Validates the configuration that is about to be used with the driver by checking it against what the camera sensor supports.
       
  1331 @param aCamCaps		The buffer that contains the capabilities of the camera driver.
       
  1332 @param aCaptureMode	The capture mode that the configuration is for.
       
  1333 @param aConfig 		The buffer that contains the camera configuration, as passed in from the user.
       
  1334 @return	KErrNotFound if the configuration is not supported by the camera sensor
       
  1335 		KErrNone if successful
       
  1336 		or one of the system wide error values.
       
  1337 */
       
  1338 TInt DCameraScLdd::DoValidateConfig(TCameraCapsV02* aCamCaps, TInt& aCaptureMode, TCameraConfigV02& aConfig)
       
  1339 	{
       
  1340 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoValidateConfig"));
       
  1341 	TAny* frameSizeCapsBuf;
       
  1342 	TInt frameSizeCapsSize;
       
  1343 	SFrameSizeCapsInfo info;
       
  1344 	SDevCamFrameSize* frameSize;
       
  1345 	TUint i;
       
  1346 	TUint l;
       
  1347 	SDevCamPixelFormat* pixelFormat;
       
  1348 	TUint start;
       
  1349 	TUint end;
       
  1350 	TInt r;
       
  1351 	pixelFormat = (SDevCamPixelFormat*) (aCamCaps + 1);
       
  1352 	if(aCaptureMode==ECamCaptureModeImage)
       
  1353 		{
       
  1354 		start=0;
       
  1355 		end=aCamCaps->iNumImagePixelFormats;
       
  1356 		}
       
  1357 	else if(aCaptureMode==ECamCaptureModeVideo)
       
  1358 		{
       
  1359 		start=aCamCaps->iNumImagePixelFormats;
       
  1360 		end=aCamCaps->iNumImagePixelFormats + aCamCaps->iNumVideoPixelFormats;
       
  1361 		pixelFormat += aCamCaps->iNumImagePixelFormats;
       
  1362 		}
       
  1363 	else if(aCaptureMode==ECamCaptureModeViewFinder)
       
  1364 		{
       
  1365 		start=aCamCaps->iNumImagePixelFormats+aCamCaps->iNumVideoPixelFormats;
       
  1366 		end=aCamCaps->iNumImagePixelFormats + aCamCaps->iNumVideoPixelFormats + aCamCaps->iNumViewFinderPixelFormats;
       
  1367 		pixelFormat += aCamCaps->iNumImagePixelFormats;
       
  1368 		pixelFormat += aCamCaps->iNumVideoPixelFormats;
       
  1369 		}
       
  1370 	else
       
  1371 		return KErrNotSupported;
       
  1372 
       
  1373 	for (i=start; i<end; i++)
       
  1374 		{
       
  1375 		if(aConfig.iPixelFormat.iPixelFormat==pixelFormat->iPixelFormat)
       
  1376 			{
       
  1377 			info.iUidPixelFormat = pixelFormat->iPixelFormat;
       
  1378 			info.iCaptureMode = (TDevCamCaptureMode) aCaptureMode;
       
  1379 			frameSizeCapsSize = pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize);
       
  1380 			NKern::ThreadEnterCS();
       
  1381 			frameSizeCapsBuf = Kern::Alloc(frameSizeCapsSize);
       
  1382 			NKern::ThreadLeaveCS();
       
  1383 			if (!frameSizeCapsBuf)
       
  1384 				{
       
  1385 				return KErrNoMemory;
       
  1386 				}
       
  1387 			TPtr8 frameSizeCapsPtr( (TUint8*)frameSizeCapsBuf, frameSizeCapsSize, frameSizeCapsSize );
       
  1388 			if ((r = Pdd()->FrameSizeCaps(info.iCaptureMode, info.iUidPixelFormat, frameSizeCapsPtr)) == KErrNone)
       
  1389 				{
       
  1390 				frameSize = (SDevCamFrameSize*) frameSizeCapsPtr.Ptr();
       
  1391 				for(l=0; l<pixelFormat->iNumFrameSizes; l++ )
       
  1392 					{
       
  1393 					if (aConfig.iFrameSize.iWidth==frameSize->iWidth && aConfig.iFrameSize.iHeight==frameSize->iHeight &&
       
  1394 						aConfig.iFrameRate >= frameSize->iMinFrameRate && aConfig.iFrameRate <= frameSize->iMaxFrameRate)
       
  1395 						{
       
  1396 						NKern::ThreadEnterCS();
       
  1397 						Kern::Free(frameSizeCapsBuf);
       
  1398 						NKern::ThreadLeaveCS();
       
  1399 						__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoValidateConfig"));
       
  1400 						return KErrNone;
       
  1401 						}
       
  1402 					frameSize++;
       
  1403 					}
       
  1404 				NKern::ThreadEnterCS();
       
  1405 				Kern::Free(frameSizeCapsBuf);
       
  1406 				NKern::ThreadLeaveCS();
       
  1407 				return KErrNotFound;
       
  1408 				}
       
  1409 			else
       
  1410 				{
       
  1411 				NKern::ThreadEnterCS();
       
  1412 				Kern::Free(frameSizeCapsBuf);
       
  1413 				NKern::ThreadLeaveCS();
       
  1414 				return r;
       
  1415 				}
       
  1416 			}
       
  1417 		pixelFormat++;
       
  1418 		}
       
  1419 	return KErrNotFound;
       
  1420 	}
       
  1421 
       
  1422 /**
       
  1423 The DFC used to re-start the PDD following a data capture error.
       
  1424 @param aChannel A pointer to the camera driver logical channel object.
       
  1425 */
       
  1426 void DCameraScLdd::RestartDfc(TAny* aChannel)
       
  1427 	{
       
  1428 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::RestartDfc"));
       
  1429 
       
  1430 	DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
       
  1431 
       
  1432 	if (!drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer)
       
  1433 		drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer=drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->NextAvailableForCapture();
       
  1434 	__ASSERT_ALWAYS(drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer,Kern::Fault(KCameraLddPanic,__LINE__));
       
  1435 
       
  1436 	if (!drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iNextBuffer)
       
  1437 		drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iNextBuffer=drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->NextAvailableForCapture();
       
  1438 
       
  1439 	drv.DoStart();
       
  1440 	}
       
  1441 
       
  1442 /**
       
  1443 The DFC used to handle power down requests from the power manager before a transition into system
       
  1444 shutdown/standby.
       
  1445 @param aChannel A pointer to the camera driver logical channel object.
       
  1446 */
       
  1447 void DCameraScLdd::PowerDownDfc(TAny* aChannel)
       
  1448 	{
       
  1449 	DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
       
  1450 	drv.Shutdown();
       
  1451 	drv.iPowerHandler->PowerDownDone();
       
  1452 	}
       
  1453 
       
  1454 /**
       
  1455 The DFC used to handle power up requests from the power manager following a transition out of system standby.
       
  1456 @param aChannel A pointer to the camera driver logical channel object.
       
  1457 */
       
  1458 void DCameraScLdd::PowerUpDfc(TAny* aChannel)
       
  1459 	{
       
  1460 	DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
       
  1461 	drv.iPowerHandler->PowerUpDone();
       
  1462 	}
       
  1463 
       
  1464 void DCameraScLdd::PanicClientThread(TInt aReason)
       
  1465 	{
       
  1466 	Kern::ThreadKill(iOwningThread, EExitPanic, aReason, KDevCameraScName);
       
  1467 	}
       
  1468 
       
  1469 /**
       
  1470 Retrieves the capabilities of the camera sensor.
       
  1471 @param aBuffer	A pointer to a descriptor passed in by the user.
       
  1472 */
       
  1473 TInt DCameraScLdd::GetSensorCaps(TAny* aBuffer)
       
  1474 	{
       
  1475 	// Return the capabilities for this device. Read this from the PDD and
       
  1476 	// then write it to the client
       
  1477 	TInt capsSize = Pdd()->CapsSize();
       
  1478 	TInt bufferSize;
       
  1479 	TInt maxBufferSize;
       
  1480 	Kern::KUDesInfo(*((TDes8*)aBuffer), bufferSize, maxBufferSize);
       
  1481 	if(capsSize>maxBufferSize)
       
  1482 		{
       
  1483 		return KErrArgument;
       
  1484 		}
       
  1485 	NKern::ThreadEnterCS();
       
  1486 	TAny* capsBuf = Kern::Alloc(capsSize);
       
  1487 	if(!capsBuf)
       
  1488 		{
       
  1489 		NKern::ThreadLeaveCS();
       
  1490 		return KErrNoMemory;
       
  1491 		}
       
  1492 
       
  1493 	TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
       
  1494 	Pdd()->Caps(capsPtr);
       
  1495 	NKern::ThreadLeaveCS();
       
  1496 	Kern::InfoCopy(*((TDes8*)aBuffer), capsPtr.Ptr(), capsSize);
       
  1497 	NKern::ThreadEnterCS();
       
  1498 	Kern::Free((TAny*)capsBuf);
       
  1499 	NKern::ThreadLeaveCS();
       
  1500 	return KErrNone;
       
  1501 	}
       
  1502 
       
  1503 /**
       
  1504 Retrieves the frame sizes supported for a given pixel format.
       
  1505 @param aBuffer	A pointer to descriptor passed in by the user.
       
  1506 @param aFrameSizeCapsInfo A structure that holds information regarding the requested capabilities.
       
  1507 */
       
  1508 TInt DCameraScLdd::GetFrameSizeCaps(TAny* aBuffer, TAny* aFrameSizeCapsInfo)
       
  1509 	{
       
  1510 	__KTRACE_CAM(Kern::Printf(">DCameraScLdd::GetFrameSizeCaps()"));
       
  1511 	TInt frameSizeCapsMaxSize;
       
  1512 	TInt frameSizeCapsSize;
       
  1513 	Kern::KUDesInfo(*((TDes8*)aBuffer),frameSizeCapsSize,frameSizeCapsMaxSize);
       
  1514 	SFrameSizeCapsInfo info;
       
  1515 	kumemget((TAny*)&info,aFrameSizeCapsInfo,sizeof(info));
       
  1516 	NKern::ThreadEnterCS();
       
  1517 	// Allocate memory on the heap for the frame size structure.
       
  1518 	TAny* frameSizeCapsBuf = Kern::Alloc(frameSizeCapsMaxSize);
       
  1519 	if (!frameSizeCapsBuf)
       
  1520 		{
       
  1521 		NKern::ThreadLeaveCS();
       
  1522 		return KErrNoMemory;
       
  1523 		}
       
  1524 	TPtr8 frameSizeCapsPtr( (TUint8*)frameSizeCapsBuf, frameSizeCapsMaxSize, frameSizeCapsMaxSize );
       
  1525 	// Request the frame sizes from the Pdd.
       
  1526 	TInt r=Pdd()->FrameSizeCaps(info.iCaptureMode, info.iUidPixelFormat, frameSizeCapsPtr);
       
  1527 	NKern::ThreadLeaveCS();
       
  1528 	if (r!=KErrNone)
       
  1529 		{
       
  1530 		NKern::ThreadEnterCS();
       
  1531 		Kern::Free((TAny*)frameSizeCapsBuf);
       
  1532 		NKern::ThreadLeaveCS();
       
  1533 		return r;
       
  1534 		}
       
  1535 	Kern::InfoCopy(*((TDes8*)aBuffer),frameSizeCapsPtr.Ptr(), frameSizeCapsMaxSize);
       
  1536 	NKern::ThreadEnterCS();
       
  1537 	Kern::Free((TAny*)frameSizeCapsBuf);
       
  1538 	NKern::ThreadLeaveCS();
       
  1539 	return KErrNone;
       
  1540 	}
       
  1541 
       
  1542 /**
       
  1543 Constructor for the buffer manager.
       
  1544 */
       
  1545 DBufferManager::DBufferManager(DCameraScLdd* aLdd)
       
  1546 	: iLdd(aLdd)
       
  1547 	{
       
  1548 //	iChunk=NULL;
       
  1549 //	iNumBuffers=0;
       
  1550 //	iImageBuffer=NULL;
       
  1551 	}
       
  1552 
       
  1553 /**
       
  1554 Destructor for the buffer manager.
       
  1555 @pre The thread must be in a critical section.
       
  1556 */
       
  1557 DBufferManager::~DBufferManager()
       
  1558 	{
       
  1559 	if (iChunk)
       
  1560 		Kern::ChunkClose(iChunk);
       
  1561 	delete[] iImageBuffer;
       
  1562 	iImageBuffer=NULL;
       
  1563 	}
       
  1564 
       
  1565 /**
       
  1566 Second stage constructor for the buffer manager. This version creates a shared chunk and a buffer object for each
       
  1567 buffer specified within this. Then it commits memory within the chunk for each of these buffers. This also involves the
       
  1568 creation of a set of buffer lists to manage the buffers.
       
  1569 @param aNumBuffers The number of buffers required in the shared chunk.
       
  1570 @param aBufferSize The size of each buffer required in the shared chunk.
       
  1571 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
  1572 @pre The thread must be in a critical section.
       
  1573 */
       
  1574 TInt DBufferManager::Create(TInt aNumBuffers,TInt aBufferSize)
       
  1575 	{
       
  1576 	__KTRACE_CAM(Kern::Printf(">DBufferManager::Create(Bufs-%d,Sz-%d)",aNumBuffers,aBufferSize));
       
  1577 
       
  1578 	TInt r=CreateBufferLists(aNumBuffers);
       
  1579 	if (r!=KErrNone)
       
  1580 		return(r);
       
  1581 
       
  1582 	// Calculate the size of the chunk required for the buffer configuration specified.
       
  1583 	aBufferSize=Kern::RoundToPageSize(aBufferSize);
       
  1584 	TInt pageSize=Kern::RoundToPageSize(1);
       
  1585 	// Leave space for guard pages around each buffer.  There is a guard page in between each buffer but
       
  1586 	// NO guard page before the first buffer or after the last buffer
       
  1587 	TUint64 chunkSize=TUint64(aBufferSize+pageSize)*aNumBuffers-pageSize;
       
  1588 	if (chunkSize>(TUint64)KMaxTInt)
       
  1589 		return(KErrNoMemory); // Need more than 2GB of memory!
       
  1590 
       
  1591 	// Create the shared chunk. The PDD supplies most of the chunk create info - but not the maximum size.
       
  1592 	TChunkCreateInfo info;
       
  1593 	info.iMaxSize=(TInt)chunkSize;
       
  1594 	iLdd->Pdd()->GetChunkCreateInfo(info);		// Call down to the PDD for the rest.
       
  1595 
       
  1596 	r = Kern::ChunkCreate(info,iChunk,iChunkBase,iChunkMapAttr);
       
  1597 	if (r!=KErrNone)
       
  1598 		return(r);
       
  1599 
       
  1600 	// Commit memory in the chunk for each buffer.
       
  1601 	TInt offset=0;
       
  1602 	TBool isContiguous;
       
  1603 	for (TInt i=0; i<aNumBuffers ; i++)
       
  1604 		{
       
  1605 		r=CommitMemoryForBuffer(offset,aBufferSize,isContiguous);
       
  1606 		if (r!=KErrNone)
       
  1607 			return(r);
       
  1608 		r=iImageBuffer[i].Create(iChunk,offset,aBufferSize,i,isContiguous);
       
  1609 		iImageBuffer[i].iId=i;
       
  1610 		if (r!=KErrNone)
       
  1611 			return(r);
       
  1612 		offset += (aBufferSize+pageSize);
       
  1613 		}
       
  1614 
       
  1615 	return(KErrNone);
       
  1616 	}
       
  1617 
       
  1618 /**
       
  1619 Second stage constructor for the buffer manager. This version opens an existing shared chunk using a client supplied
       
  1620 handle. It then creates a buffer object for each buffer that exists within the chunk as well as creating a set of buffer
       
  1621 lists to manage the buffers.
       
  1622 @param aBufConfig The shared chunk buffer configuration object - specifying the geometry of the buffer configuration
       
  1623 within the shared chunk supplied.
       
  1624 @param aChunkHandle A handle for the shared chunk supplied by the client.
       
  1625 @param anOwningThread The thread in which the given handle is valid.
       
  1626 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
  1627 @pre The thread must be in a critical section.
       
  1628 */
       
  1629 TInt DBufferManager::Create(TCameraSharedChunkBufConfig& aBufConfig,TInt aChunkHandle,DThread* anOwningThread)
       
  1630 	{
       
  1631 	__KTRACE_CAM(Kern::Printf(">DBufferManager::Create(Handle-%d)",aChunkHandle));
       
  1632 
       
  1633 	// Validate the buffer configuration information
       
  1634 	if (!aBufConfig.iFlags&KScFlagBufOffsetListInUse)
       
  1635 		return(KErrArgument);
       
  1636 
       
  1637 	TInt numBuffers=aBufConfig.iNumBuffers;
       
  1638 	TInt r=CreateBufferLists(numBuffers);
       
  1639 	if (r!=KErrNone)
       
  1640 		return(r);
       
  1641 
       
  1642 	DChunk* chunk;
       
  1643 	chunk=Kern::OpenSharedChunk(anOwningThread,aChunkHandle,ETrue);
       
  1644 	if (!chunk)
       
  1645 		return(KErrBadHandle);
       
  1646 	iChunk=chunk;
       
  1647 
       
  1648 	// Read the physical address for the 1st buffer in order to determine the kernel address and the map attributes.
       
  1649 	TInt bufferSizeInBytes=aBufConfig.iBufferSizeInBytes;
       
  1650 
       
  1651 	SBufSpecList* bufferSpec=&aBufConfig.iSpec;
       
  1652 
       
  1653 	TInt offset=bufferSpec[0].iBufferOffset;
       
  1654 
       
  1655 	TPhysAddr physAddr;
       
  1656 	r=Kern::ChunkPhysicalAddress(iChunk,offset,bufferSizeInBytes,iChunkBase,iChunkMapAttr,physAddr,NULL);
       
  1657 	if (r!=KErrNone)
       
  1658 		return(r);
       
  1659 
       
  1660 	// Store the supplied buffer info. into each buffer object.
       
  1661 
       
  1662 	for (TInt i=0; i<numBuffers; i++)
       
  1663 		{
       
  1664 		offset=bufferSpec[i].iBufferOffset;
       
  1665 		// Assume it isn't contiguous here - Create() will detect and do the right thing if it is contiguous.
       
  1666 		r=iImageBuffer[i].Create(iChunk,offset,bufferSizeInBytes,i,EFalse);
       
  1667 		iImageBuffer[i].iId=i;
       
  1668 		if (r!=KErrNone)
       
  1669 			return(r);
       
  1670 		}
       
  1671 	__KTRACE_CAM(Kern::Printf("<DBufferManager::Create - %d",KErrNone));
       
  1672 	return(KErrNone);
       
  1673 	}
       
  1674 
       
  1675 /**
       
  1676 Copies the contents of the Buffer Manager's configuration into aBufConfig
       
  1677 @param aBufConfig The buffer that the data is copied into.
       
  1678 */
       
  1679 void DBufferManager::GetBufConfig(TCameraSharedChunkBufConfig& aBufConfig)
       
  1680 	{
       
  1681 	__KTRACE_CAM(Kern::Printf(">DBufferManager::GetBufConfig"));
       
  1682 	TInt numBuffers=iNumBuffers;
       
  1683 	if (numBuffers<=0)
       
  1684 		return;
       
  1685 
       
  1686 	SBufSpecList* bufferSpec=&aBufConfig.iSpec;
       
  1687 
       
  1688 	while (numBuffers--)
       
  1689 		{
       
  1690 		bufferSpec[numBuffers].iBufferOffset=iImageBuffer[numBuffers].iChunkOffset;
       
  1691 		bufferSpec[numBuffers].iBufferId=iImageBuffer[numBuffers].iId;
       
  1692 		}
       
  1693 
       
  1694 	aBufConfig.iNumBuffers=iNumBuffers;
       
  1695 	aBufConfig.iBufferSizeInBytes=iImageBuffer[0].iSize;	// They're all the same size - so read from the 1st one.
       
  1696 	aBufConfig.iFlags|=KScFlagBufOffsetListInUse;
       
  1697 	return;
       
  1698 	}
       
  1699 
       
  1700 /**
       
  1701 Allocate an array of buffer objects, - one for each buffer contained within the shared chunk.
       
  1702 @param aNumBuffers The number of buffer objects required.
       
  1703 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
  1704 @pre The thread must be in a critical section.
       
  1705 */
       
  1706 TInt DBufferManager::CreateBufferLists(TInt aNumBuffers)
       
  1707 	{
       
  1708 	__KTRACE_CAM(Kern::Printf(">DBufferManager::CreateBufferLists(Bufs-%d)",aNumBuffers));
       
  1709 
       
  1710 	// Construct the array of buffers.
       
  1711 	iNumBuffers=aNumBuffers;
       
  1712 	iImageBuffer=new TImageBuffer[aNumBuffers];
       
  1713 	if (!iImageBuffer)
       
  1714 		return(KErrNoMemory);
       
  1715 	return(KErrNone);
       
  1716 	}
       
  1717 
       
  1718 TInt DBufferManager::CommitMemoryForBuffer(TInt aChunkOffset,TInt aSize,TBool& aIsContiguous)
       
  1719 	{
       
  1720 	__KTRACE_CAM(Kern::Printf(">DBufferManager::CommitMemoryForBuffer(Offset-%x,Sz-%d)",aChunkOffset,aSize));
       
  1721 
       
  1722 	// Try for physically contiguous memory first.
       
  1723 	TPhysAddr physicalAddress;
       
  1724 	TInt r=Kern::ChunkCommitContiguous(iChunk,aChunkOffset,aSize,physicalAddress);
       
  1725 	if (r==KErrNone)
       
  1726 		{
       
  1727 		aIsContiguous=ETrue;
       
  1728 		return(r);
       
  1729 		}
       
  1730 
       
  1731 	// Commit memory that isn't contiguous instead.
       
  1732 	aIsContiguous=EFalse;
       
  1733 	r=Kern::ChunkCommit(iChunk,aChunkOffset,aSize);
       
  1734 	return(r);
       
  1735 	}
       
  1736 
       
  1737 /**
       
  1738 Reset all image buffer lists to reflect the state at the start of the image capture process.
       
  1739 @pre The buffer/request queue mutex must be held.
       
  1740 */
       
  1741 void DBufferManager::Reset()
       
  1742 	{
       
  1743 	__KTRACE_CAM(Kern::Printf(">DBufferManager::Reset"));
       
  1744 
       
  1745 	TImageBuffer* pBuf;
       
  1746 
       
  1747 	// Before reseting buffer lists, purge the cache for all cached buffers currently in use by client.
       
  1748 	pBuf=(TImageBuffer*)iInUseBufferQ.First();
       
  1749 	SDblQueLink* anchor=&iInUseBufferQ.iA;
       
  1750 	while (pBuf!=anchor)
       
  1751 		{
       
  1752 		Purge(pBuf);
       
  1753 		pBuf=(TImageBuffer*)pBuf->iNext;
       
  1754 		}
       
  1755 
       
  1756 	// Start by reseting all the lists.
       
  1757 	iFreeBufferQ.iA.iNext=iFreeBufferQ.iA.iPrev=&iFreeBufferQ.iA;
       
  1758 	iCompletedBufferQ.iA.iNext=iCompletedBufferQ.iA.iPrev=&iCompletedBufferQ.iA;
       
  1759 	iInUseBufferQ.iA.iNext=iInUseBufferQ.iA.iPrev=&iInUseBufferQ.iA;
       
  1760 
       
  1761 	// Set the pointers to the current and the next record buffers.
       
  1762 	pBuf=iImageBuffer; 		// This is the first buffer
       
  1763 	iCurrentBuffer=pBuf++;
       
  1764 	iNextBuffer = pBuf++;
       
  1765 
       
  1766 	// Add all other buffers to the free list.
       
  1767 	TImageBuffer* bufferLimit=iImageBuffer+iNumBuffers;
       
  1768 	while(pBuf<bufferLimit)
       
  1769 		iFreeBufferQ.Add(pBuf++);
       
  1770 	}
       
  1771 
       
  1772 /**
       
  1773 Purge the cache for a cached image buffer.
       
  1774 @param aBuffer The buffer to be purged.
       
  1775 */
       
  1776 void DBufferManager::Purge(TImageBuffer* aBuffer)
       
  1777 	{
       
  1778 	aBuffer->SyncMemoryBeforeDmaRead();
       
  1779 	}
       
  1780 
       
  1781 /**
       
  1782 Update buffer lists after an image has been captured.
       
  1783 @param aResult The result of the image capture operation that has just completed.
       
  1784 @return A pointer to the next image buffer for capture - or NULL if none are available.
       
  1785 @pre The buffer/request queue mutex must be held.
       
  1786 */
       
  1787 TImageBuffer* DBufferManager::SetImageCaptured(TInt aResult)
       
  1788 	{
       
  1789 	// Take a copy of the buffer with the image just captured.
       
  1790 	__ASSERT_DEBUG(iCurrentBuffer,Kern::Fault(KCameraLddPanic,__LINE__));
       
  1791 	TImageBuffer* cur=iCurrentBuffer;
       
  1792 
       
  1793 	// Make the queued buffer the current one.
       
  1794 	iCurrentBuffer=iNextBuffer;
       
  1795 
       
  1796 	// Now we need to identify the next image buffer to queue.
       
  1797 	iNextBuffer=NextAvailableForCapture();
       
  1798 
       
  1799 	// Now add the buffer with the image just captured to the 'completed' list.
       
  1800 	if (cur)
       
  1801 		{
       
  1802 		cur->iResult=aResult;						// Store the result of the capture operation in the image buffer object.
       
  1803 		iCompletedBufferQ.Add(cur);
       
  1804 		}
       
  1805 
       
  1806 	__KTRACE_CAM(Kern::Printf("<DBufferManager::SetImageCaptured(buf=%08x)-%d",cur->iChunkOffset,aResult));
       
  1807 	return(iNextBuffer);
       
  1808 	}
       
  1809 
       
  1810 /**
       
  1811 Remove from the buffer lists the next buffer that is available to queue for transfer.
       
  1812 @return A pointer to the next image buffer for capture - or NULL if none are available.
       
  1813 @pre The buffer/request queue mutex must be held.
       
  1814 */
       
  1815 TImageBuffer* DBufferManager::NextAvailableForCapture()
       
  1816 	{
       
  1817 	// We need to identify the next image buffer to queue. Try to get one from the 'free' list.
       
  1818 	TImageBuffer* buffer=(TImageBuffer*)iFreeBufferQ.GetFirst();
       
  1819 #ifdef DISCARD_COMPLETED_TO_AVOID_OVERFLOW
       
  1820 	// If there are none left on the 'free' list then take one from the completed list.
       
  1821 	if (!buffer)
       
  1822 		buffer=(TImageBuffer*)iCompletedBufferQ.GetFirst();
       
  1823 #endif
       
  1824 	return(buffer);
       
  1825 	}
       
  1826 
       
  1827 /**
       
  1828 Get the next image from the 'completed' capture list. If there is no error associated with the buffer,
       
  1829 make it 'in use' by the client. Otherwise, return the buffer to the free list.
       
  1830 @param aRemoveLast	If true, the buffer is removed from the tail of the completed capture list, otherwise
       
  1831 					it is removed from the head of this list.
       
  1832 @return A pointer to the next completed image buffer - or NULL if there is no buffer available.
       
  1833 @pre The buffer/request queue mutex must be held.
       
  1834 */
       
  1835 TImageBuffer* DBufferManager::GetImageForClient(TBool aRemoveLast)
       
  1836 	{
       
  1837 	__KTRACE_CAM(Kern::Printf("<DBufferManager::GetImageForClient"));
       
  1838 	TImageBuffer* buffer=NULL;
       
  1839 	if (!iCompletedBufferQ.IsEmpty())
       
  1840 		{
       
  1841 		buffer = (aRemoveLast) ? (TImageBuffer*)iCompletedBufferQ.Last() : (TImageBuffer*)iCompletedBufferQ.First();
       
  1842 		buffer->Deque();
       
  1843 
       
  1844 		if (buffer->iResult==KErrNone)
       
  1845 			iInUseBufferQ.Add(buffer);
       
  1846 		else
       
  1847 			iFreeBufferQ.Add(buffer);
       
  1848 		}
       
  1849 	return(buffer);
       
  1850 	}
       
  1851 
       
  1852 /**
       
  1853 Release (move to free list) the 'in use' image specified by the given chunk offset.
       
  1854 @param aChunkOffset The chunk offset corresponding to the buffer to be freed.
       
  1855 @return The freed image buffer, or NULL if no 'in use' buffer had the specified chunk offset.
       
  1856 @return KErrNone if buffer moved to the free list;
       
  1857 		1 if the buffer needs to be queued straight away
       
  1858 		KErrArgument if no 'in use' buffer had the specified chunk offset;
       
  1859 @pre The buffer/request queue mutex must be held.
       
  1860 */
       
  1861 TInt DBufferManager::ReleaseImage(TInt aChunkOffset)
       
  1862 	{
       
  1863 	__KTRACE_CAM(Kern::Printf(">DBufferManager::ReleaseImage(chunkOffset=%08x)",aChunkOffset));
       
  1864 	TInt r=KErrArgument;
       
  1865 
       
  1866 	// Scan 'in use' list for the image buffer
       
  1867 	TImageBuffer* pBuf;
       
  1868 	pBuf=(TImageBuffer*)iInUseBufferQ.First();
       
  1869 	SDblQueLink* anchor=&iInUseBufferQ.iA;
       
  1870 	while (pBuf!=anchor && pBuf->iChunkOffset!=aChunkOffset)
       
  1871 		pBuf=(TImageBuffer*)pBuf->iNext;
       
  1872 
       
  1873 	if (pBuf!=anchor)
       
  1874 		{
       
  1875 		// Buffer found in 'in-use' list.
       
  1876 		if (!iNextBuffer)
       
  1877 			{
       
  1878 			// We need to signal the pdd to queue this buffer straight away.
       
  1879 			iNextBuffer=(TImageBuffer*)pBuf->Deque();
       
  1880 			r=1;
       
  1881 			}
       
  1882 		else
       
  1883 			{
       
  1884 			// Move buffer to the free list.
       
  1885 			iFreeBufferQ.Add(pBuf->Deque());
       
  1886 			r=KErrNone;
       
  1887 			}
       
  1888 		}
       
  1889 
       
  1890 	__KTRACE_CAM(Kern::Printf("<DBufferManager::ReleaseImage(buf=%08x)",((pBuf!=anchor) ? pBuf->iChunkOffset : -1)));
       
  1891 	return(r);
       
  1892 	}
       
  1893 
       
  1894 /**
       
  1895 Find the 'in use' image specified by the given chunk offset
       
  1896 @param aChunkOffset The chunk offset corresponding to the buffer to be freed
       
  1897 @return The image buffer, or NULL if no 'in use' buffer had the specified chunk offset
       
  1898 @pre The buffer/request queue mutex must be held.
       
  1899 */
       
  1900 TImageBuffer* DBufferManager::FindInUseImage(TInt aChunkOffset)
       
  1901 	{
       
  1902 	// Scan 'in use' list for the image buffer
       
  1903 	TImageBuffer* pBuf;
       
  1904 	pBuf=(TImageBuffer*)iInUseBufferQ.First();
       
  1905 	SDblQueLink* anchor=&iInUseBufferQ.iA;
       
  1906 	while (pBuf!=anchor && pBuf->iChunkOffset!=aChunkOffset)
       
  1907 		pBuf=(TImageBuffer*)pBuf->iNext;
       
  1908 
       
  1909 	return((pBuf!=anchor)?pBuf:NULL);
       
  1910 	}
       
  1911 
       
  1912 /**
       
  1913 Constructor for the image buffer class.
       
  1914 Clears all member data
       
  1915 */
       
  1916 TImageBuffer::TImageBuffer()
       
  1917 	{
       
  1918 	memclr(this,sizeof(*this));
       
  1919 	}
       
  1920 
       
  1921 /**
       
  1922 Destructor for the image buffer class.
       
  1923 */
       
  1924 TImageBuffer::~TImageBuffer()
       
  1925 	{
       
  1926 	delete[] iPhysicalPages;
       
  1927 	iPhysicalPages=NULL;
       
  1928 	}
       
  1929 
       
  1930 /**
       
  1931 Second stage constructor for the image buffer class - get information on the memory
       
  1932 allocated to this buffer.
       
  1933 @param aChunk	The chunk into which the memory is to be commited
       
  1934 @param aOffset	The offset within aChunk for the start of the comitted memory.
       
  1935 				Must be a multiple of the MMU page size.
       
  1936 @param aSize	The number of bytes of memory commited.
       
  1937 				Must be a multiple of the MMU page size.
       
  1938 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
  1939 @pre The thread must be in a critical section.
       
  1940 */
       
  1941 TInt TImageBuffer::Create(DChunk* aChunk,TInt aOffset,TInt aSize, TInt aId, TBool aIsContiguous)
       
  1942 	{
       
  1943 	__KTRACE_CAM(Kern::Printf(">TImageBuffer::Create(Off-%x,Sz-%d,Contig-%d)",aOffset,aSize,aIsContiguous));
       
  1944 
       
  1945 	// Save info. on the chunk the buffer is in, and the offset and size of the buffer.
       
  1946 	iChunk=aChunk;
       
  1947 	iChunkOffset=aOffset;
       
  1948 	iId=aId;
       
  1949 	iSize=aSize;
       
  1950 
       
  1951 	TInt r=KErrNone;
       
  1952 	iPhysicalPages=NULL;
       
  1953 	if (!aIsContiguous)
       
  1954 		{
       
  1955 		// Allocate an array for a list of the physical pages.
       
  1956 		iPhysicalPages = new TPhysAddr[aSize/Kern::RoundToPageSize(1)+2];
       
  1957 		if (!iPhysicalPages)
       
  1958 			r=KErrNoMemory;
       
  1959 		}
       
  1960 
       
  1961 	if (r==KErrNone)
       
  1962 		{
       
  1963 		// Get the physical addresses of the pages in the buffer.
       
  1964 		TUint32 mapAttr;
       
  1965 		r=Kern::ChunkPhysicalAddress(aChunk,aOffset,aSize,iLinearAddress,mapAttr,iPhysicalAddress,iPhysicalPages);
       
  1966 		// r = 0 or 1 on success. (1 meaning the physical pages are not contiguous).
       
  1967 		if (r==1)
       
  1968 			{
       
  1969 			// The physical pages are not contiguous.
       
  1970 			iPhysicalAddress=KPhysAddrInvalid;	// Mark the physical address as invalid.
       
  1971 			r=(aIsContiguous) ? KErrGeneral : KErrNone;
       
  1972 			}
       
  1973 		if (r==0)
       
  1974 			{
       
  1975 			delete[] iPhysicalPages;	// We shouldn't retain this info. if the physical pages are contiguous.
       
  1976 			iPhysicalPages=NULL;
       
  1977 			}
       
  1978 		}
       
  1979 	__KTRACE_CAM(Kern::Printf("<TImageBuffer::Create - %d",r));
       
  1980 	return(r);
       
  1981 	}
       
  1982 
       
  1983 /**
       
  1984 Prepares a cacheable buffer for use by the DMA engine, before an image capture.
       
  1985 */
       
  1986 void TImageBuffer::SyncMemoryBeforeDmaRead()
       
  1987 	{
       
  1988 #ifndef __WINS__
       
  1989 	if (iChunk->iMapAttr&EMapAttrCachedMax)
       
  1990 		{
       
  1991 		Cache::SyncMemoryBeforeDmaRead(iLinearAddress,iSize);
       
  1992 		}
       
  1993 #endif
       
  1994 	}
       
  1995 
       
  1996 /**
       
  1997 Prepare a cacheable buffer for use by the CPU, after an image capture using DMA.
       
  1998 */
       
  1999 void TImageBuffer::SyncMemoryAfterDmaRead()
       
  2000 	{
       
  2001 #ifndef __WINS__
       
  2002 	if (iChunk->iMapAttr&EMapAttrCachedMax)
       
  2003 		{
       
  2004 		Cache::SyncMemoryAfterDmaRead(iLinearAddress,iSize);
       
  2005 		}
       
  2006 #endif
       
  2007 	}
       
  2008 
       
  2009 /**
       
  2010 Constructor for the capture request queue.
       
  2011 */
       
  2012 TCameraScRequestQueue::TCameraScRequestQueue(NFastMutex* aMutexPtr)
       
  2013 	: iMutexPtr(aMutexPtr)
       
  2014 	{
       
  2015 	iOwningThread=NULL;
       
  2016 	memclr(&iRequest[0],sizeof(TCameraScRequest*)*KMaxCamScRequestsPending);
       
  2017 	}
       
  2018 
       
  2019 /**
       
  2020 Destructor for the capture request queue.
       
  2021 */
       
  2022 TCameraScRequestQueue::~TCameraScRequestQueue()
       
  2023 	{
       
  2024 	for (TInt i=0 ; i<KMaxCamScRequestsPending ; i++)
       
  2025 		{
       
  2026 		delete iRequest[i];
       
  2027 		iRequest[i]=NULL;
       
  2028 		}
       
  2029 	}
       
  2030 
       
  2031 /**
       
  2032 Second stage constructor for the capture request queue.
       
  2033 @param anOwningThread A pointer to the owning client thread.
       
  2034 @return KErrNone if successful;
       
  2035 		KErrNoMemory if unable to allocate memory for the capture request queue.
       
  2036 @pre The thread must be in a critical section.
       
  2037 */
       
  2038 TInt TCameraScRequestQueue::Create(DThread* anOwningThread)
       
  2039 	{
       
  2040 	iOwningThread=anOwningThread;
       
  2041 
       
  2042 	// Create the set of available request objects and add them to the unused request queue.
       
  2043 	for (TInt i=0 ; i<KMaxCamScRequestsPending ; i++)
       
  2044 		{
       
  2045 		iRequest[i]=new TCameraScRequest;
       
  2046 		if (!iRequest[i])
       
  2047 			return(KErrNoMemory);
       
  2048 		iUnusedRequestQ.Add(iRequest[i]);
       
  2049 		}
       
  2050 
       
  2051 	return(KErrNone);
       
  2052 	}
       
  2053 
       
  2054 /**
       
  2055 Store a request status pointer onto the tail of the capture request queue.
       
  2056 @param aStatus The request status pointer to be stored.
       
  2057 @return KErrNone if successful;
       
  2058 		KErrGeneral if the limit on the number of pending capture request (KMaxCamScRequestsPending) would be exceeded.
       
  2059 @pre The buffer/request queue mutex must be held.
       
  2060 */
       
  2061 TInt TCameraScRequestQueue::Add(TRequestStatus* aStatus)
       
  2062 	{
       
  2063 	TCameraScRequest* req=(TCameraScRequest*)iUnusedRequestQ.GetFirst();
       
  2064 	if (!req)
       
  2065 		return(KErrGeneral);								// Must have exceeded KMaxCamScRequestsPending
       
  2066 
       
  2067 	req->iStatus=aStatus;
       
  2068 	iPendRequestQ.Add(req);
       
  2069 	return(KErrNone);
       
  2070 	}
       
  2071 
       
  2072 /**
       
  2073 Retrieve the next request status pointer from the head of the capture request queue.
       
  2074 @return The request status pointer removed or NULL if the list is empty.
       
  2075 @pre The buffer/request queue mutex must be held.
       
  2076 */
       
  2077 TRequestStatus* TCameraScRequestQueue::Remove()
       
  2078 	{
       
  2079 	TRequestStatus* status=NULL;
       
  2080 	TCameraScRequest* req=(TCameraScRequest*)iPendRequestQ.GetFirst();
       
  2081 	if (req)
       
  2082 		{
       
  2083 		status=req->iStatus;
       
  2084 		iUnusedRequestQ.Add(req);
       
  2085 		}
       
  2086 	return(status);
       
  2087 	}
       
  2088 
       
  2089 /**
       
  2090 Remove a specifc request status pointer from the the capture request queue, completing it with a 'KErrCancel' completion reason.
       
  2091 @param aStatus The request status pointer to be completed.
       
  2092 @pre The buffer/request queue mutex must be held.
       
  2093 */
       
  2094 void TCameraScRequestQueue::Cancel(TRequestStatus* aStatus)
       
  2095 	{
       
  2096 	// Find the entry concerned
       
  2097 	TCameraScRequest* req=(TCameraScRequest*)iPendRequestQ.First();
       
  2098 	SDblQueLink* anchor=&iPendRequestQ.iA;
       
  2099 	while (req!=anchor && req->iStatus!=aStatus)
       
  2100 		req=(TCameraScRequest*)req->iNext;
       
  2101 	if (req==anchor)
       
  2102 		return;
       
  2103 
       
  2104 	// Remove and cancel it.
       
  2105 	req->Deque();
       
  2106 	iUnusedRequestQ.Add(req);
       
  2107 	NKern::FMSignal(iMutexPtr); 	// Release the request list mutex while we complete the request. This is safe.
       
  2108 	Kern::RequestComplete(iOwningThread,req->iStatus,KErrCancel);
       
  2109 	NKern::FMWait(iMutexPtr); 		// Re-acquire the request list mutex.
       
  2110 	}
       
  2111 
       
  2112 /**
       
  2113 Remove each request status pointer from the the capture request queue, completing each with a 'KErrCancel' completion reason.
       
  2114 @pre The buffer/request queue mutex must be held.
       
  2115 */
       
  2116 void TCameraScRequestQueue::CancelAll()
       
  2117 	{
       
  2118 
       
  2119 	TRequestStatus* status;
       
  2120 	while ((status=Remove())!=NULL)
       
  2121 		{
       
  2122 		NKern::FMSignal(iMutexPtr); 	// Release the request list mutex while we complete the request. This is safe.
       
  2123 		Kern::RequestComplete(iOwningThread,status,KErrCancel);
       
  2124 		NKern::FMWait(iMutexPtr); 		// Re-acquire the request list mutex.
       
  2125 		}
       
  2126 	}
       
  2127 
       
  2128 /**
       
  2129 Constructor for the camera driver power handler class.
       
  2130 @param aChannel A pointer to the camera driver logical channel which owns this power handler.
       
  2131 */
       
  2132 DCameraScPowerHandler::DCameraScPowerHandler(DCameraScLdd* aChannel)
       
  2133 :	DPowerHandler(KDevCameraScName),
       
  2134 	iChannel(aChannel)
       
  2135 	{
       
  2136 	}
       
  2137 
       
  2138 /**
       
  2139 A request from the power manager for the power down of the camera device.
       
  2140 This is called during a transition of the phone into standby or power off.
       
  2141 @param aState The target power state; can be EPwStandby or EPwOff only.
       
  2142 */
       
  2143 void DCameraScPowerHandler::PowerDown(TPowerState aPowerState)
       
  2144 	{
       
  2145 	(void)aPowerState;
       
  2146 	__KTRACE_CAM(Kern::Printf(">DCameraScPowerHandler::PowerDown(State-%d)",aPowerState));
       
  2147 
       
  2148 	// Power-down involves hardware access so queue a DFC to perform this from the driver thread.
       
  2149 	iChannel->iPowerDownDfc.Enque();
       
  2150 	}
       
  2151 
       
  2152 /**
       
  2153 A request from the power manager for the power up of the camera device.
       
  2154 This is called during a transition of the phone out of standby.
       
  2155 */
       
  2156 void DCameraScPowerHandler::PowerUp()
       
  2157 	{
       
  2158 	__KTRACE_CAM(Kern::Printf(">DCameraScPowerHandler::PowerUp"));
       
  2159 
       
  2160 	// Power-up involves hardware access so queue a DFC to perform this from the driver thread.
       
  2161 	iChannel->iPowerUpDfc.Enque();
       
  2162 	}