os/kernelhwsrv/bsptemplate/asspandvariant/template_variant/camerasc/camerasc_sensor.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/bsptemplate/asspandvariant/template_variant/camerasc/camerasc_sensor.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,552 @@
     1.4 +// Copyright (c) 2006-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 +// template\template_variant\camerasc\camerasc_sensor.cpp
    1.18 +// Implementation of the template shared chunk camera physical device driver (PDD).
    1.19 +// This file is part of the Template Base port
    1.20 +// 
    1.21 +//
    1.22 +
    1.23 +/**
    1.24 + @file
    1.25 +*/
    1.26 +
    1.27 +#include "camerasc_plat.h"
    1.28 +#include <kernel/cache.h>
    1.29 +
    1.30 +// XXX - Temporary structure containing a logo to be displayed.  Remove this when
    1.31 +//       changing this template into a "real" camera driver
    1.32 +#include "logoyuv2.cpp"
    1.33 +
    1.34 +
    1.35 +#define RGBtoBGR565(red, green, blue) (((blue & 0xf8) << 8) | ((green & 0xfc) << 3) | ((red & 0xf8) >> 3));
    1.36 +
    1.37 +#define YUVtoYUV565(luma, blueC, redC) (((luma & 0xf8) << 8) | ((blueC & 0xfc) << 3) | ((redC & 0xf8) >> 3));
    1.38 +
    1.39 +// Frame sizes and their associated frame rates supported by the Template sensor.  This selection was
    1.40 +// obtained by observation of typical formats supported by phones already on the market;  It is arbitrary
    1.41 +// and can be easily added to if desired
    1.42 +static const SDevCamFrameSize FrameSizes[] =
    1.43 +	{
    1.44 +		{ 320, 240, 1, 30 }	,		// QVGA - 0.075 MP
    1.45 +		// XXX: Although not used in this template driver, the following are suggested standard frame sizes
    1.46 +		// that should be implemented in your camera driver, as well as 320 x 240 above.  Remember to change
    1.47 +		// KNumFrameSizes below if you change the number of sizes defined in here!
    1.48 +		{ 640, 480, 1, 30 },		// VGA - 0.3 MP
    1.49 +		{ 800, 600, 1, 30 },		// SVGA - 0.5 MP
    1.50 +		{ 1024, 768, 1, 30 },		// XGA - 0.8 MP
    1.51 +		{ 2048, 1536, 1, 15 },	// QXGA - 3 MP
    1.52 +		//{ 2560, 1600, 1, 30 }		// WQXGA - 4.1 MP
    1.53 +	};
    1.54 +
    1.55 +// This constant must be updated if the number of frame sizes listed above changes
    1.56 +static const TInt KNumFrameSizes = sizeof(FrameSizes) / sizeof(SDevCamFrameSize);
    1.57 +
    1.58 +// Pixel formats supported by the three different capture modes.  These are mapped onto the appropriate
    1.59 +// array of supported frame rates by the FrameSizeCaps() function
    1.60 +static const SDevCamPixelFormat PixelFormats[] =
    1.61 +	{
    1.62 +		// Image pixel formats
    1.63 +		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 },
    1.64 +		
    1.65 +		// Video pixel formats
    1.66 +		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 },
    1.67 +
    1.68 +		// View finder pixel formats
    1.69 +		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 }
    1.70 +
    1.71 +	};
    1.72 +
    1.73 +// These constants must be updated if the number of pixel formats listed above changes
    1.74 +static const TInt KNumImagePixelFormats = 1;
    1.75 +static const TInt KNumVideoPixelFormats = 1;
    1.76 +static const TInt KNumViewFinderPixelFormats = 1;
    1.77 +
    1.78 +// Alternate logo images after this many frames
    1.79 +static const TInt KAlternateLogoFrameInterval = 5;
    1.80 +
    1.81 +static void ImageTimerCallback(TAny* aSensorIf)
    1.82 +	{
    1.83 +	DTemplateSensorIf* sensor = (DTemplateSensorIf*) aSensorIf;
    1.84 +
    1.85 +	// XXX - Call the buffer done function in the sensor class.  In this case we are just emulating the
    1.86 +	// interrupt and DFC callback that would happen when an image is captured, so we always pass in KErrNone.
    1.87 +	// In a real driver, we would read the hardware here to check that the capture happened successfully and
    1.88 +	// would pass in the appropriate error code
    1.89 +	sensor->BufferDoneCallback(KErrNone);
    1.90 +	}
    1.91 +
    1.92 +/**
    1.93 +Saves a configuration specifying such details as dimensions and pixel format in which the sensor should
    1.94 +capture images.
    1.95 +@param	aConfig	A TCameraConfigV02 structure containing the settings to be used.
    1.96 +@return	KErrNone if successful, otherwise one of the other system wide error codes.
    1.97 +*/
    1.98 +TInt DSensorIf::SetConfig(const TCameraConfigV02& aConfig)
    1.99 +	{
   1.100 +	// Manual settings for flash mode, focus, white balance etc. are not supported by the sensor,
   1.101 +	// so check for these and return KErrNotSupported if they have been requested
   1.102 +	if ((aConfig.iFlashMode != ECamFlashNone) ||
   1.103 +		(aConfig.iExposureMode != ECamExposureAuto) ||
   1.104 +		(aConfig.iZoom != 0) /*||
   1.105 +        (aConfig.iWhiteBalanceMode != ECamWBAuto) ||
   1.106 +		(aConfig.iContrast != ECamContrastAuto) ||
   1.107 +		(aConfig.iBrightness != ECamBrightnessAuto)*/)
   1.108 +		{
   1.109 +		// XXX: Remove this once support is addded for these modes
   1.110 +		return KErrNotSupported;
   1.111 +		}
   1.112 +
   1.113 +	// As well as saving the configuration, also save copies of the width and height for easy access,
   1.114 +	// as they are accessed frequently, as well as the offset in bytes between lines
   1.115 +	iConfig = aConfig;
   1.116 +	iWidth = aConfig.iFrameSize.iWidth;
   1.117 +	iHeight = aConfig.iFrameSize.iHeight;
   1.118 +	iLineOffset = (iWidth * iConfig.iPixelFormat.iPixelWidthInBytes);
   1.119 +
   1.120 +	return KErrNone;
   1.121 +	}
   1.122 +
   1.123 +/**
   1.124 +Constructor for the Template sensor class.
   1.125 +*/
   1.126 +
   1.127 +DTemplateSensorIf::DTemplateSensorIf(MSensorObserver& aObserver, TDfcQue* aDFCQueue)
   1.128 +	: iDFCQueue(aDFCQueue)
   1.129 +	{
   1.130 +	iObserver = &aObserver;
   1.131 +	iXDirection = iYDirection = 1;
   1.132 +	
   1.133 +	iCounter = 0;
   1.134 +	iFlipSwitch = EFalse;
   1.135 +	}
   1.136 +
   1.137 +/**
   1.138 +Second stage constructor for the Template sensor class.
   1.139 +
   1.140 +@return KErrNone if successful, otherwise one of the other system wide error codes.
   1.141 +*/
   1.142 +TInt DTemplateSensorIf::DoCreate()
   1.143 +	{
   1.144 +	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::DoCreate()"));
   1.145 +
   1.146 +	TInt r = KErrNone;
   1.147 +
   1.148 +	for (TInt index = 0; index < KTotalCameraRequests; ++index)
   1.149 +		{
   1.150 +		if ((iImageTimerDFCs[index] = new TDfc(ImageTimerCallback, this, iDFCQueue, 0)) == NULL)
   1.151 +			{
   1.152 +			r = KErrNoMemory;
   1.153 +
   1.154 +			break;
   1.155 +			}
   1.156 +		}
   1.157 +
   1.158 +	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::DoCreate() => Returning %d", r));
   1.159 +
   1.160 +	return r;
   1.161 +	}
   1.162 +
   1.163 +/**
   1.164 +Destructor for the Template sensor class.
   1.165 +*/
   1.166 +DTemplateSensorIf::~DTemplateSensorIf()
   1.167 +	{
   1.168 +	for (TInt index = 0; index < KTotalCameraRequests; ++index)
   1.169 +		{
   1.170 +		iImageTimers[index].Cancel();
   1.171 +		delete iImageTimerDFCs[index];
   1.172 +		}
   1.173 +	}
   1.174 +
   1.175 +/**
   1.176 +Called by the underlying sensor class when an image has been captured.
   1.177 +@param aResult	KErrNone if the image was captured successfully, otherwise one of
   1.178 +				the other system wide error codes.
   1.179 +@return KErrNone if successful, otherwise one of the other system wide error codes.
   1.180 +*/
   1.181 +TInt DTemplateSensorIf::BufferDoneCallback(TInt aResult)
   1.182 +	{
   1.183 +	TInt r = KErrNone;
   1.184 +
   1.185 +	NKern::LockedDec(iPendingRequests);
   1.186 +
   1.187 +	TLinAddr linAddr;
   1.188 +	TPhysAddr physAddr;
   1.189 +
   1.190 +	// Call the LDD to let it know that an image capture has completed.  If the LDD needs more images
   1.191 +	// to be captured, then it will return KErrNone and the virtual and physical addresses of the
   1.192 +	// next buffer to be filled will be returned in linAddr and physAddr respectively.  Note that as
   1.193 +	// will as starting a capture of an image in here, the LDD may also call CaptureNextImage() to start
   1.194 +	// capture as well
   1.195 +	r = iObserver->NotifyImageCaptureEvent(aResult, linAddr, physAddr);
   1.196 +
   1.197 +	if (r == KErrNone)
   1.198 +		{
   1.199 +		iNextRequest = ((iNextRequest + 1) % KTotalCameraRequests);
   1.200 +		NKern::LockedInc(iPendingRequests);
   1.201 +
   1.202 +		// XXX: Temporary code to be removed in a real driver.  Fill the buffer for testing
   1.203 +		//      with user side code
   1.204 +		FillBuffer(linAddr);
   1.205 +
   1.206 +		// XXX: Send buffer to sensor.  Normally the address of the buffer passed in in aLinAddr and
   1.207 +		//      aPhysAddr would be programmed into the sensor and/or bus hardware here and an interrupt
   1.208 +		//      would be generated when the iamge had been captured into the buffer.  In this simulated
   1.209 +		//      driver we will use a nanokernel timer to simulate this process
   1.210 +		iImageTimers[iNextRequest].OneShot(iImageTimerTicks, *iImageTimerDFCs[iNextRequest]);
   1.211 +		}
   1.212 +
   1.213 +	return r;
   1.214 +	}
   1.215 +
   1.216 +/**
   1.217 +Fills a buffer with a white background with a moving logo on top.
   1.218 +@param aBuffer	Pointer to the buffer to be filled.
   1.219 +*/
   1.220 +void DTemplateSensorIf::FillBuffer(TLinAddr aBuffer)
   1.221 +	{
   1.222 +	const TUint8* LogoData = Logo.iPixelData;
   1.223 +	const TUint8* LogoData2 = Logo.iPixelData2;
   1.224 +	TInt index = 0;
   1.225 +	TInt numPixels = (iConfig.iFrameSize.iWidth * iConfig.iFrameSize.iHeight);
   1.226 +	TUint yC, uC, vC;
   1.227 +	TUint16* buffer = (TUint16*) aBuffer;
   1.228 +
   1.229 +    // Alternate between the two logos for cheesy animation effect
   1.230 +    if( ++iCounter == KAlternateLogoFrameInterval )
   1.231 +         {
   1.232 +         iFlipSwitch ^= 1;
   1.233 +         iCounter = 0;
   1.234 +         }
   1.235 +	
   1.236 +	
   1.237 +	// Set the "photo" background to be all white
   1.238 +	memset(buffer, 0xff, (numPixels * 2));
   1.239 +
   1.240 +	// Point to the correct location in the buffer at which to render the logo
   1.241 +	buffer += ((iY * iConfig.iFrameSize.iWidth) + iX);
   1.242 +
   1.243 +	// Iterate through the data for the logo and copy it into the "photo"
   1.244 +	for (TUint y = 0; y < Logo.iHeight; ++y)
   1.245 +		{
   1.246 +		for (TUint x = 0; x < Logo.iWidth; ++x)
   1.247 +			{
   1.248 +			// The logo is in 24 bit BGR format so read each pixel and convert it to 16 bit BGR565
   1.249 +			// before writing it into the "photo" buffer
   1.250 +			if( iFlipSwitch )
   1.251 +			    {
   1.252 +                yC = LogoData[index];
   1.253 +                uC = LogoData[index + 1];
   1.254 +                vC = LogoData[index + 2];
   1.255 +			    }
   1.256 +			else
   1.257 +                {
   1.258 +                yC = LogoData2[index];
   1.259 +                uC = LogoData2[index + 1];
   1.260 +                vC = LogoData2[index + 2];
   1.261 +                }
   1.262 +
   1.263 +			*buffer++ = YUVtoYUV565(yC, uC, vC);
   1.264 +			// Point to the next source pixel
   1.265 +			index += 3;
   1.266 +			}
   1.267 +
   1.268 +			// Point to the start of the next line in the buffer, taking into account that the logo
   1.269 +			// is narrower than the buffer
   1.270 +			buffer += (iConfig.iFrameSize.iWidth - Logo.iWidth);
   1.271 +		}
   1.272 +
   1.273 +	// Bounce the logo around in the X direction.  This will take effect the next time this is called
   1.274 +	iX += iXDirection;
   1.275 +
   1.276 +	if (iX <= 0)
   1.277 +		{
   1.278 +		iX = 0;
   1.279 +		iXDirection = -iXDirection;
   1.280 +		}
   1.281 +	else if (iX >= (TInt) (iConfig.iFrameSize.iWidth - Logo.iWidth))
   1.282 +		{
   1.283 +		iX = (iConfig.iFrameSize.iWidth - Logo.iWidth);
   1.284 +		iXDirection = -iXDirection;
   1.285 +		}
   1.286 +
   1.287 +	// Bounce the logo around in the Y direction.  This will take effect the next time this is called
   1.288 +	iY += iYDirection;
   1.289 +
   1.290 +	if (iY <= 0)
   1.291 +		{
   1.292 +		iY = 0;
   1.293 +		iYDirection = -iYDirection;
   1.294 +		}
   1.295 +	else if (iY >= (TInt) (iConfig.iFrameSize.iHeight - Logo.iHeight))
   1.296 +		{
   1.297 +		iY = (iConfig.iFrameSize.iHeight - Logo.iHeight);
   1.298 +		iYDirection = -iYDirection;
   1.299 +		}
   1.300 +
   1.301 +	// Now flush the cache to memory, taking into account the size of each pixel.  This is not normally
   1.302 +	// necessary but given that we are emulating a camera driver in software we must ensure that the
   1.303 +	// cache is flushed to memory.  This is because in a real driver the buffer will have been filled
   1.304 +	// by DMA so upon return to the LDD, the LDD will discard the contents of the cache to ensure the
   1.305 +	// DMA-written data is ok.  In the case of filling the buffer using the CPU in this virtual camera
   1.306 +	// driver, that would result in the data being discarded!
   1.307 +	Cache::SyncMemoryBeforeDmaWrite((TLinAddr) aBuffer, (numPixels * iConfig.iPixelFormat.iPixelWidthInBytes));
   1.308 +	}
   1.309 +
   1.310 +/**
   1.311 +Based on the capture mode and pixel format passed in, copies an array of supported SFrameSize
   1.312 +structures into a buffer supplied by the LDD.  These frame sizes and their associated frame rates
   1.313 +will reflect the capabilities of the given capture mode and pixel format.
   1.314 +@param aCaptureMode			The capture mode for which to obtain the supported frame sizes.
   1.315 +@param aUidPixelFormat		The UID of the pixel format (as defined in \epoc32\include\pixelformats.h)
   1.316 +							for which to obtain the supported frame sizes.
   1.317 +@param aFrameSizeCapsBuf	A reference to a descriptor that contains a buffer into which to place
   1.318 +							the frame size structures.  It is up to the LDD to ensure that this is
   1.319 +							large enough to hold all of the frame sizes.
   1.320 +@return Always KErrNone.
   1.321 +*/
   1.322 +TInt DTemplateSensorIf::FrameSizeCaps(TDevCamCaptureMode /*aCaptureMode*/, TUidPixelFormat /*aUidPixelFormat*/, TDes8& aFrameSizeCapsBuf)
   1.323 +	{
   1.324 +	TPtrC8 sourceFrameSizes((const TUint8*) FrameSizes, sizeof(FrameSizes));
   1.325 +
   1.326 +	// Ensure the buffer passed in from the LDD is large enough and copy the requested frame sizes
   1.327 +	if (aFrameSizeCapsBuf.Size() < sourceFrameSizes.Size())
   1.328 +		{
   1.329 +		Kern::Printf("*** ECapsBufferTooSmall: %d vs %d",
   1.330 +				aFrameSizeCapsBuf.Size(),
   1.331 +				sourceFrameSizes.Size());
   1.332 +		Kern::Fault("camerasc", ECapsBufferTooSmall);
   1.333 +		}
   1.334 +	
   1.335 +	//__ASSERT_DEBUG((aFrameSizeCapsBuf.Size() >= sourceFrameSizes.Size()), Kern::Fault("camerasc", ECapsBufferTooSmall));
   1.336 +	aFrameSizeCapsBuf = sourceFrameSizes;
   1.337 +
   1.338 +	return KErrNone;
   1.339 +	}
   1.340 +
   1.341 +/**
   1.342 +Allocates a buffer large enough to hold the TCameraCapsV02 structure and its succeeding array of
   1.343 +pixel formats, and populates the structure and array with information about the capabilities of
   1.344 +the sensor.
   1.345 +@param aCameraCaps	Reference to a pointer into which to place the pointer to allocated buffer
   1.346 +@return	Size of the capabilities structure if successful, otherwise one of the other system wide
   1.347 +		error codes.
   1.348 +*/
   1.349 +TInt DTemplateSensorIf::GetCaps(TCameraCapsV02*& aCameraCaps)
   1.350 +	{
   1.351 +	// Allocate a buffer large enough to hold the TCameraCapsV02 structure and the array of pixel formats
   1.352 +	// that will follow it
   1.353 +	TInt r = (sizeof(TCameraCapsV02) + sizeof(PixelFormats));
   1.354 +	TUint8* capsBuffer = new TUint8[r];
   1.355 +
   1.356 +	if (capsBuffer)
   1.357 +		{
   1.358 +		aCameraCaps = (TCameraCapsV02*) capsBuffer;
   1.359 +
   1.360 +		// No special modes are supported at the moment
   1.361 +		aCameraCaps->iFlashModes = ECamFlashNone;
   1.362 +		aCameraCaps->iExposureModes = ECamExposureAuto; // or None?
   1.363 +		// do we still need whitebalance mode filed?
   1.364 +		aCameraCaps->iWhiteBalanceModes = ECamWBAuto | ECamWBDaylight | ECamWBCloudy | ECamWBTungsten | ECamWBFluorescent | ECamWBFlash | ECamWBSnow | ECamWBBeach;
   1.365 +		aCameraCaps->iMinZoom = 0;
   1.366 +		aCameraCaps->iMaxZoom = 0;
   1.367 +		aCameraCaps->iCapsMisc = KCamMiscContrast | KCamMiscBrightness | KCamMiscColorEffect;
   1.368 +
   1.369 +		// There isn't really such thing as inwards or outwards orientation on an SDP, but we'll pretend it's
   1.370 +		// an outwards facing camera
   1.371 +		aCameraCaps->iOrientation = ECamOrientationOutwards;
   1.372 +
   1.373 +		// Initialise the number of different pixel formats supported
   1.374 +		aCameraCaps->iNumImagePixelFormats = KNumImagePixelFormats;
   1.375 +		aCameraCaps->iNumVideoPixelFormats = KNumVideoPixelFormats;
   1.376 +		aCameraCaps->iNumViewFinderPixelFormats = KNumViewFinderPixelFormats;
   1.377 +
   1.378 +		for (TInt i = 0; i < ECamAttributeMax; i++)
   1.379 +		    {
   1.380 +		    if (ECamAttributeColorEffect == (TDevCamDynamicAttribute)(i))
   1.381 +		        {
   1.382 +		        // WhiteBalance
   1.383 +		        // In case of white balance, we shouldn't use MIN and MAX values as some of them in between MIN and MAX can be missed out.
   1.384 +		        // As this is fake driver, There doesn't seem to be any major issue though.
   1.385 +		        aCameraCaps->iDynamicRange[i].iMin = ECamWBAuto;
   1.386 +		        aCameraCaps->iDynamicRange[i].iMax = ECamWBBeach;
   1.387 +		        aCameraCaps->iDynamicRange[i].iDefault = ECamWBAuto;
   1.388 +		        }
   1.389 +		    else
   1.390 +		        {    
   1.391 +		        // TBC :: Contrast, Brightness
   1.392 +		        aCameraCaps->iDynamicRange[i].iMin = 0;
   1.393 +		        aCameraCaps->iDynamicRange[i].iMax = 6;
   1.394 +		        aCameraCaps->iDynamicRange[i].iDefault = 3;
   1.395 +		        }
   1.396 +		    }
   1.397 +
   1.398 +		// Setup some descriptors pointing to the pixel format array and the array passed in by the LDD
   1.399 +		// (located at the end of the TCameraCapsV02 structure) and copy the pixel format array
   1.400 +		TPtrC8 sourcePixelFormats((const TUint8*) PixelFormats, sizeof(PixelFormats));
   1.401 +		TPtr8 destPixelFormats((capsBuffer + sizeof(TCameraCapsV02)), sizeof(PixelFormats), sizeof(PixelFormats));
   1.402 +		destPixelFormats = sourcePixelFormats;
   1.403 +		}
   1.404 +	else
   1.405 +		{
   1.406 +		r = KErrNoMemory;
   1.407 +		}
   1.408 +
   1.409 +	return r;
   1.410 +	}
   1.411 +
   1.412 +/**
   1.413 +Powers up the sensor hardware.
   1.414 +@return KErrNone if successful, otherwise one of the other system wide error codes.
   1.415 +*/
   1.416 +TInt DTemplateSensorIf::RequestPower()
   1.417 +	{
   1.418 +	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::RequestPower()"));
   1.419 +
   1.420 +	TInt r = KErrNone;
   1.421 +
   1.422 +	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::RequestPower() => Returning %d", r));
   1.423 +
   1.424 +	return r;
   1.425 +	}
   1.426 +
   1.427 +/**
   1.428 +Powers down the sensor hardware.
   1.429 +@return KErrNone if successful, otherwise one of the other system wide error codes.
   1.430 +*/
   1.431 +TInt DTemplateSensorIf::RelinquishPower()
   1.432 +	{
   1.433 +	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::RelinquishPower()"));
   1.434 +
   1.435 +	TInt r = KErrNone;
   1.436 +
   1.437 +	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::RelinquishPower() => Returning %d", r));
   1.438 +
   1.439 +	return r;
   1.440 +	}
   1.441 +
   1.442 +/**
   1.443 +Begins capture of the next image into the buffer provided.  This function assumes that
   1.444 +Start() has already been called to start capture.  However, Stop() may also have been
   1.445 +subsequently called (for example to pause capture) and in this case, this function will
   1.446 +handle restarting the sensor.
   1.447 +@param aLinAddr		A virtual pointer to the buffer into which to capture the image.
   1.448 +@param aPhysAddr	A physical pointer to the buffer into which to capture the image.
   1.449 +					This points to the same memory as aLinAddr.
   1.450 +@return KErrNone if successful.
   1.451 +		KErrNotReady if there are no free requests to capture the image.
   1.452 +		Otherwise one of the other system wide error codes.
   1.453 +*/
   1.454 +TInt DTemplateSensorIf::CaptureNextImage(TLinAddr aLinAddr, TPhysAddr /*aPhysAddr*/)
   1.455 +	{
   1.456 +	TInt r = KErrNone;
   1.457 +
   1.458 +	// Only start capturing the next image if there are any pending request slots available
   1.459 +	if (iPendingRequests < KTotalCameraRequests)
   1.460 +		{
   1.461 +		// Queue a transfer on the next available channel and indicate that the channel is
   1.462 +		// in use
   1.463 +		iNextRequest = ((iNextRequest + 1) % KTotalCameraRequests);
   1.464 +		NKern::LockedInc(iPendingRequests);
   1.465 +
   1.466 +		// XXX: Temporary code to be removed in a real driver.  Fill the buffer for testing
   1.467 +		//      with user side code.  This is to simulate an image being captured into the buffer that
   1.468 +		//      has been passed in in aLinAddr.  As well as aLinAddr, which points to the virtual
   1.469 +		//      address of the buffer, the LDD will pass in the physical address as well, in aPhysAddr.
   1.470 +		//      Depending on the underlying sensor hardware and/or bus in use, you will have to choose
   1.471 +		//      which of these to use
   1.472 +		FillBuffer(aLinAddr);
   1.473 +
   1.474 +		// XXX: Send buffer to sensor.  Normally the address of the buffer passed in in aLinAddr and
   1.475 +		//      aPhysAddr would be programmed into the sensor and/or bus hardware here and an interrupt
   1.476 +		//      would be generated when the iamge had been captured into the buffer.  In this simulated
   1.477 +		//      driver we will use a nanokernel timer to simulate this process
   1.478 +		iImageTimers[iNextRequest].OneShot(iImageTimerTicks, *iImageTimerDFCs[iNextRequest]);
   1.479 +
   1.480 +		// If capturing has not yet started or has been paused by Stop(), start it
   1.481 +		if (!(iEnabled))
   1.482 +			{
   1.483 +			iEnabled = ETrue;
   1.484 +			}
   1.485 +		}
   1.486 +	else
   1.487 +		{
   1.488 +		r = KErrNotReady;
   1.489 +		}
   1.490 +
   1.491 +	return r;
   1.492 +	}
   1.493 +
   1.494 +/**
   1.495 +Begins capture of the first image into the buffer provided.  This function is similar to
   1.496 +CaptureNextImage(), except that it will perform any extra sensor intitialisation required
   1.497 +to start capture.
   1.498 +@param aCaptureMode	The capture mode for which to start capturing.
   1.499 +@param aLinAddr		A virtual pointer to the buffer into which to capture the image.
   1.500 +@param aPhysAddr	A physical pointer to the buffer into which to capture the image.
   1.501 +					This points to the same memory as aLinAddr.
   1.502 +@return KErrNone if successful
   1.503 +		KErrInUse if capture is already under way.
   1.504 +		KErrNotSupported if the frame size and/or frame rate are out of range.
   1.505 +		Otherwise one of the other system wide error codes.
   1.506 +*/
   1.507 +TInt DTemplateSensorIf::Start(TDevCamCaptureMode /*aCaptureMode*/, TLinAddr aLinAddr, TPhysAddr aPhysAddr)
   1.508 +	{
   1.509 +	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::Start()"));
   1.510 +
   1.511 +	TInt r = KErrNone;
   1.512 +
   1.513 +	// XXX - In a real camera driver, in here we would initialise start the capturing process in here.
   1.514 +	//       When an image is captured, the sensor hardware (or maybe the CSI bus) will generate an
   1.515 +	//       which will then be enqueued into the DFC queue that was passed into the constructor of
   1.516 +	//       the sensor class.  It is important to do the DFC processing in this DFC queue rather than
   1.517 +	//       a separate one because it ensures that fucntions in the PDD and LDD are called in a serialised
   1.518 +	//       manner, without the need for mutexts.  In this example camera driver we will convert the
   1.519 +	//       framerate into a nanokernel tick count and will use an NTimer.OneShot() call to simulate
   1.520 +	//       the sensor interrupt and DFC callback.  Divides are slow so we'll calculate the tick count
   1.521 +	//       here and will save it for later use
   1.522 +	iImageTimerTicks = ((1000000 / NKern::TickPeriod()) / iConfig.iFrameRate);
   1.523 +
   1.524 +	// XXX - Once the one off hardware initialisation has been done for starting a new capture, then
   1.525 +	//       subsequent captures can usually reuse the same code in CaptureNextImage() for starting
   1.526 +	//       the next capture
   1.527 +	r = CaptureNextImage(aLinAddr, aPhysAddr);
   1.528 +
   1.529 +	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::Start() => Returning %d", r));
   1.530 +
   1.531 +	return r;
   1.532 +	}
   1.533 +
   1.534 +/**
   1.535 +Stops capturing any image capture that is currently in progress.  This function will act
   1.536 +more like a Pause() than a Stop() capturing can be restarted from where it was stopped.
   1.537 +*/
   1.538 +TInt DTemplateSensorIf::Stop()
   1.539 +	{
   1.540 +	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::Stop()"));
   1.541 +
   1.542 +	iEnabled = EFalse;
   1.543 +	iPendingRequests = iNextRequest = 0;
   1.544 +
   1.545 +	// XXX - Cancel all of our pending image timer callbacks.  In a real driver we would write to the
   1.546 +	//       sensor and/or bus hardware here to cause them to cancel any pending image captures
   1.547 +	for (TInt index = 0; index < KTotalCameraRequests; ++index)
   1.548 +		{
   1.549 +		iImageTimers[index].Cancel();
   1.550 +		}
   1.551 +
   1.552 +	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::Stop()"));
   1.553 +
   1.554 +	return KErrNone;
   1.555 +	}