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