Hi,

I did the modifications we discussed and I added two extra
improvements (patch number 4 and 19).

The modifications are available on *bth_windows* branch [1].
I thought that it would be easier for Thiago to review the new code
if I will create a separate branch.

Claudiu

[1] - https://github.com/claudiuolteanu/subsurface/tree/bth_windows
From b5225ce0a5d94e70253d0a97b3f894234c7f93df Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 15:51:32 +0300
Subject: [PATCH 01/19] Cleanup Bluetooth local device and the discovery agent
 on exit

Do some extra cleanup when the BtDeviceSelectionDialog is destroyed.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 007fe94..ce759cc 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -61,6 +61,15 @@ BtDeviceSelectionDialog::BtDeviceSelectionDialog(QWidget *parent) :
 BtDeviceSelectionDialog::~BtDeviceSelectionDialog()
 {
 	delete ui;
+
+	// Clean the local device
+	delete localDevice;
+
+	// Clean the device discovery agent
+	if (remoteDeviceDiscoveryAgent->isActive())
+		remoteDeviceDiscoveryAgent->stop();
+
+	delete remoteDeviceDiscoveryAgent;
 }
 
 void BtDeviceSelectionDialog::on_changeDeviceState_clicked()
-- 
2.1.4

From 546184eb3d8e246ed4dd34b31d43bd37b2312e44 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 15:52:31 +0300
Subject: [PATCH 02/19] Check the last error when the BTH device scanning is
 finished

If there is no error reported when the device scanning is finished
then report to the dialog status that the scanning finished
successfully. Otherwise report the last error.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index ce759cc..3af2501 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -124,7 +124,12 @@ void BtDeviceSelectionDialog::on_scan_clicked()
 
 void BtDeviceSelectionDialog::remoteDeviceScanFinished()
 {
-	ui->dialogStatus->setText("Scanning finished.");
+	if (remoteDeviceDiscoveryAgent->error() == QBluetoothDeviceDiscoveryAgent::NoError) {
+		ui->dialogStatus->setText("Scanning finished successfully.");
+	} else {
+		deviceDiscoveryError(remoteDeviceDiscoveryAgent->error());
+	}
+
 	ui->scan->setEnabled(true);
 }
 
-- 
2.1.4

From 70ad7b8a83d3f594ec0dc5ba089aa4944e5a8a1d Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 15:56:31 +0300
Subject: [PATCH 03/19] Clear the BTH discovered devices list on each search

Clear the Bluetooth discovered devices list on each search.
In this way we will show only the devices that are in range
and active during the last scannning. Also if we clear the
list before each call we don't need to check anymore if the
discovered device is already in the list.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 3af2501..cbc247d 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -118,6 +118,7 @@ void BtDeviceSelectionDialog::on_clear_clicked()
 void BtDeviceSelectionDialog::on_scan_clicked()
 {
 	ui->dialogStatus->setText("Scanning for remote devices...");
+	ui->discoveredDevicesList->clear();
 	remoteDeviceDiscoveryAgent->start();
 	ui->scan->setEnabled(false);
 }
@@ -145,28 +146,27 @@ void BtDeviceSelectionDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMo
 
 void BtDeviceSelectionDialog::addRemoteDevice(const QBluetoothDeviceInfo &remoteDeviceInfo)
 {
-	QString deviceLabel = QString("%1  (%2)").arg(remoteDeviceInfo.name()).arg(remoteDeviceInfo.address().toString());
-	QList<QListWidgetItem *> itemsWithSameSignature = ui->discoveredDevicesList->findItems(deviceLabel, Qt::MatchStartsWith);
+	QColor pairingColor = QColor(Qt::red);
+	QString pairingStatusLabel = QString("UNPAIRED");
+	QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address());
 
-	// Check if the remote device is already in the list
-	if (itemsWithSameSignature.empty()) {
-		QListWidgetItem *item = new QListWidgetItem(deviceLabel);
-		QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address());
-		item->setData(Qt::UserRole, QVariant::fromValue(remoteDeviceInfo));
+	if (pairingStatus == QBluetoothLocalDevice::Paired) {
+		pairingStatusLabel = QString("PAIRED");
+		pairingColor = QColor(Qt::gray);
+	} else if (pairingStatus == QBluetoothLocalDevice::AuthorizedPaired) {
+		pairingStatusLabel = QString("AUTHORIZED_PAIRED");
+		pairingColor = QColor(Qt::blue);
+	}
 
-		if (pairingStatus == QBluetoothLocalDevice::Paired) {
-			item->setText(QString("%1   [State: PAIRED]").arg(item->text()));
-			item->setBackgroundColor(QColor(Qt::gray));
-		} else if (pairingStatus == QBluetoothLocalDevice::AuthorizedPaired) {
-			item->setText(QString("%1   [State: AUTHORIZED_PAIRED]").arg(item->text()));
-			item->setBackgroundColor(QColor(Qt::blue));
-		} else {
-			item->setText(QString("%1   [State: UNPAIRED]").arg(item->text()));
-			item->setTextColor(QColor(Qt::black));
-		}
+	QString deviceLabel = QString("%1 (%2)   [State: %3]").arg(remoteDeviceInfo.name(),
+								   remoteDeviceInfo.address().toString(),
+								   pairingStatusLabel);
+	QListWidgetItem *item = new QListWidgetItem(deviceLabel);
 
-		ui->discoveredDevicesList->addItem(item);
-	}
+	item->setData(Qt::UserRole, QVariant::fromValue(remoteDeviceInfo));
+	item->setBackgroundColor(pairingColor);
+
+	ui->discoveredDevicesList->addItem(item);
 }
 
 void BtDeviceSelectionDialog::itemClicked(QListWidgetItem *item)
-- 
2.1.4

From 34cd2d386e0fbb1bca7a342caf7d86a90869b22b Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 18:53:53 +0300
Subject: [PATCH 04/19] Reimplement pairingFinished method

