bsptemplate/asspandvariant/template_variant/camerasc/camerasc.cpp
branchRCL_3
changeset 257 3e88ff8f41d5
child 258 880ff05ad710
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bsptemplate/asspandvariant/template_variant/camerasc/camerasc.cpp	Wed Sep 01 12:34:56 2010 +0100
@@ -0,0 +1,535 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// template\template_variant\camerasc\camerasc.cpp
+// Implementation of the template shared chunk camera physical device driver (PDD).
+// This file is part of the Template Base port
+// 
+//
+#include "camerasc_plat.h"
+
+_LIT(KCameraScPddName, "CameraSc.TE");
+_LIT(KCameraScDfcQueueName, "CameraSc.TE.DfcQ");
+
+/**
+Standard export function for PDD factories.  This creates a DPhysicalDevice derived object, in this case,
+DTemplateCameraScPddFactory.
+*/
+DECLARE_STANDARD_PDD()
+	{
+	return new DTemplateCameraScPddFactory;
+	}
+
+/**
+Constructor for the shared chunk camera PDD factory class.
+*/
+DTemplateCameraScPddFactory::DTemplateCameraScPddFactory()
+	{
+	// We currently support only unit 0
+	iUnitsMask = 0x01;
+
+	// Set the version number for this device.  This is used to allow code to specify that it requires a
+	// minimum version of the device in order to operate.  If the version requested is less than this then
+	// the device is safe to be used
+	iVersion = RDevCameraSc::VersionRequired();
+	}
+
+/**
+Destructor for the shared chunk camera PDD factory class.
+*/
+DTemplateCameraScPddFactory::~DTemplateCameraScPddFactory()
+	{
+	}
+
+/**
+Second stage constructor for the shared chunk camera PDD factory class.  This must at least set a name for
+the driver object.
+@return KErrNone if successful, otherwise one of the system wide error codes.
+*/
+TInt DTemplateCameraScPddFactory::Install()
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPddFactory::Install()"));
+
+	TInt r;
+
+	// Create a DFC queue so that handling of both camera hardware callbacks and requests made to the LDD from
+	// user mode can be processed in the same thread, to avoid the use of semaphores
+	if ((r = Kern::DynamicDfcQCreate(iDfcQ, 26, KCameraScDfcQueueName)) == KErrNone)
+		{
+		// All PDD factories must have a unique name
+		r = SetName(&KCameraScPddName);
+		}
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPddFactory::Install() => Returning %d", r));
+
+	return r;
+	}
+
+/**
+Returns the PDD's capabilities.  This is not used by the Symbian OS device driver framework
+or by the LDD but is here as some LDDs will make use of it.
+@param aDes	A descriptor into which to write capability information.
+*/
+void DTemplateCameraScPddFactory::GetCaps(TDes8& /*aDes*/) const
+	{
+	}
+
+/**
+Called by the kernel's device driver framework to check if this PDD is suitable for use
+with a logical channel.  This is called in the context of the client thread which requested
+the creation of a logical channel, through a call to RBusLogicalChannel::DoCreate().  The
+thread is in a critical section.
+@param aUnit	The unit argument supplied by the client to RBusLogicalChannel::DoCreate()
+				This is used to determine which sensor to use.
+@param aInfo	The info argument supplied by the client to RBusLogicalChannel::DoCreate().
+@param aVer		The version number of the logical channel which will use this physical channel.
+@return KErrNone if successful, otherwise one of the system wide error codes.
+*/
+TInt DTemplateCameraScPddFactory::Validate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
+	{
+	// Check that the version requested is less than or equal to the version of this PDD
+	if (!Kern::QueryVersionSupported(RDevCameraSc::VersionRequired(), aVer))
+		{
+		return KErrNotSupported;
+		}
+
+	// Check that the unit number specifies the available sensor
+	if ((aUnit < 0) || (aUnit > 0))
+		{
+		return KErrNotSupported;
+		}
+
+	return KErrNone;
+	}
+
+/**
+Called by the kernel's device driver framework to create a physical channel object.  This
+is called in the context of the client thread which requested the creation of a logical
+channel, through a call to RBusLogicalChannel::DoCreate().  The thread is in a critical section.
+@param aChannel	Set by this function to point to the created physical channel object.
+@param aUnit	The unit argument supplied by the client to RBusLogicalChannel::DoCreate().
+@param aInfo	The info argument supplied by the client to RBusLogicalChannel::DoCreate().
+@param aVer		The version number of the logical channel which will use this physical channel.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateCameraScPddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& /*aVer*/)
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPddFactory::Create()"));
+
+	// Create an instance of the PDD channel object that will work with the Template sensor
+	DTemplateCameraScPdd* pD = new DTemplateCameraScPdd;
+
+	aChannel = pD;
+	TInt r = KErrNoMemory;
+
+	if (pD)
+		{
+		r = pD->DoCreate(this, aUnit);
+		}
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPddFactory::Create() => Returning %d", r));
+
+	return r;
+	}
+
+/**
+Called by SetUnitOpen() to see if a particular unit is open.  When called, the
+iUnitInfoMutex fast mutex will be taken, ensuring safe access to iUnitsOpenMask.
+@param aUnit	The unit number to be checked for being open.
+@return ETrue if the unit specified by aUnit is already open, otherwise EFalse.
+*/
+TBool DTemplateCameraScPddFactory::IsUnitOpen(TInt aUnit)
+	{
+	return (iUnitsOpenMask & (1 << aUnit));
+	}
+
+/**
+Attempt to change the state of the unit open state for a particular unit.
+@param aUnit	The unit number to be set to open or closed state.
+@param aIsOpen	The required new state for the unit;  either ETrue to set the state
+				to open or EFalse to set the state to closed.
+@return KErrNone if the state was updated successfully, otherwise KErrInUse if an attempt
+		was made to set the unit status to open while it is already open.
+*/
+TInt DTemplateCameraScPddFactory::SetUnitOpen(TInt aUnit, TBool aIsOpen)
+	{
+	// Wait until it is safe to access the unit state mask
+	NKern::FMWait(&iUnitInfoMutex);
+
+	// Fail a request to open a unit that is already open
+	if (aIsOpen && IsUnitOpen(aUnit))
+		{
+		__KTRACE_CAM(Kern::Printf("+ DTemplateCameraScPddFactory::SetUnitOpen() => Unit %d is already in use", aUnit));
+
+		// Release the unit state mask mutex
+		NKern::FMSignal(&iUnitInfoMutex);
+
+		return KErrInUse;
+		}
+
+	// Set or clear the unit's open status bit as required
+	if (aIsOpen)
+		{
+		iUnitsOpenMask |= (1 << aUnit);
+		}
+	else
+		{
+		iUnitsOpenMask &= ~(1 << aUnit);
+		}
+
+	// Release the unit state mask mutex
+	NKern::FMSignal(&iUnitInfoMutex);
+
+	return KErrNone;
+	}
+
+/**
+Constructor for the shared chunk camera PDD class.
+*/
+DTemplateCameraScPdd::DTemplateCameraScPdd()
+	{
+	// Set the unit number to -1 to indicate that this channel has never been registered
+	// with the PDD factory
+	iUnit = -1;
+
+	// The channel has been created but not yet configured */
+	iState = EUnconfigured;
+	}
+
+/**
+Destructor for the shared chunk camera PDD class.  This is called in the context of the client thread
+once an 'ECloseMsg' message has been sent to the device driver DFC thread.
+*/
+DTemplateCameraScPdd::~DTemplateCameraScPdd()
+	{
+	delete [] iCapsBuffer;
+	delete iSensor;
+
+	// Indicate that a physical channel is no longer open on this unit
+	if (iUnit >= 0)
+		{
+		iPhysicalDevice->SetUnitOpen(iUnit, EFalse);
+		}
+	}
+
+/**
+Second stage constructor for the H4 camera PDD.
+@param aPhysicalDevice	A pointer to the factory class that is creating this PDD
+@param aUnit			The unit argument supplied by the client to RBusLogicalChannel::DoCreate().
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateCameraScPdd::DoCreate(DTemplateCameraScPddFactory* aPhysicalDevice, TInt aUnit)
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPdd::DoCreate()"));
+
+	TInt r;
+
+	iPhysicalDevice = aPhysicalDevice;
+
+	// Check that a physical channel hasn't already been opened on this unit
+	if ((r = iPhysicalDevice->SetUnitOpen(aUnit, ETrue)) == KErrNone)
+		{
+		iUnit = aUnit;
+
+		// Create an abstracted sensor interface
+		if ((iSensor = new DTemplateSensorIf(*this, DfcQ(aUnit))) != NULL)
+			{
+			if ((r = iSensor->DoCreate()) == KErrNone)
+				{
+				// Setup the capabilities of this device for later reference
+				if ((r = iSensor->GetCaps(iCaps)) > 0)
+					{
+					// And save the size as returned from the sensor
+					iCapsSize = r;
+
+					// Although iCaps now points to a TCameraCapsV02 structure, it is actually a variable
+					// sized structure that was allocated as an array of TUint8 so save it to a TUint8
+					// ptr so that it can be deleted properly
+					iCapsBuffer = (TUint8*) iCaps;
+
+					// Enable the clocks needed by the camera subsystem and power up the sensor
+					r = iSensor->RequestPower();
+
+					// Some sensors power themselves up automatically in their DoCreate() function,
+					// so take this into account here
+					if (r == KErrAlreadyExists)
+						{
+						r = KErrNone;
+						}
+					}
+				}
+			}
+		else
+			{
+			r = KErrNoMemory;
+			}
+		}
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPdd::DoCreate() => Returning %d", r));
+
+	return r;
+	}
+
+/**
+An appropriate DFC queue to use for processing client requests (that is, those that won't be processed
+in the context of the client thread), and also for processing image completion requests from the sensor
+will have been setup by the PDD factory.  Anything needing to run in this same DFC thread can access the
+queue via this function.
+@param	aUnit	The unit number for which to get the DFC queue.
+@return	The DFC queue to be used.
+*/
+TDfcQue* DTemplateCameraScPdd::DfcQ(TInt /*aUnit*/)
+	{
+	return iPhysicalDevice->iDfcQ;
+	}
+
+/**
+Called by the LDD in order to query the capabilities of the PDD.
+@param	aCapsBuf	A reference to a descriptor owned by the LDD, containing a TCameraCapsV02 structure
+					for the capabilities.
+*/
+void DTemplateCameraScPdd::Caps(TDes8& aCapsBuf) const
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPdd::Caps()"));
+
+	// The iCaps structure will already have been created by a call to iSensor->SetCaps() in DoCreate().
+	// Simply copy it into the supplied TPckgBuf, taking into account the fact that the TCameraCapsV02
+	// buffer is of a variable size *and* may be smaller or larger than the iCaps structure
+	TPtrC8 ptr((const TUint8*) iCaps, iCapsSize);
+	aCapsBuf.FillZ(aCapsBuf.MaxLength());
+	aCapsBuf = ptr.Left(Min(ptr.Length(), aCapsBuf.MaxLength()));
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPdd::Caps()"));
+	}
+
+/**
+Called by the LDD to setup a new image configuration, including such things as image size, framerate
+and pixel format.
+@param	aConfigBuf	A reference to a TPckgBuf containing a TCameraConfigV02 configuration structure.
+@return KErrNone if successful, otherwise one of the system wide error codes.
+*/
+TInt DTemplateCameraScPdd::SetConfig(const TDesC8& aConfigBuf)
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPdd::SetConfig()"));
+
+	TInt r;
+
+	// It is only legal to call this if image capture is not already underway, so check for this
+	// before doing anything
+	if (iState <= EConfigured)
+		{
+		// Read the new configuration from the LDD into a local copy of the configuration structure,
+		// taking into account for compatibility that the TPckgBuf may be smaller or larger than the
+		// TCameraConfigV02 structure
+		TCameraConfigV02 config;
+		TPtr8 ptr((TUint8*) &config, sizeof(config));
+		Kern::InfoCopy(ptr, aConfigBuf);
+
+		// Save the new configuration for later and let the sensor also know about it
+		iConfig = config;
+		iSensor->SetConfig(config);
+
+		// Signal success and set the channel to the configured state
+		r = KErrNone;
+		iState = EConfigured;
+		}
+	else
+		{
+		r = KErrInUse;
+		}
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPdd::SetConfig() => Returning %d", r));
+
+	return r;
+	}
+
+/**
+Begins capture into the address pointed to by aLinAddr and aPhysAddr.  Both of these addresses point to
+the same buffer;  The address used by the sensor is hardware dependent.
+@param	aCaptureMode	Whether to capture in video, viewfinder or single image mode.
+@param	aLinAddr		The virtual address of the buffer into which to capture the image.
+@param	aPhysAddr		The physical address of the buffer into which to capture the image.
+@return	KErrNone if successful, otherwise one of the other system wide error codes.
+@pre	SetConfig() must first have been called.
+*/
+TInt DTemplateCameraScPdd::Start(TDevCamCaptureMode aCaptureMode, TLinAddr aLinAddr, TPhysAddr aPhysAddr)
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPdd::Start() => Configuring sensor for %d x %d capture", iConfig.iFrameSize.iWidth, iConfig.iFrameSize.iHeight));
+
+	// Ensure the precondition is met
+	__ASSERT_DEBUG((iState == EConfigured), Kern::Fault("camerasc", ENotConfigured));
+
+	// Save the capture mode for use when we call back into the LDD with the captured image
+	iCaptureMode = aCaptureMode;
+
+	// And start the sensor running
+	TInt r = iSensor->Start(aCaptureMode, aLinAddr, aPhysAddr);
+
+	// If everything was ok, set the channel to the capturing state
+	if (r == KErrNone)
+		{
+		iState = ECapturing;
+		}
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPdd::Start() => Returning %d", r));
+
+	return r;
+	}
+
+/**
+Sets the address of the buffer info which the next image will be captured.  Called by the LDD for successive
+images that are requested after the initial call to Start().
+@param	aLinAddr		The virtual address of the buffer into which to capture the image.
+@param	aPhysAddr		The physical address of the buffer into which to capture the image.
+@return	KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateCameraScPdd::CaptureNextImage(TLinAddr aLinAddr, TPhysAddr aPhysAddr)
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPdd::CaptureNextImage()"));
+
+	// Pass the call directly to the sensor abstraction
+	TInt r = iSensor->CaptureNextImage(aLinAddr, aPhysAddr);
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPdd::CaptureNextImage()=> Returning %d", r));
+
+	return(r);
+	}
+
+/**
+Stops any image capturing that is currently underway.  It is safe to call this without having called Start().
+@return	KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DTemplateCameraScPdd::Stop()
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPdd::Stop()"));
+
+	// Pass the call directly to the sensor abstraction
+	iSensor->Stop();
+
+	// Det the channel back to the configured state as it is now safe to call Start() again
+	iState = EConfigured;
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPdd::Stop()"));
+
+	return KErrNone;
+	}
+
+/**
+Power down the camera device.  This is called by the LDD when the driver channel is being closed or
+when the system is being powered down.  This is always called in the context of the DFC thread.
+*/
+void DTemplateCameraScPdd::PowerDown()
+	{
+
+#ifdef _DEBUG
+
+	// Power off the camera
+	TInt r = iSensor->RelinquishPower();
+
+	// Not being able to power down indicates a serious programming error
+	__ASSERT_DEBUG((r == KErrNone), Kern::Fault("camerasc", ECannotPowerDown));
+
+#else // ! _DEBUG
+
+	// Power off the camera
+	iSensor->RelinquishPower();
+
+#endif // ! _DEBUG
+
+	}
+
+/**
+Return the shared chunk creation information to be used by this device.
+@param	aChunkCreateInfo	A structure to be filled with the settings required for this device.
+*/
+void DTemplateCameraScPdd::GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo)
+	{
+	// Can be opened by any number of user side processes
+	aChunkCreateInfo.iType = TChunkCreateInfo::ESharedKernelMultiple;
+	// Use both L1 and L2 cache if available.  LDD will take care of pre and post DMA cache handling
+#ifdef __WINS__
+	aChunkCreateInfo.iMapAttr = 0xFF000;
+#else
+	aChunkCreateInfo.iMapAttr = EMapAttrCachedMax;
+#endif
+	// Chunk owns the memory which will be freed when the chunk is destroyed
+	aChunkCreateInfo.iOwnsMemory = ETrue;
+	// Don't queue the chunk's destruction on an DFC
+	aChunkCreateInfo.iDestroyedDfc = NULL;
+	}
+
+/**
+Returns the size of the variable sized capabilities structure in bytes.  The buffer passed into
+DTemplateCameraScPdd::GetCaps() must be at least this large to hold the fixed portion of the TCameraCapsV02
+structure, as well as the array of SDevCamPixelFormat structures that follows it.
+@return	The size in bytes of the variable sized capabilities structure.
+*/
+TInt DTemplateCameraScPdd::CapsSize()
+	{
+	return iCapsSize;
+	}
+
+/**
+Obtains information regarding the frame sizes and frame rates supported for a given combination of capture mode
+and pixel format.
+@param	aCaptureMode		The capture mode for which to obtain the information.
+@param	aUidPixelFormat		The pixel format for which to obtain the information.
+@param	aFrameSizeCapsBuf	A reference to an array of packaged SDevCamFrameSize structures, owned by the LDD, into
+							which to place the information.
+@@return	KErrNone if successful, else one of the other system wide error codes.
+*/
+TInt DTemplateCameraScPdd::FrameSizeCaps(TDevCamCaptureMode aCaptureMode, TUidPixelFormat aUidPixelFormat, TDes8& aFrameSizeCapsBuf)
+	{
+	return iSensor->FrameSizeCaps(aCaptureMode, aUidPixelFormat, aFrameSizeCapsBuf);
+	}
+
+/**
+Called by the sensor abstraction when an image is available.
+@param	aResult	KErrNone if successful, otherwise one of the system wide error codes.
+@param	aLinAddr		The virtual address of the buffer into which to capture the image.
+@param	aPhysAddr		The physical address of the buffer into which to capture the image.
+*/
+TInt DTemplateCameraScPdd::NotifyImageCaptureEvent(TInt aResult, TLinAddr& aLinAddr, TPhysAddr& aPhysAddr)
+	{
+	__KTRACE_CAM(Kern::Printf("> DTemplateCameraScPdd::NotifyImageCaptureEvent() => aResult = %d", aResult));
+
+	// Inform the LDD that a new image has been received
+	TInt r = iLdd->ImageCaptureCallback(iCaptureMode, aResult, &aLinAddr, &aPhysAddr);
+
+	// If the LDD has returned KErrAbort then something has gone wrong, and if it has returned KErrNotReady
+	// then it has no more frames available, so call Stop()
+	if (r != KErrNone)
+		{
+		Stop();
+		}
+
+	__KTRACE_CAM(Kern::Printf("< DTemplateCameraScPdd::NotifyImageCaptureEvent() => Returning %d", r));
+
+	return r;
+	}
+
+TInt DTemplateCameraScPdd::SetBrightness(TUint /*aBrightness*/)
+	{
+	return KErrNone;
+	}
+
+TInt DTemplateCameraScPdd::SetContrast(TUint /*aContrast*/)
+	{
+	return KErrNone;
+	}
+
+TInt DTemplateCameraScPdd::SetColorEffect(TUint /*aColorEffect*/)
+	{
+	return KErrNone;
+	}
+