~system-settings-touch/ubuntu-system-settings/trunk

351.2.1 by Charles Kerr
add bluetooth plugin implementation
1
/*
1506.5.7 by simon.busch at canonical
[bluetooth] Update copyright year and fix review comments
2
 * Copyright (C) 2013-2015 Canonical Ltd
351.2.1 by Charles Kerr
add bluetooth plugin implementation
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License version 3 as
6
 * published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 * GNU General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU General Public License
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 *
16
 * Authors:
17
 * Charles Kerr <charles.kerr@canonical.com>
18
 */
19
822.2.3 by Jussi Pakkanen
Made a few plugins flint++ clean.
20
#include "device.h"
21
351.2.1 by Charles Kerr
add bluetooth plugin implementation
22
#include <QDBusReply>
392.3.6 by Charles Kerr
getting ready to MP, so remove qDebug() calls
23
#include <QDebug> // qWarning()
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
24
#include <QThread>
806.1.26 by Mathieu Trudel-Lapierre
Make discoverServices() get called from a timer in a separate thread rather than blocking UI while we wait for the device to settle
25
#include <QTimer>
351.2.1 by Charles Kerr
add bluetooth plugin implementation
26
27
#include "dbus-shared.h"
28
1528.2.26 by Simon Fels
Fix bluetooth tests and enable device class tests again
29
Device::Device(const QString &path, QDBusConnection &bus) :
1606.3.1 by Simon Fels
Create new device objects for those we don't know yet but bluez asks us
30
   m_name("unknown"),
1528.2.26 by Simon Fels
Fix bluetooth tests and enable device class tests again
31
   m_strength(Device::None)
351.2.1 by Charles Kerr
add bluetooth plugin implementation
32
{
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
33
    initDevice(path, bus);
34
}
35
36
void Device::initDevice(const QString &path, QDBusConnection &bus)
37
{
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
38
    /* whenever any of the properties changes,
39
       trigger the catch-all deviceChanged() signal */
40
    QObject::connect(this, SIGNAL(nameChanged()), this, SIGNAL(deviceChanged()));
41
    QObject::connect(this, SIGNAL(iconNameChanged()), this, SIGNAL(deviceChanged()));
42
    QObject::connect(this, SIGNAL(addressChanged()), this, SIGNAL(deviceChanged()));
43
    QObject::connect(this, SIGNAL(pairedChanged()), this, SIGNAL(deviceChanged()));
742.1.2 by Mathieu Trudel-Lapierre
Once successfully paired and connected, mark a remote device as Trusted. This
44
    QObject::connect(this, SIGNAL(trustedChanged()), this, SIGNAL(deviceChanged()));
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
45
    QObject::connect(this, SIGNAL(typeChanged()), this, SIGNAL(deviceChanged()));
46
    QObject::connect(this, SIGNAL(connectionChanged()), this, SIGNAL(deviceChanged()));
47
    QObject::connect(this, SIGNAL(strengthChanged()), this, SIGNAL(deviceChanged()));
351.2.1 by Charles Kerr
add bluetooth plugin implementation
48
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
49
    m_bluezDevice.reset(new BluezDevice1(BLUEZ_SERVICE, path, bus));
1528.2.40 by Simon Fels
bluetooth: set a timeout of 60 seconds for our dbus calls to the bluez Device
50
    /* Give our calls a bit more time than the default 25 seconds to
51
     * complete whatever they are doing. In some situations (e.g. with
52
     * specific devices) the default doesn't seem to be enough to. */
53
    m_bluezDevice->setTimeout(60 * 1000 /* 60 seconds */);
54
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
55
    m_bluezDeviceProperties.reset(new FreeDesktopProperties(BLUEZ_SERVICE, path, bus));
56
57
    QObject::connect(m_bluezDeviceProperties.data(), SIGNAL(PropertiesChanged(const QString&, const QVariantMap&, const QStringList&)),
58
                     this, SLOT(slotPropertiesChanged(const QString&, const QVariantMap&, const QStringList&)));
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
59
60
    Q_EMIT(pathChanged());
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
61
62
    watchCall(m_bluezDeviceProperties->GetAll(BLUEZ_DEVICE_IFACE), [=](QDBusPendingCallWatcher *watcher) {
63
        QDBusPendingReply<QVariantMap> reply = *watcher;
64
65
        if (reply.isError()) {
66
            qWarning() << "Failed to retrieve properties for device" << m_bluezDevice->path();
67
            watcher->deleteLater();
68
            return;
69
        }
70
71
        auto properties = reply.argumentAt<0>();
72
        setProperties(properties);
73
74
        watcher->deleteLater();
75
    });
76
}
77
78
void Device::slotPropertiesChanged(const QString &interface, const QVariantMap &changedProperties,
79
                                   const QStringList &invalidatedProperties)
