os/kernelhwsrv/bsptemplate/asspandvariant/template_variant/camerasc/camerasc_sensor.cpp
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 + }