The old implementation didn't use the correct deviceLabel pattern.
When the pairing status of a device was changed the name of the device
was missing from the new label. With the new implementation when the
pairing status is changed we replace the old state with the new one and
maintain the device information from the old label.
Also we set the same pairing background colors used in the
addRemoteDevice callback. In this way the label's state is consistent
and the UX is improved.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 69 +++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 31 deletions(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index cbc247d..05a1f96 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -241,46 +241,53 @@ void BtDeviceSelectionDialog::displayPairingMenu(const QPoint &pos)
 
 void BtDeviceSelectionDialog::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
 {
+	// Determine the color, the new pairing status and the log message. By default we assume that the devices are UNPAIRED.
 	QString remoteDeviceStringAddress = address.toString();
-	QList<QListWidgetItem *> items = ui->discoveredDevicesList->findItems(remoteDeviceStringAddress, Qt::MatchContains);
-
-	if (pairing == QBluetoothLocalDevice::Paired || pairing == QBluetoothLocalDevice::Paired ) {
-		ui->dialogStatus->setText(QString("Device %1 was paired.")
-					  .arg(remoteDeviceStringAddress));
-
-		for (int i = 0; i < items.count(); ++i) {
-			QListWidgetItem *item = items.at(i);
-
-			item->setText(QString("%1   [State: PAIRED]").arg(remoteDeviceStringAddress));
-			item->setBackgroundColor(QColor(Qt::gray));
-		}
+	QColor pairingColor = QColor(Qt::red);
+	QString pairingStatusLabel = QString("UNPAIRED");
+	QString dialogStatusMessage = QString("Device %1 was unpaired.").arg(remoteDeviceStringAddress);
+	bool enableSaveButton = false;
 
-		QListWidgetItem *currentItem = ui->discoveredDevicesList->currentItem();
+	if (pairing == QBluetoothLocalDevice::Paired) {
+		pairingStatusLabel = QString("PAIRED");
+		pairingColor = QColor(Qt::gray);
+		enableSaveButton = true;
+		dialogStatusMessage = QString("Device %1 was paired.").arg(remoteDeviceStringAddress);
+	} else if (pairing == QBluetoothLocalDevice::AuthorizedPaired) {
+		pairingStatusLabel = QString("AUTHORIZED_PAIRED");
+		pairingColor = QColor(Qt::blue);
+		enableSaveButton = true;
+		dialogStatusMessage = QString("Device %1 was authorized paired.").arg(remoteDeviceStringAddress);
+	}
 
-		if (currentItem != NULL && currentItem->text().contains(remoteDeviceStringAddress, Qt::CaseInsensitive)) {
-			ui->dialogStatus->setText(QString("The device %1 can now be used for connection. You can press the Save button.")
-						  .arg(remoteDeviceStringAddress));
-			ui->save->setEnabled(true);
-		}
-	} else {
-		ui->dialogStatus->setText(QString("Device %1 was unpaired.")
-					  .arg(remoteDeviceStringAddress));
+	// Find the items which represent the BTH device and update their state
+	QList<QListWidgetItem *> items = ui->discoveredDevicesList->findItems(remoteDeviceStringAddress, Qt::MatchContains);
 
-		for (int i = 0; i < items.count(); ++i) {
-			QListWidgetItem *item = items.at(i);
+	for (int i = 0; i < items.count(); ++i) {
+		QListWidgetItem *item = items.at(i);
+		QString updatedDeviceLabel = item->text().replace(QRegularExpression("PAIRED|AUTHORIZED_PAIRED|UNPAIRED"),
+								  pairingStatusLabel);
 
-			item->setText(QString("%1   [State: UNPAIRED]").arg(remoteDeviceStringAddress));
-			item->setBackgroundColor(QColor(Qt::white));
-		}
+		item->setText(updatedDeviceLabel);
+		item->setBackgroundColor(pairingColor);
+	}
 
-		QListWidgetItem *currentItem = ui->discoveredDevicesList->currentItem();
+	// Check if the updated device is the selected one from the list and inform the user that it can/cannot start the download mode
+	QListWidgetItem *currentItem = ui->discoveredDevicesList->currentItem();
 
-		if (currentItem != NULL && currentItem->text().contains(remoteDeviceStringAddress, Qt::CaseInsensitive)) {
-			ui->dialogStatus->setText(QString("The device %1 must be paired in order to be used. Please use the context menu for pairing options.")
-						  .arg(remoteDeviceStringAddress));
-			ui->save->setEnabled(false);
+	if (currentItem != NULL && currentItem->text().contains(remoteDeviceStringAddress, Qt::CaseInsensitive)) {
+		if (pairing == QBluetoothLocalDevice::Unpaired) {
+			dialogStatusMessage = QString("The device %1 must be paired in order to be used. Please use the context menu for pairing options.")
+						     .arg(remoteDeviceStringAddress);
+		} else {
+			dialogStatusMessage = QString("The device %1 can now be used for connection. You can press the Save button.")
+						     .arg(remoteDeviceStringAddress);
 		}
 	}
+
+	// Update the save button and the dialog status message
+	ui->save->setEnabled(enableSaveButton);
+	ui->dialogStatus->setText(dialogStatusMessage);
 }
 
 void BtDeviceSelectionDialog::error(QBluetoothLocalDevice::Error error)
-- 
2.1.4

From 285298eeef26c95bcd337fbc55ac3958526eabbe Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 19:03:29 +0300
Subject: [PATCH 05/19] Add set_timeout callback for Bluetooth custom serial
 implementation

The new callback will be usefull when we will implement the support
for Windows. The implementation of native serial set_timeout method
uses a HANDLER on Windows and we will use the WinSock2 API which has
a socket descriptor.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qtserialbluetooth.cpp | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/qtserialbluetooth.cpp b/qtserialbluetooth.cpp
index 5a982d6..378f330 100644
--- a/qtserialbluetooth.cpp
+++ b/qtserialbluetooth.cpp
@@ -224,6 +224,15 @@ static int qt_serial_get_transmitted(serial_t *device)
 	return device->socket->bytesToWrite();
 }
 
+static int qt_serial_set_timeout(serial_t *device, long timeout)
+{
+	if (device == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	device->timeout = timeout;
+
+	return DC_STATUS_SUCCESS;
+}
 
 const dc_serial_operations_t qt_serial_ops = {
 	.open = qt_serial_open,
@@ -232,7 +241,8 @@ const dc_serial_operations_t qt_serial_ops = {
 	.write = qt_serial_write,
 	.flush = qt_serial_flush,
 	.get_received = qt_serial_get_received,
-	.get_transmitted = qt_serial_get_transmitted
+	.get_transmitted = qt_serial_get_transmitted,
+	.set_timeout = qt_serial_set_timeout
 };
 
 extern void dc_serial_init (dc_serial_t *serial, void *data, const dc_serial_operations_t *ops);
-- 
2.1.4

From 6bcc545f76fef2215ab1109d4fa12e7539d051c4 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 19:47:40 +0300
Subject: [PATCH 06/19] Add skeleton for Bluetooth custom serial implementation
 on Windows platforms

Add a skeleton which will be used to develop the Bluetooth custom
serial implementation for Windows platforms.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 88 ++++++++++++++++++++++++++++++++++++++-
 qt-ui/btdeviceselectiondialog.h   | 45 ++++++++++++++++++++
 qtserialbluetooth.cpp             | 72 +++++++++++++++++++++++++++++---
 3 files changed, 198 insertions(+), 7 deletions(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 05a1f96..41c64c8 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -8,7 +8,6 @@
 
 BtDeviceSelectionDialog::BtDeviceSelectionDialog(QWidget *parent) :
 	QDialog(parent),
-	localDevice(new QBluetoothLocalDevice),
 	ui(new Ui::BtDeviceSelectionDialog)
 {
 	ui->setupUi(this);
@@ -21,9 +20,16 @@ BtDeviceSelectionDialog::BtDeviceSelectionDialog(QWidget *parent) :
 	// Disable the save button because there is no device selected
 	ui->save->setEnabled(false);
 
+	// Add event for item selection
 	connect(ui->discoveredDevicesList, SIGNAL(itemClicked(QListWidgetItem*)),
 		this, SLOT(itemClicked(QListWidgetItem*)));
 
+#if defined(Q_OS_WIN)
+	// TODO do the initialization
+#else
+	// Initialize the local Bluetooth device
+	localDevice = new QBluetoothLocalDevice();
+
 	// Populate the list with local bluetooth devices
 	QList<QBluetoothHostInfo> localAvailableDevices = localDevice->allDevices();
 	int availableDevicesSize = localAvailableDevices.size();
@@ -56,15 +62,20 @@ BtDeviceSelectionDialog::BtDeviceSelectionDialog(QWidget *parent) :
 	// Initialize the device discovery agent
 	if (localDevice->isValid())
 		initializeDeviceDiscoveryAgent();
+#endif
 }
 
 BtDeviceSelectionDialog::~BtDeviceSelectionDialog()
 {
 	delete ui;
 
+#if defined(Q_OS_WIN)
+	// Terminate the use of Winsock 2 DLL
+	WSACleanup();
+#else
 	// Clean the local device
 	delete localDevice;
-
+#endif
 	// Clean the device discovery agent
 	if (remoteDeviceDiscoveryAgent->isActive())
 		remoteDeviceDiscoveryAgent->stop();
@@ -74,6 +85,9 @@ BtDeviceSelectionDialog::~BtDeviceSelectionDialog()
 
 void BtDeviceSelectionDialog::on_changeDeviceState_clicked()
 {
+#if defined(Q_OS_WIN)
+	// TODO add implementation
+#else
 	if (localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff) {
 		ui->dialogStatus->setText("Trying to turn on the local Bluetooth device...");
 		localDevice->powerOn();
@@ -81,6 +95,7 @@ void BtDeviceSelectionDialog::on_changeDeviceState_clicked()
 		ui->dialogStatus->setText("Trying to turn off the local Bluetooth device...");
 		localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
 	}
+#endif
 }
 
 void BtDeviceSelectionDialog::on_save_clicked()
@@ -136,16 +151,23 @@ void BtDeviceSelectionDialog::remoteDeviceScanFinished()
 
 void BtDeviceSelectionDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode)
 {
+#if defined(Q_OS_WIN)
+	// TODO add implementation
+#else
 	bool on = !(mode == QBluetoothLocalDevice::HostPoweredOff);
 
 	ui->dialogStatus->setText(QString("The local Bluetooth device was turned %1.")
 				  .arg(on? "ON" : "OFF"));
 	ui->deviceState->setChecked(on);
 	ui->scan->setEnabled(on);
+#endif
 }
 
 void BtDeviceSelectionDialog::addRemoteDevice(const QBluetoothDeviceInfo &remoteDeviceInfo)
 {
+#if defined(Q_OS_WIN)
+	// TODO add the remote device
+#else
 	QColor pairingColor = QColor(Qt::red);
 	QString pairingStatusLabel = QString("UNPAIRED");
 	QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address());
@@ -167,10 +189,14 @@ void BtDeviceSelectionDialog::addRemoteDevice(const QBluetoothDeviceInfo &remote
 	item->setBackgroundColor(pairingColor);
 
 	ui->discoveredDevicesList->addItem(item);
+#endif
 }
 
 void BtDeviceSelectionDialog::itemClicked(QListWidgetItem *item)
 {
+#if defined(Q_OS_WIN)
+	// TODO enable the save button and log the information about the selected item
+#else
 	QBluetoothDeviceInfo remoteDeviceInfo = item->data(Qt::UserRole).value<QBluetoothDeviceInfo>();
 	QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address());
 
@@ -183,10 +209,14 @@ void BtDeviceSelectionDialog::itemClicked(QListWidgetItem *item)
 					  .arg(remoteDeviceInfo.address().toString()));
 		ui->save->setEnabled(true);
 	}
+#endif
 }
 
 void BtDeviceSelectionDialog::localDeviceChanged(int index)
 {
+#if defined(Q_OS_WIN)
+	// TODO add implementation
+#else
 	QBluetoothAddress localDeviceSelectedAddress = ui->localSelectedDevice->itemData(index, Qt::UserRole).value<QBluetoothAddress>();
 
 	// Delete the old localDevice
@@ -207,10 +237,14 @@ void BtDeviceSelectionDialog::localDeviceChanged(int index)
 	// Initialize the device discovery agent
 	if (localDevice->isValid())
 		initializeDeviceDiscoveryAgent();
+#endif
 }
 
 void BtDeviceSelectionDialog::displayPairingMenu(const QPoint &pos)
 {
+#if defined(Q_OS_WIN)
+	// TODO add implementation
+#else
 	QMenu menu(this);
 	QAction *pairAction = menu.addAction("Pair");
 	QAction *removePairAction = menu.addAction("Remove Pairing");
@@ -237,6 +271,7 @@ void BtDeviceSelectionDialog::displayPairingMenu(const QPoint &pos)
 					  .arg(currentRemoteDeviceInfo.address().toString()));
 		localDevice->requestPairing(currentRemoteDeviceInfo.address(), QBluetoothLocalDevice::Unpaired);
 	}
+#endif
 }
 
 void BtDeviceSelectionDialog::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
