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