baseport/syborg/webcamera/webcamera_ldd.cpp
changeset 52 0dfaca43d90e
child 124 606eafc6d6a8
--- /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;
+	}
+