Fixed bridge USB config.
authorTom Sutcliffe <thomas.sutcliffe@accenture.com>
Mon, 20 Sep 2010 15:37:51 +0100
changeset 62 60f47003f4b1
parent 61 4349d4d62266
child 63 6a2083f7eeb8
Fixed bridge USB config.
build/s60/tb92/vt100usbcons_preamble.script
commands/usb/usb.cpp
core/group/autostart.script
core/group/comm.script
documentation/change_history.pod
plugins/consoles/vt100cons/doc/vt100cons.pod
plugins/consoles/vt100cons/src/usb/vtc_usb.cpp
plugins/consoles/vt100cons/src/usb/vtc_usb.h
plugins/consoles/vt100cons/src/vtc_busdevcons.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/s60/tb92/vt100usbcons_preamble.script	Mon Sep 20 15:37:51 2010 +0100
@@ -0,0 +1,17 @@
+#!fshell
+# vt100usbcons_preamble.script
+# 
+# Copyright (c) 2010 Accenture. All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the "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:
+# Accenture - Initial contribution
+#
+
+# This is needed to prevent TRK from hogging the USB port on DFS.
+
+kill --all --match trkserver*
+sleep 1 # Give USB time to clean up trk's death
--- a/commands/usb/usb.cpp	Thu Sep 16 15:06:08 2010 +0100
+++ b/commands/usb/usb.cpp	Mon Sep 20 15:37:51 2010 +0100
@@ -68,6 +68,9 @@
 	}
 
 #define CASE_LIT(x) case x: { _LIT(KName, #x); return &KName; }
+#define CASE_LIT2(x, y) case x: { _LIT(KName, y); return &KName; }
+
+_LIT(KUnknown, "?");
 
 const TDesC* DeviceState(TUsbDeviceState aState)
 	{
@@ -82,7 +85,6 @@
 		CASE_LIT(EUsbDeviceStateSuspended);
 		default:
 			{
-			_LIT(KUnknown, "?");
 			return &KUnknown;
 			}
 		}
@@ -98,10 +100,19 @@
 		CASE_LIT(EUsbServiceStopping);
 		CASE_LIT(EUsbServiceFatalError);
 		default:
-			{
-			_LIT(KUnknown, "?");
 			return &KUnknown;
-			}
+		}
+	}
+
+const TDesC* ClassName(TUid aClass)
+	{
+	switch (aClass.iUid)
+		{
+		CASE_LIT2(0x101FBF22, "ACM");
+		CASE_LIT2(0x101fbf24, "Obex");
+		CASE_LIT2(0x10204bbc, "Mass storage");
+		default:
+			return &KUnknown;
 		}
 	}
 
@@ -118,10 +129,26 @@
 	Printf(_L("Usb Service state = %S (%d)\r\n"), ServiceState(servicestate), servicestate);
 
 	RArray<TInt> ids;
+	CleanupClosePushL(ids);
 	LeaveIfErr(iUsb.GetPersonalityIds(ids), _L("Couldn't get personalities ids"));
 	for (TInt i = 0; i < ids.Count(); i++)
 		{
 		Printf(_L("Personality %d\r\n"), ids[i]);
+		RArray<TUid> classUids;
+		CleanupClosePushL(classUids);
+		TInt err = iUsb.GetSupportedClasses(ids[i], classUids);
+		if (err)
+			{
+			PrintWarning(_L("Couldn't get classes for personality %d, err=%d"), ids[i], err);
+			}
+		else
+			{
+			for (TInt classIdx = 0; classIdx < classUids.Count(); classIdx++)
+				{
+				Printf(_L("    0x%08x (%S)\r\n"), classUids[classIdx], ClassName(classUids[classIdx]));
+				}
+			}
+		CleanupStack::PopAndDestroy(&classUids);
 		}
 
 	if (iArguments.IsPresent(&iPersonality))
@@ -132,4 +159,5 @@
 		LeaveIfErr(stat.Int(), _L("Couldn't start USB personality %d"), iPersonality);
 		Printf(_L("USB started ok.\r\n"));
 		}
+	CleanupStack::PopAndDestroy(&ids);
 	}
--- a/core/group/autostart.script	Thu Sep 16 15:06:08 2010 +0100
+++ b/core/group/autostart.script	Mon Sep 20 15:37:51 2010 +0100
@@ -11,4 +11,4 @@
 # Accenture - Initial contribution
 #
 
-source $SCRIPT_PATH\comm.script
+source comm.script
--- a/core/group/comm.script	Thu Sep 16 15:06:08 2010 +0100
+++ b/core/group/comm.script	Mon Sep 20 15:37:51 2010 +0100
@@ -31,6 +31,9 @@
 # QEMU simulator - assumes you're using 2nd emulated serial port for fshell, ie with options similar to "-serial file:rdebug.txt -serial COMx"
 variant qemu && export ARGS "--console vt100busdevcons --console-title pdd=eserial,ldd=ecomm,rate=115200,port=1"
 
