bsptemplate/asspandvariant/template_variant/camerasc/camerasc_sensor.cpp
branchRCL_3
changeset 257 3e88ff8f41d5
child 258 880ff05ad710
equal deleted inserted replaced
256:c1f20ce4abcf 257:3e88ff8f41d5
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // template\template_variant\camerasc\camerasc_sensor.cpp
       
    15 // Implementation of the template shared chunk camera physical device driver (PDD).
       
    16 // This file is part of the Template Base port
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file
       
    22 */
       
    23 
       
    24 #include "camerasc_plat.h"
       
    25 #include <kernel/cache.h>
       
    26 
       
    27 // XXX - Temporary structure containing a logo to be displayed.  Remove this when
       
    28 //       changing this template into a "real" camera driver
       
    29 #include "logoyuv2.cpp"
       
    30 
       
    31 
       
    32 #define RGBtoBGR565(red, green, blue) (((blue & 0xf8) << 8) | ((green & 0xfc) << 3) | ((red & 0xf8) >> 3));
       
    33 
       
    34 #define YUVtoYUV565(luma, blueC, redC) (((luma & 0xf8) << 8) | ((blueC & 0xfc) << 3) | ((redC & 0xf8) >> 3));
       
    35 
       
    36 // Frame sizes and their associated frame rates supported by the Template sensor.  This selection was
       
    37 // obtained by observation of typical formats supported by phones already on the market;  It is arbitrary
       
    38 // and can be easily added to if desired
       
    39 static const SDevCamFrameSize FrameSizes[] =
       
    40 	{
       
    41 		{ 320, 240, 1, 30 }	,		// QVGA - 0.075 MP
       
    42 		// XXX: Although not used in this template driver, the following are suggested standard frame sizes
       
    43 		// that should be implemented in your camera driver, as well as 320 x 240 above.  Remember to change
       
    44 		// KNumFrameSizes below if you change the number of sizes defined in here!
       
    45 		{ 640, 480, 1, 30 },		// VGA - 0.3 MP
       
    46 		{ 800, 600, 1, 30 },		// SVGA - 0.5 MP
       
    47 		{ 1024, 768, 1, 30 },		// XGA - 0.8 MP
       
    48 		{ 2048, 1536, 1, 15 },	// QXGA - 3 MP
       
    49 		//{ 2560, 1600, 1, 30 }		// WQXGA - 4.1 MP
       
    50 	};
       
    51 
       
    52 // This constant must be updated if the number of frame sizes listed above changes
       
    53 static const TInt KNumFrameSizes = sizeof(FrameSizes) / sizeof(SDevCamFrameSize);
       
    54 
       
    55 // Pixel formats supported by the three different capture modes.  These are mapped onto the appropriate
       
    56 // array of supported frame rates by the FrameSizeCaps() function
       
    57 static const SDevCamPixelFormat PixelFormats[] =
       
    58 	{
       
    59 		// Image pixel formats
       
    60 		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 },
       
    61 		
       
    62 		// Video pixel formats
       
    63 		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 },
       
    64 
       
    65 		// View finder pixel formats
       
    66 		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 }
       
    67 
       
    68 	};
       
    69 
       
    70 // These constants must be updated if the number of pixel formats listed above changes
       
    71 static const TInt KNumImagePixelFormats = 1;
       
    72 static const TInt KNumVideoPixelFormats = 1;
       
    73 static const TInt KNumViewFinderPixelFormats = 1;
       
    74 
       
    75 // Alternate logo images after this many frames
       
    76 static const TInt KAlternateLogoFrameInterval = 5;
       
    77 
       
    78 static void ImageTimerCallback(TAny* aSensorIf)
       
    79 	{
       
    80 	DTemplateSensorIf* sensor = (DTemplateSensorIf*) aSensorIf;
       
    81 
       
    82 	// XXX - Call the buffer done function in the sensor class.  In this case we are just emulating the
       
    83 	// interrupt and DFC callback that would happen when an image is captured, so we always pass in KErrNone.
       
    84 	// In a real driver, we would read the hardware here to check that the capture happened successfully and
       
    85 	// would pass in the appropriate error code
       
    86 	sensor->BufferDoneCallback(KErrNone);
       
    87 	}
       
    88 
       
    89 /**
       
    90 Saves a configuration specifying such details as dimensions and pixel format in which the sensor should
       
    91 capture images.
       
    92 @param	aConfig	A TCameraConfigV02 structure containing the settings to be used.
       
    93 @return	KErrNone if successful, otherwise one of the other system wide error codes.
       
    94 */
       
    95 TInt DSensorIf::SetConfig(const TCameraConfigV02& aConfig)
       
    96 	{
       
    97 	// Manual settings for flash mode, focus, white balance etc. are not supported by the sensor,
       
    98 	// so check for these and return KErrNotSupported if they have been requested
       
    99 	if ((aConfig.iFlashMode != ECamFlashNone) ||
       
   100 		(aConfig.iExposureMode != ECamExposureAuto) ||
       
   101 		(aConfig.iZoom != 0) /*||
       
   102         (aConfig.iWhiteBalanceMode != ECamWBAuto) ||
       
   103 		(aConfig.iContrast != ECamContrastAuto) ||
       
   104 		(aConfig.iBrightness != ECamBrightnessAuto)*/)
       
   105 		{
       
   106 		// XXX: Remove this once support is addded for these modes
       
   107 		return KErrNotSupported;
       
   108 		}
       
   109 
       
   110 	// As well as saving the configuration, also save copies of the width and height for easy access,
       
   111 	// as they are accessed frequently, as well as the offset in bytes between lines
       
   112 	iConfig = aConfig;
       
   113 	iWidth = aConfig.iFrameSize.iWidth;
       
   114 	iHeight = aConfig.iFrameSize.iHeight;
       
   115 	iLineOffset = (iWidth * iConfig.iPixelFormat.iPixelWidthInBytes);
       
   116 
       
   117 	return KErrNone;
       
   118 	}
       
   119 
       
   120 /**
       
   121 Constructor for the Template sensor class.
       
   122 */
       
   123 
       
   124 DTemplateSensorIf::DTemplateSensorIf(MSensorObserver& aObserver, TDfcQue* aDFCQueue)
       
   125 	: iDFCQueue(aDFCQueue)
       
   126 	{
       
   127 	iObserver = &aObserver;
       
   128 	iXDirection = iYDirection = 1;
       
   129 	
       
   130 	iCounter = 0;
       
   131 	iFlipSwitch = EFalse;
       
   132 	}
       
   133 
       
   134 /**
       
   135 Second stage constructor for the Template sensor class.
       
   136 
       
   137 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   138 */
       
   139 TInt DTemplateSensorIf::DoCreate()
       
   140 	{
       
   141 	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::DoCreate()"));
       
   142 
       
   143 	TInt r = KErrNone;
       
   144 
       
   145 	for (TInt index = 0; index < KTotalCameraRequests; ++index)
       
   146 		{
       
   147 		if ((iImageTimerDFCs[index] = new TDfc(ImageTimerCallback, this, iDFCQueue, 0)) == NULL)
       
   148 			{
       
   149 			r = KErrNoMemory;
       
   150 
       
   151 			break;
       
   152 			}
       
   153 		}
       
   154 
       
   155 	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::DoCreate() => Returning %d", r));
       
   156 
       
   157 	return r;
       
   158 	}
       
   159 
       
   160 /**
       
   161 Destructor for the Template sensor class.
       
   162 */
       
   163 DTemplateSensorIf::~DTemplateSensorIf()
       
   164 	{
       
   165 	for (TInt index = 0; index < KTotalCameraRequests; ++index)
       
   166 		{
       
   167 		iImageTimers[index].Cancel();
       
   168 		delete iImageTimerDFCs[index];
       
   169 		}
       
   170 	}
       
   171 
       
   172 /**
       
   173 Called by the underlying sensor class when an image has been captured.
       
   174 @param aResult	KErrNone if the image was captured successfully, otherwise one of
       
   175 				the other system wide error codes.
       
   176 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   177 */
       
   178 TInt DTemplateSensorIf::BufferDoneCallback(TInt aResult)
       
   179 	{
       
   180 	TInt r = KErrNone;
       
   181 
       
   182 	NKern::LockedDec(iPendingRequests);
       
   183 
       
   184 	TLinAddr linAddr;
       
   185 	TPhysAddr physAddr;
       
   186 
       
   187 	// Call the LDD to let it know that an image capture has completed.  If the LDD needs more images
       
   188 	// to be captured, then it will return KErrNone and the virtual and physical addresses of the
       
   189 	// next buffer to be filled will be returned in linAddr and physAddr respectively.  Note that as
       
   190 	// will as starting a capture of an image in here, the LDD may also call CaptureNextImage() to start
       
   191 	// capture as well
       
   192 	r = iObserver->NotifyImageCaptureEvent(aResult, linAddr, physAddr);
       
   193 
       
   194 	if (r == KErrNone)
       
   195 		{
       
   196 		iNextRequest = ((iNextRequest + 1) % KTotalCameraRequests);
       
   197 		NKern::LockedInc(iPendingRequests);
       
   198 
       
   199 		// XXX: Temporary code to be removed in a real driver.  Fill the buffer for testing
       
   200 		//      with user side code
       
   201 		FillBuffer(linAddr);
       
   202 
       
   203 		// XXX: Send buffer to sensor.  Normally the address of the buffer passed in in aLinAddr and
       
   204 		//      aPhysAddr would be programmed into the sensor and/or bus hardware here and an interrupt
       
   205 		//      would be generated when the iamge had been captured into the buffer.  In this simulated
       
   206 		//      driver we will use a nanokernel timer to simulate this process
       
   207 		iImageTimers[iNextRequest].OneShot(iImageTimerTicks, *iImageTimerDFCs[iNextRequest]);
       
   208 		}
       
   209 
       
   210 	return r;
       
   211 	}
       
   212 
       
   213 /**
       
   214 Fills a buffer with a white background with a moving logo on top.
       
   215 @param aBuffer	Pointer to the buffer to be filled.
       
   216 */
       
   217 void DTemplateSensorIf::FillBuffer(TLinAddr aBuffer)
       
   218 	{
       
   219 	const TUint8* LogoData = Logo.iPixelData;
       
   220 	const TUint8* LogoData2 = Logo.iPixelData2;
       
   221 	TInt index = 0;
       
   222 	TInt numPixels = (iConfig.iFrameSize.iWidth * iConfig.iFrameSize.iHeight);
       
   223 	TUint yC, uC, vC;
       
   224 	TUint16* buffer = (TUint16*) aBuffer;
       
   225 
       
   226     // Alternate between the two logos for cheesy animation effect
       
   227     if( ++iCounter == KAlternateLogoFrameInterval )
       
   228          {
       
   229          iFlipSwitch ^= 1;
       
   230          iCounter = 0;
       
   231          }
       
   232 	
       
   233 	
       
   234 	// Set the "photo" background to be all white
       
   235 	memset(buffer, 0xff, (numPixels * 2));
       
   236 
       
   237 	// Point to the correct location in the buffer at which to render the logo
       
   238 	buffer += ((iY * iConfig.iFrameSize.iWidth) + iX);
       
   239 
       
   240 	// Iterate through the data for the logo and copy it into the "photo"
       
   241 	for (TUint y = 0; y < Logo.iHeight; ++y)
       
   242 		{
       
   243 		for (TUint x = 0; x < Logo.iWidth; ++x)
       
   244 			{
       
   245 			// The logo is in 24 bit BGR format so read each pixel and convert it to 16 bit BGR565
       
   246 			// before writing it into the "photo" buffer
       
   247 			if( iFlipSwitch )
       
   248 			    {
       
   249                 yC = LogoData[index];
       
   250                 uC = LogoData[index + 1];
       
   251                 vC = LogoData[index + 2];
       
   252 			    }
       
   253 			else
       
   254                 {
       
   255                 yC = LogoData2[index];
       
   256                 uC = LogoData2[index + 1];
       
   257                 vC = LogoData2[index + 2];
       
   258                 }
       
   259 
       
   260 			*buffer++ = YUVtoYUV565(yC, uC, vC);
       
   261 			// Point to the next source pixel
       
   262 			index += 3;
       
   263 			}
       
   264 
       
   265 			// Point to the start of the next line in the buffer, taking into account that the logo
       
   266 			// is narrower than the buffer
       
   267 			buffer += (iConfig.iFrameSize.iWidth - Logo.iWidth);
       
   268 		}
       
   269 
       
   270 	// Bounce the logo around in the X direction.  This will take effect the next time this is called
       
   271 	iX += iXDirection;
       
   272 
       
   273 	if (iX <= 0)
       
   274 		{
       
   275 		iX = 0;
       
   276 		iXDirection = -iXDirection;
       
   277 		}
       
   278 	else if (iX >= (TInt) (iConfig.iFrameSize.iWidth - Logo.iWidth))
       
   279 		{
       
   280 		iX = (iConfig.iFrameSize.iWidth - Logo.iWidth);
       
   281 		iXDirection = -iXDirection;
       
   282 		}
       
   283 
       
   284 	// Bounce the logo around in the Y direction.  This will take effect the next time this is called
       
   285 	iY += iYDirection;
       
   286 
       
   287 	if (iY <= 0)
       
   288 		{
       
   289 		iY = 0;
       
   290 		iYDirection = -iYDirection;
       
   291 		}
       
   292 	else if (iY >= (TInt) (iConfig.iFrameSize.iHeight - Logo.iHeight))
       
   293 		{
       
   294 		iY = (iConfig.iFrameSize.iHeight - Logo.iHeight);
       
   295 		iYDirection = -iYDirection;
       
   296 		}
       
   297 
       
   298 	// Now flush the cache to memory, taking into account the size of each pixel.  This is not normally
       
   299 	// necessary but given that we are emulating a camera driver in software we must ensure that the
       
   300 	// cache is flushed to memory.  This is because in a real driver the buffer will have been filled
       
   301 	// by DMA so upon return to the LDD, the LDD will discard the contents of the cache to ensure the
       
   302 	// DMA-written data is ok.  In the case of filling the buffer using the CPU in this virtual camera
       
   303 	// driver, that would result in the data being discarded!
       
   304 	Cache::SyncMemoryBeforeDmaWrite((TLinAddr) aBuffer, (numPixels * iConfig.iPixelFormat.iPixelWidthInBytes));
       
   305 	}
       
   306 
       
   307 /**
       
   308 Based on the capture mode and pixel format passed in, copies an array of supported SFrameSize
       
   309 structures into a buffer supplied by the LDD.  These frame sizes and their associated frame rates
       
   310 will reflect the capabilities of the given capture mode and pixel format.
       
   311 @param aCaptureMode			The capture mode for which to obtain the supported frame sizes.
       
   312 @param aUidPixelFormat		The UID of the pixel format (as defined in \epoc32\include\pixelformats.h)
       
   313 							for which to obtain the supported frame sizes.
       
   314 @param aFrameSizeCapsBuf	A reference to a descriptor that contains a buffer into which to place
       
   315 							the frame size structures.  It is up to the LDD to ensure that this is
       
   316 							large enough to hold all of the frame sizes.
       
   317 @return Always KErrNone.
       
   318 */
       
   319 TInt DTemplateSensorIf::FrameSizeCaps(TDevCamCaptureMode /*aCaptureMode*/, TUidPixelFormat /*aUidPixelFormat*/, TDes8& aFrameSizeCapsBuf)
       
   320 	{
       
   321 	TPtrC8 sourceFrameSizes((const TUint8*) FrameSizes, sizeof(FrameSizes));
       
   322 
       
   323 	// Ensure the buffer passed in from the LDD is large enough and copy the requested frame sizes
       
   324 	if (aFrameSizeCapsBuf.Size() < sourceFrameSizes.Size())
       
   325 		{
       
   326 		Kern::Printf("*** ECapsBufferTooSmall: %d vs %d",
       
   327 				aFrameSizeCapsBuf.Size(),
       
   328 				sourceFrameSizes.Size());
       
   329 		Kern::Fault("camerasc", ECapsBufferTooSmall);
       
   330 		}
       
   331 	
       
   332 	//__ASSERT_DEBUG((aFrameSizeCapsBuf.Size() >= sourceFrameSizes.Size()), Kern::Fault("camerasc", ECapsBufferTooSmall));
       
   333 	aFrameSizeCapsBuf = sourceFrameSizes;
       
   334 
       
   335 	return KErrNone;
       
   336 	}
       
   337 
       
   338 /**
       
   339 Allocates a buffer large enough to hold the TCameraCapsV02 structure and its succeeding array of
       
   340 pixel formats, and populates the structure and array with information about the capabilities of
       
   341 the sensor.
       
   342 @param aCameraCaps	Reference to a pointer into which to place the pointer to allocated buffer
       
   343 @return	Size of the capabilities structure if successful, otherwise one of the other system wide
       
   344 		error codes.
       
   345 */
       
   346 TInt DTemplateSensorIf::GetCaps(TCameraCapsV02*& aCameraCaps)
       
   347 	{
       
   348 	// Allocate a buffer large enough to hold the TCameraCapsV02 structure and the array of pixel formats
       
   349 	// that will follow it
       
   350 	TInt r = (sizeof(TCameraCapsV02) + sizeof(PixelFormats));
       
   351 	TUint8* capsBuffer = new TUint8[r];
       
   352 
       
   353 	if (capsBuffer)
       
   354 		{
       
   355 		aCameraCaps = (TCameraCapsV02*) capsBuffer;
       
   356 
       
   357 		// No special modes are supported at the moment
       
   358 		aCameraCaps->iFlashModes = ECamFlashNone;
       
   359 		aCameraCaps->iExposureModes = ECamExposureAuto; // or None?
       
   360 		// do we still need whitebalance mode filed?
       
   361 		aCameraCaps->iWhiteBalanceModes = ECamWBAuto | ECamWBDaylight | ECamWBCloudy | ECamWBTungsten | ECamWBFluorescent | ECamWBFlash | ECamWBSnow | ECamWBBeach;
       
   362 		aCameraCaps->iMinZoom = 0;
       
   363 		aCameraCaps->iMaxZoom = 0;
       
   364 		aCameraCaps->iCapsMisc = KCamMiscContrast | KCamMiscBrightness | KCamMiscColorEffect;
       
   365 
       
   366 		// There isn't really such thing as inwards or outwards orientation on an SDP, but we'll pretend it's
       
   367 		// an outwards facing camera
       
   368 		aCameraCaps->iOrientation = ECamOrientationOutwards;
       
   369 
       
   370 		// Initialise the number of different pixel formats supported
       
   371 		aCameraCaps->iNumImagePixelFormats = KNumImagePixelFormats;
       
   372 		aCameraCaps->iNumVideoPixelFormats = KNumVideoPixelFormats;
       
   373 		aCameraCaps->iNumViewFinderPixelFormats = KNumViewFinderPixelFormats;
       
   374 
       
   375 		for (TInt i = 0; i < ECamAttributeMax; i++)
       
   376 		    {
       
   377 		    if (ECamAttributeColorEffect == (TDevCamDynamicAttribute)(i))
       
   378 		        {
       
   379 		        // WhiteBalance
       
   380 		        // 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.
       
   381 		        // As this is fake driver, There doesn't seem to be any major issue though.
       
   382 		        aCameraCaps->iDynamicRange[i].iMin = ECamWBAuto;
       
   383 		        aCameraCaps->iDynamicRange[i].iMax = ECamWBBeach;
       
   384 		        aCameraCaps->iDynamicRange[i].iDefault = ECamWBAuto;
       
   385 		        }
       
   386 		    else
       
   387 		        {    
       
   388 		        // TBC :: Contrast, Brightness
       
   389 		        aCameraCaps->iDynamicRange[i].iMin = 0;
       
   390 		        aCameraCaps->iDynamicRange[i].iMax = 6;
       
   391 		        aCameraCaps->iDynamicRange[i].iDefault = 3;
       
   392 		        }
       
   393 		    }
       
   394 
       
   395 		// Setup some descriptors pointing to the pixel format array and the array passed in by the LDD
       
   396 		// (located at the end of the TCameraCapsV02 structure) and copy the pixel format array
       
   397 		TPtrC8 sourcePixelFormats((const TUint8*) PixelFormats, sizeof(PixelFormats));
       
   398 		TPtr8 destPixelFormats((capsBuffer + sizeof(TCameraCapsV02)), sizeof(PixelFormats), sizeof(PixelFormats));
       
   399 		destPixelFormats = sourcePixelFormats;
       
   400 		}
       
   401 	else
       
   402 		{
       
   403 		r = KErrNoMemory;
       
   404 		}
       
   405 
       
   406 	return r;
       
   407 	}
       
   408 
       
   409 /**
       
   410 Powers up the sensor hardware.
       
   411 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   412 */
       
   413 TInt DTemplateSensorIf::RequestPower()
       
   414 	{
       
   415 	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::RequestPower()"));
       
   416 
       
   417 	TInt r = KErrNone;
       
   418 
       
   419 	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::RequestPower() => Returning %d", r));
       
   420 
       
   421 	return r;
       
   422 	}
       
   423 
       
   424 /**
       
   425 Powers down the sensor hardware.
       
   426 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   427 */
       
   428 TInt DTemplateSensorIf::RelinquishPower()
       
   429 	{
       
   430 	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::RelinquishPower()"));
       
   431 
       
   432 	TInt r = KErrNone;
       
   433 
       
   434 	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::RelinquishPower() => Returning %d", r));
       
   435 
       
   436 	return r;
       
   437 	}
       
   438 
       
   439 /**
       
   440 Begins capture of the next image into the buffer provided.  This function assumes that
       
   441 Start() has already been called to start capture.  However, Stop() may also have been
       
   442 subsequently called (for example to pause capture) and in this case, this function will
       
   443 handle restarting the sensor.
       
   444 @param aLinAddr		A virtual pointer to the buffer into which to capture the image.
       
   445 @param aPhysAddr	A physical pointer to the buffer into which to capture the image.
       
   446 					This points to the same memory as aLinAddr.
       
   447 @return KErrNone if successful.
       
   448 		KErrNotReady if there are no free requests to capture the image.
       
   449 		Otherwise one of the other system wide error codes.
       
   450 */
       
   451 TInt DTemplateSensorIf::CaptureNextImage(TLinAddr aLinAddr, TPhysAddr /*aPhysAddr*/)
       
   452 	{
       
   453 	TInt r = KErrNone;
       
   454 
       
   455 	// Only start capturing the next image if there are any pending request slots available
       
   456 	if (iPendingRequests < KTotalCameraRequests)
       
   457 		{
       
   458 		// Queue a transfer on the next available channel and indicate that the channel is
       
   459 		// in use
       
   460 		iNextRequest = ((iNextRequest + 1) % KTotalCameraRequests);
       
   461 		NKern::LockedInc(iPendingRequests);
       
   462 
       
   463 		// XXX: Temporary code to be removed in a real driver.  Fill the buffer for testing
       
   464 		//      with user side code.  This is to simulate an image being captured into the buffer that
       
   465 		//      has been passed in in aLinAddr.  As well as aLinAddr, which points to the virtual
       
   466 		//      address of the buffer, the LDD will pass in the physical address as well, in aPhysAddr.
       
   467 		//      Depending on the underlying sensor hardware and/or bus in use, you will have to choose
       
   468 		//      which of these to use
       
   469 		FillBuffer(aLinAddr);
       
   470 
       
   471 		// XXX: Send buffer to sensor.  Normally the address of the buffer passed in in aLinAddr and
       
   472 		//      aPhysAddr would be programmed into the sensor and/or bus hardware here and an interrupt
       
   473 		//      would be generated when the iamge had been captured into the buffer.  In this simulated
       
   474 		//      driver we will use a nanokernel timer to simulate this process
       
   475 		iImageTimers[iNextRequest].OneShot(iImageTimerTicks, *iImageTimerDFCs[iNextRequest]);
       
   476 
       
   477 		// If capturing has not yet started or has been paused by Stop(), start it
       
   478 		if (!(iEnabled))
       
   479 			{
       
   480 			iEnabled = ETrue;
       
   481 			}
       
   482 		}
       
   483 	else
       
   484 		{
       
   485 		r = KErrNotReady;
       
   486 		}
       
   487 
       
   488 	return r;
       
   489 	}
       
   490 
       
   491 /**
       
   492 Begins capture of the first image into the buffer provided.  This function is similar to
       
   493 CaptureNextImage(), except that it will perform any extra sensor intitialisation required
       
   494 to start capture.
       
   495 @param aCaptureMode	The capture mode for which to start capturing.
       
   496 @param aLinAddr		A virtual pointer to the buffer into which to capture the image.
       
   497 @param aPhysAddr	A physical pointer to the buffer into which to capture the image.
       
   498 					This points to the same memory as aLinAddr.
       
   499 @return KErrNone if successful
       
   500 		KErrInUse if capture is already under way.
       
   501 		KErrNotSupported if the frame size and/or frame rate are out of range.
       
   502 		Otherwise one of the other system wide error codes.
       
   503 */
       
   504 TInt DTemplateSensorIf::Start(TDevCamCaptureMode /*aCaptureMode*/, TLinAddr aLinAddr, TPhysAddr aPhysAddr)
       
   505 	{
       
   506 	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::Start()"));
       
   507 
       
   508 	TInt r = KErrNone;
       
   509 
       
   510 	// XXX - In a real camera driver, in here we would initialise start the capturing process in here.
       
   511 	//       When an image is captured, the sensor hardware (or maybe the CSI bus) will generate an
       
   512 	//       which will then be enqueued into the DFC queue that was passed into the constructor of
       
   513 	//       the sensor class.  It is important to do the DFC processing in this DFC queue rather than
       
   514 	//       a separate one because it ensures that fucntions in the PDD and LDD are called in a serialised
       
   515 	//       manner, without the need for mutexts.  In this example camera driver we will convert the
       
   516 	//       framerate into a nanokernel tick count and will use an NTimer.OneShot() call to simulate
       
   517 	//       the sensor interrupt and DFC callback.  Divides are slow so we'll calculate the tick count
       
   518 	//       here and will save it for later use
       
   519 	iImageTimerTicks = ((1000000 / NKern::TickPeriod()) / iConfig.iFrameRate);
       
   520 
       
   521 	// XXX - Once the one off hardware initialisation has been done for starting a new capture, then
       
   522 	//       subsequent captures can usually reuse the same code in CaptureNextImage() for starting
       
   523 	//       the next capture
       
   524 	r = CaptureNextImage(aLinAddr, aPhysAddr);
       
   525 
       
   526 	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::Start() => Returning %d", r));
       
   527 
       
   528 	return r;
       
   529 	}
       
   530 
       
   531 /**
       
   532 Stops capturing any image capture that is currently in progress.  This function will act
       
   533 more like a Pause() than a Stop() capturing can be restarted from where it was stopped.
       
   534 */
       
   535 TInt DTemplateSensorIf::Stop()
       
   536 	{
       
   537 	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::Stop()"));
       
   538 
       
   539 	iEnabled = EFalse;
       
   540 	iPendingRequests = iNextRequest = 0;
       
   541 
       
   542 	// XXX - Cancel all of our pending image timer callbacks.  In a real driver we would write to the
       
   543 	//       sensor and/or bus hardware here to cause them to cancel any pending image captures
       
   544 	for (TInt index = 0; index < KTotalCameraRequests; ++index)
       
   545 		{
       
   546 		iImageTimers[index].Cancel();
       
   547 		}
       
   548 
       
   549 	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::Stop()"));
       
   550 
       
   551 	return KErrNone;
       
   552 	}