80
{
81
    Q_UNUSED(invalidatedProperties);
82
83
   if (interface != BLUEZ_DEVICE_IFACE)
84
      return;
85
86
   setProperties(changedProperties);
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
87
}
88
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
89
void Device::setProperties(const QMap<QString,QVariant> &properties)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
90
{
91
    QMapIterator<QString,QVariant> it(properties);
92
    while (it.hasNext()) {
93
        it.next();
94
        updateProperty(it.key(), it.value());
95
    }
96
}
97
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
98
void Device::setConnectAfterPairing(bool value)
99
{
100
    if (m_connectAfterPairing == value)
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
101
        return;
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
102
103
    m_connectAfterPairing = value;
104
}
105
106
void Device::disconnect()
107
{
1528.2.18 by Simon Fels
Correct connection state handling after State property for profiles/devices
108
    setConnection(Device::Disconnecting);
109
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
110
    QDBusPendingCall call = m_bluezDevice->Disconnect();
1506.5.1 by simon.busch at canonical
Rework bluetooth device actions to fix a number of different problems
111
1481.3.1 by simon.busch at canonical
Convert Bluetooth connect/disconnect operations to async ones to not block the
112
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
1506.5.1 by simon.busch at canonical
Rework bluetooth device actions to fix a number of different problems
113
    QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) {
114
        QDBusPendingReply<void> reply = *watcher;
115
116
        if (reply.isError()) {
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
117
            qWarning() << "Could not disconnect device:"
1506.5.1 by simon.busch at canonical
Rework bluetooth device actions to fix a number of different problems
118
                       << reply.error().message();
1528.2.18 by Simon Fels
Correct connection state handling after State property for profiles/devices
119
120
            // Make sure we switch the connection indicator back to
121
            // a sane state
122
            updateConnection();
1506.5.1 by simon.busch at canonical
Rework bluetooth device actions to fix a number of different problems
123
        }
124
125
        watcher->deleteLater();
126
    });
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
127
}
128
1528.2.18 by Simon Fels
Correct connection state handling after State property for profiles/devices
129
void Device::connectAfterPairing()
130
{
131
    if (!m_connectAfterPairing)
132
        return;
133
134
    connect();
135
}
136
1528.2.17 by Simon Fels
If device is not paired yet but should be connected pair it first and
137
void Device::pair()
138
{
1528.2.18 by Simon Fels
Correct connection state handling after State property for profiles/devices
139
    if (m_paired) {
140
        // If we are already paired we just have to make sure we
141
        // trigger the connection process if we have to
142
        connectAfterPairing();
143
        return;
144
    }
145
1528.2.19 by Simon Fels
Update connection state according to the device state
146
    setConnection(Device::Connecting);
147
148
    m_isPairing = true;
149
1528.2.17 by Simon Fels
If device is not paired yet but should be connected pair it first and
150
    auto call = m_bluezDevice->asyncCall("Pair");
151
152
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
153
    QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) {
154
        QDBusPendingReply<void> reply = *watcher;
1528.2.27 by Simon Fels
Close pairing popup according to the result of the actual operation. The
155
        bool success = true;
1528.2.17 by Simon Fels
If device is not paired yet but should be connected pair it first and
156
157
        if (reply.isError()) {
1528.2.19 by Simon Fels
Update connection state according to the device state
158
            qWarning() << "Failed to pair with device:"
159
                       << reply.error().message();
160
            updateConnection();
1528.2.27 by Simon Fels
Close pairing popup according to the result of the actual operation. The
161
            success = false;
1528.2.17 by Simon Fels
If device is not paired yet but should be connected pair it first and
162
        }
163
1528.2.19 by Simon Fels
Update connection state according to the device state
164
        m_isPairing = false;
1528.2.18 by Simon Fels
Correct connection state handling after State property for profiles/devices
165
1528.2.27 by Simon Fels
Close pairing popup according to the result of the actual operation. The
166
        Q_EMIT(pairingDone(success));
167
168
        watcher->deleteLater();
169
    });
