Update contrib.
1 // Copyright (c) 2005-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // its implementation.
19 @file An example camera device driver which uses Shared Chunks in
24 #include <kernel/kern_priv.h>
25 #include <kernel/cache.h>
27 #include "camera1_dev.h"
29 #if 0 // Set true for tracing
40 Standard export function for LDDs. This creates a DLogicalDevice derived object,
41 in this case, our DCamera1Factory
43 DECLARE_STANDARD_LDD()
45 return new DCamera1Factory;
51 DCamera1Factory::DCamera1Factory()
53 // Set version number for this device
54 iVersion=RCamera1::VersionRequired();
55 // Indicate that do support units or a PDD
60 Second stage constructor for DCamera1Factory.
61 This must at least set a name for the driver object.
63 @return KErrNone if successful, otherwise one of the other system wide error codes.
65 TInt DCamera1Factory::Install()
67 return SetName(&RCamera1::Name());
73 DCamera1Factory::~DCamera1Factory()
78 Return the drivers capabilities.
79 Called in the response to an RDevice::GetCaps() request.
81 @param aDes User-side descriptor to write capabilities information into
83 void DCamera1Factory::GetCaps(TDes8& aDes) const
85 // Create a capabilities object
87 caps.iVersion = iVersion;
88 // Write it back to user memory
89 Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
93 Called by the kernel's device driver framework to create a Logical Channel.
94 This is called in the context of the user thread (client) which requested the creation of a Logical Channel
95 (E.g. through a call to RBusLogicalChannel::DoCreate)
96 The thread is in a critical section.
98 @param aChannel Set to point to the created Logical Channel
100 @return KErrNone if successful, otherwise one of the other system wide error codes.
102 TInt DCamera1Factory::Create(DLogicalChannelBase*& aChannel)
104 aChannel=new DCamera1Channel;
116 Default configuration for driver (640x480 pixels of 32bits captured at 15 frames/sec)
118 static const RCamera1::TConfig DefaultConfig = {{640,480},4,15};
123 DCamera1Channel::DCamera1Channel()
124 : iDfcQ(Kern::TimerDfcQ()), // This test uses the timer DFC queue for DFCs
125 iStateChangeDfc(StateChangeDfcTrampoline,this,1), // DFC is priority '1'
126 iConfig(DefaultConfig),
127 iCaptureTimer(CaptureDfcTrampoline,this)
132 Second stage constructor called by the kernel's device driver framework.
133 This is called in the context of the user thread (client) which requested the creation of a Logical Channel
134 (E.g. through a call to RBusLogicalChannel::DoCreate)
135 The thread is in a critical section.
137 @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
138 @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
139 @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate
141 @return KErrNone if successful, otherwise one of the other system wide error codes.
143 TInt DCamera1Channel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
145 // Check client has EMultimediaDD capability
146 if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by CAPTURE1")))
147 return KErrPermissionDenied;
150 if (!Kern::QueryVersionSupported(RCamera1::VersionRequired(),aVer))
151 return KErrNotSupported;
154 iStateChangeDfc.SetDfcQ(iDfcQ);
157 return Kern::MutexCreate(iStateChangeMutex,KNullDesC,KMutexOrdGeneral7);
163 DCamera1Channel::~DCamera1Channel()
165 DoCancel(RCamera1::EAllRequests);
167 iStateChangeDfc.Cancel();
168 if(iStateChangeMutex)
169 iStateChangeMutex->Close(0);
171 iCaptureBuffers->Close();
175 Process a request on this logical channel.
177 @param aReqNo Request number:
178 ==KMaxTInt, a 'DoCancel' message
179 >=0, a 'DoControl' message with function number equal to iValue
180 <0, a 'DoRequest' message with function number equal to ~iValue
181 @param a1 First argument. For DoRequest requests this is a pointer to the TRequestStatus.
182 @param a2 Second argument. For DoRequest this is a pointer to the 2 actual TAny* arguments.
184 @return Result. Ignored by device driver framework for DoRequest requests.
186 TInt DCamera1Channel::Request(TInt aReqNo, TAny* a1, TAny* a2)
188 // Decode the message type and dispatch it to the relevent handler function...
189 if ((TUint)aReqNo<(TUint)KMaxTInt)
190 return DoControl(aReqNo,a1,a2);
192 return DoCancel((TInt)a1);
193 return DoRequest(aReqNo,a1,a2);
197 Process synchronous 'control' requests
199 TInt DCamera1Channel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
201 TRACE(Kern::Printf(">DCamera1Channel::DoControl fn=%d\n",aFunction);)
203 (void)a2; // a2 not used in this example
205 TInt r = KErrNotSupported;
208 case RCamera1::EGetConfig:
209 r = GetConfig((TDes8*)a1);
212 case RCamera1::ESetConfig:
213 r = SetConfig((const TDesC8*)a1);
216 case RCamera1::EStartCapture:
220 case RCamera1::EEndCapture:
224 case RCamera1::EReleaseImage:
225 r = ImageRelease((TInt)a1);
228 case RCamera1::ECaptureImage:
229 CaptureImage((TRequestStatus*)a1,(TInt)a2);
233 TRACE(Kern::Printf("<DCamera1Channel::DoControl result=%d\n",r);)
239 Process asynchronous requests.
240 This driver doesn't have any 'DoRequest' requests because we handle asyncronous
241 requests using 'DoControl' for performance reasons. I.e. to avoid having to read
242 the arguments with kumemget()
244 TInt DCamera1Channel::DoRequest(TInt aNotReqNo, TAny* a1, TAny* a2)
246 TRACE(Kern::Printf(">DCamera1Channel::DoRequest req=%d\n",aNotReqNo);)
250 kumemget32(a,a2,sizeof(a));
251 TRequestStatus* status=(TRequestStatus*)a1;
252 TInt reqNo = ~aNotReqNo;
258 case RCamera1::ECaptureImage:
259 // Not used because we do 'ECaptureImage' as a DoControl rather than
260 // a DoRequest for performance reasons
263 r = KErrNotSupported;
267 // Complete request if there was an error
269 Kern::RequestComplete(&Kern::CurrentThread(),status,r);
271 TRACE(Kern::Printf("<DCamera1Channel::DoRequest result=%d\n",r);)
273 return KErrNone; // Result is ignored by device driver framework for DoRequest requests
277 Process cancelling of asynchronous requests.
279 TInt DCamera1Channel::DoCancel(TUint aMask)
281 TRACE(Kern::Printf(">DCamera1Channel::DoCancel mask=%08x\n",aMask);)
283 if(aMask&(1<<RCamera1::ECaptureImage))
284 CaptureImageCancel();
286 TRACE(Kern::Printf("<DCamera1Channel::DoCancel\n");)
292 // Methods for processing configuration control messages
296 Process a GetConfig control message. This writes the current driver configuration to a
297 RCamera1::TConfigBuf supplied by the client.
299 TInt DCamera1Channel::GetConfig(TDes8* aConfigBuf)
301 // Write the config to the client
302 Kern::InfoCopy(*aConfigBuf,(const TUint8*)&iConfig,sizeof(iConfig));
307 Process a SetConfig control message. This sets the driver configuration using a
308 RCamera1::TConfigBuf supplied by the client.
310 TInt DCamera1Channel::SetConfig(const TDesC8* aConfigBuf)
312 // Create a config structure.
313 RCamera1::TConfig config(DefaultConfig);
315 // Note: We have constructed a config using DefaultConfig, this is to allow
316 // backwards compatibility when a client gives us an old (and shorter) version
317 // of the config structure.
319 // Read the config structure from client
320 TPtr8 ptr((TUint8*)&config,sizeof(config));
321 Kern::KUDesGet(ptr,*aConfigBuf);
323 // For some settings we allow zero to mean default...
324 if(!config.iImageSize.iWidth)
325 config.iImageSize.iWidth = DefaultConfig.iImageSize.iWidth;
326 if(!config.iImageSize.iHeight)
327 config.iImageSize.iHeight = DefaultConfig.iImageSize.iHeight;
328 if(!config.iImageBytesPerPixel)
329 config.iImageBytesPerPixel = DefaultConfig.iImageBytesPerPixel;
331 // Validate configuration
332 TInt scale = DefaultConfig.iImageSize.iWidth/config.iImageSize.iWidth;
333 if(scale*config.iImageSize.iWidth != DefaultConfig.iImageSize.iWidth)
335 if(scale*config.iImageSize.iHeight != DefaultConfig.iImageSize.iHeight)
337 if(config.iImageBytesPerPixel<=0 || config.iImageBytesPerPixel>4)
340 if(config.iFrameRate<0)
342 if(config.iNumImageBuffers<1)
346 DCaptureBuffers* buffers;
349 // Need to be in critical section whilst holding a DMutex
350 NKern::ThreadEnterCS();
352 // Claim state change mutex. Note, the return value is ignored because a Wait
353 // can only fail if the mutex is destroyed whilst waiting for it, this can't
354 // happen in our driver.
355 Kern::MutexWait(*iStateChangeMutex);
357 // Check we aren't in the middle of capturing images
366 iCaptureRateTicks = config.iFrameRate ? 1000000/config.iFrameRate/NKern::TickPeriod() : KMaxTInt;
367 if(iCaptureRateTicks<1)
368 iCaptureRateTicks = 1;
370 // Claim ownership of old buffers
371 NKern::FMWait(&iCaptureMutex);
372 buffers = iCaptureBuffers;
373 iCaptureBuffers = NULL;
374 NKern::FMSignal(&iCaptureMutex);
376 // Delete old buffers
380 // Contruct new buffer object
381 imageSize = iConfig.iImageSize.iWidth*iConfig.iImageSize.iHeight*iConfig.iImageBytesPerPixel;
382 buffers = DCaptureBuffers::New(2+iConfig.iNumImageBuffers,imageSize);
389 // Use the new buffers if another thread didn't create them first
390 NKern::FMWait(&iCaptureMutex);
391 iCaptureBuffers = buffers;
392 NKern::FMSignal(&iCaptureMutex);
394 // Create handle for chunk
395 r = Kern::MakeHandleAndOpen(NULL, iCaptureBuffers->iChunk);
398 // Release state change mutex
399 Kern::MutexSignal(*iStateChangeMutex);
401 NKern::ThreadLeaveCS();
407 // Methods for processing start/end capture
411 Start image capturing
413 TInt DCamera1Channel::StartCapture()
415 // Need to be in critical section whilst holding a DMutex
416 NKern::ThreadEnterCS();
418 // Claim state change mutex. Note, the return value is ignored because a Wait
419 // can only fail if the mutex is destroyed whilst waiting for it, this can't
420 // happen in our driver.
421 Kern::MutexWait(*iStateChangeMutex);
423 NKern::FMWait(&iCaptureMutex);
427 r = KErrNotReady; // SetConfig not yet been called
429 r = KErrInUse; // StartCapture has already been called
432 // Initialise image buffer state for capturing images
433 iCaptureBuffers->Reset();
435 // Flag capturing started
440 NKern::FMSignal(&iCaptureMutex);
442 // Get state change DFC to initialise camera hardware for capture
446 // Release state change mutex
447 Kern::MutexSignal(*iStateChangeMutex);
449 NKern::ThreadLeaveCS();
457 TInt DCamera1Channel::EndCapture()
459 // Need to be in critical section whilst holding a DMutex
460 NKern::ThreadEnterCS();
462 // Claim state change mutex. Note, the return value is ignored because a Wait
463 // can only fail if the mutex is destroyed whilst waiting for it, this can't
464 // happen in our driver.
465 Kern::MutexWait(*iStateChangeMutex);
469 // Get state change DFC to reset camera hardware
472 // Flag capture ended
473 NKern::FMWait(&iCaptureMutex);
475 NKern::FMSignal(&iCaptureMutex);
477 // Cancel any pending caoture request
478 CaptureImageCancel();
481 // Release state change mutex
482 Kern::MutexSignal(*iStateChangeMutex);
484 NKern::ThreadLeaveCS();
490 Performs state change on Start/EndCapture by calling state change DFC
491 Call with iStateChangeMutex held.
493 @param aNewState True to start image capture, false to stop image capture.
495 void DCamera1Channel::StateChange(TBool aNewState)
497 iNewState = aNewState;
498 NKern::FSSetOwner(&iStateChangeSemaphore,NULL);
499 iStateChangeDfc.Enque();
500 NKern::FSWait(&iStateChangeSemaphore);
504 DFC callback called when Start/EndCapture requests are made.
506 void DCamera1Channel::StateChangeDfcTrampoline(TAny* aSelf)
508 // Just call non-static method
509 ((DCamera1Channel*)aSelf)->StateChangeDfc();
513 DFC callback called when Start/EndCapture requests are made.
515 void DCamera1Channel::StateChangeDfc()
517 TRACE(Kern::Printf(">DCamera1Channel::StateChangeDfc\n");)
519 // Call relevent state change function
526 NKern::FSSignal(&iStateChangeSemaphore);
528 TRACE(Kern::Printf("<DCamera1Channel::StateChangeDfc\n");)
532 // Methods for processing CaptureImage
536 Process Capture Image request
538 void DCamera1Channel::CaptureImage(TRequestStatus* aRequestStatus,TInt aReleaseImage)
542 // Get the thread making the request
543 DThread* requestThread = &Kern::CurrentThread();
545 // Release image (if one was specified)
546 if(aReleaseImage!=-1)
548 r = ImageRelease(aReleaseImage);
553 NKern::FMWait(&iCaptureMutex);
556 r = KErrNotReady; // StartCapture hasn't yet been called
557 else if(iCaptureRequestStatus)
558 r = KErrInUse; // There is already a pending CaptureImage request
561 // See if an image is already available...
562 DImageBuffer* buffer=iCaptureBuffers->ImageForClient();
565 // Return offset of buffer to client
566 r = buffer->iChunkOffset;
570 // Image not found...
571 if(!iCaptureBuffers->iFreeBuffers[0])
572 r = KErrOverflow; // Out of buffers
575 // Wait for new image to become available
576 iCaptureRequestStatus = aRequestStatus;
577 requestThread->Open(); // can't fail because this is the current thread
578 iCaptureRequestThread = requestThread;
584 NKern::FMSignal(&iCaptureMutex);
587 // Complete request if there was an error
589 Kern::RequestComplete(requestThread,aRequestStatus,r);
593 Signal Capture Image request completed
595 void DCamera1Channel::CaptureImageCancel()
597 // Need to be in critical section so we don't die whilst owning the capture image request
598 NKern::ThreadEnterCS();
600 // Claim the capture image request
601 NKern::FMWait(&iCaptureMutex);
602 DThread* thread = iCaptureRequestThread;;
603 TRequestStatus* status = iCaptureRequestStatus;
604 iCaptureRequestStatus = NULL;
605 NKern::FMSignal(&iCaptureMutex);
610 Kern::RequestComplete(thread,status,KErrCancel);
614 NKern::ThreadLeaveCS();
618 DFC callback called when after a new image has been captured
619 In this example code this is called by
621 void DCamera1Channel::CaptureDfcTrampoline(TAny* aSelf)
623 // Just call non-static method
624 ((DCamera1Channel*)aSelf)->CaptureDfc();
628 DFC callback called when a new image has been captured
630 void DCamera1Channel::CaptureDfc()
632 TRACE(Kern::Printf(">DCamera1Channel::CaptureDfc\n");)
634 NKern::FMWait(&iCaptureMutex);
636 // Update image buffers state
637 iCaptureBuffers->ImageCaptured();
639 // Did client request an image and is one available?
640 DImageBuffer* clientBuffer;
641 if(iCaptureRequestStatus && (clientBuffer=iCaptureBuffers->ImageForClient())!=NULL )
643 // Claim the client request
644 DThread* thread = iCaptureRequestThread;
645 TRequestStatus* status = iCaptureRequestStatus;
646 iCaptureRequestStatus = NULL;
648 NKern::FMSignal(&iCaptureMutex);
650 // We now own the client request but we don't have to worry about
651 // being in a critical section because we are running in a DFC thread
652 // which can't be killed
654 // Complete client request with the chunk offset for a captured image
655 // (We use AsyncClose() here because we are running in a high priority DFC and
656 // don't want to take the penalty for possibly deleting a thread in this context.)
657 Kern::RequestComplete(thread,status,clientBuffer->iChunkOffset);
658 thread->AsyncClose();
661 NKern::FMSignal(&iCaptureMutex);
663 // Get camera hardware to capture next image
666 TRACE(Kern::Printf("<DCamera1Channel::CaptureDfc\n");)
670 Release a buffer which was being used by client
672 @param aChunkOffset The chunk offset corresponding to the buffer to be freed
674 @return KErrNone if successful.
675 KErrNotFound if no 'in use' buffer had the specified chunk offset.
677 TInt DCamera1Channel::ImageRelease(TInt aChunkOffset)
679 // Need to be in critical section so we don't die whilst holding reference on buffers
680 NKern::ThreadEnterCS();
682 // Get reference to buffers object and find the buffer we want
683 NKern::FMWait(&iCaptureMutex);
684 DCaptureBuffers* buffers = iCaptureBuffers;
685 DImageBuffer* buffer = NULL;
689 buffer = buffers->InUseImage(aChunkOffset);
691 NKern::FMSignal(&iCaptureMutex);
695 r = KErrNotFound; // Buffer not found
698 // Purge the CPU cache for the buffer.
699 // Note, we don't do this whilst holding iCaptureMutex because it can
701 // Also, it doesn't mater that e aren't holding the mutex because:
702 // 1. The buffer can't be delete because we have a reference count on iCaptureBuffers
703 // 2. Reentrancy of the Purge method is safe
704 buffers->Purge(buffer);
706 // Release buffer (move it to the free list)
707 NKern::FMWait(&iCaptureMutex);
708 r = buffers->ImageRelease(aChunkOffset) ? KErrNone : KErrArgument;
709 NKern::FMSignal(&iCaptureMutex);
712 // Close reference on buffers
716 NKern::ThreadLeaveCS();
726 Construct a new set of buffers
728 @param aNumBuffers Number of buffers
729 @param aBufferSize Size of each buffer in bytes
731 @return Pointer to the created DCaptureBuffers or NULL if the system ran out of memory
733 DCaptureBuffers* DCaptureBuffers::New(TInt aNumBuffers,TInt aBufferSize)
735 DCaptureBuffers* buffers = new DCaptureBuffers;
738 TInt r = buffers->Create(aNumBuffers,aBufferSize);
742 // An error other than 'no memory' must be a programming error in the driver
743 __NK_ASSERT_ALWAYS(r==KErrNoMemory);
749 Construct with access count of one
751 DCaptureBuffers::DCaptureBuffers()
757 Create all buffers and lists
759 TInt DCaptureBuffers::Create(TInt aNumBuffers,TInt aBufferSize)
761 // Allocate buffer lists
762 DImageBuffer** lists = (DImageBuffer**)Kern::AllocZ(3*aNumBuffers*sizeof(DImageBuffer*));
765 iBufferLists = lists;
766 iFreeBuffers = lists;
767 iCompletedBuffers = lists+aNumBuffers;
768 iInUseBuffers = lists+2*aNumBuffers;
771 aBufferSize = Kern::RoundToPageSize(aBufferSize);
772 TInt pageSize = Kern::RoundToPageSize(1);
773 TUint64 chunkSize = TUint64(aBufferSize+pageSize)*aNumBuffers+pageSize;
774 if(chunkSize>(TUint64)KMaxTInt)
775 return KErrNoMemory; // Need more than 2GB of memory!
778 TChunkCreateInfo info;
779 info.iType = TChunkCreateInfo::ESharedKernelMultiple;
780 info.iMaxSize = (TInt)chunkSize;
782 info.iMapAttr = EMapAttrCachedMax;
786 info.iOwnsMemory = ETrue;
787 TInt r = Kern::ChunkCreate(info,iChunk,iChunkBase,iChunkMapAttr);
791 // Construct array of buffers
792 iNumBuffers = aNumBuffers;
793 iImageBuffer = new DImageBuffer[aNumBuffers];
797 // Create each buffer
798 TInt offset = pageSize;
801 r = iImageBuffer[--aNumBuffers].Create(iChunk,offset,aBufferSize);
804 offset += aBufferSize+pageSize;
813 DCaptureBuffers::~DCaptureBuffers()
816 Kern::ChunkClose(iChunk);
817 delete [] iImageBuffer;
818 Kern::Free(iBufferLists);
822 Increment access count of buffers
824 void DCaptureBuffers::Open()
826 __e32_atomic_tas_ord32(&iAccessCount, 1, 1, 0);
830 Decrement access count of buffers.
831 Deleting them if the count is decremented to zero.
833 void DCaptureBuffers::Close()
835 __ASSERT_NO_FAST_MUTEX;
837 if(__e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0) == 1)
842 Reset all image buffer lists to reflect the state at the start of image capture process
844 void DCaptureBuffers::Reset()
846 // Purge cache for all buffers in use by client.
847 DImageBuffer** list = iInUseBuffers;
848 DImageBuffer* buffer;
849 while((buffer=*list++)!=NULL)
852 // Get pointers to first buffer
853 buffer = iImageBuffer;
855 // Set buffers for current and next images
856 iCurrentBuffer = buffer++;
857 iNextBuffer = buffer++;
859 // Add all other buffers to the free list
860 DImageBuffer** free = iFreeBuffers;
861 DImageBuffer* bufferLimit = iImageBuffer+iNumBuffers;
862 while(buffer<bufferLimit)
866 // Start with no completed or used buffers
867 iCompletedBuffers[0] = 0;
868 iInUseBuffers[0] = 0;
872 Purge cache for an image buffer.
873 @param aBuffer The buffer.
875 void DCaptureBuffers::Purge(DImageBuffer* aBuffer)
877 Cache::SyncMemoryBeforeDmaRead(iChunkBase+aBuffer->iChunkOffset,aBuffer->iSize,iChunkMapAttr);
881 Remove an image buffer to the start of the given image list.
882 @return A pointer to the image buffer or NULL if the list was empty
884 DImageBuffer* DCaptureBuffers::Remove(DImageBuffer** aList)
886 DImageBuffer* buffer=aList[0];
901 Add an image buffer to the end of the given image list.
903 DImageBuffer* DCaptureBuffers::Add(DImageBuffer** aList, DImageBuffer* aBuffer)
905 while(*aList) aList++;
911 Update buffer lists after an image has been captured.
912 @return A pointer to the catptured image buffer
914 DImageBuffer* DCaptureBuffers::ImageCaptured()
916 // Add captured image to completed list
917 DImageBuffer* buffer = iCurrentBuffer;
918 DCaptureBuffers::Add(iCompletedBuffers,buffer);
920 // Make queued buffer the current one
921 iCurrentBuffer = iNextBuffer;
923 // Queue a new buffer
924 iNextBuffer = DCaptureBuffers::Remove(iFreeBuffers);
926 iNextBuffer = DCaptureBuffers::Remove(iCompletedBuffers);
928 TRACE(Kern::Printf("DCaptureBuffers::ImageCaptured buf=%08x\n",buffer->iChunkOffset);)
934 Get the next image from the completed capture list and make it 'in use' by the client
936 @return A pointer to the next completed image buffer
938 DImageBuffer* DCaptureBuffers::ImageForClient()
940 DImageBuffer* buffer=Remove(iCompletedBuffers);
942 DCaptureBuffers::Add(iInUseBuffers,buffer);
944 TRACE(Kern::Printf("DCaptureBuffers::ImageForClient buf=%08x\n",buffer ? buffer->iChunkOffset : -1);)
950 Release (move to free list) the 'in use' image specified by the given chunk offset.
952 @param aChunkOffset The chunk offset corresponding to the buffer to be freed
954 @return The freed image buffer, or NULL if no 'in use' buffer had the specified chunk offset.
956 DImageBuffer* DCaptureBuffers::ImageRelease(TInt aChunkOffset)
958 // Scan 'in use' list for the image buffer
959 DImageBuffer** list = iInUseBuffers;
960 DImageBuffer* buffer;
961 while((buffer=*list++)!=NULL && buffer->iChunkOffset!=aChunkOffset)
964 // Move buffer to the free list (if found)
966 buffer = Add(iFreeBuffers,Remove(list-1));
968 TRACE(Kern::Printf("DCaptureBuffers::ImageRelease buf=%08x\n",buffer ? buffer->iChunkOffset : -1);)
974 Find the 'in use' image specified by the given chunk offset
976 @param aChunkOffset The chunk offset corresponding to the buffer to be freed
978 @return The image buffer, or NULL if no 'in use' buffer had the specified chunk offset
980 DImageBuffer* DCaptureBuffers::InUseImage(TInt aChunkOffset)
982 // Scan 'in use' list for the image buffer
983 DImageBuffer** list = iInUseBuffers;
984 DImageBuffer* buffer;
985 while((buffer=*list++)!=NULL && buffer->iChunkOffset!=aChunkOffset)
996 Constructor clears all member data
998 DImageBuffer::DImageBuffer()
1000 memclr(this,sizeof(*this));
1004 Commit memory for this buffer.
1006 @param aChunk The chunk into which the memory is to be commited
1007 @param aOffset The offset within aChunk for the start of the comitted memory.
1008 Must be a multiple of the MMU page size.
1009 @param aSize The number of bytes of memory to commit.
1010 Must be a multiple of the MMU page size.
1012 @return KErrNone if successful, otherwise one of the other system wide error codes.
1014 TInt DImageBuffer::Create(DChunk* aChunk, TInt aOffset, TInt aSize)
1019 iChunkOffset = aOffset;
1022 // Try for physically contiguous memory first
1023 r = Kern::ChunkCommitContiguous(aChunk,aOffset,aSize,iPhysicalAddress);
1027 // failed to get contiguous memory...
1029 // Mark physical address invalid
1030 iPhysicalAddress = KPhysAddrInvalid;
1032 // Commit discontiguous memory
1033 r = Kern::ChunkCommit(aChunk,aOffset,aSize);
1037 // Allocate array for list of physical pages
1038 iPhysicalPages = new TPhysAddr[aSize/Kern::RoundToPageSize(1)];
1040 return KErrNoMemory;
1042 // Get physical addresses of pages in buffer
1046 r = Kern::ChunkPhysicalAddress(aChunk,aOffset,aSize,kernAddr,mapAttr,physAddr,iPhysicalPages);
1047 // r = 0 or 1 on success. (1 meaning the physical pages are not-contiguous)
1056 DImageBuffer::~DImageBuffer()
1058 delete [] iPhysicalPages;
1062 // Program camera hardware
1066 Initialise camera hardware to start capturing images
1067 First buffer to fill is iCaptureBuffers->iCurrentBuffer.
1068 Next buffer to fill will be iCaptureBuffers->iNextBuffer.
1070 void DCamera1Channel::DoStartCapture()
1072 // For this example test...
1074 TRACE(Kern::Printf("DCamera1Channel::DoStartCapture buf=%08x cnt=%04d\n",iCaptureBuffers->iCurrentBuffer->iChunkOffset,iCaptureCounter);)
1076 // Initialise frame counter
1077 iCaptureCounter = 0;
1079 // Put frame counter into current image buffer. (This is the 'image' data we capture).
1080 *(TInt*)(iCaptureBuffers->iChunkBase+iCaptureBuffers->iCurrentBuffer->iChunkOffset) = iCaptureCounter++;
1083 TInt r=iCaptureTimer.OneShot(iCaptureRateTicks,ETrue);
1084 __NK_ASSERT_ALWAYS(r==KErrNone);
1088 Reset camera hardware to stop capturing images
1090 void DCamera1Channel::DoEndCapture()
1092 // For this example test...
1094 TRACE(Kern::Printf("DCamera1Channel::DoEndCapture\n");)
1097 iCaptureTimer.Cancel();
1101 Setup camera hardware to capture next image
1102 Next buffer to fill will be iCaptureBuffers->iNextBuffer;
1104 @param aLastImage The last image just captured. I.e. the completed capture which caused
1105 this method to be called
1107 void DCamera1Channel::DoNextCapture()
1109 // For this example test...
1111 TRACE(Kern::Printf("DCamera1Channel::DoNextCapture cur=%08x cnt=%04d nxt=%08x\n",iCaptureBuffers->iCurrentBuffer->iChunkOffset,iCaptureCounter,iCaptureBuffers->iNextBuffer->iChunkOffset);)
1113 // Put frame counter into current image buffer. (This is the 'image' data we capture).
1114 *(TInt*)(iCaptureBuffers->iChunkBase+iCaptureBuffers->iCurrentBuffer->iChunkOffset) = iCaptureCounter++;
1116 // Restart the timer
1117 TInt r = iCaptureTimer.Again(iCaptureRateTicks);
1120 // Timer would have already expired.
1122 // In a real device driver this is analogous to iCurrentBuffer already being filled
1123 // and the DMA queue being emptied. I.e. we have missed some frames.
1127 TRACE(Kern::Printf("DCamera1Channel::DoNextCapture frame dropped cnt=%04d\n",iCaptureCounter);)
1129 // Skip a frame count
1133 r = iCaptureTimer.OneShot(iCaptureRateTicks,ETrue);
1135 __NK_ASSERT_ALWAYS(r==KErrNone);