--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/baseport/syborg/webcamera/webcamera_ldd.cpp Wed Mar 24 13:46:59 2010 +0900
@@ -0,0 +1,586 @@
+/*
+* Copyright (c) 2010 ISB.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* ISB - initial contribution.
+*
+* Contributors:
+*
+* Description: USB driver for test
+*
+*/
+
+#include <kern_priv.h>
+#include "webcamera_ldd.h"
+#include <webcamera_driver.h>
+
+#define DP(format...) Kern::Printf(format)
+
+_LIT(KDriver1PanicCategory,"WebcameraDevice");
+
+/**
+ *Create Logic device.
+ *
+ */
+DECLARE_STANDARD_LDD()
+ {
+ DP("DECLARE_STANDARD_LDD()");
+ return new DWebcameraLogicalDevice;
+ }
+
+/**
+ Constructor
+*/
+DWebcameraLogicalDevice::DWebcameraLogicalDevice()
+ {
+ DP("DWebcameraLogicalDevice()");
+ // Set version number for this device
+ iVersion=RWebcameraDevice::VersionRequired();
+ // Indicate that we work with a PDD
+ iParseMask=KDeviceAllowPhysicalDevice;
+ }
+
+/**
+ Destructor
+*/
+DWebcameraLogicalDevice::~DWebcameraLogicalDevice()
+ {
+ }
+
+/**
+ Second stage constructor for DDriver1Factory.
+ This must at least set a name for the driver object.
+
+ @return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DWebcameraLogicalDevice::Install()
+ {
+ DP("DWebcameraLogicalDevice::Install()");
+
+ return SetName(&RWebcameraDevice::Name());
+ }
+
+/**
+ Return the drivers capabilities.
+ Called in the response to an RDevice::GetCaps() request.
+
+ @param aDes User-side descriptor to write capabilities information into
+*/
+void DWebcameraLogicalDevice::GetCaps(TDes8& aDes) const
+ {
+ // Create a capabilities object
+ RWebcameraDevice::TCaps caps;
+ caps.iVersion = iVersion;
+ // Write it back to user memory
+ Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
+ }
+
+/**
+ Called by the kernel's device driver framework to create a Logical Channel.
+ This is called in the context of the user thread (client) which requested the creation of a Logical Channel
+ (E.g. through a call to RBusLogicalChannel::DoCreate)
+ The thread is in a critical section.
+
+ @param aChannel Set to point to the created Logical Channel
+
+ @return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DWebcameraLogicalDevice::Create(DLogicalChannelBase*& aChannel)
+ {
+ DP("DWebcameraLogicalDevice::Create() start");
+ aChannel = new DWebcameraLogicalChannel;
+ if(!aChannel)
+ return KErrNoMemory;
+ return KErrNone;
+ DP("DWebcameraLogicalDevice::Create() end");
+ }
+
+/**
+ Constructor
+*/
+DWebcameraLogicalChannel::DWebcameraLogicalChannel()
+ : iReceiveDataDfc(GetOneFlameDfc, this, 1)
+ ,iCaptureDfc(CaptureDfc,this,1)
+ {
+ DP("DWebcameraLogicalChannel::DWebcameraLogicalChannel() start");
+
+ // Get pointer to client threads DThread object
+ iClient=&Kern::CurrentThread();
+ // Open a reference on client thread so it's control block can't dissapear until
+ // this driver has finished with it.
+ ((DObject*)iClient)->Open();
+
+ DP("DWebcameraLogicalChannel::DWebcameraLogicalChannel() end");
+ }
+
+/**
+ Destructor
+*/
+DWebcameraLogicalChannel::~DWebcameraLogicalChannel()
+ {
+ DP("DWebcameraLogicalChannel::~DWebcameraLogicalChannel() start");
+ // Cancel all processing that we may be doing
+ DoCancel(RWebcameraDevice::EAllRequests);
+ if (iComm)
+ {
+ delete iComm;
+ }
+ if (iChunk)
+ {
+ Epoc::FreePhysicalRam(iPhysAddr, iSize);
+ }
+ // Close our reference on the client thread
+ Kern::SafeClose((DObject*&)iClient,NULL);
+ DP("DWebcameraLogicalChannel::~DWebcameraLogicalChannel() end");
+ }
+
+/**
+ Called when a user thread requests a handle to this channel.
+*/
+TInt DWebcameraLogicalChannel::RequestUserHandle(DThread* aThread, TOwnerType aType)
+ {
+ // Make sure that only our client can get a handle
+ if (aType!=EOwnerThread || aThread!=iClient)
+ return KErrAccessDenied;
+ return KErrNone;
+ }
+
+/**
+ Second stage constructor called by the kernel's device driver framework.
+ This is called in the context of the user thread (client) which requested the creation of a Logical Channel
+ (E.g. through a call to RBusLogicalChannel::DoCreate)
+ The thread is in a critical section.
+
+ @param aUnit The unit argument supplied by the client
+ @param aInfo The info argument supplied by the client
+ @param aVer The version argument supplied by the client
+
+ @return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt DWebcameraLogicalChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
+ {
+ DP("DWebcameraLogicalChannel::DoCreate() start");
+ if(!Kern::CurrentThreadHasCapability(ECapability_None,__PLATSEC_DIAGNOSTIC_STRING("Checked by Webcamera")))
+ {
+ return KErrPermissionDenied;
+ }
+ // Check version
+ if (!Kern::QueryVersionSupported(RWebcameraDevice::VersionRequired(),aVer))
+ {
+ return KErrNotSupported;
+ }
+ // Setup LDD for receiving client messages
+ SetDfcQ(Kern::DfcQue0());
+ iMsgQ.Receive();
+ // Associate DFCs with the same queue we set above to receive client messages on
+ iReceiveDataDfc.SetDfcQ(iDfcQ);
+ iCaptureDfc.SetDfcQ(iDfcQ);
+ // Give PDD a pointer to this channel
+ Pdd()->iLdd=this;
+
+ //allocate Memory
+ iSize=Kern::RoundToPageSize(BUFSIZE);
+ TInt rtn=Epoc::AllocPhysicalRam(iSize, iPhysAddr);
+ if (rtn != KErrNone)
+ {
+ return rtn;
+ }
+ rtn=DPlatChunkHw::New(iChunk, iPhysAddr, iSize,EMapAttrUserRw|EMapAttrBufferedC);
+ if (rtn != KErrNone)
+ {
+ if (iPhysAddr)
+ {
+ Epoc::FreePhysicalRam(iPhysAddr, iSize);
+ }
+ return rtn;
+ }
+ iLAdr = reinterpret_cast<TUint8*>(iChunk->LinearAddress());
+
+ iComm=HBuf8::New(BUFSIZE);
+ if (!iComm)
+ {
+ return KErrNotSupported;
+ }
+ iReceiveDataBuffer=iComm;
+ iCaptureBuffer=iComm;
+
+ DP("DWebcameraLogicalChannel::DoCreate() end");
+ return KErrNone;
+ }
+
+/**
+ Process a message for this logical channel.
+ This function is called in the context of a DFC thread.
+
+ @param aMessage The message to process.
+ The iValue member of this distinguishes the message type:
+ iValue==ECloseMsg, channel close message
+ iValue==KMaxTInt, a 'DoCancel' message
+ iValue>=0, a 'DoControl' message with function number equal to iValue
+ iValue<0, a 'DoRequest' message with function number equal to ~iValue
+*/
+void DWebcameraLogicalChannel::HandleMsg(TMessageBase* aMsg)
+ {
+ DP("DWebcameraLogicalChannel::HandleMsg() start");
+ TThreadMessage& m=*(TThreadMessage*)aMsg;
+
+ // Get message type
+ TInt id=m.iValue;
+ DP("id=%d",id);
+
+ // Decode the message type and dispatch it to the relevent handler function...
+ if (id==(TInt)ECloseMsg)
+ {
+ DoCancel(RWebcameraDevice::EAllRequests);
+ m.Complete(KErrNone, EFalse);
+ return;
+ }
+
+ if(m.Client()!=iClient)
+ {
+ Kern::ThreadKill(m.Client(),
+ EExitPanic,
+ ERequestFromWrongThread,
+ KDriver1PanicCategory);
+ m.Complete(KErrNone,ETrue);
+ return;
+ }
+
+ if (id==KMaxTInt)
+ {
+ DoCancel(m.Int0());
+ m.Complete(KErrNone,ETrue);
+ return;
+ }
+
+ if (id<0)
+ {
+ // DoRequest
+ TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+ TInt rtn =DoRequest(~id,pS,m.Ptr1(),aMsg);
+
+ if (rtn != KErrNone)
+ Kern::RequestComplete(iClient,pS,rtn);
+ m.Complete(KErrNone,ETrue);
+ }
+ else
+ {
+ // DoControl
+ TInt rtn = DoControl(id,m.Ptr0(),aMsg);
+ m.Complete(rtn,ETrue);
+ }
+ DP("DWebcameraLogicalChannel::HandleMsg() end");
+ }
+
+/**
+ Process synchronous 'control' requests
+*/
+TInt DWebcameraLogicalChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+ {
+ DP("DWebcameraLogicalChannel::DoControl() start");
+ TInt rtn;
+ TThreadMessage& m=*(TThreadMessage*)a2;
+ TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+
+ switch (aFunction)
+ {
+ case RWebcameraDevice::EGetConfig:
+// rtn = GetConfig((TDes8*)a1);
+ rtn = KErrNone;
+ if ( rtn != KErrNone )
+ {
+ Kern::RequestComplete(iClient,pS,rtn);
+ }
+ break;
+ case RWebcameraDevice::ESetConfig:
+ // rtn = SetConfig((const TDesC8*)a1);
+ break;
+
+ default:
+ rtn = KErrNotSupported;
+ Kern::RequestComplete(iClient,pS,rtn);
+ break;
+ }
+ DP("DWebcameraLogicalChannel::DoControl() end");
+ return rtn;
+
+ }
+
+/**
+ Process asynchronous requests.
+*/
+TInt DWebcameraLogicalChannel::DoRequest(TInt aReqNo,
+ TRequestStatus* aStatus,
+ TAny* a1,
+ TAny* a2)
+ {
+ DP("DWebcameraLogicalChannel::DoRequest() start");
+ TInt rtn;
+ TThreadMessage& m=*(TThreadMessage*)a2;
+
+ iRequesting =ETrue;
+ rtn = KErrNone;
+ DP("aReqNo=%d",aReqNo);
+ switch(aReqNo)
+ {
+ case RWebcameraDevice::EStart:
+ DP("EStart=%d",RWebcameraDevice::EStart);
+ iReceiveDataStatus = aStatus;
+ iReceiving = ETrue ;
+ iReceiveDataBuffer->FillZ(iCaptureBuffer->MaxLength());
+ iReceiveDataBuffer->Zero();
+ DP("iReceiveDataBuffer Len=%d",iReceiveDataBuffer->MaxLength());
+ DP("iReceiveDataBuffer Len=%d",iReceiveDataBuffer->Length());
+ rtn = Pdd()->StartViewerFinder(iPhysAddr,iSize);
+ if ( rtn != KErrNone )
+ {
+ DP("rtn=%d",rtn);
+ iReceiving = EFalse ;
+ Kern::RequestComplete(iClient,aStatus,rtn);
+ }
+ else
+ {
+ DP("rtn=%d",rtn);
+ // Example Platform Security capability check which tests the
+ // client for ECapability_None (which always passes)...
+ if ( iRequesting == EFalse )
+ {
+ DP("iRequesting=EFalse");
+ iReceiving = EFalse ;
+ Kern::RequestComplete(iClient,
+ iReceiveDataStatus,
+ iReceiveDataResult);
+ }
+ else
+ {
+ DP("iRequesting=ETrue");
+ iReceiveDataDescriptor=(TDes8*)a1;
+ }
+ }
+ break;
+ case RWebcameraDevice::ECapture:
+ iCaptureing = ETrue ;
+ iCaptureStatus = aStatus;
+ iCaptureBuffer->FillZ(iCaptureBuffer->MaxLength());
+ iCaptureBuffer->Zero();
+ DP("iCaptureBuffer Len=%d",iCaptureBuffer->MaxLength());
+ DP("iCaptureBuffer Len=%d",iCaptureBuffer->Length());
+ rtn = Pdd()->StartCapture(iPhysAddr,iSize);
+ DP("rtn=%d",rtn);
+ if ( rtn != KErrNone )
+ {
+ iCaptureing = EFalse ;
+ Kern::RequestComplete(iClient,aStatus,rtn);
+ }
+ else
+ {
+ if ( iRequesting == EFalse )
+ {
+ DP("iRequesting=EFalse");
+ iReceiving = EFalse ;
+ Kern::RequestComplete(iClient,iCaptureStatus,iCaptureResult);
+ }
+ else
+ {
+ DP("Capture iRequesting=ETrue");
+ iCaptureDescriptor=(TDes8*)a1;
+ }
+ }
+ break;
+ default:
+ rtn=KErrNotSupported;
+ Kern::RequestComplete(iClient,aStatus,rtn);
+ break;
+ }
+ iRequesting = EFalse;
+
+ DP("DWebcameraLogicalChannel::DoRequest() end");
+ return rtn;
+
+ }
+
+/**
+ Process cancelling of asynchronous requests.
+*/
+void DWebcameraLogicalChannel::DoCancel(TUint aMask)
+ {
+ DP("DWebcameraLogicalChannel::DoCancel() start");
+ TInt rtn;
+ DP("aMask=%d",aMask);
+ if (aMask&(1<<RWebcameraDevice::EStart))
+ {
+ DP("RWebcameraDevice::EStart=%d",RWebcameraDevice::EStart);
+ if (iReceiveDataStatus)
+ {
+ DP("iReceiveDataStatus=%d",iReceiveDataStatus);
+ Pdd()->Stop(DWebcameraDriverBase::USB_cancel);
+ iReceiving = EFalse ;
+ iReceiveDataDfc.Cancel();
+ Kern::RequestComplete(iClient,iReceiveDataStatus,KErrCancel);
+ }
+ }
+ if (aMask&(1<<RWebcameraDevice::ECapture))
+ {
+ DP("RWebcameraDevice::ECapture=%d",RWebcameraDevice::ECapture);
+ if (iCaptureStatus)
+ {
+ Pdd()->Stop(DWebcameraDriverBase::USB_cancel);
+ iReceiving = EFalse ;
+ iCaptureDfc.Cancel();
+ Kern::RequestComplete(iClient,iCaptureStatus,KErrCancel);
+ }
+ }
+ DP("DWebcameraLogicalChannel::DoCancel() end");
+ }
+
+/**
+ Called by PDD from ISR to indicate that a ReceiveData operation has completed.
+*/
+void DWebcameraLogicalChannel::GetOneFlameComplete(TInt aDataSize)
+ {
+ DP("DWebcameraLogicalChannel::GetOneFlameComplete() start");
+ DP("datasize=%d",aDataSize);
+ iSaveSize=iSize - aDataSize;
+ // Queue DFC
+ iReceiveDataDfc.Add();
+ //set size of received data
+ if (iSaveSize > 0)
+ {
+ iReceiveDataResult = KErrNone;
+ }
+ else
+ {
+ iReceiveDataResult = KErrUnknown;//TODO:define of error
+ }
+ DP("DWebcameraLogicalChannel::GetOneFlameComplete() end");
+ }
+
+/**
+ Called by PDD from ISR to indicate that a get capture image operation has completed.
+*/
+void DWebcameraLogicalChannel::CaptureComplete(TInt aDataSize)
+ {
+ DP("DWebcameraLogicalChannel::CaptureComplete() start");
+ DP("datasize=%d",aDataSize);
+ iSaveSize=iSize - aDataSize;
+ // Queue DFC
+ iCaptureDfc.Add();
+ //set size of received data
+ if (iSaveSize > 0)
+ {
+ iCaptureResult = KErrNone;
+ }
+ else
+ {
+ iCaptureResult = KErrUnknown;//TODO:define of error
+ }
+ DP("DWebcameraLogicalChannel::CaptureComplete() end");
+ }
+
+/**
+ DFC Callback which gets triggered after the PDD has signalled that getting oneflame completed.
+ This just casts aPtr and calls DoGetOneFlameComplete().
+*/
+void DWebcameraLogicalChannel::GetOneFlameDfc(TAny* aPtr)
+ {
+ DP("DWebcameraLogicalChannel::GetOneFlameDfc() start");
+ ((DWebcameraLogicalChannel*)aPtr)->DoGetOneFlameComplete();
+ DP("DWebcameraLogicalChannel::GetOneFlameDfc() end");
+ }
+
+/**
+ DFC Callback which gets triggered after the PDD has signalled that getting Capture image completed.
+ This just casts aPtr and calls DoCaptureComplete().
+*/
+void DWebcameraLogicalChannel::CaptureDfc(TAny* aPtr)
+ {
+ DP("DWebcameraLogicalChannel::CaptureDfc() start");
+ ((DWebcameraLogicalChannel*)aPtr)->DoCaptureComplete();
+ DP("DWebcameraLogicalChannel::CaptureDfc() end");
+ }
+
+/**
+ Called from a DFC after the PDD has signalled that getting oneflame completed.
+*/
+void DWebcameraLogicalChannel::DoGetOneFlameComplete()
+ {
+ DP("DWebcameraLogicalChannel::DoGetOneFlameComplete() start");
+ iReceiveDataBuffer->Copy(iLAdr,iSaveSize);
+ DP("iReceiveDataBuffer Len=%d",iReceiveDataBuffer->Length());
+ // Write data to client from our buffer
+ TInt result=Kern::ThreadDesWrite(iClient,iReceiveDataDescriptor,*iReceiveDataBuffer,0);
+ // Finished with client descriptor, so NULL it to help detect coding errors
+ iReceiveDataDescriptor = NULL;
+
+ // Use result code from PDD if it was an error
+ if(iReceiveDataResult!=KErrNone)
+ result = iReceiveDataResult;
+
+ // Complete clients request
+ Kern::RequestComplete(iClient,iReceiveDataStatus,result);
+ DP("DWebcameraLogicalChannel::DoGetOneFlameComplete() end");
+ }
+
+/**
+ Called from a DFC after the PDD has signalled that getting Capture image completed.
+*/
+void DWebcameraLogicalChannel::DoCaptureComplete()
+ {
+ DP("DWebcameraLogicalChannel::DoCaptureComplete() start");
+ iCaptureBuffer->Copy(iLAdr,iSaveSize);
+ DP("iCaptureBuffer Len=%d",iCaptureBuffer->Length());
+ // Write data to client from our buffer
+ TInt result=Kern::ThreadDesWrite(iClient,iCaptureDescriptor,*iCaptureBuffer,0);
+ // Finished with client descriptor, so NULL it to help detect coding errors
+ iCaptureDescriptor = NULL;
+
+ // Use result code from PDD if it was an error
+ if(iCaptureResult!=KErrNone)
+ result = iCaptureResult;
+
+ // Complete clients request
+ Kern::RequestComplete(iClient,iCaptureStatus,result);
+ DP("DWebcameraLogicalChannel::DoCaptureComplete() end");
+ }
+
+/**
+ Process a GetConfig control message. This writes the current driver configuration to a
+ RWebcameraDevice::TConfigBuf supplied by the client.
+*/
+TInt DWebcameraLogicalChannel::GetConfig(TDes8* aConfigBuf)
+ {
+ //unsupported
+ }
+
+/**
+ Process a SetConfig control message. This sets the driver configuration using a
+ RWebcameraDevice::TConfigBuf supplied by the client.
+*/
+TInt DWebcameraLogicalChannel::SetConfig(const TDesC8* aConfigBuf)
+ {
+ //unsupported
+ }
+
+/**
+ Fill a TConfig with the drivers current configuration.
+*/
+/*void DWebcameraLogicalChannel::CurrentConfig(RWebcameraDevice::TConfig& aConfig)
+ {
+ //unsupported
+ }
+*/
+
+/**
+ *Get the point to Physical channel.
+ */
+DWebcameraDriverBase* DWebcameraLogicalChannel::Pdd()
+ {
+ DP("DWebcameraLogicalChannel::Pdd() start");
+ return (DWebcameraDriverBase*)iPdd;
+ }
+