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