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