merge last changes from 3.0 RCL_2_4
authorChad Peckham <chad.peckham@nokia.com>
Mon, 22 Mar 2010 17:42:44 -0500
branchRCL_2_4
changeset 1124 f68b7751b408
parent 1117 74cd9ab9faa5
child 1125 07b11b189a25
merge last changes from 3.0
connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/agent/PCCSDiscoveryAgent.java
connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/messages.properties
connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/DMAPIDefinitions.java
connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/IConnAPILibrary.java
connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/PCCSConnection.java
--- a/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/agent/PCCSDiscoveryAgent.java	Fri Mar 19 14:43:14 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/agent/PCCSDiscoveryAgent.java	Mon Mar 22 17:42:44 2010 -0500
@@ -162,8 +162,12 @@
 			try {
 				do {
 					if (DEBUG) System.out.println("updateThread updating: " + numPendingUpdates);
-					updateConnections2(pccs.getGoodConnectionList());
-					numPendingUpdates--;
+					if (numPendingUpdates > 1) {
+						numPendingUpdates--;
+					} else {
+						updateConnections2(pccs.getGoodConnectionList());
+						numPendingUpdates--;
+					}
 				} while (numPendingUpdates > 0);
 				
 				if (DEBUG) System.out.println("updateThread exiting");
--- a/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/messages.properties	Fri Mar 19 14:43:14 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/messages.properties	Mon Mar 22 17:42:44 2010 -0500
@@ -1,8 +1,8 @@
 Activator_Agent_Name=PC Suite Device Discovery Agent
 Activator_PCCS_Location=http://www2.connecting.nokia.com/nmp/swp/pcsuite.nsf/document/ES336ZAHVY?OpenDocument
 Activator_PCSuite_Location=https://tools.ext.nokia.com/PCsuite
-ConnAPILibrary_PCCS_Not_Found_Error=Agent could not find a PC Connectivity Solution (PCCS) installation. For more information go to: 
-ConnAPILibrary_PCSuite_Not_Found_Error=Agent could not find a PC Suite installation. To install PC Suite, go to: 
+ConnAPILibrary_PCCS_Not_Found_Error=Carbide could not find the PC Connectivity Solution (PCCS) installation. For more information go to: 
+ConnAPILibrary_PCSuite_Not_Found_Error=Carbide could not find a PC Suite installation. To install PC Suite, go to: 
 GUID_0=Wrong array size \!
 PCCSConnection_Bad_Personality_DontSwitch_Warning1=The "{0}" device is currently in "{1}" USB personality, which is not compatible with on-device debugging. 
 PCCSConnection_Bad_Personality_DontSwitch_Warning2=Switch to "{2}" personality in order to do debugging.
@@ -12,10 +12,10 @@
 PCCSConnection_PCCS_CONARegisterNotifyCallback_Error=PCCS CONARegisterNotifyCallback API returned error %x
 PCCSConnection_PCCS_CONARegisterNotifyCallback_Pointer_Error=PCCS CONARegisterNotifyCallback API contained an invalid function pointer
 PCCSConnection_PCCS_Not_Enough_Memory_Error=Not enough memory to open the PCCS Device Management connection
-PCCSConnection_PCCS_Version_Error=The requested PC Connectivity Solution DMAPI version (3.4) is not installed on this machine. To install a later version go to: 
-PCCSConnection_PCSuite_Version_Error=The current PC Suite installation does not support the required level of API for this agent. To install a later version go to: 
+PCCSConnection_PCCS_Version_Error=Carbide requires a later version of the PC Connectivity Solution (PCCS) installed. To install a later version go to: 
+PCCSConnection_PCSuite_Version_Error=Carbide requires a later version of the PC/OVI Suite installed. To install a later version go to: 
 PCCSConnection_Personality_Switch_Error=Connected device "{0}" does not support getting/setting the USB personality from the current personality.
-PCCSDiscoveryAgent_PCCS_Not_Found_Error=Agent could not find the PC Connectivity Solution (PCCS) installation.
-PCCSDiscoveryAgent_PCCS_Version_Error=Agent requires a later version of the PC Connectivity Solution (PCCS) installed.
-PCCSDiscoveryAgent_PCSuite_Not_Found_Error=Agent could not find a PC Suite installation.
-PCCSDiscoveryAgent_PCSuite_Version_Error=Agent requires a later version of the PC Suite installed.
+PCCSDiscoveryAgent_PCCS_Not_Found_Error=Carbide could not find the PC Connectivity Solution (PCCS) installation.
+PCCSDiscoveryAgent_PCCS_Version_Error=Carbide requires a later version of the PC Connectivity Solution (PCCS) installed.
+PCCSDiscoveryAgent_PCSuite_Not_Found_Error=Carbide could not find a PC Suite installation.
+PCCSDiscoveryAgent_PCSuite_Version_Error=Carbide requires a later version of the PC/OVI Suite installed.
--- a/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/DMAPIDefinitions.java	Fri Mar 19 14:43:14 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/DMAPIDefinitions.java	Mon Mar 22 17:42:44 2010 -0500
@@ -33,6 +33,7 @@
 	public static final int DMAPI_VERSION_35		=35;
 	public static final int DMAPI_VERSION_36		=36;
 	public static final int DMAPI_VERSION_37		=37;
+	public static final int DMAPI_VERSION_38		=38;
 	//=========================================================
 	// Device callback status values
 	public static final int CONAPI_DEVICE_LIST_UPDATED		=0x00;	// List is updated. No any specific information.
--- a/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/IConnAPILibrary.java	Fri Mar 19 14:43:14 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/IConnAPILibrary.java	Mon Mar 22 17:42:44 2010 -0500
@@ -62,9 +62,9 @@
 	int MCAPI_GetAPIVersion();
 	int CONAOpenMM(LPAPIHANDLE phMCHandle, int dwValue);
 	int CONACloseMM(APIHANDLE hMCHandle);
-	int CONAMMGetMedia(APIHANDLE hMCHandle, IntBuffer pdwCountOfMedia, CONAPI_MEDIA.ByReference[] ppMedia); //TODO: c++ - CONAPI_MEDIA**	ppMedia
-	int CONAMMGetMedia(APIHANDLE hMCHandle, IntBuffer pdwCountOfMedia, CONAPI_MEDIA.ByReference ppMedia); //TODO: c++ - CONAPI_MEDIA**	ppMedia
-	int CONAMMGetMedia(APIHANDLE hMCHandle, IntBuffer pdwCountOfMedia, PointerByReference ppMedia); //TODO: c++ - CONAPI_MEDIA**	ppMedia
+	int CONAMMGetMedia(APIHANDLE hMCHandle, IntBuffer pdwCountOfMedia, CONAPI_MEDIA.ByReference[] ppMedia);
+	int CONAMMGetMedia(APIHANDLE hMCHandle, IntBuffer pdwCountOfMedia, CONAPI_MEDIA.ByReference ppMedia);
+	int CONAMMGetMedia(APIHANDLE hMCHandle, IntBuffer pdwCountOfMedia, PointerByReference ppMedia);
 	int CONAMMSetMedia(APIHANDLE hMCHandle, CONAPI_MEDIA[] pMedia);
 	int CONAMMSetMedia(APIHANDLE hMCHandle, Pointer pMedia);
 	int CONAMMFreeMediaStructures(int dwCountOfMedia, CONAPI_MEDIA[] pMedia);
--- a/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/PCCSConnection.java	Fri Mar 19 14:43:14 2010 -0500
+++ b/connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/PCCSConnection.java	Mon Mar 22 17:42:44 2010 -0500
@@ -43,6 +43,8 @@
 
 	private static final String NOT_KNOWN = "not known"; //$NON-NLS-1$ // used for all string structure elements that come back from PCCS as null
 	private boolean DEBUG = false;
+	private volatile boolean pendingEvents;
+	private boolean DEBUG_EVENTS = false;
 	
 	public class DeviceNotificationCallback implements IConnAPIDeviceCallback {
 
@@ -54,7 +56,7 @@
 			//  and the serial number is not filled in. If the serial number is null,
 			//  everything else will be null (according to the PCCS docs)
 			//  TODO: bug in PCCS API: 
-			if (DEBUG) System.out.printf("DeviceNotificationCallback %x %s\n", dwStatus, (pstrSerialNumber == null ? "serNum: null" : pstrSerialNumber.getPointer().getString(0, true))); //$NON-NLS-1$ //$NON-NLS-2$
+			if (DEBUG_EVENTS) System.out.printf("DeviceNotificationCallback %x %s\n", dwStatus, (pstrSerialNumber == null ? "serNum: null" : pstrSerialNumber.getPointer().getString(0, true))); //$NON-NLS-1$ //$NON-NLS-2$
 			String serialNumber = NOT_KNOWN;
 			if (pstrSerialNumber != null) {
 				serialNumber = pstrSerialNumber.getPointer().getString(0, true);
@@ -86,7 +88,8 @@
 				}
 			}
 			// fire events
-			if (DEBUG) System.out.println("DeviceNotificationCallback: fire events");
+			pendingEvents = true;
+			if (DEBUG_EVENTS) System.out.println("DeviceNotificationCallback: fire events pendingEvents: " + pendingEvents);
 			Iterator<DeviceEventListener> iter = listeners.iterator();
 			while (iter.hasNext()) {
 				iter.next().onDeviceEvent(eventType, serialNumber);
@@ -100,7 +103,7 @@
 	private DeviceNotificationCallback pfnCallback = new DeviceNotificationCallback();
 	public static final int PCCS_NOT_FOUND = 1;
 	public static final int PCCS_WRONG_VERSION = 2;
-	private static final int DMAPI_VERSION = DMAPIDefinitions.DMAPI_VERSION_34;
+	private static final int DMAPI_VERSION = DMAPIDefinitions.DMAPI_VERSION_38;
 	
 	private APIHANDLE dmHandle = APIHANDLE.INVALID_HANDLE_VALUE;
 	private APIHANDLE mcHandle = APIHANDLE.INVALID_HANDLE_VALUE;
@@ -393,12 +396,16 @@
 	 */
 	private DeviceInfo[] getCompleteDeviceList() {
 		DeviceInfo[] deviceInfo = null;
+		
+		// open the DMAPI
 		APIHANDLE handle = APIHANDLE.INVALID_HANDLE_VALUE;
 		try {
 			handle = loadDMAPI();
 		} catch (CoreException e) {
 			return deviceInfo;
 		}
+		
+		// get the device count
 		IntByReference pdwCount = new IntByReference(0);
 		int dwResult = library.CONAGetDeviceCount(handle, pdwCount);
 		if (DEBUG) System.out.printf("CONAGetDeviceCount: %x number of devices: %d\n", dwResult, pdwCount.getValue()); //$NON-NLS-1$
@@ -410,9 +417,9 @@
 			return deviceInfo;
 		}
 		
+		// get the device list
 		int deviceCount = pdwCount.getValue();
 		if (deviceCount > 0) {
-			
 			CONAPI_DEVICE[] pDevices = (CONAPI_DEVICE[])new CONAPI_DEVICE().toArray(deviceCount);
 			dwResult = library.CONAGetDevices(handle, pdwCount, pDevices);
 			if (DEBUG) System.out.printf("CONAGetDevices: %x number of devices: %d\n", dwResult, deviceCount); //$NON-NLS-1$
@@ -512,82 +519,68 @@
 	 * @throws CoreException
 	 */
 	public synchronized Collection<DeviceConnection> getGoodConnectionList() throws CoreException {
-		DeviceInfo[] deviceList = getCompleteDeviceList();
+
 		Collection<DeviceConnection> goodConnections = new ArrayList<DeviceConnection>();
 
+		if (DEBUG_EVENTS) System.out.println("getGoodConnectionList pendingEvents: " + pendingEvents);
+		pendingEvents = false;
+		
+		// get all DMAPI devices
+		DeviceInfo[] deviceList = getCompleteDeviceList();
+
+		// if no DMAPI devices exist
+		//   forget all previous non-switched devices
+		//   and return an empty connection list
 		if (deviceList == null) { 
-			// forget all non switched devices
 			forgetAllNoSwitchConnectionsNotInCurrentList(null);
 			return goodConnections;
 		}
+
+		// get number of expected USB devices
+		int numUSBDevicesExpected = getNumUSBDevicesExpected(deviceList);
 		
-		try {
-			loadUPAPI();
-		} catch (CoreException e) {
-			Activator.logError(e);
+		// PCSuite has a problem where a single device could have multiple USB connections
+		//   but shouldn't have... Attempt to split them out into separate devices.
+		if (numUSBDevicesExpected > 0) {
+			deviceList = adjustForMulitpleUSBConnectionsPerDevice(deviceList);
+		}
+		
+		// if we still couldn't get one USB device per DMAPI device, then error
+		if (deviceList.length < numUSBDevicesExpected) {
+			String message = MessageFormat.format(
+					"PCSuite is reporting more USB connections ({0}) than the number of connected devices ({1}). Carbide cannot match devices to USB connections. Try connecting only a single device.", 
+					numUSBDevicesExpected, deviceList.length);
+			logMessage(message, IStatus.ERROR);
 			return goodConnections;
 		}
-		boolean upapiOpen = true;
-		int numUSBDevicesExpected = 0;
-		for (DeviceInfo device : deviceList) {
-			Collection<DeviceConnectionInfo> connectionList = device.connections;
-			for (DeviceConnectionInfo connInfo : connectionList) {
-				if (connInfo.media.equals("usb")) {
-					numUSBDevicesExpected++;
-				}
-			}
-		}
-		if (DEBUG) System.out.println("numDevices: "+ deviceList.length + " numUSBDevicesExpected: " + numUSBDevicesExpected);
-		if (deviceList.length < numUSBDevicesExpected) {
-			// error - number of total devices should be equal to or more than number of USB devices
-			//   i.e., only 1 USB connection is permitted per device
-			String message = MessageFormat.format(
-					"PCSuite is reporting more USB connections ({0}) than the number of connected devices ({1}). Carbide cannot match devices to USB connections.", 
-					numUSBDevicesExpected, deviceList.length);
-			Activator.logMessage(message, IStatus.ERROR);
-			closeUPAPI();
-			return goodConnections;
-		}
-		
+
+		// if there is only one device, forget all previous devices that were
+		//  not switched to Suite mode
 		if (deviceList.length == 1) {
-			// forget all non switched devices
 			forgetAllNoSwitchConnectionsNotInCurrentList(null);
 		}
 
+		// get all the USB personalities for the current connections
 		Collection<DeviceUSBPersonalityInfo> personalityList = null;
 		if (numUSBDevicesExpected > 0) {
-			int attempt = 1;
-			do {
-				personalityList = getAllDeviceUSBPersonalities();
-				if (personalityList == null || personalityList.size() < numUSBDevicesExpected) {
-					if (DEBUG) System.out.printf("Error %d getting USB personalities: %d of %d total\n", attempt, (personalityList != null) ? personalityList.size() : 0, numUSBDevicesExpected); //$NON-NLS-1$
-					if (attempt > 10) {
-						break; // bomb - leave UPAPI open, we need it later
-					}
-					attempt++;
-					// UPAPI seems to need a reload
+			try {
+				loadUPAPI();
+				int numUSBDevices = getNumberUPAPIDevices(numUSBDevicesExpected);
+				if (numUSBDevices < numUSBDevicesExpected) {
 					closeUPAPI();
-					upapiOpen = false;
-					try {
-						Thread.sleep(1000);
-					} catch (InterruptedException e) {
-					}
-					loadUPAPI();
-					upapiOpen = true;
+					return null;
 				}
-			} while (personalityList == null || personalityList.size() < numUSBDevicesExpected);
-		}
-		// if we failed getting the USB personalities above - UPAPI will be closed
-		//  so reopen it
-		// else we finally got the USB personalities, UPAPI is still open
-		if (!upapiOpen) {
-			loadUPAPI();
-			upapiOpen = true;
+			} catch (CoreException e) {
+				closeUPAPI();
+				return null;
+			}
+			personalityList = getAllDeviceUSBPersonalities(numUSBDevicesExpected);
 		}
 		
+		// forget all previous non-suite-switched devices not in current list
 		forgetAllNoSwitchConnectionsNotInCurrentList(personalityList);
 		
-		// go through each connected device and check for good connection modes (e.g. USB in debuggable mode)
+		// go through each connected device and check for good connection modes (e.g. USB in a Suite mode)
 		if (DEBUG) System.out.printf("getGoodConnectionList: sizeof deviceList: %d\n", deviceList.length); //$NON-NLS-1$
 		for (DeviceInfo device : deviceList) {
 			Collection<DeviceConnectionInfo> connectionList = device.connections;
@@ -602,7 +595,7 @@
 						if (DEBUG) System.out.println("getGoodConnectionList: personality not found for device: " + device.friendlyName + "-- continue"); //$NON-NLS-1$
 						String msg = MessageFormat.format(Messages.PCCSConnection_Personality_Switch_Error,
 								device.friendlyName);
-						Activator.logMessage(msg, IStatus.ERROR);
+						logMessage(msg, IStatus.ERROR);
 						continue;
 					}
 					if (isGoodUSBPersonality(device, connInfo, personality)) {
@@ -632,11 +625,143 @@
 				}
 			}
 		}
-		if (upapiOpen)
-			closeUPAPI();
+		closeUPAPI();
 		
 		return goodConnections;
 	}
+	private void logMessage(String message, int error) {
+		if (DEBUG_EVENTS) System.out.println("logMessage: pendingEvents: " + pendingEvents);
+		if (pendingEvents == false)
+			Activator.logMessage(message, IStatus.ERROR);
+	}
+
+	/**
+	 * Assumes UPAPI is loaded
+	 * @param numUSBDevicesExpected
+	 * @return
+	 */
+	private int getNumberUPAPIDevices(int numUSBDevicesExpected) {
+		int numFound = 0;
+		
+		int attempt = 1;
+		do {
+			IntBuffer pdwDeviceCount = IntBuffer.allocate(1);
+			pdwDeviceCount.put(numUSBDevicesExpected);
+			int dwResult = library.UPAPI_QueryDeviceCount(upHandle, pdwDeviceCount);
+			if (dwResult == PCCSErrors.CONA_OK) {
+				numFound = pdwDeviceCount.get(0);
+				if (DEBUG) System.out.printf("getNumberUSBDevices: try=%d found=%d of %d\n", attempt, numFound, numUSBDevicesExpected);
+				if (numFound == numUSBDevicesExpected)
+					break;
+				
+				attempt++;
+				if (attempt > 10)
+					break;
+				try {
+					Thread.sleep(1000);
+				} catch (InterruptedException e) {
+				}
+				
+			} else {
+				if (DEBUG) System.out.printf("getNumberUSBDevices: try=%d dwResult=%x\n", attempt, dwResult);
+				attempt++;
+				if (attempt > 10)
+					break;
+				try {
+					Thread.sleep(1000);
+				} catch (InterruptedException e) {
+				}
+			}
+		} while (numFound < numUSBDevicesExpected);
+		if (numFound == 0) {
+			if (Activator.isSymSEELayout()) {
+				String pattern = "PCCS reported {0} devices connected to USB, but did not return any USB personalities for these devices. " +
+					"Either these devices require a later version of PCCS or the devices are not responding to part of the PCCS API. " +
+					"If the latest PCCS version is installed, try disconnecting the devices and reconnecting in PC/OVI Suite mode. " +
+					"The latest PCCS can be found here: " + Activator.getLoadErrorURL();
+				String message = MessageFormat.format(pattern, numUSBDevicesExpected);
+				logMessage(message, IStatus.ERROR);
+			} else {
+				String pattern = "PC/OVI Suite reported {0} devices connected to USB, but did not return any USB personalities for these devices. " +
+					"Either these devices require a later version of PC/OVI Suite or the devices are not responding to part of the PC/OVI Suite API. " +
+					"If the latest PC/OVI Suite version is installed, try disconnecting the devices and reconnecting in PC/OVI Suite mode. " +
+					"The latest PC/OVI Suite can be found here: " + Activator.getLoadErrorURL();
+				String message = MessageFormat.format(pattern, numUSBDevicesExpected);
+				logMessage(message, IStatus.ERROR);
+			}
+		} else if (numFound < numUSBDevicesExpected) {
+			if (Activator.isSymSEELayout()) {
+				String pattern = "PCCS reported {0} devices connected to USB, but found only {1} USB personalities for these devices. " +
+					"Either a device requires a later version of PCCS or a device is not responding to part of the PCCS API. " +
+					"If the latest PCCS version is installed, try disconnecting the device and reconnecting in PC/OVI Suite mode. " +
+					"The latest PCCS can be found here: " + Activator.getLoadErrorURL();
+				String message = MessageFormat.format(pattern, numUSBDevicesExpected, numFound);
+				logMessage(message, IStatus.ERROR);
+			} else {
+				String pattern = "PC/OVI Suite reported {0} devices connected to USB, but found only {1} USB personalities for these devices. " +
+					"Either a device requires a later version of PCSuite or a device is not responding to part of the PC/OVI Suite API. " +
+					"If the latest PC/OVI Suite version is installed, try disconnecting the device and reconnecting in PC/OVI Suite mode. " +
+					"The latest PC/OVI Suite can be found here: " + Activator.getLoadErrorURL();
+				String message = MessageFormat.format(pattern, numUSBDevicesExpected, numFound);
+				logMessage(message, IStatus.ERROR);
+			}
+		}
+		return numFound;
+	}
+
+	private int getNumUSBDevicesExpected(DeviceInfo[] deviceList) {
+		int numUSBDevicesExpected = 0;
+		for (DeviceInfo device : deviceList) {
+			Collection<DeviceConnectionInfo> connectionList = device.connections;
+			for (DeviceConnectionInfo connInfo : connectionList) {
+				if (connInfo.media.equals("usb")) {
+					numUSBDevicesExpected++;
+				}
+			}
+		}
+		if (DEBUG) System.out.println("numDevices: "+ deviceList.length + " numUSBDevicesExpected: " + numUSBDevicesExpected);
+		return numUSBDevicesExpected;
+	}
+
+	private DeviceInfo[] adjustForMulitpleUSBConnectionsPerDevice(
+			DeviceInfo[] deviceList) {
+		
+		// This is to work-around a PCSuite problem where multiple USB connections can be associated
+		//  with the same device - a no-no in current Nokia-land.
+		// This happens when the serial number coming from DMAPI is <null> and PCSuite assumes all the devices with the
+		//  same <null> serial number are the same device
+		Collection<DeviceInfo> newList = new ArrayList<DeviceInfo>();
+		for (DeviceInfo device : deviceList) {
+			if (device.numberOfConnections > 1) {
+				DeviceConnectionInfo[] connection = (DeviceConnectionInfo[]) device.connections.toArray(new DeviceConnectionInfo[device.numberOfConnections]);
+				int numUSBConnections = 0;
+				for (int i = 0; i < device.numberOfConnections; i++) {
+					if (connection[i].media.equals("usb"))
+						numUSBConnections++;
+				}
+				if (numUSBConnections > 1) {
+					for(int i = 0; i < device.numberOfConnections; i++) {
+						if (connection[i].media.equals("usb")) {
+							DeviceInfo newDevice = new DeviceInfo();
+							newDevice.serialNumber = NOT_KNOWN;
+							newDevice.friendlyName = connection[i].deviceName;
+							newDevice.mfr = device.mfr;
+							newDevice.model = NOT_KNOWN;
+							newDevice.numberOfConnections = 1;
+							newDevice.connections.add(connection[i]);
+							newList.add(newDevice);
+						}
+					}
+				} else {
+					newList.add(device);
+				}
+			} else {
+				newList.add(device);
+			}
+		}
+		return newList.toArray(new DeviceInfo[newList.size()]);
+	}
+
 	/**
 	 * Forget all previous "no-switch-personality" devices that are not in current list (e.g., device is now disconnected)
 	 * 
@@ -668,7 +793,7 @@
 	/**
 	 * Find a matching device in the personality list (all USB devices).<p>
 	 * Might have to use a combination of the serial number and device ID to match with ID's from personality.
-	 * @param numUSBPersonalities 
+	 * @param numUSBDevicesExpected 
 	 *
 	 * @param serialNumber - serial number from connectivity API
 	 * @param address - this contains the device ID from the connectivity API
@@ -677,33 +802,44 @@
 	 */
 	private DeviceUSBPersonalityInfo findPersonality(int numUSBDevicesExpected, String serialNumber, String address, Collection<DeviceUSBPersonalityInfo> personalityList) {
 	
-		if (DEBUG) System.out.println("findPersonality: start"); //$NON-NLS-1$
+		if (DEBUG) System.out.println("\nfindPersonality: start"); //$NON-NLS-1$
 		if (personalityList == null || personalityList.isEmpty()) {
-			if (DEBUG) System.out.println("findPersonality: list is empty");
+			if (DEBUG) System.out.println("findPersonality: list is empty\n");
 			return null;
 		}
 
+		int numLeft = numUSBDevicesExpected;
 		for (DeviceUSBPersonalityInfo personality : personalityList) {
 			if (DEBUG) {
-				System.out.printf("findPersonality: serialNums: %s\t%s\n", serialNumber, personality.serialNumber); //$NON-NLS-1$
+				System.out.printf("findPersonality: serialNums: device:%s\t usb:%s\n", serialNumber, personality.serialNumber); //$NON-NLS-1$
 				System.out.printf("findPersonality: address: %s\tdeviceID: %s\n", address, personality.deviceID); //$NON-NLS-1$
 			}
+			if (personality.matchedToDMDevice) {
+				if (DEBUG) System.out.println("device matched already -- continue");
+				numLeft--;
+				continue;
+			}
 			// sometimes the serial numbers match except the personality one has an added 0
 			if (!serialNumber.equals(NOT_KNOWN) && !personality.serialNumber.equals(NOT_KNOWN)) {
 				// serial number not null from both DMAPI and UPAPI
 				if (serialNumber.equals(personality.serialNumber)) {
-					if (DEBUG) System.out.println("findPersonality: serialNums match"); //$NON-NLS-1$
+					if (DEBUG) System.out.println("findPersonality: serialNums match\n"); //$NON-NLS-1$
+					personality.matchedToDMDevice = true;
 					return personality;
 				} else if (new String(serialNumber+"0").equals(personality.serialNumber)) { //$NON-NLS-1$
-					if (DEBUG) System.out.println("findPersonality: serialNums match (by appending '0' to DMAPI)"); //$NON-NLS-1$
+					if (DEBUG) System.out.println("findPersonality: serialNums match (by appending '0' to DMAPI)\n"); //$NON-NLS-1$
+					personality.matchedToDMDevice = true;
 					return personality;
 				} else {
-					if (DEBUG) System.out.println("findPersonality: both serialNums != null && serialNums do not match");  //$NON-NLS-1$
+					if (DEBUG) System.out.println("findPersonality: both serialNums != null && serialNums do not match\n");  //$NON-NLS-1$
 				}
 			}
 			// cannot use serial numbers! try using device IDs
 			if (!address.equals(NOT_KNOWN) && !personality.deviceID.equals(NOT_KNOWN)) {
-				// example device ids:
+				// example DMAPI addresses:
+				//   0\VID_0421&PID_0078\7&2382d757&0 (no serial number)
+				//   0\VID_0421&PID_007B\354172020011853 (serial number comes at end)
+				// example UPAPI device ids:
 				//   0\VID_0421&PID_00AB\0 (no serial number as part of id)
 				//   004401011418023\VID_0421&PID_0500\0 (serial number comes at front)
 				// compare Device IDs
@@ -711,37 +847,42 @@
 				String endid = address.substring(address.lastIndexOf('\\')+1);
 				if (personality.deviceID.contains(vidpid) && personality.deviceID.contains(endid)) {
 					if (DEBUG) System.out.println("findPersonality: address matches deviceID with end number\n"); //$NON-NLS-1$
+					personality.matchedToDMDevice = true;
 					return personality;
 				}
 				else if (personality.deviceID.contains(vidpid) && personality.deviceID.contains(serialNumber)) {
 					if (DEBUG) System.out.println("findPersonality: address matches deviceID with serial number\n"); //$NON-NLS-1$
+					personality.matchedToDMDevice = true;
 					return personality;
 				} else {
 					if (serialNumber.equals(NOT_KNOWN)) {
-						if (personality.deviceID.contains(vidpid) && numUSBDevicesExpected == 1) {
+						if (personality.deviceID.contains(vidpid) && numLeft == 1) {
 							if (DEBUG) System.out.println("findPersonality: serial number not known, but VID/PID match\n"); //$NON-NLS-1$
+							personality.matchedToDMDevice = true;
 							return personality;
 						}
 					}
 					String begin = personality.deviceID.substring(0, personality.deviceID.indexOf('\\'));
-					if (begin.equals("0") || numUSBDevicesExpected == 1) {
+					if (begin.equals("0") || numLeft == 1) {
 						// no serial number at beginning
 						if (personality.deviceID.contains(vidpid)) {
 							if (DEBUG) System.out.println("findPersonality: address matches deviceID without serial number\n"); //$NON-NLS-1$
+							personality.matchedToDMDevice = true;
 							return personality;
 						}
 					}
 				}
 			}
 			// sometimes the serial number is part of the address!
-			if (!address.equals(NOT_KNOWN) && !personality.serialNumber.equals(NOT_KNOWN)) {
+			if (!personality.serialNumber.equals(NOT_KNOWN)) {
 				if (address.endsWith(personality.serialNumber)) {
-					if (DEBUG) System.out.println("findPersonality: address contains serialNumber");
+					if (DEBUG) System.out.println("findPersonality: address contains serialNumber\n");
+					personality.matchedToDMDevice = true;
 					return personality;
 				}
 			}
 		}
-		if (DEBUG) System.out.println("findPersonality end return null"); //$NON-NLS-1$
+		if (DEBUG) System.out.println("findPersonality return no match\n"); //$NON-NLS-1$
 		return null;
 	}
 
@@ -834,20 +975,23 @@
 		final IStatus status = new Status(IStatus.WARNING, Activator.PLUGIN_ID, message);
 		
 		String prompt = MessageFormat.format("Switch to {0} mode now.", goodDesc);
-		
-		RemoteConnectionsActivator.getStatusDisplay().displayStatusWithAction(status, prompt, new Runnable() {
-			public void run() {
-				WString pstrDeviceId = new WString(personality.deviceID);
-				int dwResult = library.UPAPI_SetPersonality(upHandle, pstrDeviceId, goodCode);
-				if (dwResult != PCCSErrors.CONA_OK) {
-					forgetNoSwitchConnections(personality.deviceID);
-					String message = status.getMessage() + "\nThe device returned an error when trying to switch. Disconnect and reconnect in the proper mode.";
-					Activator.logMessage(message, IStatus.ERROR);
-					if (DEBUG) System.out.printf("UPAPI_SetPersonality failed: %x\n", dwResult); //$NON-NLS-1$
+
+		if (DEBUG_EVENTS) System.out.println("askToSwitchPersonality: pendingEvents: " + pendingEvents);
+
+		if (pendingEvents == false) {
+			RemoteConnectionsActivator.getStatusDisplay().displayStatusWithAction(status, prompt, new Runnable() {
+				public void run() {
+					WString pstrDeviceId = new WString(personality.deviceID);
+					int dwResult = library.UPAPI_SetPersonality(upHandle, pstrDeviceId, goodCode);
+					if (dwResult != PCCSErrors.CONA_OK) {
+						forgetNoSwitchConnections(personality.deviceID);
+						String message = status.getMessage() + "\nThe device returned an error when trying to switch. Disconnect and reconnect in the proper mode.";
+						logMessage(message, IStatus.ERROR);
+						if (DEBUG) System.out.printf("UPAPI_SetPersonality failed: %x\n", dwResult); //$NON-NLS-1$
+					}
 				}
-			}
-		});
-
+			});
+		}
 	}
 
 	/**
@@ -863,61 +1007,51 @@
 	 * This function assumes the UPAPI has already been loaded by the caller
 	 * @return - list of personalities
 	 */
-	private Collection<DeviceUSBPersonalityInfo> getAllDeviceUSBPersonalities() {
+	private Collection<DeviceUSBPersonalityInfo> getAllDeviceUSBPersonalities(int numUSBDevicesExpected) {
 		Collection<DeviceUSBPersonalityInfo> p = new ArrayList<DeviceUSBPersonalityInfo>();
 		boolean apiError = false;
 
 		// how many USB devices are connected
-		IntBuffer pdwDeviceCount = IntBuffer.allocate(1);
-		int dwResult = library.UPAPI_QueryDeviceCount(upHandle, pdwDeviceCount);
-		if (dwResult == PCCSErrors.CONA_OK) {
-			int dwDeviceCount = pdwDeviceCount.get(0);
-			if (DEBUG) System.out.printf("UPAPI_QueryDeviceCount: dwDeviceCount: %d\n", dwDeviceCount); //$NON-NLS-1$
-			if (dwDeviceCount > 0) {
-				UP_DEVICE_DESCRIPTOR[] pDeviceDescriptor = (UP_DEVICE_DESCRIPTOR[])new UP_DEVICE_DESCRIPTOR().toArray(dwDeviceCount);
-				
-				// get the descriptor for all USB device
-				dwResult = library.UPAPI_QueryDevices(upHandle, pdwDeviceCount, pDeviceDescriptor);
-				if (dwResult == PCCSErrors.CONA_OK) {
-					if (DEBUG) System.out.printf("UPAPI_QueryDevices dwDeviceCount: %d\n", dwDeviceCount); //$NON-NLS-1$
+		if (numUSBDevicesExpected > 0) {
+			UP_DEVICE_DESCRIPTOR[] pDeviceDescriptor = (UP_DEVICE_DESCRIPTOR[])new UP_DEVICE_DESCRIPTOR().toArray(numUSBDevicesExpected);
+			
+			IntBuffer pdwDeviceCount = IntBuffer.allocate(1);
+			pdwDeviceCount.put(numUSBDevicesExpected);
+			// get the descriptor for all USB device
+			int dwResult = library.UPAPI_QueryDevices(upHandle, pdwDeviceCount, pDeviceDescriptor);
+			if (dwResult == PCCSErrors.CONA_OK) {
+				if (DEBUG) System.out.printf("UPAPI_QueryDevices dwDeviceCount: %d\n", numUSBDevicesExpected); //$NON-NLS-1$
+				int numUSBDevicesFound = pdwDeviceCount.get(0);
+				UP_DEVICE_DESCRIPTOR[] devices = pDeviceDescriptor;
+				// 
+		        for (int i = 0; i < numUSBDevicesFound; i++) {
+					// save important device descriptor information for each device
+		        	DeviceUSBPersonalityInfo deviceInfo = new DeviceUSBPersonalityInfo();
 					
-					UP_DEVICE_DESCRIPTOR[] devices = pDeviceDescriptor;
-					// 
-			        for (int i = 0; i < dwDeviceCount; i++) {
-						// save important device descriptor information for each device
-			        	DeviceUSBPersonalityInfo deviceInfo = new DeviceUSBPersonalityInfo();
-						
-						// device ID is very important to get personalities and for matching with
-						//  the connectivity API
-						if (devices[i].pstrDeviceID != null) {
-							deviceInfo.deviceID = devices[i].pstrDeviceID.getPointer().getString(0, true);
-						} else {
-							deviceInfo.deviceID = NOT_KNOWN;
-						}
-						if (DEBUG) System.out.println("UPAPI_QueryDevices: ID found: " + deviceInfo.deviceID);
-						// nice to have, but maybe null on some devices
-						if (devices[i].pstrSerialNumber != null) {
-							deviceInfo.serialNumber = devices[i].pstrSerialNumber.getPointer().getString(0, true);
-						} else {
-							deviceInfo.serialNumber = NOT_KNOWN;
-						}
-						// now get the personality descriptor for this device
-						apiError = getPersonalityDescriptors(p, deviceInfo);
+					// device ID is very important to get personalities and for matching with
+					//  the connectivity API
+					if (devices[i].pstrDeviceID != null) {
+						deviceInfo.deviceID = devices[i].pstrDeviceID.getPointer().getString(0, true);
+					} else {
+						deviceInfo.deviceID = NOT_KNOWN;
 					}
-			        if (DEBUG) System.out.println("getAllDeviceUSBPersonalities all devices read"); //$NON-NLS-1$
-				} else {
-					apiError = true;
-					if (DEBUG)
-						System.out.printf("UPAPI_QueryDevices dwResult = %x\n", dwResult); //$NON-NLS-1$
+					if (DEBUG) System.out.println("UPAPI_QueryDevices: ID found: " + deviceInfo.deviceID);
+					// nice to have, but maybe null on some devices
+					if (devices[i].pstrSerialNumber != null) {
+						deviceInfo.serialNumber = devices[i].pstrSerialNumber.getPointer().getString(0, true);
+					} else {
+						deviceInfo.serialNumber = NOT_KNOWN;
+					}
+					// now get the personality descriptor for this device
+					apiError = getPersonalityDescriptors(p, deviceInfo);
 				}
-				dwResult = library.UPAPI_FreeDeviceDescriptor(dwDeviceCount, pDeviceDescriptor);
+		        if (DEBUG) System.out.println("getAllDeviceUSBPersonalities all devices read"); //$NON-NLS-1$
+				dwResult = library.UPAPI_FreeDeviceDescriptor(numUSBDevicesFound, pDeviceDescriptor);
 			} else {
-		        if (DEBUG) System.out.println("getAllDeviceUSBPersonalities no devices"); //$NON-NLS-1$
+				apiError = true;
+				if (DEBUG)
+					System.out.printf("UPAPI_QueryDevices dwResult = %x\n", dwResult); //$NON-NLS-1$
 			}
-		} else {
-			apiError = true;
-			if (DEBUG)
-				System.out.printf("UPAPI_QueryDeviceCount dwResult = %x\n", dwResult); //$NON-NLS-1$
 		}
 		if (DEBUG) System.out.printf("getAllDeviceUSBPersonalities return size : %s\n", p.size()); //$NON-NLS-1$
 		return p;
@@ -975,11 +1109,13 @@
 			if (dwResult == PCCSErrors.CONA_OK) {
 				if (pStringDescriptor.pstrDescription != null) {
 					desc = pStringDescriptor.pstrDescription.getPointer().getString(0, true);
+				} else {
+					desc = "Personality code: " + code.toString();
 				}
 				if (DEBUG) System.out.printf("UPAPI_GetStringDescriptor code: %d, desc: %s\n", code.intValue(), desc); //$NON-NLS-1$
 				dwResult = library.UPAPI_FreeStringDescriptor(pStringDescriptor);
 			} else {
-				apiError = true;
+				desc = "Personality code: " + code.toString();
 				if (DEBUG)
 					System.out.printf("UPAPI_GetStringDescriptor dwResult = %x\n", dwResult); //$NON-NLS-1$
 			}
@@ -1073,6 +1209,7 @@
 		//  int = personality code
 		//  string = personality description for code from device
 		Map<Integer, String> supportedPersonalities;
+		boolean matchedToDMDevice;
 	}
 	public void testPrerequisites() throws CoreException {
 		try {