@@ -337,6 +372,9 @@ QString BtDeviceSelectionDialog::getSelectedDeviceName()
 
 void BtDeviceSelectionDialog::updateLocalDeviceInformation()
 {
+#if defined(Q_OS_WIN)
+	// TODO add implementation
+#else
 	// Check if the selected Bluetooth device can be accessed
 	if (!localDevice->isValid()) {
 		QString na = QString("Not available");
@@ -376,10 +414,14 @@ void BtDeviceSelectionDialog::updateLocalDeviceInformation()
 
 	connect(localDevice, SIGNAL(error(QBluetoothLocalDevice::Error)),
 		this, SLOT(error(QBluetoothLocalDevice::Error)));
+#endif
 }
 
 void BtDeviceSelectionDialog::initializeDeviceDiscoveryAgent()
 {
+#if defined(Q_OS_WIN)
+	// TODO initialize the discovery agent
+#else
 	// Intialize the discovery agent
 	remoteDeviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(localDevice->address());
 
@@ -399,4 +441,46 @@ void BtDeviceSelectionDialog::initializeDeviceDiscoveryAgent()
 		this, SLOT(remoteDeviceScanFinished()));
 	connect(remoteDeviceDiscoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
 		this, SLOT(deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error)));
+#endif
+}
+
+#if defined(Q_OS_WIN)
+static QString getLastErrorAsString()
+{
+	// TODO get the last error
+}
+
+WinBluetoothDeviceDiscoveryAgent::WinBluetoothDeviceDiscoveryAgent(QObject *parent) : QThread(parent)
+{
+}
+
+WinBluetoothDeviceDiscoveryAgent::~WinBluetoothDeviceDiscoveryAgent()
+{
+}
+
+bool WinBluetoothDeviceDiscoveryAgent::isActive() const
+{
+	return running;
+}
+
+QString WinBluetoothDeviceDiscoveryAgent::errorToString() const
+{
+	return lastErrorToString;
+}
+
+QBluetoothDeviceDiscoveryAgent::Error WinBluetoothDeviceDiscoveryAgent::error() const
+{
+	return lastError;
+}
+
+void WinBluetoothDeviceDiscoveryAgent::run()
+{
+	// TODO initialize the resources and start the device discovery
+}
+
+void WinBluetoothDeviceDiscoveryAgent::stop()
+{
+	// Stop the inqury
+	stopped = true;
 }