170
}
171
172
void Device::cancelPairing()
173
{
174
   if (!m_isPairing)
175
      return;
176
177
    auto call = m_bluezDevice->asyncCall("CancelPairing");
178
179
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
180
    QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) {
181
        QDBusPendingReply<void> reply = *watcher;
182
183
        if (reply.isError()) {
184
            qWarning() << "Failed to cancel pairing attempt with device:"
185
                       << reply.error().message();
186
            updateConnection();
187
        } else {
188
            // Only mark us a not pairing when call succeeded
189
            m_isPairing = false;
190
        }
191
1528.2.17 by Simon Fels
If device is not paired yet but should be connected pair it first and
192
        watcher->deleteLater();
193
    });
194
}
195
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
196
void Device::connect()
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
197
{
1528.2.19 by Simon Fels
Update connection state according to the device state
198
    // If we have just paired then the device switched to connected = true for
199
    // a short moment as BlueZ opened up a RFCOMM channel to perform SDP. If
200
    // we should connect with the device on specific profiles now we go ahead
201
    // here even if we're marked as connected as this still doesn't mean we're
202
    // connected on any profile. Calling org.bluez.Device1.Connect multiple
203
    // times doesn't hurt an will not fail.
204
    if (m_isConnected && !m_connectAfterPairing)
1528.2.18 by Simon Fels
Correct connection state handling after State property for profiles/devices
205
       return;
206
207
    setConnection(Device::Connecting);
208
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
209
    QDBusPendingCall call = m_bluezDevice->asyncCall("Connect");
1506.5.1 by simon.busch at canonical
Rework bluetooth device actions to fix a number of different problems
210
1481.3.1 by simon.busch at canonical
Convert Bluetooth connect/disconnect operations to async ones to not block the
211
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
1506.5.1 by simon.busch at canonical
Rework bluetooth device actions to fix a number of different problems
212
    QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) {
213
        QDBusPendingReply<void> reply = *watcher;
214
215
        if (reply.isError()) {
216
            qWarning() << "Could not connect device:"
217
                       << reply.error().message();
218
        } else {
219
            makeTrusted(true);
220
        }
221
1528.2.19 by Simon Fels
Update connection state according to the device state
222
        // Regardless if the Connected property has changed or not we update
223
        // the connection state here as the connection process is over now
224
        // and we should have received any state change already at this
225
        // point.
226
        updateConnection();
227
1506.5.1 by simon.busch at canonical
Rework bluetooth device actions to fix a number of different problems
228
        watcher->deleteLater();
229
    });
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
230
}
231
806.1.20 by Mathieu Trudel-Lapierre
Use a watcher to warn if setting the Trusted property on a device fails.
232
void Device::slotMakeTrustedDone(QDBusPendingCallWatcher *call)
233
{
234
    QDBusPendingReply<void> reply = *call;
235
236
    if (reply.isError()) {
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
237
        qWarning() << "Could not mark device as trusted:"
806.1.20 by Mathieu Trudel-Lapierre
Use a watcher to warn if setting the Trusted property on a device fails.
238
                   << reply.error().message();
239
    }
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
240
806.1.20 by Mathieu Trudel-Lapierre
Use a watcher to warn if setting the Trusted property on a device fails.
241
    call->deleteLater();
242
}
243
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
244
void Device::makeTrusted(bool trusted)
742.1.2 by Mathieu Trudel-Lapierre
Once successfully paired and connected, mark a remote device as Trusted. This
245
{
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
246
    auto call = m_bluezDeviceProperties->Set(BLUEZ_DEVICE_IFACE, "Trusted", QDBusVariant(trusted));
247
248
    auto watcher = new QDBusPendingCallWatcher(call, this);
249
    QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
250
                     this, SLOT(slotMakeTrustedDone(QDBusPendingCallWatcher*)));
