source: subsurface/desktop-widgets/btdeviceselectiondialog.cpp @ 81362e64

Last change on this file since 81362e64 was 81362e64, checked in by Dirk Hohndel <dirk@…>, 7 months ago

BT address 0 is bogus

Grey out those devices in the scanning list and prevent
the user from selecting those.

Signed-off-by: Robert C. Helling <helling@…>

  • Property mode set to 100644
File size: 22.6 KB
Line 
1// SPDX-License-Identifier: GPL-2.0
2#include <QShortcut>
3#include <QDebug>
4#include <QMessageBox>
5#include <QMenu>
6
7#include "ui_btdeviceselectiondialog.h"
8#include "btdeviceselectiondialog.h"
9
10#if defined(Q_OS_WIN)
11Q_DECLARE_METATYPE(QBluetoothDeviceDiscoveryAgent::Error)
12#endif
13#if QT_VERSION < 0x050500
14Q_DECLARE_METATYPE(QBluetoothDeviceInfo)
15#endif
16
17BtDeviceSelectionDialog::BtDeviceSelectionDialog(QWidget *parent) :
18        QDialog(parent),
19        ui(new Ui::BtDeviceSelectionDialog),
20        remoteDeviceDiscoveryAgent(0)
21{
22        ui->setupUi(this);
23
24        // Quit button callbacks
25        QShortcut *quit = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this);
26        connect(quit, SIGNAL(activated()), this, SLOT(reject()));
27        connect(ui->quit, SIGNAL(clicked()), this, SLOT(reject()));
28
29        // Translate the UI labels
30        ui->localDeviceDetails->setTitle(tr("Local Bluetooth device details"));
31        ui->selectDeviceLabel->setText(tr("Select device:"));
32        ui->deviceAddressLabel->setText(tr("Address:"));
33        ui->deviceNameLabel->setText(tr("Name:"));
34        ui->deviceState->setText(tr("Bluetooth powered on"));
35        ui->changeDeviceState->setText(tr("Turn on/off"));
36        ui->discoveredDevicesLabel->setText(tr("Discovered devices"));
37        ui->scan->setText(tr("Scan"));
38        ui->clear->setText(tr("Clear"));
39        ui->save->setText(tr("Save"));
40        ui->quit->setText(tr("Quit"));
41
42        // Disable the save button because there is no device selected
43        ui->save->setEnabled(false);
44
45        // Add event for item selection
46        connect(ui->discoveredDevicesList, SIGNAL(itemClicked(QListWidgetItem*)),
47                this, SLOT(itemClicked(QListWidgetItem*)));
48
49#if defined(Q_OS_WIN)
50        ULONG       ulRetCode = SUCCESS;
51        WSADATA     WSAData = { 0 };
52
53        // Initialize WinSock and ask for version 2.2.
54        ulRetCode = WSAStartup(MAKEWORD(2, 2), &WSAData);
55        if (ulRetCode != SUCCESS) {
56                QMessageBox::critical(this, "Bluetooth",
57                                                   tr("Could not initialize Winsock version 2.2"), QMessageBox::Ok);
58                return;
59        }
60
61        // Initialize the device discovery agent
62        initializeDeviceDiscoveryAgent();
63
64        // On Windows we cannot select a device or show information about the local device
65        ui->localDeviceDetails->hide();
66#else
67        // Initialize the local Bluetooth device
68        localDevice = new QBluetoothLocalDevice();
69
70        // Populate the list with local bluetooth devices
71        QList<QBluetoothHostInfo> localAvailableDevices = localDevice->allDevices();
72        int availableDevicesSize = localAvailableDevices.size();
73
74        if (availableDevicesSize > 1) {
75                int defaultDeviceIndex = -1;
76
77                for (int it = 0; it < availableDevicesSize; it++) {
78                        QBluetoothHostInfo localAvailableDevice = localAvailableDevices.at(it);
79                        ui->localSelectedDevice->addItem(localAvailableDevice.name(),
80                                                         QVariant::fromValue(localAvailableDevice.address()));
81
82                        if (localDevice->address() == localAvailableDevice.address())
83                                defaultDeviceIndex = it;
84                }
85
86                // Positionate the current index to the default device and register to index changes events
87                ui->localSelectedDevice->setCurrentIndex(defaultDeviceIndex);
88                connect(ui->localSelectedDevice, SIGNAL(currentIndexChanged(int)),
89                        this, SLOT(localDeviceChanged(int)));
90        } else {
91                // If there is only one local Bluetooth adapter hide the combobox and the label
92                ui->selectDeviceLabel->hide();
93                ui->localSelectedDevice->hide();
94        }
95
96        // Update the UI information about the local device
97        updateLocalDeviceInformation();
98
99        // Initialize the device discovery agent
100        if (localDevice->isValid())
101                initializeDeviceDiscoveryAgent();
102#endif
103}
104
105BtDeviceSelectionDialog::~BtDeviceSelectionDialog()
106{
107        delete ui;
108
109#if defined(Q_OS_WIN)
110        // Terminate the use of Winsock 2 DLL
111        WSACleanup();
112#else
113        // Clean the local device
114        delete localDevice;
115#endif
116        if (remoteDeviceDiscoveryAgent) {
117                // Clean the device discovery agent
118                if (remoteDeviceDiscoveryAgent->isActive()) {
119                        remoteDeviceDiscoveryAgent->stop();
120#if defined(Q_OS_WIN)
121                        remoteDeviceDiscoveryAgent->wait();
122#endif
123                }
124
125                delete remoteDeviceDiscoveryAgent;
126        }
127}
128
129void BtDeviceSelectionDialog::on_changeDeviceState_clicked()
130{
131#if defined(Q_OS_WIN)
132        // TODO add implementation
133#else
134        if (localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff) {
135                ui->dialogStatus->setText(tr("Trying to turn on the local Bluetooth device..."));
136                localDevice->powerOn();
137        } else {
138                ui->dialogStatus->setText(tr("Trying to turn off the local Bluetooth device..."));
139                localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
140        }
141#endif
142}
143
144void BtDeviceSelectionDialog::on_save_clicked()
145{
146        // Get the selected device. There will be always a selected device if the save button is enabled.
147        QListWidgetItem *currentItem = ui->discoveredDevicesList->currentItem();
148        QBluetoothDeviceInfo remoteDeviceInfo = currentItem->data(Qt::UserRole).value<QBluetoothDeviceInfo>();
149
150        // Save the selected device
151        selectedRemoteDeviceInfo = QSharedPointer<QBluetoothDeviceInfo>(new QBluetoothDeviceInfo(remoteDeviceInfo));
152
153        if (remoteDeviceDiscoveryAgent->isActive()) {
154                // Stop the SDP agent if the clear button is pressed and enable the Scan button
155                remoteDeviceDiscoveryAgent->stop();
156#if defined(Q_OS_WIN)
157                remoteDeviceDiscoveryAgent->wait();
158#endif
159                ui->scan->setEnabled(true);
160        }
161
162        // Close the device selection dialog and set the result code to Accepted
163        accept();
164}
165
166void BtDeviceSelectionDialog::on_clear_clicked()
167{
168        ui->dialogStatus->setText(tr("Remote devices list was cleared."));
169        ui->discoveredDevicesList->clear();
170        ui->save->setEnabled(false);
171
172        if (remoteDeviceDiscoveryAgent->isActive()) {
173                // Stop the SDP agent if the clear button is pressed and enable the Scan button
174                remoteDeviceDiscoveryAgent->stop();
175#if defined(Q_OS_WIN)
176                remoteDeviceDiscoveryAgent->wait();
177#endif
178                ui->scan->setEnabled(true);
179        }
180}
181
182void BtDeviceSelectionDialog::on_scan_clicked()
183{
184        ui->dialogStatus->setText(tr("Scanning for remote devices..."));
185        ui->discoveredDevicesList->clear();
186        remoteDeviceDiscoveryAgent->start();
187        ui->scan->setEnabled(false);
188}
189
190void BtDeviceSelectionDialog::remoteDeviceScanFinished()
191{
192        if (remoteDeviceDiscoveryAgent->error() == QBluetoothDeviceDiscoveryAgent::NoError) {
193                ui->dialogStatus->setText(tr("Scanning finished successfully."));
194        } else {
195                deviceDiscoveryError(remoteDeviceDiscoveryAgent->error());
196        }
197
198        ui->scan->setEnabled(true);
199}
200
201void BtDeviceSelectionDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode)
202{
203#if defined(Q_OS_WIN)
204        // TODO add implementation
205#else
206        bool on = !(mode == QBluetoothLocalDevice::HostPoweredOff);
207
208        //: %1 will be replaced with "turned on" or "turned off"
209        ui->dialogStatus->setText(tr("The local Bluetooth device was %1.")
210                                  .arg(on? tr("turned on") : tr("turned off")));
211        ui->deviceState->setChecked(on);
212        ui->scan->setEnabled(on);
213#endif
214}
215
216void BtDeviceSelectionDialog::addRemoteDevice(const QBluetoothDeviceInfo &remoteDeviceInfo)
217{
218#if defined(Q_OS_WIN)
219        // On Windows we cannot obtain the pairing status so we set only the name and the address of the device
220        QString deviceLabel = QString("%1 (%2)").arg(remoteDeviceInfo.name(),
221                                                     remoteDeviceInfo.address().toString());
222        QColor pairingColor = QColor(Qt::white);
223#else
224        // By default we use the status label and the color for the UNPAIRED state
225        QColor pairingColor = QColor(Qt::red);
226        QString pairingStatusLabel = tr("UNPAIRED");
227        QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address());
228
229        if (pairingStatus == QBluetoothLocalDevice::Paired) {
230                pairingStatusLabel = tr("PAIRED");
231                pairingColor = QColor(Qt::gray);
232        } else if (pairingStatus == QBluetoothLocalDevice::AuthorizedPaired) {
233                pairingStatusLabel = tr("AUTHORIZED_PAIRED");
234                pairingColor = QColor(Qt::blue);
235        }
236        if (remoteDeviceInfo.address().isNull())
237                pairingColor = QColor(Qt::gray);
238
239
240        QString deviceLabel = tr("%1 (%2)   [State: %3]").arg(remoteDeviceInfo.name(),
241                                                              remoteDeviceInfo.address().toString(),
242                                                              pairingStatusLabel);
243#endif
244        // Create the new item, set its information and add it to the list
245        QListWidgetItem *item = new QListWidgetItem(deviceLabel);
246
247        item->setData(Qt::UserRole, QVariant::fromValue(remoteDeviceInfo));
248        item->setBackgroundColor(pairingColor);
249
250        ui->discoveredDevicesList->addItem(item);
251}
252
253void BtDeviceSelectionDialog::itemClicked(QListWidgetItem *item)
254{
255        // By default we assume that the devices are paired
256        QBluetoothDeviceInfo remoteDeviceInfo = item->data(Qt::UserRole).value<QBluetoothDeviceInfo>();
257        QString statusMessage = tr("The device %1 can be used for connection. You can press the Save button.")
258                                  .arg(remoteDeviceInfo.address().toString());
259        bool enableSaveButton = true;
260
261#if !defined(Q_OS_WIN)
262        // On other platforms than Windows we can obtain the pairing status so if the devices are not paired we disable the button
263        QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address());
264
265        if (pairingStatus == QBluetoothLocalDevice::Unpaired) {
266                statusMessage = tr("The device %1 must be paired in order to be used. Please use the context menu for pairing options.")
267                                  .arg(remoteDeviceInfo.address().toString());
268                enableSaveButton = false;
269        }
270        if (remoteDeviceInfo.address().isNull()) {
271                statusMessage = tr("A device needs a non-zero address for a connection.");
272                enableSaveButton = false;
273        }
274#endif
275        // Update the status message and the save button
276        ui->dialogStatus->setText(statusMessage);
277        ui->save->setEnabled(enableSaveButton);
278}
279
280void BtDeviceSelectionDialog::localDeviceChanged(int index)
281{
282#if defined(Q_OS_WIN)
283        // TODO add implementation
284#else
285        QBluetoothAddress localDeviceSelectedAddress = ui->localSelectedDevice->itemData(index, Qt::UserRole).value<QBluetoothAddress>();
286
287        // Delete the old localDevice
288        if (localDevice)
289                delete localDevice;
290
291        // Create a new local device using the selected address
292        localDevice = new QBluetoothLocalDevice(localDeviceSelectedAddress);
293
294        ui->dialogStatus->setText(tr("The local device was changed."));
295
296        // Clear the discovered devices list
297        on_clear_clicked();
298
299        // Update the UI information about the local device
300        updateLocalDeviceInformation();
301
302        // Initialize the device discovery agent
303        if (localDevice->isValid())
304                initializeDeviceDiscoveryAgent();
305#endif
306}
307
308void BtDeviceSelectionDialog::displayPairingMenu(const QPoint &pos)
309{
310#if defined(Q_OS_WIN)
311        // TODO add implementation
312#else
313        QMenu menu(this);
314        QAction *pairAction = menu.addAction(tr("Pair"));
315        QAction *removePairAction = menu.addAction(tr("Remove pairing"));
316        QAction *chosenAction = menu.exec(ui->discoveredDevicesList->viewport()->mapToGlobal(pos));
317        QListWidgetItem *currentItem = ui->discoveredDevicesList->currentItem();
318        QBluetoothDeviceInfo currentRemoteDeviceInfo = currentItem->data(Qt::UserRole).value<QBluetoothDeviceInfo>();
319        QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(currentRemoteDeviceInfo.address());
320
321        //TODO: disable the actions
322        if (pairingStatus == QBluetoothLocalDevice::Unpaired) {
323                pairAction->setEnabled(true);
324                removePairAction->setEnabled(false);
325        } else {
326                pairAction->setEnabled(false);
327                removePairAction->setEnabled(true);
328        }
329
330        if (chosenAction == pairAction) {
331                ui->dialogStatus->setText(tr("Trying to pair device %1")
332                                            .arg(currentRemoteDeviceInfo.address().toString()));
333                localDevice->requestPairing(currentRemoteDeviceInfo.address(), QBluetoothLocalDevice::Paired);
334        } else if (chosenAction == removePairAction) {
335                ui->dialogStatus->setText(tr("Trying to unpair device %1")
336                                            .arg(currentRemoteDeviceInfo.address().toString()));
337                localDevice->requestPairing(currentRemoteDeviceInfo.address(), QBluetoothLocalDevice::Unpaired);
338        }
339#endif
340}
341
342void BtDeviceSelectionDialog::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
343{
344        // Determine the color, the new pairing status and the log message. By default we assume that the devices are UNPAIRED.
345        QString remoteDeviceStringAddress = address.toString();
346        QColor pairingColor = QColor(Qt::red);
347        QString pairingStatusLabel = tr("UNPAIRED");
348        QString dialogStatusMessage = tr("Device %1 was unpaired.").arg(remoteDeviceStringAddress);
349        bool enableSaveButton = false;
350
351        if (pairing == QBluetoothLocalDevice::Paired) {
352                pairingStatusLabel = tr("PAIRED");
353                pairingColor = QColor(Qt::gray);
354                enableSaveButton = true;
355                dialogStatusMessage = tr("Device %1 was paired.").arg(remoteDeviceStringAddress);
356        } else if (pairing == QBluetoothLocalDevice::AuthorizedPaired) {
357                pairingStatusLabel = tr("AUTHORIZED_PAIRED");
358                pairingColor = QColor(Qt::blue);
359                enableSaveButton = true;
360                dialogStatusMessage = tr("Device %1 was paired and is authorized.").arg(remoteDeviceStringAddress);
361        }
362
363        // Find the items which represent the BTH device and update their state
364        QList<QListWidgetItem *> items = ui->discoveredDevicesList->findItems(remoteDeviceStringAddress, Qt::MatchContains);
365        QRegularExpression pairingExpression = QRegularExpression(QString("%1|%2|%3").arg(tr("PAIRED"),
366                                                                                          tr("AUTHORIZED_PAIRED"),
367                                                                                          tr("UNPAIRED")));
368
369        for (int i = 0; i < items.count(); ++i) {
370                QListWidgetItem *item = items.at(i);
371                QString updatedDeviceLabel = item->text().replace(QRegularExpression(pairingExpression),
372                                                                  pairingStatusLabel);
373
374                item->setText(updatedDeviceLabel);
375                item->setBackgroundColor(pairingColor);
376        }
377
378        // Check if the updated device is the selected one from the list and inform the user that it can/cannot start the download mode
379        QListWidgetItem *currentItem = ui->discoveredDevicesList->currentItem();
380
381        if (currentItem != NULL && currentItem->text().contains(remoteDeviceStringAddress, Qt::CaseInsensitive)) {
382                if (pairing == QBluetoothLocalDevice::Unpaired) {
383                        dialogStatusMessage = tr("The device %1 must be paired in order to be used. Please use the context menu for pairing options.")
384                                                .arg(remoteDeviceStringAddress);
385                } else {
386                        dialogStatusMessage = tr("The device %1 can now be used for connection. You can press the Save button.")
387                                                .arg(remoteDeviceStringAddress);
388                }
389        }
390
391        // Update the save button and the dialog status message
392        ui->save->setEnabled(enableSaveButton);
393        ui->dialogStatus->setText(dialogStatusMessage);
394}
395
396void BtDeviceSelectionDialog::error(QBluetoothLocalDevice::Error error)
397{
398        ui->dialogStatus->setText(tr("Local device error: %1.")
399                                    .arg((error == QBluetoothLocalDevice::PairingError)? tr("Pairing error. If the remote device requires a custom PIN code, "
400                                                                                            "please try to pair the devices using your operating system. ")
401                                                                                       : tr("Unknown error")));
402}
403
404void BtDeviceSelectionDialog::deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error error)
405{
406        QString errorDescription;
407
408        switch (error) {
409        case QBluetoothDeviceDiscoveryAgent::PoweredOffError:
410                errorDescription = tr("The Bluetooth adaptor is powered off, power it on before doing discovery.");
411                break;
412        case QBluetoothDeviceDiscoveryAgent::InputOutputError:
413                errorDescription = tr("Writing to or reading from the device resulted in an error.");
414                break;
415        default:
416#if defined(Q_OS_WIN)
417                errorDescription = remoteDeviceDiscoveryAgent->errorToString();
418#else
419                errorDescription = tr("An unknown error has occurred.");
420#endif
421                break;
422        }
423
424        ui->dialogStatus->setText(tr("Device discovery error: %1.").arg(errorDescription));
425}
426
427QString BtDeviceSelectionDialog::getSelectedDeviceAddress()
428{
429        if (selectedRemoteDeviceInfo) {
430                QBluetoothDeviceInfo *deviceInfo = selectedRemoteDeviceInfo.data();
431                QBluetoothDeviceInfo::CoreConfigurations flags;
432                QString prefix = "";
433
434                flags = deviceInfo->coreConfigurations();
435                if (flags == QBluetoothDeviceInfo::LowEnergyCoreConfiguration)
436                        prefix = "LE:";
437                return prefix + deviceInfo->address().toString();
438        }
439
440        return QString();
441}
442
443QString BtDeviceSelectionDialog::getSelectedDeviceName()
444{
445        if (selectedRemoteDeviceInfo) {
446                return selectedRemoteDeviceInfo.data()->name();
447        }
448
449        return QString();
450}
451
452void BtDeviceSelectionDialog::updateLocalDeviceInformation()
453{
454#if defined(Q_OS_WIN)
455        // TODO add implementation
456#else
457        // Check if the selected Bluetooth device can be accessed
458        if (!localDevice->isValid()) {
459                QString na = tr("Not available");
460
461                // Update the UI information
462                ui->deviceAddress->setText(na);
463                ui->deviceName->setText(na);
464
465                // Announce the user that there is a problem with the selected local Bluetooth adapter
466                ui->dialogStatus->setText(tr("The local Bluetooth adapter cannot be accessed."));
467
468                // Disable the buttons
469                ui->save->setEnabled(false);
470                ui->scan->setEnabled(false);
471                ui->clear->setEnabled(false);
472                ui->changeDeviceState->setEnabled(false);
473
474                return;
475        }
476
477        // Set UI information about the local device
478        ui->deviceAddress->setText(localDevice->address().toString());
479        ui->deviceName->setText(localDevice->name());
480
481        connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)),
482                this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode)));
483
484        // Initialize the state of the local device and activate/deactive the scan button
485        hostModeStateChanged(localDevice->hostMode());
486
487        // Add context menu for devices to be able to pair them
488        ui->discoveredDevicesList->setContextMenuPolicy(Qt::CustomContextMenu);
489        connect(ui->discoveredDevicesList, SIGNAL(customContextMenuRequested(QPoint)),
490                this, SLOT(displayPairingMenu(QPoint)));
491        connect(localDevice, SIGNAL(pairingFinished(QBluetoothAddress, QBluetoothLocalDevice::Pairing)),
492                this, SLOT(pairingFinished(QBluetoothAddress, QBluetoothLocalDevice::Pairing)));
493
494        connect(localDevice, SIGNAL(error(QBluetoothLocalDevice::Error)),
495                this, SLOT(error(QBluetoothLocalDevice::Error)));
496#endif
497}
498
499void BtDeviceSelectionDialog::initializeDeviceDiscoveryAgent()
500{
501#if defined(Q_OS_WIN)
502        // Register QBluetoothDeviceInfo metatype
503        qRegisterMetaType<QBluetoothDeviceInfo>();
504
505        // Register QBluetoothDeviceDiscoveryAgent metatype (Needed for QBluetoothDeviceDiscoveryAgent::Error)
506        qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::Error>();
507
508        // Intialize the discovery agent
509        remoteDeviceDiscoveryAgent = new WinBluetoothDeviceDiscoveryAgent(this);
510#else
511        // Intialize the discovery agent
512        remoteDeviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(localDevice->address());
513
514        // Test if the discovery agent was successfully created
515        if (remoteDeviceDiscoveryAgent->error() == QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError) {
516                ui->dialogStatus->setText(tr("The device discovery agent was not created because the %1 address does not "
517                                             "match the physical adapter address of any local Bluetooth device.")
518                                            .arg(localDevice->address().toString()));
519                ui->scan->setEnabled(false);
520                ui->clear->setEnabled(false);
521                return;
522        }
523#endif
524        connect(remoteDeviceDiscoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
525                this, SLOT(addRemoteDevice(QBluetoothDeviceInfo)));
526        connect(remoteDeviceDiscoveryAgent, SIGNAL(finished()),
527                this, SLOT(remoteDeviceScanFinished()));
528        connect(remoteDeviceDiscoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
529                this, SLOT(deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error)));
530}
531
532#if defined(Q_OS_WIN)
533WinBluetoothDeviceDiscoveryAgent::WinBluetoothDeviceDiscoveryAgent(QObject *parent) : QThread(parent)
534{
535        // Initialize the internal flags by their default values
536        running = false;
537        stopped = false;
538        lastError = QBluetoothDeviceDiscoveryAgent::NoError;
539        lastErrorToString = tr("No error");
540}
541
542WinBluetoothDeviceDiscoveryAgent::~WinBluetoothDeviceDiscoveryAgent()
543{
544}
545
546bool WinBluetoothDeviceDiscoveryAgent::isActive() const
547{
548        return running;
549}
550
551QString WinBluetoothDeviceDiscoveryAgent::errorToString() const
552{
553        return lastErrorToString;
554}
555
556QBluetoothDeviceDiscoveryAgent::Error WinBluetoothDeviceDiscoveryAgent::error() const
557{
558        return lastError;
559}
560
561void WinBluetoothDeviceDiscoveryAgent::run()
562{
563        // Initialize query for device and start the lookup service
564        WSAQUERYSET queryset;
565        HANDLE hLookup;
566        int result = SUCCESS;
567
568        running = true;
569        lastError = QBluetoothDeviceDiscoveryAgent::NoError;
570        lastErrorToString = tr("No error");
571
572        memset(&queryset, 0, sizeof(WSAQUERYSET));
573        queryset.dwSize = sizeof(WSAQUERYSET);
574        queryset.dwNameSpace = NS_BTH;
575
576        // The LUP_CONTAINERS flag is used to signal that we are doing a device inquiry
577        // while LUP_FLUSHCACHE flag is used to flush the device cache for all inquiries
578        // and to do a fresh lookup instead.
579        result = WSALookupServiceBegin(&queryset, LUP_CONTAINERS | LUP_FLUSHCACHE, &hLookup);
580
581        if (result != SUCCESS) {
582                // Get the last error and emit a signal
583                lastErrorToString = qt_error_string();
584                lastError = QBluetoothDeviceDiscoveryAgent::PoweredOffError;
585                emit error(lastError);
586
587                // Announce that the inquiry finished and restore the stopped flag
588                running = false;
589                stopped = false;
590
591                return;
592        }
593
594        // Declare the necessary variables to collect the information
595        BYTE buffer[4096];
596        DWORD bufferLength = sizeof(buffer);
597        WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
598
599        memset(buffer, 0, sizeof(buffer));
600
601        pResults->dwSize = sizeof(WSAQUERYSET);
602        pResults->dwNameSpace = NS_BTH;
603        pResults->lpBlob = NULL;
604
605        //Start looking for devices
606        while (result == SUCCESS && !stopped){
607                // LUP_RETURN_NAME and LUP_RETURN_ADDR flags are used to return the name and the address of the discovered device
608                result = WSALookupServiceNext(hLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR, &bufferLength, pResults);
609
610                if (result == SUCCESS) {
611                        // Found a device
612                        QString deviceAddress(BTH_ADDR_BUF_LEN, Qt::Uninitialized);
613                        DWORD addressSize = BTH_ADDR_BUF_LEN;
614
615                        // Collect the address of the device from the WSAQUERYSET
616                        SOCKADDR_BTH *socketBthAddress = (SOCKADDR_BTH *) pResults->lpcsaBuffer->RemoteAddr.lpSockaddr;
617
618                        // Convert the BTH_ADDR to string
619                        if (WSAAddressToStringW((LPSOCKADDR) socketBthAddress,
620                                                sizeof (*socketBthAddress),
621                                                NULL,
622                                                reinterpret_cast<wchar_t*>(deviceAddress.data()),
623                                                &addressSize
624                                                ) != 0) {
625                                // Get the last error and emit a signal
626                                lastErrorToString = qt_error_string();
627                                lastError = QBluetoothDeviceDiscoveryAgent::UnknownError;
628                                emit(lastError);
629
630                                break;
631                        }
632
633                        // Remove the round parentheses
634                        deviceAddress.remove(')');
635                        deviceAddress.remove('(');
636
637                        // Save the name of the discovered device and truncate the address
638                        QString deviceName = QString(pResults->lpszServiceInstanceName);
639                        deviceAddress.truncate(BTH_ADDR_PRETTY_STRING_LEN);
640
641                        // Create an object with information about the discovered device
642                        QBluetoothDeviceInfo deviceInfo = QBluetoothDeviceInfo(QBluetoothAddress(deviceAddress), deviceName, 0);
643
644                        // Raise a signal with information about the found remote device
645                        emit deviceDiscovered(deviceInfo);
646                } else {
647                        // Get the last error and emit a signal
648                        lastErrorToString = qt_error_string();
649                        lastError = QBluetoothDeviceDiscoveryAgent::UnknownError;
650                        emit(lastError);
651                }
652        }
653
654        // Announce that the inquiry finished and restore the stopped flag
655        running = false;
656        stopped = false;
657
658        // Restore the error status
659        lastError = QBluetoothDeviceDiscoveryAgent::NoError;
660
661        // End the lookup service
662        WSALookupServiceEnd(hLookup);
663}
664
665void WinBluetoothDeviceDiscoveryAgent::stop()
666{
667        // Stop the inqury
668        stopped = true;
669}
670#endif
Note: See TracBrowser for help on using the repository browser.