diff -r 000000000000 -r a41df078684a bsptemplate/asspandvariant/template_variant/camerasc/camerasc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bsptemplate/asspandvariant/template_variant/camerasc/camerasc.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,532 @@ +// 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 + aChunkCreateInfo.iMapAttr = EMapAttrCachedMax; + // 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 aValue) + { + return KErrNotSupported; + } + +TInt DTemplateCameraScPdd::SetContrast(TUint aValue) + { + return KErrNotSupported; + } + +TInt DTemplateCameraScPdd::SetColorEffect(TUint aValue) + { + return KErrNotSupported; + }