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