742.1.2 by Mathieu Trudel-Lapierre
Once successfully paired and connected, mark a remote device as Trusted. This
251
}
252
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
253
void Device::setName(const QString &name)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
254
{
255
    if (m_name != name) {
256
        m_name = name;
257
        Q_EMIT(nameChanged());
258
    }
259
}
260
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
261
void Device::setIconName(const QString &iconName)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
262
{
263
    if (m_iconName != iconName) {
264
        m_iconName = iconName;
265
        Q_EMIT(iconNameChanged());
266
    }
267
}
268
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
269
void Device::setAddress(const QString &address)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
270
{
271
    if (m_address != address) {
272
        m_address = address;
273
        Q_EMIT(addressChanged());
274
    }
275
}
276
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
277
void Device::setType(Type type)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
278
{
279
    if (m_type != type) {
280
        m_type = type;
281
        Q_EMIT(typeChanged());
282
        updateIcon();
283
    }
284
}
285
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
286
void Device::setPaired(bool paired)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
287
{
288
    if (m_paired != paired) {
289
        m_paired = paired;
290
        Q_EMIT(pairedChanged());
291
    }
292
}
293
742.1.2 by Mathieu Trudel-Lapierre
Once successfully paired and connected, mark a remote device as Trusted. This
294
void Device::setTrusted(bool trusted)
295
{
296
    if (m_trusted != trusted) {
297
        m_trusted = trusted;
298
        Q_EMIT(trustedChanged());
299
    }
300
}
301
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
302
void Device::setConnection(Connection connection)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
303
{
304
    if (m_connection != connection) {
305
        m_connection = connection;
306
        Q_EMIT(connectionChanged());
307
    }
308
}
309
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
310
void Device::updateIcon()
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
311
{
312
    /* bluez-provided icon is unreliable? In testing I'm getting
313
       an "audio-card" icon from bluez for my NoiseHush N700 headset.
314
       Try to guess the icon from the device type,
315
       and use the bluez-provided icon as a fallback */
316
317
    const auto type = getType();
318
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
319
    switch (type) {
320
    case Type::Headset:
321
        setIconName("image://theme/audio-headset-symbolic");
322
        break;
323
    case Type::Headphones:
324
        setIconName("image://theme/audio-headphones-symbolic");
325
        break;
326
    case Type::Carkit:
327
        setIconName("image://theme/audio-carkit-symbolic");
328
        break;
329
    case Type::Speakers:
330
    case Type::OtherAudio:
331
        setIconName("image://theme/audio-speakers-symbolic");
332
        break;
333
    case Type::Mouse:
334
        setIconName("image://theme/input-mouse-symbolic");
335
        break;
336
    case Type::Keyboard:
337
        setIconName("image://theme/input-keyboard-symbolic");
338
        break;
339
    case Type::Cellular:
340
        setIconName("image://theme/phone-cellular-symbolic");
341
        break;
342
    case Type::Smartphone:
343
        setIconName("image://theme/phone-smartphone-symbolic");
344
        break;
345
    case Type::Phone:
346
        setIconName("image://theme/phone-uncategorized-symbolic");
347
        break;
348
    case Type::Computer:
349
        setIconName("image://theme/computer-symbolic");
350
        break;
1343.3.1 by jonas-drange
remove trailing and spurious spaces
351
    default:
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
352
        setIconName(QString("image://theme/%1").arg(m_fallbackIconName));
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
353
    }
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
354
}
355
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
356
void Device::updateConnection()
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
357
{
358
    Connection c;
1343.3.1 by jonas-drange
remove trailing and spurious spaces
359
1528.2.18 by Simon Fels
Correct connection state handling after State property for profiles/devices
360
    c = m_isConnected ? Connection::Connected : Connection::Disconnected;
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
361
362
    setConnection(c);
351.2.1 by Charles Kerr
add bluetooth plugin implementation
363
}
364
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
365
void Device::updateProperty(const QString &key, const QVariant &value)
351.2.1 by Charles Kerr
add bluetooth plugin implementation
366
{
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
367
    if (key == "Name") {
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
368
        setName(value.toString());
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
369
    } else if (key == "Address") {
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
370
        setAddress(value.toString());
371
    } else if (key == "Connected") {
372
        m_isConnected = value.toBool();
373
        updateConnection();
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
374
    } else if (key == "Class") {
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
375
        setType(getTypeFromClass(value.toUInt()));
1679.2.1 by Konrad Zapałowicz
bluetooth: Add Appearance characteristic to type conversion
376
    } else if (key == "Appearance") {
377
        setType(getTypeFromAppearance(value.toUInt()));
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
378
    } else if (key == "Paired") {
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
379
        setPaired(value.toBool());
1528.2.19 by Simon Fels
Update connection state according to the device state
380
381
        if (m_paired && m_connectAfterPairing) {
382
           connectAfterPairing();
383
           return;
384
        }
385
742.1.2 by Mathieu Trudel-Lapierre
Once successfully paired and connected, mark a remote device as Trusted. This
386
        updateConnection();
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
387
    } else if (key == "Trusted") {
742.1.2 by Mathieu Trudel-Lapierre
Once successfully paired and connected, mark a remote device as Trusted. This
388
        setTrusted(value.toBool());
1528.2.3 by Simon Fels
Also port device management to new BlueZ 5 API
389
    } else if (key == "Icon") {
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
390
        m_fallbackIconName = value.toString();
391
        updateIcon ();
1506.5.5 by simon.busch at canonical
[bluetooth] correctly handle passed in RSSI values to report a signal strength
392
    } else if (key == "RSSI") {
393
        m_strength = getStrengthFromRssi(value.toInt());
394
        Q_EMIT(strengthChanged());
351.2.1 by Charles Kerr
add bluetooth plugin implementation
395
    }
396
}
397
1679.2.1 by Konrad Zapałowicz
bluetooth: Add Appearance characteristic to type conversion
398
/* Determine the Type from the bits in the Appearance field.
399
   https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml */
