diff --git a/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp
index 8dcfa4b9042a9a3d0cb5d417943a354d9279ee42..ad2869aac5812ea9a87bcefb197299f47a26e948 100644
--- a/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp
+++ b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp
@@ -30,6 +30,7 @@
 #include "s60debuggerbluetoothstarter.h"
 #include "bluetoothlistener.h"
 #include "debuggermanager.h"
+#include "trkoptions.h"
 
 namespace Debugger {
 namespace Internal {
@@ -48,5 +49,24 @@ trk::BluetoothListener *S60DebuggerBluetoothStarter::createListener()
     return rc;
 }
 
+trk::PromptStartCommunicationResult
+S60DebuggerBluetoothStarter::startCommunication(const TrkDevicePtr &trkDevice,
+                                                 const QString &device,
+                                                 int communicationType,
+                                                 QWidget *msgBoxParent,
+                                                 QString *errorMessage)
+{
+    // Bluetooth?
+    if (communicationType == TrkOptions::BlueTooth) {
+        S60DebuggerBluetoothStarter bluetoothStarter(trkDevice);
+        bluetoothStarter.setDevice(device);
+        return trk::promptStartBluetooth(bluetoothStarter, msgBoxParent, errorMessage);
+    }
+    // Serial
+    BaseCommunicationStarter serialStarter(trkDevice);
+    serialStarter.setDevice(device);
+    return trk::promptStartSerial(serialStarter, msgBoxParent, errorMessage);
+}
+
 } // namespace Internal
 } // namespace Debugger
diff --git a/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.h b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.h
index 226e00072ac4af1403bf411162cf70a28df2d537..234afa2c2c9c731917befdb53737bcc512678d1e 100644
--- a/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.h
+++ b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.h
@@ -31,6 +31,7 @@
 #define S60DEBUGGERBLUETOOTHSTARTER_H
 
 #include "communicationstarter.h"
