plugins/consoles/vt100cons/src/usb/vtc_usb.cpp
changeset 62 60f47003f4b1
parent 0 7f656887cf89
child 63 6a2083f7eeb8
--- a/plugins/consoles/vt100cons/src/usb/vtc_usb.cpp	Thu Sep 16 15:06:08 2010 +0100
+++ b/plugins/consoles/vt100cons/src/usb/vtc_usb.cpp	Mon Sep 20 15:37:51 2010 +0100
@@ -20,6 +20,14 @@
 	return new CUsbConsole;
 	}
 	
+TUsbPortConfig::TUsbPortConfig()
+	:iPort(KNullDesC), iPersonality(-1)
+	{
+	}
+
+#define ErrOrDebug(err) (((err) < 0  && (err) != KErrAlreadyExists) ? EError : EDebug)
+
+
 //______________________________________________________________________________
 //						CUsbConsole
 CUsbConsole::CUsbConsole()
@@ -33,18 +41,18 @@
 	
 void CUsbConsole::ConstructL(const TDesC& aTitle)
 	{
+	TUsbPortConfig portConfig;
+	User::LeaveIfError(ReadConfig(aTitle, portConfig));
+
 	User::LeaveIfError(iUsb.Connect());
 	
 	TRequestStatus stat;
-	// assume USB device already started
-	/*iUsb.Start(stat);
-	User::WaitForRequest(stat);
-	// KErrAccessDenied returned if already started;
-	if (stat.Int()!=KErrAccessDenied)
+	if (portConfig.iPersonality >= 0)
 		{
-		Message(EError, KUsbError, stat.Int(), 1);
-		User::LeaveIfError(stat.Int());
-		}*/
+		iUsb.TryStart(portConfig.iPersonality, stat);
+		User::WaitForRequest(stat);
+		Message(ErrOrDebug(stat.Int()), _L("Starting USB personality %d returned %d"), portConfig.iPersonality, stat.Int());
+		}
 
 	// Wait for an enumeration that supports ACM (this is so that if the device defaulted to say mass storage and was then reconfigured to a personality with ACM, we wait for the ACM reconfiguration
 	TBool gotAcm = EFalse;
@@ -52,12 +60,15 @@
 		{
 		TUsbDeviceState usbState;
 		User::LeaveIfError(iUsb.GetDeviceState(usbState));
-		if (usbState & EUsbDeviceStateConfigured)
+		if (usbState & (EUsbDeviceStateConfigured|EUsbDeviceStatePowered)) // We should only need to check for EUsbDeviceStateConfigured, but some HW doesn't go to configured state if the cable is inserted before USB is started
 			{
 			// Check if we have ACM
 			TInt currentPersonality;
-			User::LeaveIfError(iUsb.GetCurrentPersonalityId(currentPersonality));
-			User::LeaveIfError(iUsb.ClassSupported(currentPersonality, KECACMUid, gotAcm));
+			TInt err = iUsb.GetCurrentPersonalityId(currentPersonality);
+			if (!err)
+				{
+				err = iUsb.ClassSupported(currentPersonality, KECACMUid, gotAcm);
+				}
 			_LIT(KGotIt, "Current USB personality has ACM, proceeding");
 			_LIT(KNotGotIt, "Current USB personality doesn't have ACM, waiting for re-enumeration");
 			if (gotAcm) Message(EInformation, KGotIt);
@@ -69,7 +80,7 @@
 			// We're not enumerated, or we are but don't have ACM. So wait for a (re-)enumeration
 			_LIT(KWaitingForEnumeration, "Waiting for USB enumeration (please connect USB cable)");
 			Message(EInformation, KWaitingForEnumeration);
-			iUsb.DeviceStateNotification(EUsbDeviceStateConfigured, usbState, stat);
+			iUsb.DeviceStateNotification(EUsbDeviceStateConfigured|EUsbDeviceStatePowered, usbState, stat);
 			User::WaitForRequest(stat);
 			if (stat.Int() != KErrNone)
 				{
@@ -77,8 +88,8 @@
 				Message(EError, KUsbError, stat.Int());
 				User::Leave(stat.Int());
 				}
-			_LIT(KUsbEnumerated, "USB cable connected.");
-			Message(EInformation, KUsbEnumerated);
+			_LIT(KUsbEnumerated, "USB state changed to %d.");
+			Message(EInformation, KUsbEnumerated, usbState);
 			}
 		}
 	
@@ -107,7 +118,46 @@
 		Message(EInformation, _L("Preamble script failed with %d"), err);
 		}
 
-	//TODO should we ensure that the port passed in here is an ACM::%s port?
-	Message(EInformation, _L("Opening %S"), &aTitle);
-	CVtcSerialConsole::ConstructL(aTitle);
+	Message(EInformation, _L("Opening %S"), &portConfig.iPort);
+	CVtcSerialConsole::ConstructL(portConfig.iPort);
 	}
+
+TInt CUsbConsole::ReadConfig(const TDesC& aConfigDes, TUsbPortConfig& aConfig)
+	{
+	_LIT(KKeywordPort, "port");
+	_LIT(KKeywordPersonality, "personality");
+
+	TBool keywordFound(EFalse);
+	TLex lex(aConfigDes);
+	while (!lex.Eos())
+		{
+		TPtrC keyword;
+		TPtrC value;
+		TInt err = ReadKeywordValuePair(lex, keyword, value);
+		if (err != KErrNone)
+			{
+			break;
+			}
+
+		if (keyword == KKeywordPort)
+			{
+			aConfig.iPort.Set(value);
+			keywordFound = ETrue;
+			}
+		else if (keyword == KKeywordPersonality)
+			{
+			TLex lex(value);
+			TInt err = lex.Val(aConfig.iPersonality);
+			if (err) return err;
+			keywordFound = ETrue;
+			}
+		}
+
+	if (!keywordFound)
+		{
+		// Treat unrecognised string as a port (to preserve backwards compatibility with earlier releases).
+		aConfig.iPort.Set(aConfigDes);
+		}
+
+	return KErrNone;
+	}