+#endif
diff --git a/qt-ui/btdeviceselectiondialog.h b/qt-ui/btdeviceselectiondialog.h
index b6c34e8..e980c9c 100644
--- a/qt-ui/btdeviceselectiondialog.h
+++ b/qt-ui/btdeviceselectiondialog.h
@@ -8,14 +8,55 @@
 #include <QtBluetooth/qbluetoothglobal.h>
 #include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
 
+#if defined(Q_OS_WIN)
+	#include <QThread>
+	#include <winsock2.h>
+	#include <ws2bth.h>
+
+	#define SUCCESS				0
+	#define BTH_ADDR_STR_LEN                100
+
+	#undef ERROR				// this is already declared in our headers
+	#undef IGNORE				// this is already declared in our headers
+	#undef DC_VERSION			// this is already declared in libdivecomputer header
+#endif
+
 #if QT_VERSION < 0x050500
 Q_DECLARE_METATYPE(QBluetoothDeviceInfo)
 #endif
 
+#if defined(Q_OS_WIN)
+Q_DECLARE_METATYPE(QBluetoothDeviceDiscoveryAgent::Error)
+#endif
+
 namespace Ui {
 	class BtDeviceSelectionDialog;
 }
 
+#if defined(Q_OS_WIN)
+class WinBluetoothDeviceDiscoveryAgent : public QThread {
+	Q_OBJECT
+signals:
+	void deviceDiscovered(const QBluetoothDeviceInfo &info);
+	void error(QBluetoothDeviceDiscoveryAgent::Error error);
+
+public:
+	WinBluetoothDeviceDiscoveryAgent(QObject *parent);
+	~WinBluetoothDeviceDiscoveryAgent();
+	bool isActive() const;
+	QString errorToString() const;
+	QBluetoothDeviceDiscoveryAgent::Error error() const;
+	virtual void run();
+	virtual void stop();
+
+private:
+	bool running;
+	bool stopped;
+	QString lastErrorToString;
+	QBluetoothDeviceDiscoveryAgent::Error lastError;
+};
+#endif
+
 class BtDeviceSelectionDialog : public QDialog {
 	Q_OBJECT
 
@@ -42,8 +83,12 @@ private slots:
 
 private:
 	Ui::BtDeviceSelectionDialog *ui;
+#if defined(Q_OS_WIN)
+	WinBluetoothDeviceDiscoveryAgent *remoteDeviceDiscoveryAgent;
+#else
 	QBluetoothLocalDevice *localDevice;
 	QBluetoothDeviceDiscoveryAgent *remoteDeviceDiscoveryAgent;
+#endif
 	QSharedPointer<QBluetoothDeviceInfo> selectedRemoteDeviceInfo;
 
 	void updateLocalDeviceInformation();
diff --git a/qtserialbluetooth.cpp b/qtserialbluetooth.cpp
index 378f330..37ea225 100644
--- a/qtserialbluetooth.cpp
+++ b/qtserialbluetooth.cpp
@@ -10,6 +10,12 @@
 
 #if defined(SSRF_CUSTOM_SERIAL)
 
+#if defined(Q_OS_WIN)
+	#include <winsock2.h>
+	#include <windows.h>
+	#include <ws2bth.h>
+#endif
+
 #include <libdivecomputer/custom_serial.h>
 
 extern "C" {
@@ -19,7 +25,11 @@ typedef struct serial_t {
 	/*
 	 * RFCOMM socket used for Bluetooth Serial communication.
 	 */
+#if defined(Q_OS_WIN)
+	SOCKET socket;
+#else
 	QBluetoothSocket *socket;
+#endif
 	long timeout;
 } serial_t;
 
@@ -40,6 +50,9 @@ static int qt_serial_open(serial_t **out, dc_context_t *context, const char* dev
 	// Default to blocking reads.
 	serial_port->timeout = -1;
 
+#if defined(Q_OS_WIN)
+	// TODO connect the device
+#else
 	// Create a RFCOMM socket
 	serial_port->socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
 
@@ -118,7 +131,7 @@ static int qt_serial_open(serial_t **out, dc_context_t *context, const char* dev
 			return QBluetoothSocket::UnknownSocketError;
 		}
 	}
-
+#endif
 	*out = serial_port;
 
 	return DC_STATUS_SUCCESS;
@@ -126,19 +139,36 @@ static int qt_serial_open(serial_t **out, dc_context_t *context, const char* dev
 
 static int qt_serial_close(serial_t *device)
 {
-	if (device == NULL || device->socket == NULL)
+	if (device == NULL)
 		return DC_STATUS_SUCCESS;
 
+#if defined(Q_OS_WIN)
+	// TODO do the cleanup
+#else
+	if (device->socket == NULL) {
+		free(device);
+		return DC_STATUS_SUCCESS;
+	}
+
 	device->socket->close();
 
 	delete device->socket;
 	free(device);
+#endif
 
 	return DC_STATUS_SUCCESS;
 }
 
 static int qt_serial_read(serial_t *device, void* data, unsigned int size)
 {
+#if defined(Q_OS_WIN)
+	if (device == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	// TODO read *size* bytes from the device
+
+	return 0;
+#else
 	if (device == NULL || device->socket == NULL)
 		return DC_STATUS_INVALIDARGS;
 
@@ -167,10 +197,19 @@ static int qt_serial_read(serial_t *device, void* data, unsigned int size)
 	}
 
 	return nbytes;
+#endif
 }
 
 static int qt_serial_write(serial_t *device, const void* data, unsigned int size)
 {
+#if defined(Q_OS_WIN)
+	if (device == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	// TODO write *size* bytes from data to the device
+
+	return 0;
+#else
 	if (device == NULL || device->socket == NULL)
 		return DC_STATUS_INVALIDARGS;
 
@@ -196,32 +235,54 @@ static int qt_serial_write(serial_t *device, const void* data, unsigned int size
 	}
 
 	return nbytes;
+#endif
 }
 
 static int qt_serial_flush(serial_t *device, int queue)
 {
-	if (device == NULL || device->socket == NULL)
+	if (device == NULL)
 		return DC_STATUS_INVALIDARGS;
-
-	//TODO: add implementation
+#if !defined(Q_OS_WIN)
+	if (device->socket == NULL)
+		return DC_STATUS_INVALIDARGS;
+#endif
+	// TODO: add implementation
 
 	return DC_STATUS_SUCCESS;
 }
 
 static int qt_serial_get_received(serial_t *device)
 {
+#if defined(Q_OS_WIN)
+	if (device == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	// TODO use WSAIoctl to get the information
+
+	return 0;
+#else
 	if (device == NULL || device->socket == NULL)
 		return DC_STATUS_INVALIDARGS;
 
 	return device->socket->bytesAvailable();
+#endif
 }
 
 static int qt_serial_get_transmitted(serial_t *device)
 {
+#if defined(Q_OS_WIN)
+	if (device == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	// TODO add implementation
+
+	return 0;
+#else
 	if (device == NULL || device->socket == NULL)
 		return DC_STATUS_INVALIDARGS;
 
 	return device->socket->bytesToWrite();
+#endif
 }
 
 static int qt_serial_set_timeout(serial_t *device, long timeout)
@@ -234,6 +295,7 @@ static int qt_serial_set_timeout(serial_t *device, long timeout)
 	return DC_STATUS_SUCCESS;
 }
 
+
 const dc_serial_operations_t qt_serial_ops = {
 	.open = qt_serial_open,
 	.close = qt_serial_close,
-- 
2.4.3

From 4c78c629d5a5d5b115152007e3c64fc21397d67d Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 19:49:55 +0300
Subject: [PATCH 07/19] Add implementation for BTH custom serial open method on
 Windows platforms

Implement the custom serial open method using the WinSocket2 API.
First the device address is converted from text representation into
a sockaddr structure. Then a connection is initiated to the device
using device's Serial Port service.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qtserialbluetooth.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/qtserialbluetooth.cpp b/qtserialbluetooth.cpp
index 37ea225..0edd3d4 100644
--- a/qtserialbluetooth.cpp
+++ b/qtserialbluetooth.cpp
@@ -51,7 +51,49 @@ static int qt_serial_open(serial_t **out, dc_context_t *context, const char* dev
 	serial_port->timeout = -1;
 
 #if defined(Q_OS_WIN)
-	// TODO connect the device
+	// Create a RFCOMM socket
+	serial_port->socket = ::socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
+
+	if (serial_port->socket == INVALID_SOCKET)
+		return DC_STATUS_IO;
+
+	SOCKADDR_BTH socketBthAddress;
+	int socketBthAddressBth = sizeof (socketBthAddress);
+	char *address = strdup(devaddr);
+
+	ZeroMemory(&socketBthAddress, socketBthAddressBth);
+	qDebug() << "Trying to connect to address " << devaddr;
+
+	if (WSAStringToAddressA(address,
+				AF_BTH,
+				NULL,
+				(LPSOCKADDR) &socketBthAddress,
+				&socketBthAddressBth
+				) != 0) {
+		qDebug() << "FAiled to convert the address " << address;
+		free(address);
+
+		return DC_STATUS_IO;
+	}
+
+	free(address);
+
+	socketBthAddress.addressFamily = AF_BTH;
+	socketBthAddress.port = BT_PORT_ANY;
+	memset(&socketBthAddress.serviceClassId, 0, sizeof(socketBthAddress.serviceClassId));
+	socketBthAddress.serviceClassId = SerialPortServiceClass_UUID;
+
+	// Try to connect to the device
+	if (::connect(serial_port->socket,
+		      (struct sockaddr *) &socketBthAddress,
+		      socketBthAddressBth
+		      ) != 0) {
+		qDebug() << "Failed to connect to device";
+
+		return DC_STATUS_NODEVICE;
+	}
+
+	qDebug() << "Succesfully connected to device";
 #else
 	// Create a RFCOMM socket
 	serial_port->socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
-- 
2.1.4

From 8bbda5c1a2f756e647dbb78944e75d2c7ed5cae7 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 19:50:22 +0300
Subject: [PATCH 08/19] Add implementation for BTH custom serial close method
 on Windows

Implement the close method used on Windows platforms for our custom
serial implementation.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qtserialbluetooth.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/qtserialbluetooth.cpp b/qtserialbluetooth.cpp
index 0edd3d4..20f2ecd 100644
--- a/qtserialbluetooth.cpp
+++ b/qtserialbluetooth.cpp
@@ -185,7 +185,9 @@ static int qt_serial_close(serial_t *device)
 		return DC_STATUS_SUCCESS;
 
 #if defined(Q_OS_WIN)
-	// TODO do the cleanup
+	// Cleanup
+	closesocket(device->socket);
+	free(device);
 #else
 	if (device->socket == NULL) {
 		free(device);
-- 
2.1.4

From 33799a849989d50be57d7fe3ab26631cef3b8705 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 19:51:08 +0300
Subject: [PATCH 09/19] Add implementation for BTH custom serial read method
 used on Windows

Implement the read method used for our custom serial implementation
on Windows platforms.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qtserialbluetooth.cpp | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/qtserialbluetooth.cpp b/qtserialbluetooth.cpp
index 20f2ecd..9d1c14b 100644
--- a/qtserialbluetooth.cpp
+++ b/qtserialbluetooth.cpp
@@ -209,9 +209,22 @@ static int qt_serial_read(serial_t *device, void* data, unsigned int size)
 	if (device == NULL)
 		return DC_STATUS_INVALIDARGS;
 
-	// TODO read *size* bytes from the device
+	unsigned int nbytes = 0;
+	int rc;
 
-	return 0;
+	while (nbytes < size) {
+		rc = recv (device->socket, (char *) data + nbytes, size - nbytes, 0);
+
+		if (rc < 0) {
+			return -1; // Error during recv call.
+		} else if (rc == 0) {
+			break; // EOF reached.
+		}
+
+		nbytes += rc;
+	}
+
+	return nbytes;
 #else
 	if (device == NULL || device->socket == NULL)
 		return DC_STATUS_INVALIDARGS;
-- 
2.1.4

From 2337819ffc56492e71cfbac82db71a267344d8e6 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 19:51:42 +0300
Subject: [PATCH 10/19] Add implementation for BTH custom serial write method
 used on Windows

Implement the write method used for our custom serial implementation
on Windows platforms.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qtserialbluetooth.cpp | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/qtserialbluetooth.cpp b/qtserialbluetooth.cpp
index 9d1c14b..45fc8d1 100644
--- a/qtserialbluetooth.cpp
+++ b/qtserialbluetooth.cpp
@@ -263,9 +263,20 @@ static int qt_serial_write(serial_t *device, const void* data, unsigned int size
 	if (device == NULL)
 		return DC_STATUS_INVALIDARGS;
 
-	// TODO write *size* bytes from data to the device
+	unsigned int nbytes = 0;
+	int rc;
 
-	return 0;
+	while (nbytes < size) {
+	    rc = send(device->socket, (char *) data + nbytes, size - nbytes, 0);
+
+	    if (rc < 0) {
+	       return -1; // Error during send call.
+	    }
+
+	    nbytes += rc;
+	}
+
+	return nbytes;
 #else
 	if (device == NULL || device->socket == NULL)
 		return DC_STATUS_INVALIDARGS;
-- 
2.1.4

From 75407a54725bce83989cca1de760d5ff0bc5ae2c Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 19:55:00 +0300
Subject: [PATCH 11/19] Add internal method for the last error raised on
 Windows

Implement an internal method which can be used to get a pretty print
message about the last error from a Windows platform.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 695cc27..0bc4e7f 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -447,7 +447,21 @@ void BtDeviceSelectionDialog::initializeDeviceDiscoveryAgent()
 #if defined(Q_OS_WIN)
 static QString getLastErrorAsString()
 {
-	// TODO get the last error
+	LPVOID lpMsgBuf = NULL;
+	DWORD lastError = GetLastError();
+
+	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+			  NULL,
+			  lastError,
+			  0,
+			  (LPTSTR) &lpMsgBuf,
+			  0,NULL)) {
+		return QString((char *)lpMsgBuf);
+	} else {
+		qDebug() << "Failed to format the message for the last error! Error number : " << lastError;
+	}
+
+	return QString("Unknown error");
 }
 
 WinBluetoothDeviceDiscoveryAgent::WinBluetoothDeviceDiscoveryAgent(QObject *parent) : QThread(parent)
-- 
2.1.4

From 9f08d1df99393dbf9c04369427d6a6a93e8e43a4 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 19:57:28 +0300
Subject: [PATCH 12/19] Add implementation for our custom BTH device discovery
 service

Implement a custom lookup service for remote Bluetooth devices
discovery. This will be used on Windows platforms to collect
information about the name and the address of a remote Bluetooth
device.

In the beginning we initialize the queryset with the necessary
flags and we start the lookup service. When a device is discovered
we collect information about its name and its address and we
raise a signal with it using the same signature as the one emitted
by QtBluetoothDeviceDiscoveryAgent implementation.

Finally we end the lookup service and we reset the internal flags.

This code was written with the help of the sample code documenting the
relevant APIs provided by Microsoft Corporation at
https://code.msdn.microsoft.com/windowsdesktop/Bluetooth-Connection-e3263296
which is under the MS-LPL. No code from the samples was copied and the
code in this commit is covered by the GPL and not the MS-LPL

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 100 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 99 insertions(+), 1 deletion(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 0bc4e7f..25e9c15 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -489,7 +489,105 @@ QBluetoothDeviceDiscoveryAgent::Error WinBluetoothDeviceDiscoveryAgent::error()
 
 void WinBluetoothDeviceDiscoveryAgent::run()
 {
-	// TODO initialize the resources and start the device discovery
+	// Initialize query for device and start the lookup service
+	WSAQUERYSET queryset;
+	HANDLE hLookup;
+	int result = SUCCESS;
+
+	running = true;
+	lastError = QBluetoothDeviceDiscoveryAgent::NoError;
+
+	memset(&queryset, 0, sizeof(WSAQUERYSET));
+	queryset.dwSize = sizeof(WSAQUERYSET);
+	queryset.dwNameSpace = NS_BTH;
+
+	// The LUP_CONTAINERS flag is used to signal that we are doing a device inquiry
+	// while LUP_FLUSHCACHE flag is used to flush the device cache for all inquiries
+	// and to do a fresh lookup instead.
+	result = WSALookupServiceBegin(&queryset, LUP_CONTAINERS | LUP_FLUSHCACHE, &hLookup);
+
+	if (result != SUCCESS) {
+		// Get the last error and emit a signal
+		lastErrorToString = getLastErrorAsString();
+		lastError = QBluetoothDeviceDiscoveryAgent::PoweredOffError;
+		emit error(lastError);
+
+		// Announce that the inquiry finished and restore the stopped flag
+		running = false;
+		stopped = false;
+
+		return;
+	}
+
+	// Declare the necessary variables to collect the information
+	BYTE buffer[4096];
+	DWORD bufferLength = sizeof(buffer);
+	WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
+
+	memset(buffer, 0, sizeof(buffer));
+
+	pResults->dwSize = sizeof(WSAQUERYSET);
+	pResults->dwNameSpace = NS_BTH;
+	pResults->lpBlob = NULL;
+
+	//Start looking for devices
+	while (result == SUCCESS && !stopped){
+		// LUP_RETURN_NAME and LUP_RETURN_ADDR flags are used to return the name and the address of the discovered device
+		result = WSALookupServiceNext(hLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR, &bufferLength, pResults);
+
+		if (result == SUCCESS) {
+			// Found a device
+			char addressAsString[BTH_ADDR_STR_LEN];
+			DWORD addressSize = sizeof (addressAsString);
+
+			// Collect the address of the device from the WSAQUERYSET
+			SOCKADDR_BTH *socketBthAddress = (SOCKADDR_BTH *) pResults->lpcsaBuffer->RemoteAddr.lpSockaddr;
+
+			// Convert the BTH_ADDR to string
+			if (WSAAddressToStringA((LPSOCKADDR) socketBthAddress,
+						sizeof (*socketBthAddress),
+						NULL,
+						addressAsString,
+						&addressSize
+						) != 0) {
+				// Get the last error and emit a signal
+				lastErrorToString = getLastErrorAsString();
+				lastError = QBluetoothDeviceDiscoveryAgent::UnknownError;
+				emit(lastError);
+
+				break;
+			}
+
+			// Save the address and the name of the discovered device
+			QString deviceName = QString(pResults->lpszServiceInstanceName);
+			QString deviceAddress = QString(addressAsString);
+
+			// Remove the round parentheses
+			deviceAddress.remove(')');
+			deviceAddress.remove('(');
+
+			// Create an object with information about the discovered device
+			QBluetoothDeviceInfo deviceInfo = QBluetoothDeviceInfo(QBluetoothAddress(deviceAddress), deviceName, 0);
+
+			// Raise a signal with information about the found remote device
+			emit deviceDiscovered(deviceInfo);
+		} else {
+			// Get the last error and emit a signal
+			lastErrorToString = getLastErrorAsString();
+			lastError = QBluetoothDeviceDiscoveryAgent::UnknownError;
+			emit(lastError);
+		}
+	}
+
+	// Announce that the inquiry finished and restore the stopped flag
+	running = false;
+	stopped = false;
+
+	// Restore the error status
+	lastError = QBluetoothDeviceDiscoveryAgent::NoError;
+
+	// End the lookup service
+	WSALookupServiceEnd(hLookup);
 }
 
 void WinBluetoothDeviceDiscoveryAgent::stop()
-- 
2.1.4

From dccb8b2397e1f8aa858d058d49b548d1aaeda08a Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 20:01:18 +0300
Subject: [PATCH 13/19] Initialize WinSock and hide the information about the
 local device

On Windows we cannot select a device or show information about the
local device. Therefore we disable the UI section related to local
device details.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 25e9c15..e8a2f0a 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -25,7 +25,23 @@ BtDeviceSelectionDialog::BtDeviceSelectionDialog(QWidget *parent) :
 		this, SLOT(itemClicked(QListWidgetItem*)));
 
 #if defined(Q_OS_WIN)
-	// TODO do the initialization
+	ULONG       ulRetCode = SUCCESS;
+	WSADATA     WSAData = { 0 };
+
+	// Initialize WinSock and ask for version 2.2.
+	ulRetCode = WSAStartup(MAKEWORD(2, 2), &WSAData);
+	if (ulRetCode != SUCCESS) {
+		QMessageBox::StandardButton warningBox;
+		warningBox = QMessageBox::critical(this, "Bluetooth",
+						   "Could not initialize the Winsock version 2.2", QMessageBox::Ok);
+		return;
+	}
+
+	// Initialize the device discovery agent
+	initializeDeviceDiscoveryAgent();
+
+	// On Windows we cannot select a device or show information about the local device
+	ui->localDeviceDetails->hide();
 #else
 	// Initialize the local Bluetooth device
 	localDevice = new QBluetoothLocalDevice();
-- 
2.1.4

From fbd41a0735595cef4db9eb342cfa547cd0204c25 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 20:04:54 +0300
Subject: [PATCH 14/19] Wait for BTH device discovery thread to finish on stop
 call

We should wait for the WinBluetoothDeviceDiscoveryAgent completion
when the stop method was called.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index e8a2f0a..814bcf0 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -93,8 +93,12 @@ BtDeviceSelectionDialog::~BtDeviceSelectionDialog()
 	delete localDevice;
 #endif
 	// Clean the device discovery agent
-	if (remoteDeviceDiscoveryAgent->isActive())
+	if (remoteDeviceDiscoveryAgent->isActive()) {
 		remoteDeviceDiscoveryAgent->stop();
+#if defined(Q_OS_WIN)
+		remoteDeviceDiscoveryAgent->wait();
+#endif
+	}
 
 	delete remoteDeviceDiscoveryAgent;
 }
@@ -126,6 +130,9 @@ void BtDeviceSelectionDialog::on_save_clicked()
 	if (remoteDeviceDiscoveryAgent->isActive()) {
 		// Stop the SDP agent if the clear button is pressed and enable the Scan button
 		remoteDeviceDiscoveryAgent->stop();
+#if defined(Q_OS_WIN)
+		remoteDeviceDiscoveryAgent->wait();
+#endif
 		ui->scan->setEnabled(true);
 	}
 
@@ -142,6 +149,9 @@ void BtDeviceSelectionDialog::on_clear_clicked()
 	if (remoteDeviceDiscoveryAgent->isActive()) {
 		// Stop the SDP agent if the clear button is pressed and enable the Scan button
 		remoteDeviceDiscoveryAgent->stop();
+#if defined(Q_OS_WIN)
+		remoteDeviceDiscoveryAgent->wait();
+#endif
 		ui->scan->setEnabled(true);
 	}
 }
-- 
2.1.4

From 37f77e1924ba58a5993c0a1dd9a66ac9765240ba Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 20:10:05 +0300
Subject: [PATCH 15/19] Add implementation for add remote Bluetooth device
 handler

On Windows we cannot determine the pairing status of the
device. Therefore we print only information about its name
and about its BTH address.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 814bcf0..2667afe 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -192,7 +192,12 @@ void BtDeviceSelectionDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMo
 void BtDeviceSelectionDialog::addRemoteDevice(const QBluetoothDeviceInfo &remoteDeviceInfo)
 {
 #if defined(Q_OS_WIN)
-	// TODO add the remote device
+	QString deviceLabel = QString("%1 (%2)").arg(remoteDeviceInfo.name(),
+						     remoteDeviceInfo.address().toString());
+	QListWidgetItem *item = new QListWidgetItem(deviceLabel);
+
+	item->setData(Qt::UserRole, QVariant::fromValue(remoteDeviceInfo));
+	ui->discoveredDevicesList->addItem(item);
 #else
 	QColor pairingColor = QColor(Qt::red);
 	QString pairingStatusLabel = QString("UNPAIRED");
-- 
2.1.4

From ab79c26cfd4796f0ef5e111316f9ebe3717af605 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 20:13:49 +0300
Subject: [PATCH 16/19] Add implementation for BTH device item selection on
 Windows platforms

When a Bluetooth device is selected from the discovered list
display information about its address and enable the save button.
On Windows we don't need to check if the devices are paired because
the pairing process is done automatically on the connection step.
If the devices are not paired Windows will ask for user's permission
to continue the process.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 2667afe..dd90c4e 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -226,7 +226,11 @@ void BtDeviceSelectionDialog::addRemoteDevice(const QBluetoothDeviceInfo &remote
 void BtDeviceSelectionDialog::itemClicked(QListWidgetItem *item)
 {
 #if defined(Q_OS_WIN)
-	// TODO enable the save button and log the information about the selected item
+	QBluetoothDeviceInfo remoteDeviceInfo = item->data(Qt::UserRole).value<QBluetoothDeviceInfo>();
+
+	ui->dialogStatus->setText(QString("The device %1 can be used for connection. You can press the Save button.")
+				  .arg(remoteDeviceInfo.address().toString()));
+	ui->save->setEnabled(true);
 #else
 	QBluetoothDeviceInfo remoteDeviceInfo = item->data(Qt::UserRole).value<QBluetoothDeviceInfo>();
 	QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address());
-- 
2.1.4

From 11cc99833a17fd406bb5c7573705c34180baf336 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 20:15:39 +0300
Subject: [PATCH 17/19] Get a pretty print message when a device discovery
 error occured

Try to get a pretty print message when a device discovery error
is raised and it is unknown.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index dd90c4e..235b38a 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -380,7 +380,11 @@ void BtDeviceSelectionDialog::deviceDiscoveryError(QBluetoothDeviceDiscoveryAgen
 		errorDescription = QString("Writing or reading from the device resulted in an error.");
 		break;
 	default:
+#if defined(Q_OS_WIN)
+		errorDescription = remoteDeviceDiscoveryAgent->errorToString();
+#else
 		errorDescription = QString("An unknown error has occurred.");
+#endif
 		break;
 	}
 
-- 
2.1.4

From 5194c4f3fa26c8cc09d4c988286dca4435008867 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 20:18:11 +0300
Subject: [PATCH 18/19] Add implementation for device discovery agent
 initialization (Windows)

Register the metatypes needed for Windows platforms and initialize
our custom device discovery agent.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/btdeviceselectiondialog.cpp | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp
index 235b38a..617b310 100644
--- a/qt-ui/btdeviceselectiondialog.cpp
+++ b/qt-ui/btdeviceselectiondialog.cpp
@@ -459,7 +459,21 @@ void BtDeviceSelectionDialog::updateLocalDeviceInformation()
 void BtDeviceSelectionDialog::initializeDeviceDiscoveryAgent()
 {
 #if defined(Q_OS_WIN)
-	// TODO initialize the discovery agent
+	// Register QBluetoothDeviceInfo metatype
+	qRegisterMetaType<QBluetoothDeviceInfo>();
+
+	// Register QBluetoothDeviceDiscoveryAgent metatype (Needed for QBluetoothDeviceDiscoveryAgent::Error)
+	qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::Error>();
+
+	// Intialize the discovery agent
+	remoteDeviceDiscoveryAgent = new WinBluetoothDeviceDiscoveryAgent(this);
+
+	connect(remoteDeviceDiscoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
+		this, SLOT(addRemoteDevice(QBluetoothDeviceInfo)));
+	connect(remoteDeviceDiscoveryAgent, SIGNAL(finished()),
+		this, SLOT(remoteDeviceScanFinished()));
+	connect(remoteDeviceDiscoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
+		this, SLOT(deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error)));
 #else
 	// Intialize the discovery agent
 	remoteDeviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(localDevice->address());
-- 
2.1.4

From ab1851ffc7cd2868b292b649775bba68c14da869 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <olteanu.clau...@ymail.com>
Date: Sun, 16 Aug 2015 20:24:33 +0300
Subject: [PATCH 19/19] Use the address of the BTH device if its name is empty

There are moments when the name of the device is not collected
properly and it is unavailable. Instead of showing an empty string
then print the address of the device.

Signed-off-by: Claudiu Olteanu <olteanu.clau...@ymail.com>
---
 qt-ui/downloadfromdivecomputer.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/qt-ui/downloadfromdivecomputer.cpp b/qt-ui/downloadfromdivecomputer.cpp
index 4127376..907a49a 100644
--- a/qt-ui/downloadfromdivecomputer.cpp
+++ b/qt-ui/downloadfromdivecomputer.cpp
@@ -554,7 +554,13 @@ void DownloadFromDCWidget::bluetoothSelectionDialogIsFinished(int result)
 {
 	if (result == QDialog::Accepted) {
 		/* Make the selected Bluetooth device default */
-		ui.device->setCurrentText(btDeviceSelectionDialog->getSelectedDeviceName());
+		QString selectedDeviceName = btDeviceSelectionDialog->getSelectedDeviceName();
+
+		if (selectedDeviceName == NULL || selectedDeviceName.isEmpty()) {
+			ui.device->setCurrentText(btDeviceSelectionDialog->getSelectedDeviceAddress());
+		} else {
+			ui.device->setCurrentText(selectedDeviceName);
+		}
 	} else if (result == QDialog::Rejected){
 		/* Disable Bluetooth download mode */
 		ui.bluetoothMode->setChecked(false);
-- 
2.1.4

_______________________________________________
subsurface mailing list
subsurface@subsurface-divelog.org
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to