+#include "bluetoothlistener_gui.h"
 
 namespace Debugger {
 namespace Internal {
@@ -38,15 +39,24 @@ namespace Internal {
 /* S60DebuggerBluetoothStarter: Creates a listener in 'Listen' mode
  * parented on the Debugger manager which outputs to the debugger window.
  * Note: This is a "last resort" starter, normally, the run configuration
- * should have already started a listener. */
+ * should have already started a listener.
+ * Provides a static convenience to prompt for both connection types.  */
 
 class S60DebuggerBluetoothStarter : public trk::AbstractBluetoothStarter
-{
+{    
 public:
-    explicit S60DebuggerBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
+    static trk::PromptStartCommunicationResult
+        startCommunication(const TrkDevicePtr &trkDevice,
+                           const QString &device,
+                           int communicationType,
+                           QWidget *msgBoxParent,
+                           QString *errorMessage);
 
-protected:
+protected:    
     virtual trk::BluetoothListener *createListener();
+
+private:
+    explicit S60DebuggerBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
 };
 
 } // namespace Internal
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp
index e954396c30aeb00ad7860778c229eecf570e332b..bf23a09eab59024e29b17094bca9a6fcdafbc692 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp
@@ -1512,30 +1512,22 @@ void TrkGdbAdapter::startAdapter()
     debugMessage(_("TRYING TO START ADAPTER"));
     logMessage(QLatin1String("### Starting TrkGdbAdapter"));
     m_trkDevice->setSerialFrame(effectiveTrkDeviceType() != TrkOptions::BlueTooth);
-    // Prompt the user for a bluetooth connection
-    const QString device = effectiveTrkDevice();
-    QString message;    
-    if (effectiveTrkDeviceType() == TrkOptions::BlueTooth) {
-        S60DebuggerBluetoothStarter starter(m_trkDevice);
-        starter.setDevice(device);
-        const trk::StartBluetoothGuiResult src = trk::startBluetoothGui(starter, 0, &message);
-        switch (src) {
-        case trk::BluetoothGuiConnected:
-            break;
-        case trk::BluetoothGuiCanceled:
-            emit adapterStartFailed(message, QString());
-            return;
-        case trk::BluetoothGuiError:
-            emit adapterStartFailed(message, TrkOptionsPage::settingsId());
-            return;
-        };
-    } else {
-        if (!m_trkDevice->isOpen() && !m_trkDevice->open(device, &message)) {
-            message = tr("Failed to connect to %1: %2\nCheck whether TRK is running.").arg(device).arg(message);
-            logMessage(message);
-            emit adapterStartFailed(message, TrkOptionsPage::settingsId());
-            return;
-        }
+    // Prompt the user to start communication
+    QString message;        
+    const trk::PromptStartCommunicationResult src =
+            S60DebuggerBluetoothStarter::startCommunication(m_trkDevice,
+                                                            effectiveTrkDevice(),
+                                                            effectiveTrkDeviceType(),
+                                                            0, &message);
+    switch (src) {
+    case trk::PromptStartCommunicationConnected:
+        break;
+    case trk::PromptStartCommunicationCanceled:
+        emit adapterStartFailed(message, QString());
+        return;
+    case trk::PromptStartCommunicationError:
+        emit adapterStartFailed(message, TrkOptionsPage::settingsId());
+        return;
     }
 
     QTC_ASSERT(m_gdbServer == 0, delete m_gdbServer);
diff --git a/src/plugins/debugger/gdb/trkoptions.h b/src/plugins/debugger/gdb/trkoptions.h
index f4a288fe0743d902d641867db7fe4c34d8ebc89e..470b66ab52f8c56d5514879db68b90a4f6fd6bcb 100644
--- a/src/plugins/debugger/gdb/trkoptions.h
+++ b/src/plugins/debugger/gdb/trkoptions.h
@@ -46,6 +46,7 @@ namespace Internal {
 
 struct TrkOptions
 {
+    // Matches the communication enumeration from the S60 devices listener.
     enum Mode { Serial, BlueTooth };
 
     TrkOptions();
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
index d547c3b6d83d77568d2764459da2766ec9479b3d..0804a9fe258c781192fad92b8158d293befc92f0 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
@@ -582,21 +582,24 @@ void S60DeviceRunControlBase::signsisProcessFinished()
     initLauncher(runFileName, m_launcher);
     emit addToOutputWindow(this, tr("Package: %1\nDeploying application to '%2'...").arg(lsFile(copySrc), m_serialPortFriendlyName));
     QString errorMessage;
-    // Prompt the user to start up the Blue tooth connection
-    if (m_communicationType == BlueToothCommunication) {
-        S60RunConfigBluetoothStarter starter(m_launcher->trkDevice());
-        switch (trk::startBluetoothGui(starter, 0, &errorMessage)) {
-        case trk::BluetoothGuiConnected:
-            break;
-        case trk::BluetoothGuiCanceled:
-        case trk::BluetoothGuiError:
-            delete m_launcher;
-            m_launcher = 0;
-            error(this, errorMessage);
-            emit finished();
-            return;
-        };
-    }
+    // Prompt the user to start up the Blue tooth connection    
+    const trk::PromptStartCommunicationResult src =
+            S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(),
+                                                             m_serialPortName,
+                                                             m_communicationType, 0,
+                                                             &errorMessage);
+    switch (src) {
+    case trk::PromptStartCommunicationConnected:
+        break;
+    case trk::PromptStartCommunicationCanceled:
+    case trk::PromptStartCommunicationError:
+        delete m_launcher;
+        m_launcher = 0;
+        error(this, errorMessage);
+        emit finished();
+        return;
+    };
+
     if (!m_launcher->startServer(&errorMessage)) {
         delete m_launcher;
         m_launcher = 0;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
index 0b1554b1bae58ab3191eb1ee110c454751ae3613..46ebf4f0443c8d4ed549304377b8ead268f2eaae 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
@@ -302,22 +302,22 @@ bool S60DeviceRunConfigurationWidget::getDeviceInfo(QString *message)
     const CommunicationDevice commDev = currentDevice();
     launcher->setSerialFrame(commDev.type == SerialPortCommunication);
     launcher->setTrkServerName(commDev.portName);
-    // Prompt the user to start
-    if (commDev.type == BlueToothCommunication) {
-        S60RunConfigBluetoothStarter starter(launcher->trkDevice());
-        starter.setDevice(launcher->trkServerName());
-        const trk::StartBluetoothGuiResult src = trk::startBluetoothGui(starter, this, message);
-        switch (src) {
-        case trk::BluetoothGuiConnected:
-            break;
-        case trk::BluetoothGuiCanceled:
-            launcher->deleteLater();
-            return true;
-        case trk::BluetoothGuiError:
-            launcher->deleteLater();
-            return false;
-        };
-    }
+    // Prompt user
+    const trk::PromptStartCommunicationResult src =
+            S60RunConfigBluetoothStarter::startCommunication(launcher->trkDevice(),
+                                                             commDev.portName,
+                                                             commDev.type, this,
+                                                             message);
+    switch (src) {
+    case trk::PromptStartCommunicationConnected:
+        break;
+    case trk::PromptStartCommunicationCanceled:
+        launcher->deleteLater();
+        return true;
+    case trk::PromptStartCommunicationError:
+        launcher->deleteLater();
+        return false;
+    };
     if (!launcher->startServer(message)) {
         launcher->deleteLater();
         return false;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp
index 1481dcacbc9d755e803a511a0a208a3e4f7c5cec..b12aa0f1d292196e81e9f31e5362ee4877537cb7 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp
@@ -29,6 +29,7 @@
 
 #include "s60runconfigbluetoothstarter.h"
 #include "bluetoothlistener.h"
+#include "serialdevicelister.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/messagemanager.h>
@@ -49,5 +50,25 @@ trk::BluetoothListener *S60RunConfigBluetoothStarter::createListener()
     connect(rc, SIGNAL(message(QString)), core->messageManager(), SLOT(printToOutputPane(QString)));
     return rc;
 }
+
+trk::PromptStartCommunicationResult
+S60RunConfigBluetoothStarter::startCommunication(const TrkDevicePtr &trkDevice,
+                                                 const QString &device,
+                                                 int communicationType,
+                                                 QWidget *msgBoxParent,
+                                                 QString *errorMessage)
+{
+    // Bluetooth?
+    if (communicationType == BlueToothCommunication) {
+        S60RunConfigBluetoothStarter bluetoothStarter(trkDevice);
+        bluetoothStarter.setDevice(device);
+        return trk::promptStartBluetooth(bluetoothStarter, msgBoxParent, errorMessage);
+    }
+    // Serial
+    BaseCommunicationStarter serialStarter(trkDevice);
+    serialStarter.setDevice(device);
+    return trk::promptStartSerial(serialStarter, msgBoxParent, errorMessage);
+}
+
 } // namespace Internal
 } // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h
index 0da8817b323dc445c18eebdbc1c93adb1a7cd415..70ea0123f5d44ca5772a9e1d42dd03a31663c6c9 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h
@@ -31,20 +31,34 @@
 #define S60RUNCONFIGBLUETOOTHSTARTER_H
 
 #include "communicationstarter.h"
+#include "bluetoothlistener_gui.h"
 
 namespace Qt4ProjectManager {
 namespace Internal {
 
 /* S60RunConfigBluetoothStarter: Creates a listener in 'Listen' mode
- * parented on the Qt Creator core which outputs to the message manager. */
+ * parented on the Qt Creator core which outputs to the message manager.
+ * Provides a static convenience to prompt for both connection types. */
 
 class S60RunConfigBluetoothStarter : public trk::AbstractBluetoothStarter
 {
 public:
-    explicit S60RunConfigBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
+    typedef  trk::AbstractBluetoothStarter::TrkDevicePtr TrkDevicePtr;
+
+    // Convenience function to start communication depending on type,
+    // passing on the right messages.
+    static trk::PromptStartCommunicationResult
+            startCommunication(const TrkDevicePtr &trkDevice,
+                               const QString &device,
+                               int communicationType,
+                               QWidget *msgBoxParent,
+                               QString *errorMessage);
 
 protected:
     virtual trk::BluetoothListener *createListener();
+
+private:
+    explicit S60RunConfigBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
 };
 
 } // namespace Internal
diff --git a/src/shared/trk/bluetoothlistener_gui.cpp b/src/shared/trk/bluetoothlistener_gui.cpp
index ee21c82a7c5c6b2850bef35954b33fac682e969e..edcb40a9a52564706ab5df041f415a0f83fdda32 100644
--- a/src/shared/trk/bluetoothlistener_gui.cpp
+++ b/src/shared/trk/bluetoothlistener_gui.cpp
@@ -38,38 +38,62 @@
 
 namespace trk {
 
-StartBluetoothGuiResult
-    startBluetoothGui(AbstractBluetoothStarter &starter,
-                      QWidget *msgBoxParent,
-                      QString *errorMessage)
+PromptStartCommunicationResult
+    promptStartCommunication(BaseCommunicationStarter &starter,
+                             const QString &msgBoxTitle,
+                             const QString &msgBoxText,
+                             QWidget *msgBoxParent,
+                             QString *errorMessage)
 {
     errorMessage->clear();
+    // Initial connection attempt.
     switch (starter.start()) {
-    case AbstractBluetoothStarter::Started:
+    case BaseCommunicationStarter::Started:
         break;
-    case AbstractBluetoothStarter::ConnectionSucceeded:
-        return BluetoothGuiConnected;
-    case AbstractBluetoothStarter::StartError:
+    case BaseCommunicationStarter::ConnectionSucceeded:
+        return PromptStartCommunicationConnected;
+    case BaseCommunicationStarter::StartError:
         *errorMessage = starter.errorString();
-        return BluetoothGuiError;
+        return PromptStartCommunicationError;
     }
-    // Run the starter with the event loop of a message box, close it
-    // with the finished signals.
-    const QString title = QCoreApplication::translate("trk::startBluetoothGui", "Waiting for Bluetooth Connection");
-    const QString message = QCoreApplication::translate("trk::startBluetoothGui", "Connecting to %1...").arg(starter.device());
-    QMessageBox messageBox(QMessageBox::Information, title, message, QMessageBox::Cancel, msgBoxParent);
+    // Run the starter with the event loop of a message box, have the box
+    // closed by the signals of the starter.
+    QMessageBox messageBox(QMessageBox::Information, msgBoxTitle, msgBoxText, QMessageBox::Cancel, msgBoxParent);
     QObject::connect(&starter, SIGNAL(connected()), &messageBox, SLOT(close()));
     QObject::connect(&starter, SIGNAL(timeout()), &messageBox, SLOT(close()));
-    messageBox.exec();
-    // Only starter.state() is reliable here.
-    if (starter.state() == AbstractBluetoothStarter::Running) {
-        *errorMessage = QCoreApplication::translate("trk::startBluetoothGui", "Connection on %1 canceled.").arg(starter.device());
-        return BluetoothGuiCanceled;
-    }
-    if (starter.state() != AbstractBluetoothStarter::Connected) {
+    messageBox.exec();    
+    // Only starter.state() is reliable here to obtain the state.
+    switch (starter.state()) {
+    case AbstractBluetoothStarter::Running:
+        *errorMessage = QCoreApplication::translate("trk::promptStartCommunication", "Connection on %1 canceled.").arg(starter.device());
+        return PromptStartCommunicationCanceled;
+    case AbstractBluetoothStarter::TimedOut:
         *errorMessage = starter.errorString();
-        return BluetoothGuiError;
+        return PromptStartCommunicationError;
+    case AbstractBluetoothStarter::Connected:
+        break;
     }
-    return BluetoothGuiConnected;
+    return PromptStartCommunicationConnected;
+}
+
+PromptStartCommunicationResult
+    promptStartSerial(BaseCommunicationStarter &starter,
+                         QWidget *msgBoxParent,
+                         QString *errorMessage)
+{
+    const QString title = QCoreApplication::translate("trk::promptStartCommunication", "Waiting for TRK");
+    const QString message = QCoreApplication::translate("trk::promptStartCommunication", "Waiting for TRK to start on %1...").arg(starter.device());
+    return promptStartCommunication(starter, title, message, msgBoxParent, errorMessage);
 }
+
+PromptStartCommunicationResult
+    promptStartBluetooth(BaseCommunicationStarter &starter,
+                         QWidget *msgBoxParent,
+                         QString *errorMessage)
+{
+    const QString title = QCoreApplication::translate("trk::promptStartCommunication", "Waiting for Bluetooth Connection");
+    const QString message = QCoreApplication::translate("trk::promptStartCommunication", "Connecting to %1...").arg(starter.device());
+    return promptStartCommunication(starter, title, message, msgBoxParent, errorMessage);
+}
+
 } // namespace trk
diff --git a/src/shared/trk/bluetoothlistener_gui.h b/src/shared/trk/bluetoothlistener_gui.h
index 2a7c57e291ae53ec7d3bdf53fcac0e4b4cb60d26..83cce425ea35ce6e4cae1463ef22ce16c78630ca 100644
--- a/src/shared/trk/bluetoothlistener_gui.h
+++ b/src/shared/trk/bluetoothlistener_gui.h
@@ -37,22 +37,39 @@ class QWidget;
 QT_END_NAMESPACE
 
 namespace trk {
-    class AbstractBluetoothStarter;
+class BaseCommunicationStarter;
 
-    /* startBluetoothGui(): Prompt the user to start a Bluetooth
-     * connection with a message box he can cancel. Pass in
-     * the starter with device and parameters set up.  */
+/* promptStartCommunication(): Convenience functions that
+ * prompt the user to start a communication (launching or
+ * connecting TRK) using a modal message box in which they can cancel.
+ * Pass in the starter with device and parameters set up.  */
 
-    enum StartBluetoothGuiResult {
-        BluetoothGuiConnected,
-        BluetoothGuiCanceled,
-        BluetoothGuiError
-    };
+enum PromptStartCommunicationResult {
+    PromptStartCommunicationConnected,
+    PromptStartCommunicationCanceled,
+    PromptStartCommunicationError
+};
 
-    StartBluetoothGuiResult
-        startBluetoothGui(AbstractBluetoothStarter &starter,
+PromptStartCommunicationResult
+        promptStartCommunication(BaseCommunicationStarter &starter,
+                                 const QString &msgBoxTitle,
+                                 const QString &msgBoxText,
+                                 QWidget *msgBoxParent,
+                                 QString *errorMessage);
+
+// Convenience to start a serial connection (messages prompting
+// to launch Trk).
+PromptStartCommunicationResult
+        promptStartSerial(BaseCommunicationStarter &starter,
                           QWidget *msgBoxParent,
                           QString *errorMessage);
+
+// Convenience to start blue tooth connection (messages
+// prompting to connect).
+PromptStartCommunicationResult
+        promptStartBluetooth(BaseCommunicationStarter &starter,
+                             QWidget *msgBoxParent,
+                             QString *errorMessage);
 } // namespace trk
 
 #endif // BLUETOOTHLISTENER_GUI_H
diff --git a/src/shared/trk/communicationstarter.cpp b/src/shared/trk/communicationstarter.cpp
index 58a954cd26be473bbb535d1654f7e59fcf57efab..b425db2506280b3a22293d2a7e7b04171103d42d 100644
--- a/src/shared/trk/communicationstarter.cpp
+++ b/src/shared/trk/communicationstarter.cpp
@@ -35,11 +35,12 @@
 #include <QtCore/QEventLoop>
 
 namespace trk {
+
 // --------------- AbstractBluetoothStarter
-struct AbstractBluetoothStarterPrivate {
-    explicit AbstractBluetoothStarterPrivate(const AbstractBluetoothStarter::TrkDevicePtr &d);
+struct BaseCommunicationStarterPrivate {
+    explicit BaseCommunicationStarterPrivate(const BaseCommunicationStarter::TrkDevicePtr &d);
 
-    const AbstractBluetoothStarter::TrkDevicePtr trkDevice;
+    const BaseCommunicationStarter::TrkDevicePtr trkDevice;
     BluetoothListener *listener;
     QTimer *timer;
     int intervalMS;
@@ -47,11 +48,10 @@ struct AbstractBluetoothStarterPrivate {
     int n;
     QString device;
     QString errorString;
-    AbstractBluetoothStarter::State state;
+    BaseCommunicationStarter::State state;
 };
 
-AbstractBluetoothStarterPrivate::AbstractBluetoothStarterPrivate(const AbstractBluetoothStarter::TrkDevicePtr &d) :
-
+BaseCommunicationStarterPrivate::BaseCommunicationStarterPrivate(const BaseCommunicationStarter::TrkDevicePtr &d) :
         trkDevice(d),
         listener(0),
         timer(0),
@@ -59,32 +59,38 @@ AbstractBluetoothStarterPrivate::AbstractBluetoothStarterPrivate(const AbstractB
         attempts(-1),
         n(0),
         device(QLatin1String("/dev/rfcomm0")),
-        state(AbstractBluetoothStarter::TimedOut)
+        state(BaseCommunicationStarter::TimedOut)
 {
 }
 
-AbstractBluetoothStarter::AbstractBluetoothStarter(const TrkDevicePtr &trkDevice, QObject *parent) :
+BaseCommunicationStarter::BaseCommunicationStarter(const TrkDevicePtr &trkDevice, QObject *parent) :
         QObject(parent),
-        d(new AbstractBluetoothStarterPrivate(trkDevice))
+        d(new BaseCommunicationStarterPrivate(trkDevice))
 {
 }
 
-AbstractBluetoothStarter::~AbstractBluetoothStarter()
+BaseCommunicationStarter::~BaseCommunicationStarter()
 {
     stopTimer();
     delete d;
 }
 
-void AbstractBluetoothStarter::stopTimer()
+void BaseCommunicationStarter::stopTimer()
 {
     if (d->timer && d->timer->isActive())
         d->timer->stop();
 }
 
-AbstractBluetoothStarter::StartResult AbstractBluetoothStarter::start()
+bool BaseCommunicationStarter::initializeStartupResources(QString *errorMessage)
+{
+    errorMessage->clear();
+    return true;
+}
+
+BaseCommunicationStarter::StartResult BaseCommunicationStarter::start()
 {
     if (state() == Running) {
-        d->errorString = QLatin1String("Internal error, attempt to re-start AbstractBluetoothStarter.\n");
+        d->errorString = QLatin1String("Internal error, attempt to re-start BaseCommunicationStarter.\n");
         return StartError;
     }
     // Before we instantiate timers, and such, try to open the device,
@@ -92,10 +98,9 @@ AbstractBluetoothStarter::StartResult AbstractBluetoothStarter::start()
     // 'Watch' mode
     if (d->trkDevice->open(d->device , &(d->errorString)))
         return ConnectionSucceeded;
-    // Fire up the listener
+    // Pull up resources for next attempt
     d->n = 0;
-    d->listener = createListener();
-    if (!d->listener->start(d->device, &(d->errorString)))
+    if (!initializeStartupResources(&(d->errorString)))
         return StartError;
     // Start timer
     if (!d->timer) {
@@ -109,49 +114,49 @@ AbstractBluetoothStarter::StartResult AbstractBluetoothStarter::start()
     return Started;
 }
 
-AbstractBluetoothStarter::State AbstractBluetoothStarter::state() const
+BaseCommunicationStarter::State BaseCommunicationStarter::state() const
 {
     return d->state;
 }
 
-int AbstractBluetoothStarter::intervalMS() const
+int BaseCommunicationStarter::intervalMS() const
 {
     return d->intervalMS;
 }
 
-void AbstractBluetoothStarter::setIntervalMS(int i)
+void BaseCommunicationStarter::setIntervalMS(int i)
 {
     d->intervalMS = i;
     if (d->timer)
         d->timer->setInterval(i);
 }
 
-int AbstractBluetoothStarter::attempts() const
+int BaseCommunicationStarter::attempts() const
 {
     return d->attempts;
 }
 
-void AbstractBluetoothStarter::setAttempts(int a)
+void BaseCommunicationStarter::setAttempts(int a)
 {
     d->attempts = a;
 }
 
-QString AbstractBluetoothStarter::device() const
+QString BaseCommunicationStarter::device() const
 {
     return d->device;
 }
 
-void AbstractBluetoothStarter::setDevice(const QString &dv)
+void BaseCommunicationStarter::setDevice(const QString &dv)
 {
     d->device = dv;
 }
 
-QString AbstractBluetoothStarter::errorString() const
+QString BaseCommunicationStarter::errorString() const
 {
     return d->errorString;
 }
 
-void AbstractBluetoothStarter::slotTimer()
+void BaseCommunicationStarter::slotTimer()
 {
     ++d->n;
     // Check for timeout
@@ -166,17 +171,32 @@ void AbstractBluetoothStarter::slotTimer()
         if (d->trkDevice->open(d->device , &(d->errorString))) {
             stopTimer();
             const QString msg = tr("%1: Connection attempt %2 succeeded.").arg(d->device).arg(d->n);
-            d->listener->emitMessage(msg);
+            emit message(msg);
             d->state = Connected;
             emit connected();
         } else {
             const QString msg = tr("%1: Connection attempt %2 failed: %3 (retrying)...")
                                 .arg(d->device).arg(d->n).arg(d->errorString);
-            d->listener->emitMessage(msg);
+            emit message(msg);
         }
     }
 }
 
+// --------------- AbstractBluetoothStarter
+
+AbstractBluetoothStarter::AbstractBluetoothStarter(const TrkDevicePtr &trkDevice, QObject *parent) :
+    BaseCommunicationStarter(trkDevice, parent)
+{
+}
+
+bool AbstractBluetoothStarter::initializeStartupResources(QString *errorMessage)
+{
+    // Create the listener and forward messages to it.
+    BluetoothListener *listener = createListener();
+    connect(this, SIGNAL(message(QString)), listener, SLOT(emitMessage(QString)));
+    return listener->start(device(), errorMessage);
+}
+
 // -------- ConsoleBluetoothStarter
 ConsoleBluetoothStarter::ConsoleBluetoothStarter(const TrkDevicePtr &trkDevice,
                                                  QObject *listenerParent,
diff --git a/src/shared/trk/communicationstarter.h b/src/shared/trk/communicationstarter.h
index e90578dc1717989610e86fcd6e94fef8b3fffa07..7b89e2472ed0a6c0583e7348362821a822075389 100644
--- a/src/shared/trk/communicationstarter.h
+++ b/src/shared/trk/communicationstarter.h
@@ -36,25 +36,28 @@
 namespace trk {
 class TrkDevice;
 class BluetoothListener;
-struct AbstractBluetoothStarterPrivate;
-
-/* AbstractBluetoothStarter: Repeatedly tries to open a trk device
- * until a connection succeeds, allowing to do something else in the
- * foreground (local event loop or asynchronous operation).
- * Note that in case a Listener is already running in watch mode, it might
- * also happen that connection succeeds immediately.
- * Implementations must provide a factory function that creates and sets up the
- * listener (mode, message connection, etc). */
-
-class AbstractBluetoothStarter : public QObject {
+struct BaseCommunicationStarterPrivate;
+
+/* BaseCommunicationStarter: A QObject that repeatedly tries to open a
+ * trk device until a connection succeeds or a timeout occurs (emitting
+ * signals), allowing to do something else in the foreground (local event loop
+ * [say QMessageBox] or some asynchronous operation). If the initial
+ * connection attempt in start() fails, the
+ * virtual initializeStartupResources() is called to initialize resources
+ * required to pull up the communication (namely Bluetooth listeners).
+ * The base class can be used as is to prompt the user to launch TRK for a serial
+ * communication as this requires no further resource setup. */
+
+class BaseCommunicationStarter : public QObject {
     Q_OBJECT
-    Q_DISABLE_COPY(AbstractBluetoothStarter)
+    Q_DISABLE_COPY(BaseCommunicationStarter)
 public:
-            typedef QSharedPointer<TrkDevice> TrkDevicePtr;
+    typedef QSharedPointer<TrkDevice> TrkDevicePtr;
 
     enum State { Running, Connected, TimedOut };
 
-    virtual ~AbstractBluetoothStarter();
+    explicit BaseCommunicationStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
+    virtual ~BaseCommunicationStarter();
 
     int intervalMS() const;
     void setIntervalMS(int i);
@@ -80,19 +83,40 @@ public:
 signals:
     void connected();
     void timeout();
+    void message(const QString &);
 
 private slots:
     void slotTimer();
 
 protected:
-    explicit AbstractBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
-    // Overwrite to create and parametrize the listener.
-    virtual BluetoothListener *createListener() = 0;
+    virtual bool initializeStartupResources(QString *errorMessage);
 
 private:
     inline void stopTimer();
 
-    AbstractBluetoothStarterPrivate *d;
+    BaseCommunicationStarterPrivate *d;
+};
+
+/* AbstractBluetoothStarter: Repeatedly tries to open a trk Bluetooth
+ * device. Note that in case a Listener is already running mode, the
+ * connection will succeed immediately.
+ * initializeStartupResources() is implemented to fire up the listener.
+ * Introduces a new virtual createListener() that derived classes must
+ * implement as a factory function that creates and sets up the
+ * listener (mode, message connection, etc). */
+
+class AbstractBluetoothStarter : public BaseCommunicationStarter {
+    Q_OBJECT
+    Q_DISABLE_COPY(AbstractBluetoothStarter)
+public:
+
+protected:
+    explicit AbstractBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
+
+    // Implemented to fire up the listener.
+    virtual bool initializeStartupResources(QString *errorMessage);
+    // New virtual: Overwrite to create and parametrize the listener.
+    virtual BluetoothListener *createListener() = 0;
 };
 
 /* ConsoleBluetoothStarter: Convenience class for console processes. Creates a
@@ -102,12 +126,11 @@ class ConsoleBluetoothStarter : public AbstractBluetoothStarter {
     Q_OBJECT
     Q_DISABLE_COPY(ConsoleBluetoothStarter)
 public:
-
-            static bool startBluetooth(const TrkDevicePtr& trkDevice,
-                                       QObject *listenerParent,
-                                       const QString &device,
-                                       int attempts,
-                                       QString *errorMessage);
+    static bool startBluetooth(const TrkDevicePtr& trkDevice,
+                               QObject *listenerParent,
+                               const QString &device,
+                               int attempts,
+                               QString *errorMessage);
 
 protected:
     virtual BluetoothListener *createListener();
diff --git a/src/shared/trk/trk.pri b/src/shared/trk/trk.pri
index 5b0e067b15840566822e3e38ac546ae3086e2498..2ce17c0a6c68980811b893171e4c73022a21d603 100644
--- a/src/shared/trk/trk.pri
+++ b/src/shared/trk/trk.pri
@@ -14,6 +14,7 @@ SOURCES += $$PWD/trkutils.cpp \
     $$PWD/bluetoothlistener.cpp \
     $$PWD/communicationstarter.cpp
 
+# Tests/trklauncher is a console application
 contains(QT, gui) {
    HEADERS += $$PWD/bluetoothlistener_gui.h
     SOURCES += $$PWD/bluetoothlistener_gui.cpp