400
Device::Type Device::getTypeFromAppearance(quint32 c)
401
{
402
    /* is it a HID class device? */
403
    if (c & 0x03C0) {
404
        switch (c & 0x000f) {
405
        case 0x1:
406
            return Type::Keyboard;
407
        case 0x02:
408
            return Type::Mouse;
409
        }
410
    }
411
    return Type::Other;
412
}
413
351.2.13 by Charles Kerr
better explanation of what Device::getTypeFromClass() is for
414
/* Determine the Type from the bits in the Class of Device (CoD) field.
415
   https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband */
379.1.1 by Charles Kerr
copyediting: in function definitions, don't add a line break between the return type and function name.
416
Device::Type Device::getTypeFromClass (quint32 c)
351.2.1 by Charles Kerr
add bluetooth plugin implementation
417
{
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
418
    switch ((c & 0x1f00) >> 8) {
419
    case 0x01:
351.2.1 by Charles Kerr
add bluetooth plugin implementation
420
        return Type::Computer;
421
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
422
    case 0x02:
423
        switch ((c & 0xfc) >> 2) {
424
        case 0x01:
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
425
            return Type::Cellular;
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
426
        case 0x03:
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
427
            return Type::Smartphone;
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
428
        case 0x04:
429
            return Type::Modem;
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
430
        default:
431
            return Type::Phone;
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
432
        }
433
        break;
434
435
    case 0x03:
436
        return Type::Network;
437
438
    case 0x04:
439
        switch ((c & 0xfc) >> 2) {
440
        case 0x01:
441
        case 0x02:
442
            return Type::Headset;
443
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
444
        case 0x05:
445
            return Type::Speakers;
446
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
447
        case 0x06:
448
            return Type::Headphones;
449
806.1.1 by Mathieu Trudel-Lapierre
* Bluetooth UI redesign:
450
        case 0x08:
451
            return Type::Carkit;
452
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
453
        case 0x0b: // vcr
454
        case 0x0c: // video camera
455
        case 0x0d: // camcorder
456
            return Type::Video;
457
458
        default:
459
            return Type::OtherAudio;
460
        }
924.2.1 by Jussi Pakkanen
Fix most compiler warnings.
461
        break;
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
462
463
    case 0x05:
464
        switch ((c & 0xc0) >> 6) {
465
        case 0x00:
466
            switch ((c & 0x1e) >> 2) {
351.2.1 by Charles Kerr
add bluetooth plugin implementation
467
            case 0x01:
468
            case 0x02:
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
469
                return Type::Joypad;
470
            }
471
            break;
472
473
        case 0x01:
474
            return Type::Keyboard;
475
476
        case 0x02:
477
            switch ((c & 0x1e) >> 2) {
351.2.1 by Charles Kerr
add bluetooth plugin implementation
478
            case 0x05:
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
479
                return Type::Tablet;
351.2.1 by Charles Kerr
add bluetooth plugin implementation
480
            default:
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
481
                return Type::Mouse;
482
            }
483
        }
351.2.1 by Charles Kerr
add bluetooth plugin implementation
484
        break;
485
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
486
    case 0x06:
351.2.1 by Charles Kerr
add bluetooth plugin implementation
487
        if ((c & 0x80) != 0)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
488
            return Type::Printer;
351.2.1 by Charles Kerr
add bluetooth plugin implementation
489
        if ((c & 0x20) != 0)
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
490
            return Type::Camera;
351.2.1 by Charles Kerr
add bluetooth plugin implementation
491
        break;
1528.2.39 by Simon Fels
Detect bluetooth watch devices
492
493
    case 0x07:
494
        if ((c & 0x4) != 0)
495
            return Type::Watch;
496
        break;
351.2.1 by Charles Kerr
add bluetooth plugin implementation
497
    }
498
351.2.12 by Charles Kerr
copyediting: make whitespace, indentation, brace style, type modifier alignment more consistent with the rest of the codebase
499
    return Type::Other;
351.2.1 by Charles Kerr
add bluetooth plugin implementation
500
}
501
1506.5.5 by simon.busch at canonical
[bluetooth] correctly handle passed in RSSI values to report a signal strength
502
Device::Strength Device::getStrengthFromRssi(int rssi)
503
{
504
    /* Modelled similar to what Mac OS X does.
505
     * See http://www.cnet.com/how-to/how-to-check-bluetooth-connection-strength-in-os-x/ */
506
507
    if (rssi >= -60)
508
        return Excellent;
509
    else if (rssi < -60 && rssi >= -70)
510
        return Good;
511
    else if (rssi < -70 && rssi >= -90)
512
        return Fair;
513
    else if (rssi < -90)
514
        return Poor;
515
516
    return None;
517
}