|
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 } |