+# Bridge - terminal keyboard is broken for some reason, but USB now works
+variant -u 0x85001100 && export ARGS "--console vt100usbcons --console-title port=ACM::1,personality=1"
+
 # Add new variants here
 
 
--- a/documentation/change_history.pod	Thu Sep 16 15:06:08 2010 +0100
+++ b/documentation/change_history.pod	Mon Sep 20 15:37:51 2010 +0100
@@ -14,6 +14,16 @@
 
 =head1 FShell Change History
 
+=head2 Release 002 [Not yet released]
+
+=over 5
+
+=item *
+
+Added support for automatically starting a USB personality to vt100usbcons via a new C<personality=x> key-value pair. See the L<vt100usbcons|vt100cons/usb variant> documentation for more information.
+
+=back
+
 =head2 Release 001
 
 =over 5
--- a/plugins/consoles/vt100cons/doc/vt100cons.pod	Thu Sep 16 15:06:08 2010 +0100
+++ b/plugins/consoles/vt100cons/doc/vt100cons.pod	Mon Sep 20 15:37:51 2010 +0100
@@ -122,7 +122,27 @@
 
 =head2 USB Variant
 
-Vt100usbcons behaves the same as the serial variant, with the exception that it waits for USB to enumerate into a personality that supports ACM if not already present. In other words it waits for the USB cable to be inserted before trying to open the port. If necessary it also waits for the user to select a config that includes some USB serial ports. It expects the C<--console-title> argument to be of the format C<ACM::x> where x is the port number. This number is platform-specific but is usually 0 or 1. Generally this will be taken care of already in the platform-specific build of the toolkit and you can just launch the "fshell (USB)" icon.
+Vt100usbcons behaves the same as the serial variant, with the exception that it waits for USB to enumerate into a personality that supports ACM if not already present. In other words it waits for the USB cable to be inserted before trying to open the port. If necessary it also waits for the user to select a config that includes some USB serial ports. 
+
+vt100usbcons.dll is configured via the C<--console-title> string in a similar way to the serial variant. The follow keyword / value pairs are supported:
+
+=over 5
+
+=item * C<port=name>
+
+The USB port name. This is platform specific but is usually C<ACM::0> or C<ACM::1>. Generally this will be taken care of already in the platform-specific configuration and you can just launch the "fshell (USB)" icon or run "comm.script".
+
+=item * C<personality=value>
+
+If it is necessary to start a USB personality before connecting, specify the personality number here, for example C<personality=1>. This parameter is not usually needed except on some text-shell builds.
+
+=back
+
+Example usage:
+
+  fshell --console vt100usbcons --console-title port=ACM::1,personality=1
+
+For compatibility with earlier releases, the C<port=> may be ommitted if there are no other configuration parameters. For example "fshell --console vt100usbcons --console-title ACM::1".
 
 =head2 Bluetooth Variant
 
--- 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;
+	}
--- a/plugins/consoles/vt100cons/src/usb/vtc_usb.h	Thu Sep 16 15:06:08 2010 +0100
+++ b/plugins/consoles/vt100cons/src/usb/vtc_usb.h	Mon Sep 20 15:37:51 2010 +0100
@@ -17,6 +17,15 @@
 #include <usbman.h>
 #include "vtc_serial.h"
 
+class TUsbPortConfig
+	{
+public:
+	TUsbPortConfig();
+
+	TPtrC iPort;
+	TInt iPersonality;
+	};
+
 NONSHARABLE_CLASS(CUsbConsole) : public CVtcSerialConsole
 	{
 public:
@@ -25,6 +34,9 @@
 private: // From CVtcSerialConsole.
 	virtual void ConstructL(const TDesC& aTitle);
 private:
+	TInt ReadConfig(const TDesC& aConfigDes, TUsbPortConfig& aConfig);
+
+private:
 	RUsb iUsb;
 	};
 
--- a/plugins/consoles/vt100cons/src/vtc_busdevcons.cpp	Thu Sep 16 15:06:08 2010 +0100
+++ b/plugins/consoles/vt100cons/src/vtc_busdevcons.cpp	Mon Sep 20 15:37:51 2010 +0100
@@ -106,7 +106,8 @@
 		else if (keyword == KKeywordPort)
 			{
 			TLex lex(value);
-			User::LeaveIfError(lex.Val(aConfig.iPort));
+			TInt err = lex.Val(aConfig.iPort);
+			if (err) return err;
 			keywordFound = ETrue;
 			}
 		else if (keyword == KKeywordRate)