usbmgmt/usbmgr/device/classdrivers/acm/classimplementation/ecacm/src/ActiveDataAvailableNotifier.cpp
changeset 0 c9bc50fca66e
child 29 59aa7d6e3e0f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usbmgmt/usbmgr/device/classdrivers/acm/classimplementation/ecacm/src/ActiveDataAvailableNotifier.cpp	Tue Feb 02 02:02:59 2010 +0200
@@ -0,0 +1,168 @@
+/*
+* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+#include <e32std.h>
+#include <d32usbc.h>
+#include "ActiveDataAvailableNotifier.h"
+#include "AcmConstants.h"
+#include "AcmPanic.h"
+#include "AcmUtils.h"
+#include "NotifyDataAvailableObserver.h"
+#include <usb/usblogger.h>
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, "ECACM");
+#endif
+
+CActiveDataAvailableNotifier::CActiveDataAvailableNotifier(
+								MNotifyDataAvailableObserver& aParent, 
+								RDevUsbcClient& aLdd,
+								TEndpointNumber aEndpoint)
+ :	CActive(KEcacmAOPriority), 
+	iParent(aParent),
+	iLdd(aLdd),
+	iEndpoint(aEndpoint)
+/**
+ * Constructor.
+ *
+ * @param aParent The object that will be notified if a 
+ * NotifyDataAvailable() request has been made and incoming data 
+ * arrives at the LDD.
+ * @param aLdd The LDD handle to be used for posting read requests.
+ * @param aEndpoint The endpoint to read from.
+ */
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CActiveDataAvailableNotifier::~CActiveDataAvailableNotifier()
+/**
+ * Destructor.
+ */
+	{
+	LOG_FUNC
+
+	Cancel();
+	}
+
+CActiveDataAvailableNotifier* CActiveDataAvailableNotifier::NewL(
+								MNotifyDataAvailableObserver& aParent, 
+								RDevUsbcClient& aLdd,
+								TEndpointNumber aEndpoint)
+/**
+ * Standard two phase constructor.
+ *
+ * @param aParent The object that will be notified if a 
+ * NotifyDataAvailable() request has been made and incoming data 
+ * arrives at the LDD.
+ * @param aLdd The LDD handle to be used for posting read requests.
+ * @param aEndpoint The endpoint to read from.
+ * @return Ownership of a new CActiveReadOneOrMoreReader object.
+ */
+	{
+	LOG_STATIC_FUNC_ENTRY
+
+	CActiveDataAvailableNotifier* self = 
+		new(ELeave) CActiveDataAvailableNotifier(aParent, aLdd, aEndpoint);
+	return self;
+	}
+
+void CActiveDataAvailableNotifier::NotifyDataAvailable()
+/**
+ * When incoming data arrives at the LDD notify the caller.
+ */
+	{
+	LOGTEXT(_L8(">>CActiveDataAvailableNotifier::NotifyDataAvailable"));
+
+	iLdd.ReadOneOrMore(iStatus, iEndpoint, iUnusedBuf, 0);
+	SetActive();
+
+	LOGTEXT(_L8("<<CActiveDataAvailableNotifier::NotifyDataAvailable"));
+	}
+
+void CActiveDataAvailableNotifier::DoCancel()
+/**
+ * Cancel an outstanding request.
+ */
+	{
+	LOG_FUNC
+
+	iLdd.ReadCancel(iEndpoint);
+	}
+
+void CActiveDataAvailableNotifier::RunL()
+/**
+ * This function will be called when the zero byte ReadOneOrMore() call on the LDD
+ * completes. This could have been caused by the receipt of a Zero Length Packet in
+ * which case there is no data available to be read. In this situation 
+ * NotifyDataAvailable() is called again, otherwise the parent is notified.
+ * We also have to be careful about getting into an infinite loop if the cable has 
+ * been detached.
+ */
+	{
+	LOG_LINE
+	LOG_FUNC
+	LOGTEXT2(_L8("\tiStatus = %d"), iStatus.Int());
+	
+	TBool complete = EFalse;
+	TInt completeErr = KErrNone;
+
+	TInt recBufSize;
+	TInt err = iLdd.QueryReceiveBuffer(iEndpoint, recBufSize);
+	if ( err == KErrNone )
+		{
+		if ( recBufSize != 0 )
+			{
+			// There is data available.
+			complete = ETrue;
+			completeErr = KErrNone;
+			}
+		else
+			{
+			// There is no data available. This may be because we got a ZLP, but 
+			// before we simply repost the notification, check to see if the LDD 
+			// is still working. If there isn't then we should complete to the 
+			// client to avoid getting ourselves into an infinite loop.
+			if ( iStatus.Int() == KErrNone )
+				{
+				NotifyDataAvailable();
+				}
+			else
+				{
+				complete = ETrue;
+				// The Active Reader and Active Writer objects pass LDD-specific 
+				// errors straight up the stack, so I don't see a problem with 
+				// doing the same here. [As opposed to genericising them into 
+				// KErrCommsLineFail for instance.]
+				completeErr = iStatus.Int();
+				}
+			}
+		}
+	else // QueryReceiveBuffer failed
+		{
+		complete = ETrue;
+		completeErr = err;
+		}
+
+	if ( complete )
+		{
+		iParent.NotifyDataAvailableCompleted(completeErr);
+		}
+	}
+
+//
+// End of file