connectivity/com.nokia.carbide.remoteConnections.discovery.pccs/src/com/nokia/carbide/remoteconnections/discovery/pccs/pccsnative/PCCSConnection.java
/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* 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:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.carbide.remoteconnections.discovery.pccs.pccsnative;
import java.nio.IntBuffer;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import org.eclipse.cdt.utils.WindowsRegistry;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import com.nokia.carbide.remoteconnections.RemoteConnectionsActivator;
import com.nokia.carbide.remoteconnections.discovery.pccs.Activator;
import com.nokia.carbide.remoteconnections.discovery.pccs.Messages;
import com.nokia.carbide.remoteconnections.discovery.pccs.pccsnative.IConnAPILibrary.IConnAPIDeviceCallback;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.ShortByReference;
public class PCCSConnection {
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 {
/* (non-Javadoc)
* @see com.nokia.carbide.remoteconnections.discovery.pccs.pccsnative.IConnAPILibrary.IConnAPIDeviceCallback#invoke(int, com.sun.jna.ptr.ShortByReference)
*/
public int invoke(final int dwStatus, final ShortByReference pstrSerialNumber) {
// check for NULL, since I am seeing bogus events coming from PCCS before the real one
// 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_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);
}
DeviceEventListener.DeviceEvent eventType = DeviceEventListener.DeviceEvent.DEVICE_LIST_UPDATED;
// decode dwStatus per PCCS docs
switch(DMAPIDefinitions.GET_CONAPI_CB_STATUS(dwStatus)) {
case DMAPIDefinitions.CONAPI_DEVICE_LIST_UPDATED:
eventType = DeviceEventListener.DeviceEvent.DEVICE_LIST_UPDATED;
break;
case DMAPIDefinitions.CONAPI_DEVICE_ADDED:
eventType = DeviceEventListener.DeviceEvent.DEVICE_ADDED;
break;
case DMAPIDefinitions.CONAPI_DEVICE_REMOVED:
eventType = DeviceEventListener.DeviceEvent.DEVICE_REMOVED;
break;
case DMAPIDefinitions.CONAPI_DEVICE_UPDATED:
switch(DMAPIDefinitions.GET_CONAPI_CB_INFO(dwStatus)) {
case DMAPIDefinitions.CONAPI_CONNECTION_ADDED:
eventType = DeviceEventListener.DeviceEvent.DEVICE_UPDATED_ADDEDCONNECTION;
break;
case DMAPIDefinitions.CONAPI_CONNECTION_REMOVED:
eventType = DeviceEventListener.DeviceEvent.DEVICE_UPDATED_REMOVEDCONNECTION;
break;
case DMAPIDefinitions.CONAPI_DEVICE_RENAMED:
eventType = DeviceEventListener.DeviceEvent.DEVICE_UPDATED_RENAMED;
break;
}
}
// 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);
}
return PCCSErrors.CONA_OK;
}
}
private static final Collection<DeviceEventListener> listeners = new LinkedList<DeviceEventListener>();
private IConnAPILibrary library;
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_38;
private APIHANDLE dmHandle = APIHANDLE.INVALID_HANDLE_VALUE;
private APIHANDLE mcHandle = APIHANDLE.INVALID_HANDLE_VALUE;
private APIHANDLE upHandle = APIHANDLE.INVALID_HANDLE_VALUE;
private Collection<String> noSwitchConnections = new ArrayList<String>();
public PCCSConnection() {
}
public void open() throws CoreException {
if (library == null) {
try {
library = IConnAPILibrary.INSTANCE;
} catch (UnsatisfiedLinkError e) {
String msg;
if (Activator.isSymSEELayout()) {
msg = Messages.ConnAPILibrary_PCCS_Not_Found_Error + Activator.getLoadErrorURL();
} else {
msg = Messages.ConnAPILibrary_PCSuite_Not_Found_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCSConnection.PCCS_NOT_FOUND, msg, e));
} catch (NoClassDefFoundError e) {
String msg;
if (Activator.isSymSEELayout()) {
msg = Messages.ConnAPILibrary_PCCS_Not_Found_Error + Activator.getLoadErrorURL();
} else {
msg = Messages.ConnAPILibrary_PCSuite_Not_Found_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCSConnection.PCCS_NOT_FOUND, msg, e));
}
}
// this uses the MCAPI only to enable required media
ensureMediaEnabled();
// load DMAPI
initDMAPI();
dmHandle = loadDMAPI();
if (!APIHANDLE.INVALID_HANDLE_VALUE.equals(dmHandle)) {
startDMNotifications(dmHandle);
}
}
private void initDMAPI() throws CoreException {
int dwResult = library.DMAPI_Initialize(DMAPI_VERSION, null);
if (dwResult != PCCSErrors.CONA_OK) {
terminateDMAPI();
String msg;
if (Activator.isSymSEELayout()) {
msg = String.format("PCCS DMAPI_Initialize API returned error on initialization %x", dwResult); //$NON-NLS-1$
if (dwResult == PCCSErrors.ECONA_UNSUPPORTED_API_VERSION) {
msg = Messages.PCCSConnection_PCCS_Version_Error + Activator.getLoadErrorURL();
}
} else {
msg = Messages.PCCSConnection_PCSuite_Version_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCS_WRONG_VERSION, msg, null));
}
if (DEBUG) System.out.println("initDMAPI"); //$NON-NLS-1$
}
private void startDMNotifications(APIHANDLE handle) throws CoreException {
// register a call back
int dwResult = library.CONARegisterNotifyCallback(handle, PCCSTypeDefinitions.API_REGISTER, pfnCallback);
if (dwResult != PCCSErrors.CONA_OK) {
library.CONACloseDM(handle);
handle = APIHANDLE.INVALID_HANDLE_VALUE;
String msg = String.format(Messages.PCCSConnection_PCCS_CONARegisterNotifyCallback_Error, dwResult);
if (dwResult == PCCSErrors.ECONA_INVALID_POINTER) {
msg = Messages.PCCSConnection_PCCS_CONARegisterNotifyCallback_Pointer_Error;
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, dwResult, msg, null));
}
if (DEBUG) System.out.println("startDMNotifications"); //$NON-NLS-1$
}
private void ensureMediaEnabled() throws CoreException {
// open the MCAPI
loadMCAPI();
// get media list
IntBuffer pdwCount = IntBuffer.allocate(1);
CONAPI_MEDIA.ByReference ppMedia = new CONAPI_MEDIA.ByReference();
int dwResult = library.CONAMMGetMedia(mcHandle, pdwCount, ppMedia);
if (DEBUG)
System.out.printf("CONAMMGetMedia dwResult = %x\tpdwCount = %d\n", dwResult, pdwCount.get(0)); //$NON-NLS-1$
int count = pdwCount.get(0);
Pointer pMedia = ppMedia.getPointer();
Pointer nativePointer = pMedia.getPointer(0); // save this for freeing media
int size = ppMedia.size();
if (count > 0) {
CONAPI_MEDIA media[] = new CONAPI_MEDIA[count];
for (int i = 0; i < count; i++) {
// get pointer from offset of native pointer
Pointer sharedP = nativePointer.share(0 + i*size);
media[i] = new CONAPI_MEDIA(sharedP);
// and read the data from native memory
media[i].read();
}
for (int i = 0; i < count; i++) {
if (MCAPIDefinitions.CONAPI_GET_MEDIA_TYPE(media[i].dwMedia) == MCAPIDefinitions.CONAPI_MEDIA_USB) {
if (MCAPIDefinitions.CONAPI_IS_MEDIA_UNACTIVE(media[i].dwState)) {
media[i].dwState = MCAPIDefinitions.CONAPI_MEDIA_ACTIVE;
dwResult = library.CONAMMSetMedia(mcHandle, media);
if (DEBUG)
System.out.printf("CONAMMSetMedia dwResult = %x\n", dwResult); //$NON-NLS-1$
}
}
}
dwResult = library.CONAMMFreeMediaStructures(count, nativePointer);
if (DEBUG)
System.out.printf("CONAMMFreeMediaStructures dwResult = %x\n", dwResult); //$NON-NLS-1$
}
// close MCAPI
closeMCAPI();
}
/**
* Opens Device Management API (DMAPI) for use. Note: initDMAPI must be called prior to this.<br>
* initDMAPI need be called only once, but this can be called whenever we need a handle to
* the DMAPI.
*
* @throws CoreException
*/
private APIHANDLE loadDMAPI() throws CoreException {
// open a DM handle
APIHANDLE handle = APIHANDLE.INVALID_HANDLE_VALUE;
LPAPIHANDLE pHandle = new LPAPIHANDLE();
int dwResult = library.CONAOpenDM(pHandle);
if (dwResult != PCCSErrors.CONA_OK) {
String msg = String.format(Messages.PCCSConnection_PCCS_CONAOpenDM_Error, dwResult);
if (dwResult == PCCSErrors.ECONA_NOT_ENOUGH_MEMORY) {
msg = Messages.PCCSConnection_PCCS_Not_Enough_Memory_Error;
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, dwResult, msg, null));
} else {
handle = pHandle.getValue();
}
if (DEBUG) System.out.printf("loadDMAPI handle=%s\n", handle.toString()); //$NON-NLS-1$
return handle;
}
private void loadMCAPI() throws CoreException {
int dwResult = PCCSErrors.CONA_OK;
dwResult = library.MCAPI_Initialize(MCAPIDefinitions.MCAPI_VERSION_32, null);
if (dwResult != PCCSErrors.CONA_OK) {
library.MCAPI_Terminate(null);
String msg;
if (Activator.isSymSEELayout()) {
msg = String.format("PCCS MCAPI_Initialize API returned error on initialization %x", dwResult); //$NON-NLS-1$
if (dwResult == PCCSErrors.ECONA_UNSUPPORTED_API_VERSION) {
msg = Messages.PCCSConnection_PCCS_Version_Error + Activator.getLoadErrorURL();
}
} else {
msg = Messages.PCCSConnection_PCSuite_Version_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCS_WRONG_VERSION, msg, null));
}
LPAPIHANDLE pHandle = new LPAPIHANDLE();
dwResult = library.CONAOpenMM(pHandle, 0);
if (dwResult != PCCSErrors.CONA_OK) {
library.MCAPI_Terminate(null);
String msg = String.format("PCCS CONAOpenMM API returned error on initialization %x", dwResult); //$NON-NLS-1$
if (dwResult == PCCSErrors.ECONA_NOT_ENOUGH_MEMORY) {
msg = Messages.PCCSConnection_PCCS_Not_Enough_Memory_Error;
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, dwResult, msg, null));
} else {
mcHandle = pHandle.getValue();
}
if (DEBUG) System.out.println("\n-----loadMCAPI"); //$NON-NLS-1$
}
private void loadUPAPI() throws CoreException {
int dwResult = PCCSErrors.CONA_OK;
dwResult = library.UPAPI_Initialize(UPAPIDefinitions.UPAPI_VERSION_10, null);
if (dwResult != PCCSErrors.CONA_OK) {
library.UPAPI_Terminate(null);
String msg;
msg = String.format("PCCS UPAPI_Initialize API returned error on initialization %x", dwResult); //$NON-NLS-1$
if (DEBUG) System.out.println(msg);
if (Activator.isSymSEELayout()) {
if (dwResult == PCCSErrors.ECONA_UNSUPPORTED_API_VERSION) {
msg = Messages.PCCSConnection_PCCS_Version_Error + Activator.getLoadErrorURL();
}
} else {
msg = Messages.PCCSConnection_PCSuite_Version_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCS_WRONG_VERSION, msg, null));
}
LPAPIHANDLE pHandle = new LPAPIHANDLE();
dwResult = library.UPAPI_OpenUSBPersonality(0, pHandle);
if (dwResult != PCCSErrors.CONA_OK) {
library.UPAPI_Terminate(null);
String msg = String.format("PCCS OpenUSBPersonality API returned error on initialization %x", dwResult); //$NON-NLS-1$
if (DEBUG) System.out.println(msg);
if (dwResult == PCCSErrors.ECONA_NOT_ENOUGH_MEMORY) {
msg = Messages.PCCSConnection_PCCS_Not_Enough_Memory_Error;
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, dwResult, msg, null));
} else {
upHandle = pHandle.getValue();
}
if (DEBUG) System.out.println("\n-----loadUPAPI"); //$NON-NLS-1$
}
public void close() throws CoreException {
if (library == null)
return;
stopDMNotifications(dmHandle);
// DMAPI should only one be open
dmHandle = closeDMAPI(dmHandle);
terminateDMAPI();
}
private void terminateDMAPI() {
// Terminate Device management API
/*int dwResult =*/ library.DMAPI_Terminate(null);
if (DEBUG) System.out.println("terminateDMAPI"); //$NON-NLS-1$
}
private void stopDMNotifications(APIHANDLE handle) {
// int dwResult = PCCSErrors.CONA_OK;
if (!APIHANDLE.INVALID_HANDLE_VALUE.equals(handle)) {
// unregister callback
/*dwResult =*/ library.CONARegisterNotifyCallback(handle, PCCSTypeDefinitions.API_UNREGISTER, pfnCallback);
}
if (DEBUG) System.out.println("stopDMNotifications"); //$NON-NLS-1$
}
/**
* Closes the DMAPI.
* @throws CoreException
*/
private APIHANDLE closeDMAPI(APIHANDLE handle) throws CoreException {
int dwResult = PCCSErrors.CONA_OK;
if (!APIHANDLE.INVALID_HANDLE_VALUE.equals(handle)) {
// close DM connection
dwResult = library.CONACloseDM(handle);
if (DEBUG) System.out.printf("closeDMAPI ret=%x handle=%s\n", dwResult, handle.toString()); //$NON-NLS-1$
handle = APIHANDLE.INVALID_HANDLE_VALUE;
}
return handle;
}
private void closeMCAPI() {
// int dwResult = PCCSErrors.CONA_OK;
if (!APIHANDLE.INVALID_HANDLE_VALUE.equals(mcHandle)) {
// close DM connection
/*dwResult =*/ library.CONACloseDM(mcHandle);
mcHandle = APIHANDLE.INVALID_HANDLE_VALUE;
// Terminate Device management API
/*dwResult =*/ library.MCAPI_Terminate(null);
}
if (DEBUG) System.out.println("closeMCAPI----\n"); //$NON-NLS-1$
}
private void closeUPAPI() {
int dwResult = PCCSErrors.CONA_OK;
if (!APIHANDLE.INVALID_HANDLE_VALUE.equals(upHandle)) {
// close DM connection
dwResult = library.UPAPI_CloseUSBPersonality(upHandle);
if (dwResult != PCCSErrors.CONA_OK) {
if (DEBUG) System.out.printf("UPAPI_CloseUSBPersonality dwResult = %x\n", dwResult); //$NON-NLS-1$
}
upHandle = APIHANDLE.INVALID_HANDLE_VALUE;
// Terminate Device management API
dwResult = library.UPAPI_Terminate(null);
if (dwResult != PCCSErrors.CONA_OK) {
if (DEBUG) System.out.printf("UPAPI_Terminate dwResult = %x\n", dwResult); //$NON-NLS-1$
}
}
if (DEBUG) System.out.println("closeUPAPI----\n"); //$NON-NLS-1$
}
/**
* All devices detected are gotten here - BT, USB, etc.
* No checking of a valid connection is done here
*
* @return DeviceInfo[] - null if no devices connected
*/
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$
if (dwResult != PCCSErrors.CONA_OK) {
try {
closeDMAPI(handle);
} catch (CoreException e) {
}
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$
if (dwResult != PCCSErrors.CONA_OK) {
try {
closeDMAPI(handle);
} catch (CoreException e) {
}
return deviceInfo;
}
// Extract device information and connection info
deviceInfo = new DeviceInfo[deviceCount];
CONAPI_DEVICE[] devices = pDevices;
for (int i = 0; i < deviceCount; i++) {
deviceInfo[i] = new DeviceInfo();
if (devices[i].pstrSerialNumber != null) {
deviceInfo[i].serialNumber = devices[i].pstrSerialNumber.getPointer().getString(0, true);
} else {
// TODO: docs say if ser num == null --> device unsupported, but this is a bug in PCCS
deviceInfo[i].serialNumber = NOT_KNOWN; //$NON-NLS-1$
}
if (devices[i].pstrFriendlyName != null) {
deviceInfo[i].friendlyName = devices[i].pstrFriendlyName.getPointer().getString(0, true);
} else {
deviceInfo[i].friendlyName = NOT_KNOWN; //$NON-NLS-1$
}
if (devices[i].pstrModel != null) {
deviceInfo[i].model = devices[i].pstrModel.getPointer().getString(0, true);
} else {
deviceInfo[i].model = NOT_KNOWN; //$NON-NLS-1$
}
if (devices[i].pstrManufacturer != null) {
deviceInfo[i].mfr = devices[i].pstrManufacturer.getPointer().getString(0, true);
} else {
deviceInfo[i].mfr = NOT_KNOWN; //$NON-NLS-1$
}
int numConnections = deviceInfo[i].numberOfConnections = devices[i].dwNumberOfItems;
CONAPI_CONNECTION_INFO[] conn = null;
if (numConnections > 0)
conn = (CONAPI_CONNECTION_INFO[])devices[i].pItems.toArray(numConnections);
for (int j = 0; j < numConnections; j++) {
DeviceConnectionInfo connInfo = new DeviceConnectionInfo();
connInfo.deviceID = conn[j].dwDeviceID;
switch(conn[j].dwMedia){
case PCCSTypeDefinitions.API_MEDIA_BLUETOOTH:
connInfo.media = "bluetooth"; //$NON-NLS-1$
break;
case PCCSTypeDefinitions.API_MEDIA_IRDA:
connInfo.media = "irda"; //$NON-NLS-1$
break;
case PCCSTypeDefinitions.API_MEDIA_SERIAL:
connInfo.media = "serial-ca42"; //$NON-NLS-1$
break;
default:
case PCCSTypeDefinitions.API_MEDIA_USB:
connInfo.media = "usb"; //$NON-NLS-1$
break;
}
// fill-in friendly name with device name if the former was null
if (conn[j].pstrDeviceName != null) {
connInfo.deviceName = conn[j].pstrDeviceName.getPointer().getString(0,true);
if (deviceInfo[i].friendlyName.equals(NOT_KNOWN)) { //$NON-NLS-1$
deviceInfo[i].friendlyName = connInfo.deviceName;
}
} else {
connInfo.deviceName = NOT_KNOWN; //$NON-NLS-1$
}
// if the address is not known, this is serious - we may weed out this connection later
if (conn[j].pstrAddress != null) {
connInfo.address = conn[j].pstrAddress.getPointer().getString(0, true);
} else {
connInfo.address = NOT_KNOWN; // $NON-NLS-1$
}
connInfo.state = conn[j].dwState;
deviceInfo[i].connections.add(connInfo);
}
}
dwResult = library.CONAFreeDeviceStructure(deviceCount, pDevices);
}
try {
closeDMAPI(handle);
} catch (CoreException e) {
}
return deviceInfo;
}
/**
* Gets the complete list of connections and weeds out "good" connections (i.e., non-debuggable)
*
* @return
* @throws CoreException
*/
public synchronized Collection<DeviceConnection> getGoodConnectionList() throws CoreException {
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) {
forgetAllNoSwitchConnectionsNotInCurrentList(null);
return goodConnections;
}
// get number of expected USB devices
int numUSBDevicesExpected = getNumUSBDevicesExpected(deviceList);
// 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;
}
// if there is only one device, forget all previous devices that were
// not switched to Suite mode
if (deviceList.length == 1) {
forgetAllNoSwitchConnectionsNotInCurrentList(null);
}
// get all the USB personalities for the current connections
Collection<DeviceUSBPersonalityInfo> personalityList = null;
if (numUSBDevicesExpected > 0) {
try {
loadUPAPI();
int numUSBDevices = getNumberUPAPIDevices(numUSBDevicesExpected);
if (numUSBDevices < numUSBDevicesExpected) {
closeUPAPI();
return null;
}
} 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 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;
if (DEBUG) System.out.printf("getGoodConnectionList: sizeof connectionList: %d\n", connectionList.size()); //$NON-NLS-1$
for (DeviceConnectionInfo connInfo : connectionList) {
if (DEBUG) {
System.out.printf("getGoodConnectionList: name: %s media: %s\n", device.friendlyName, connInfo.media); //$NON-NLS-1$
}
if (connInfo.media.equals("usb")) { //$NON-NLS-1$
DeviceUSBPersonalityInfo personality = findPersonality(numUSBDevicesExpected, device.serialNumber, connInfo.address, personalityList);
if (personality == null) {
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);
logMessage(msg, IStatus.ERROR);
continue;
}
if (isGoodUSBPersonality(device, connInfo, personality)) {
// if current mode was bad, and we switched, then we'll pick it up at next notification
// if current mode is still bad, don't put into good list
// if current mode is good, store it to good list
DeviceConnection newConnection = new DeviceConnection();
newConnection.friendlyName = device.friendlyName;
if (!device.serialNumber.equals(NOT_KNOWN))
newConnection.serialNumber = device.serialNumber;
else if (!personality.serialNumber.equals(NOT_KNOWN))
newConnection.serialNumber = personality.serialNumber;
else
newConnection.serialNumber = NOT_KNOWN;
newConnection.media = connInfo.media;
newConnection.port = connInfo.port; // port may be IP address or COM Port depending on personality
newConnection.mode = connInfo.mode;
newConnection.address = connInfo.address;
if (!newConnection.friendlyName.equals(NOT_KNOWN) && !newConnection.address.equals(NOT_KNOWN))
goodConnections.add(newConnection);
}
} else if (connInfo.media.equals("bluetooth")) { //$NON-NLS-1$
// TODO: Bluetooth - not supported yet
} else {
// TODO: what else?
}
}
}
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)
*
* @param personalityList
*/
private void forgetAllNoSwitchConnectionsNotInCurrentList(
Collection<DeviceUSBPersonalityInfo> personalityList) {
if (personalityList == null || personalityList.isEmpty()) {
if (DEBUG) System.out.println("forgetAllNoSwitchConnectionsNotInCurrentList: all");
noSwitchConnections.clear();
} else if (noSwitchConnections == null || noSwitchConnections.isEmpty()) {
if (DEBUG) System.out.println("forgetAllNoSwitchConnectionsNotInCurrentList: noSwitchConnections already empty");
return;
} else {
for (String id : new ArrayList<String>(noSwitchConnections)) {
boolean found = false;
for (DeviceUSBPersonalityInfo personality : personalityList) {
if (id.equals(personality.deviceID)) {
found = true;
}
}
if (!found) {
if (DEBUG) System.out.println("forgetAllNoSwitchConnectionsNotInCurrentList: " + id);
noSwitchConnections.remove(id);
}
}
}
}
/**
* 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 numUSBDevicesExpected
*
* @param serialNumber - serial number from connectivity API
* @param address - this contains the device ID from the connectivity API
* @param personalityList - all USB-connected devices
* @return - null if no personality found
*/
private DeviceUSBPersonalityInfo findPersonality(int numUSBDevicesExpected, String serialNumber, String address, Collection<DeviceUSBPersonalityInfo> personalityList) {
if (DEBUG) System.out.println("\nfindPersonality: start"); //$NON-NLS-1$
if (personalityList == null || personalityList.isEmpty()) {
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: 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\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)\n"); //$NON-NLS-1$
personality.matchedToDMDevice = true;
return personality;
} else {
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 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
String vidpid = address.substring(address.indexOf('\\'), address.lastIndexOf('\\'));
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) && 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") || 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 (!personality.serialNumber.equals(NOT_KNOWN)) {
if (address.endsWith(personality.serialNumber)) {
if (DEBUG) System.out.println("findPersonality: address contains serialNumber\n");
personality.matchedToDMDevice = true;
return personality;
}
}
}
if (DEBUG) System.out.println("findPersonality return no match\n"); //$NON-NLS-1$
return null;
}
/**
* This will do a switch if the user wants us to.
*
* @param device - USB-connected device
* @param connInfo - connection information for this USB-connected device
* @param personalities - USB personalities of all devices (not just this one)
* @return true - iff we're in a 'good' USB personality already
* if we have to switch, the device will disconnect and reconnect in the other personality
*
* Only 'good' personalities are:
* PC Suite - Serial
* OVI Suite - Serial
* RNDIS - TCP/IP - currently unsupported
*/
private boolean isGoodUSBPersonality(DeviceInfo device,
DeviceConnectionInfo connInfo,
DeviceUSBPersonalityInfo personality) {
if (DEBUG) System.out.printf("isGoodUSBPersonality: current personality: %d %s\n", personality.currentPersonalityCode, personality.currentPersonalityDescription); //$NON-NLS-1$
// currently assume that mode is always 'serial'
if (personality.currentPersonalityCode == UPAPIDefinitions.UPAPI_PERSONALITY_CODE_PC_SUITE ||
personality.currentPersonalityCode == UPAPIDefinitions.UPAPI_PERSONALITY_CODE_OVI_SUITE) {
connInfo.mode = "serial"; //$NON-NLS-1$
connInfo.port = getUSBComPort(connInfo.address);
// good personality
forgetNoSwitchConnections(personality.deviceID);
return true;
}
// bad personality - switch? if dontAskAgain is true - return bad personality
int goodCode = UPAPIDefinitions.UPAPI_PERSONALITY_CODE_PC_SUITE;
if (personality.supportedPersonalities.containsKey(new Integer(UPAPIDefinitions.UPAPI_PERSONALITY_CODE_OVI_SUITE))) {
goodCode = UPAPIDefinitions.UPAPI_PERSONALITY_CODE_OVI_SUITE;
}
String goodDesc = personality.supportedPersonalities.get(new Integer(goodCode));
if (!noSwitchConnectionsContains(personality.deviceID))
// ask to switch
askToSwitchPersonality(device, personality, goodCode, goodDesc);
// was bad personality - if we switched, it will be good next notification
if (DEBUG) System.out.println("isGoodUSBPersonality: return false"); //$NON-NLS-1$
return false;
}
/**
* Search previous "no-switch-personality" list for a new device (e.g., user already said no before - don't ask again unless he reconnects)
*
* @param deviceID
* @return
*/
private boolean noSwitchConnectionsContains(String deviceID) {
if (!noSwitchConnections.isEmpty()) {
for (String id : noSwitchConnections) {
if (id.equals(deviceID)) {
return true;
}
}
}
return false;
}
/**
* Forget one device in previous "no-switch-personality" list (e.g., device is now in a good personality and doesn't need switching)
*
* @param deviceID
*/
private void forgetNoSwitchConnections(String deviceID) {
if (noSwitchConnections.isEmpty()) {
if (DEBUG) System.out.println("forgetNoSwitchConnections empty");
return;
}
if (DEBUG) System.out.println("forgetNoSwitchConnections: " + deviceID);
noSwitchConnections.remove(deviceID);
}
private void askToSwitchPersonality(final DeviceInfo device,
final DeviceUSBPersonalityInfo personality, final int goodCode, final String goodDesc) {
// remember this device so we don't ask again unless it changes personality or is reconnected
rememberNoSwitchConnections(personality.deviceID);
String message = MessageFormat.format(
"''{0}'' is currently in {1} mode\nand must be in {2} mode to be usable in Carbide.",
device.friendlyName,
personality.currentPersonalityDescription,
goodDesc);
final IStatus status = new Status(IStatus.WARNING, Activator.PLUGIN_ID, message);
String prompt = MessageFormat.format("Switch to {0} mode now.", goodDesc);
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$
}
}
});
}
}
/**
* Device is bad personality and user said 'no' to switch (we won't ask again for this device unless it is reconnected or now in a good mode)
*
* @param deviceID
*/
private void rememberNoSwitchConnections(String deviceID) {
if (DEBUG) System.out.println("rememberNoSwitchConnections: " + deviceID);
noSwitchConnections.add(deviceID);
}
/**
* This function assumes the UPAPI has already been loaded by the caller
* @return - list of personalities
*/
private Collection<DeviceUSBPersonalityInfo> getAllDeviceUSBPersonalities(int numUSBDevicesExpected) {
Collection<DeviceUSBPersonalityInfo> p = new ArrayList<DeviceUSBPersonalityInfo>();
boolean apiError = false;
// how many USB devices are connected
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();
// 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);
}
if (DEBUG) System.out.println("getAllDeviceUSBPersonalities all devices read"); //$NON-NLS-1$
dwResult = library.UPAPI_FreeDeviceDescriptor(numUSBDevicesFound, pDeviceDescriptor);
} else {
apiError = true;
if (DEBUG)
System.out.printf("UPAPI_QueryDevices dwResult = %x\n", dwResult); //$NON-NLS-1$
}
}
if (DEBUG) System.out.printf("getAllDeviceUSBPersonalities return size : %s\n", p.size()); //$NON-NLS-1$
return p;
}
private boolean getPersonalityDescriptors(
Collection<DeviceUSBPersonalityInfo> p,
DeviceUSBPersonalityInfo deviceInfo) {
int dwResult;
boolean apiError = false;
// make device ID a wide string so JNA marshals it appropriately
WString pid = new WString(deviceInfo.deviceID);
UP_PERSONALITY_DESCRIPTORS[] persDesc = (UP_PERSONALITY_DESCRIPTORS[])new UP_PERSONALITY_DESCRIPTORS().toArray(1);
persDesc[0].dwSize = 12; // important - won't work without this
dwResult = library.UPAPI_GetPersonalityDescriptors(upHandle, pid, persDesc);
if (dwResult == PCCSErrors.CONA_OK) {
// store personality information
deviceInfo.currentPersonalityCode = (persDesc[0].bCurrentPersonality & 0xff);
// get num of supported personalities
int numPers = (persDesc[0].bNumOfPersonalities & 0xff);
if (DEBUG) System.out.printf("UPAPI_GetPersonalityDescriptors numPers = %d\n", numPers); //$NON-NLS-1$
// get all the supported personalities for this device
apiError = getSupportedPersonalities(deviceInfo, pid, persDesc, numPers);
} else {
apiError = true;
if (DEBUG)
System.out.printf("UPAPI_GetPersonalityDescriptors dwResult = %x\n", dwResult); //$NON-NLS-1$
}
dwResult = library.UPAPI_FreePersonalityDescriptors(persDesc);
if (apiError == false) {
if (DEBUG) System.out.println("getAllDeviceUSBPersonalities deviceInfo added"); //$NON-NLS-1$
p.add(deviceInfo);
}
return apiError;
}
private boolean getSupportedPersonalities(DeviceUSBPersonalityInfo deviceInfo, WString pid,
UP_PERSONALITY_DESCRIPTORS[] persDesc, int numPers) {
int dwResult;
UP_PERSONALITY[] pSupportedPersonality = null;
if (numPers > 0) {
pSupportedPersonality = (UP_PERSONALITY[])persDesc[0].pPersonalities.toArray(numPers);
deviceInfo.supportedPersonalities = new HashMap<Integer, String>();
}
boolean apiError = false;
// now get the string descriptor for each supported personality
for (int j = 0; j < numPers; j++) {
Integer code = new Integer(pSupportedPersonality[j].bPersonalityCode);
int stringIndex = (pSupportedPersonality[j].bPersonalityIndex & 0xff);
UP_STRING_DESCRIPTOR pStringDescriptor = new UP_STRING_DESCRIPTOR();
String desc = NOT_KNOWN;
pStringDescriptor.dwSize = 12; // this is important
dwResult = library.UPAPI_GetStringDescriptor(upHandle, pid, stringIndex, 0, pStringDescriptor);
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 {
desc = "Personality code: " + code.toString();
if (DEBUG)
System.out.printf("UPAPI_GetStringDescriptor dwResult = %x\n", dwResult); //$NON-NLS-1$
}
if (apiError == false)
deviceInfo.supportedPersonalities.put(code, desc);
}
if (deviceInfo.supportedPersonalities.isEmpty()) {
deviceInfo.currentPersonalityDescription = MessageFormat.format(Messages.PCCSConnection_Generic_Personality_Description, Integer.toString(deviceInfo.currentPersonalityCode));
} else {
deviceInfo.currentPersonalityDescription = deviceInfo.supportedPersonalities.get(new Integer(deviceInfo.currentPersonalityCode));
}
if (DEBUG) System.out.printf("current Desc found: %s\n", deviceInfo.currentPersonalityDescription); //$NON-NLS-1$
return apiError;
}
// private String getBTComPort(String address) {
// // TODO Auto-generated method stub
// return null;
// }
public String getUSBComPort(String address) {
if (address != null && address.length() > 0) {
String id, key, subKey, parentIdPrefix = null, portName;
WindowsRegistry wr = WindowsRegistry.getRegistry();
key = "SYSTEM\\ControlSet001\\Enum\\USB" + address.substring(address.indexOf('\\'), address.lastIndexOf('\\')); //$NON-NLS-1$
id = address.substring(address.lastIndexOf('\\') + 1);
int i = 0;
do {
subKey = wr.getLocalMachineKeyName(key, i);
if (subKey != null && subKey.equalsIgnoreCase(id)) {
key += "\\" + subKey; //$NON-NLS-1$
parentIdPrefix = wr.getLocalMachineValue(key, "ParentIdPrefix"); //$NON-NLS-1$
break;
}
i++;
} while (subKey != null);
if (parentIdPrefix != null) {
key = "SYSTEM\\ControlSet001\\Enum\\NMWCD"; //$NON-NLS-1$
subKey = address.substring(address.indexOf('\\'), address.lastIndexOf('\\'));
key += subKey + "&IF_JAVACOMM"; //$NON-NLS-1$
i = 0;
do {
subKey = wr.getLocalMachineKeyName(key, i);
if (subKey != null && subKey.contains(parentIdPrefix)) {
key += "\\" + subKey + "\\Device Parameters"; //$NON-NLS-1$ //$NON-NLS-2$
portName = wr.getLocalMachineValue(key, "PortName"); //$NON-NLS-1$
if (portName != null) {
portName = portName.substring(portName.indexOf('M') + 1);
return portName;
}
break;
}
i++;
} while (subKey != null);
}
}
return null;
}
public void addEventListenter(DeviceEventListener listener) {
listeners.add(listener);
}
public void removeEventListener(DeviceEventListener listener) {
listeners.remove(listener);
}
public interface DeviceEventListener {
public enum DeviceEvent {
DEVICE_LIST_UPDATED, // not any specific information
DEVICE_ADDED,
DEVICE_REMOVED,
DEVICE_UPDATED_ADDEDCONNECTION,
DEVICE_UPDATED_REMOVEDCONNECTION,
DEVICE_UPDATED_RENAMED,
DEVICE_UPDATED_UNKNOWN,
}
public void onDeviceEvent(DeviceEvent eventType, String serialNumber);
}
/**
* Class to hold USB personality information from UPAPI per Device
*/
private class DeviceUSBPersonalityInfo {
String deviceID; // from device descriptor
String serialNumber; // from device descriptor
int currentPersonalityCode; // from personality descriptor
String currentPersonalityDescription; // from list of supported personalities
// list of supported personalities
// int = personality code
// string = personality description for code from device
Map<Integer, String> supportedPersonalities;
boolean matchedToDMDevice;
}
public void testPrerequisites() throws CoreException {
try {
if (library == null)
library = IConnAPILibrary.INSTANCE;
} catch (UnsatisfiedLinkError e) {
String msg;
if (Activator.isSymSEELayout()) {
msg = Messages.ConnAPILibrary_PCCS_Not_Found_Error + Activator.getLoadErrorURL();
} else {
msg = Messages.ConnAPILibrary_PCSuite_Not_Found_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCSConnection.PCCS_NOT_FOUND, msg, e));
} catch (NoClassDefFoundError e) {
String msg;
if (Activator.isSymSEELayout()) {
msg = Messages.ConnAPILibrary_PCCS_Not_Found_Error + Activator.getLoadErrorURL();
} else {
msg = Messages.ConnAPILibrary_PCSuite_Not_Found_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCSConnection.PCCS_NOT_FOUND, msg, e));
}
testDMAPI();
testUPAPI();
testMCAPI();
}
/*
* Tests version of DMAPI and leaves it closed
*/
private void testDMAPI() throws CoreException {
int dwResult = library.DMAPI_Initialize(DMAPI_VERSION, null);
library.DMAPI_Terminate(null);
if (dwResult != PCCSErrors.CONA_OK) {
String msg;
if (Activator.isSymSEELayout()) {
msg = String.format("PCCS DMAPI_Initialize API returned error on initialization %x", dwResult); //$NON-NLS-1$
if (dwResult == PCCSErrors.ECONA_UNSUPPORTED_API_VERSION) {
msg = Messages.PCCSConnection_PCCS_Version_Error + Activator.getLoadErrorURL();
}
} else {
msg = Messages.PCCSConnection_PCSuite_Version_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCS_WRONG_VERSION, msg, null));
}
}
/*
* Test version of UPAPI and leaves it closed
*/
private void testUPAPI() throws CoreException {
int dwResult = PCCSErrors.CONA_OK;
dwResult = library.UPAPI_Initialize(UPAPIDefinitions.UPAPI_VERSION_10, null);
library.UPAPI_Terminate(null);
if (dwResult != PCCSErrors.CONA_OK) {
String msg;
msg = String.format("PCCS UPAPI_Initialize API returned error on initialization %x", dwResult); //$NON-NLS-1$
if (DEBUG) System.out.println(msg);
if (Activator.isSymSEELayout()) {
if (dwResult == PCCSErrors.ECONA_UNSUPPORTED_API_VERSION) {
msg = Messages.PCCSConnection_PCCS_Version_Error + Activator.getLoadErrorURL();
}
} else {
msg = Messages.PCCSConnection_PCSuite_Version_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCS_WRONG_VERSION, msg, null));
}
}
/*
* Test version of MCAPI and leaves it closed
*/
private void testMCAPI() throws CoreException {
int dwResult = PCCSErrors.CONA_OK;
dwResult = library.MCAPI_Initialize(MCAPIDefinitions.MCAPI_VERSION_32, null);
library.MCAPI_Terminate(null);
if (dwResult != PCCSErrors.CONA_OK) {
String msg;
if (Activator.isSymSEELayout()) {
msg = String.format("PCCS MCAPI_Initialize API returned error on initialization %x", dwResult); //$NON-NLS-1$
if (dwResult == PCCSErrors.ECONA_UNSUPPORTED_API_VERSION) {
msg = Messages.PCCSConnection_PCCS_Version_Error + Activator.getLoadErrorURL();
}
} else {
msg = Messages.PCCSConnection_PCSuite_Version_Error + Activator.getLoadErrorURL();
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, PCCS_WRONG_VERSION, msg, null));
}
}
}