summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2016-06-05 00:51:39 +0200
committerJavier <dev.git@javispedro.com>2016-06-05 00:51:39 +0200
commit1905841f4008a58932368a7099e370e5758544c4 (patch)
tree241b95d68b288b2c54ef0df61096ec5b70e8acf5
parent365f98a9f973f5ead0886073ebcaa9bf7c5f0f47 (diff)
downloadlibgato-1905841f4008a58932368a7099e370e5758544c4.tar.gz
libgato-1905841f4008a58932368a7099e370e5758544c4.zip
initial attempts to work with paired devices
-rw-r--r--gatoaddress.cpp20
-rw-r--r--gatoaddress.h14
-rw-r--r--gatoattclient.cpp11
-rw-r--r--gatoattclient.h3
-rw-r--r--gatoperipheral.cpp41
-rw-r--r--gatoperipheral.h5
-rw-r--r--gatosocket.cpp111
-rw-r--r--gatosocket.h1
-rw-r--r--rpm/libgato.spec2
-rw-r--r--rpm/libgato.yaml2
10 files changed, 126 insertions, 84 deletions
diff --git a/gatoaddress.cpp b/gatoaddress.cpp
index b99a977..6f1c583 100644
--- a/gatoaddress.cpp
+++ b/gatoaddress.cpp
@@ -31,34 +31,39 @@ struct GatoAddressPrivate : QSharedData
bdaddr_t bd;
quint64 u64;
} addr;
+ GatoAddress::Type type;
};
GatoAddress::GatoAddress()
: d(new GatoAddressPrivate)
{
d->addr.u64 = 0;
+ d->type = TypeNull;
}
-GatoAddress::GatoAddress(quint64 addr)
+GatoAddress::GatoAddress(quint64 addr, Type type)
: d(new GatoAddressPrivate)
{
d->addr.u64 = addr;
+ d->type = type;
}
-GatoAddress::GatoAddress(quint8 addr[])
+GatoAddress::GatoAddress(quint8 addr[], Type type)
: d(new GatoAddressPrivate)
{
d->addr.u64 = 0;
for (int i = 0; i < 6; i++) {
d->addr.bd.b[i] = addr[i];
}
+ d->type = type;
}
-GatoAddress::GatoAddress(const QString &addr)
+GatoAddress::GatoAddress(const QString &addr, Type type)
: d(new GatoAddressPrivate)
{
d->addr.u64 = 0;
str2ba(addr.toLatin1().constData(), &d->addr.bd);
+ d->type = type;
}
GatoAddress::GatoAddress(const GatoAddress &o)
@@ -83,6 +88,11 @@ bool GatoAddress::isNull() const
return toUInt64() == 0;
}
+GatoAddress::Type GatoAddress::type() const
+{
+ return d->type;
+}
+
quint64 GatoAddress::toUInt64() const
{
return d->addr.u64;
@@ -104,10 +114,10 @@ QString GatoAddress::toString() const
bool operator==(const GatoAddress &a, const GatoAddress &b)
{
- return a.toUInt64() == b.toUInt64();
+ return a.toUInt64() == b.toUInt64() && a.type() == b.type();
}
uint qHash(const GatoAddress &a)
{
- return qHash(a.toUInt64());
+ return qHash(a.toUInt64() + a.type());
}
diff --git a/gatoaddress.h b/gatoaddress.h
index 9b551e7..b64fea9 100644
--- a/gatoaddress.h
+++ b/gatoaddress.h
@@ -10,16 +10,24 @@ class GatoAddressPrivate;
class LIBGATO_EXPORT GatoAddress
{
public:
+ enum Type {
+ TypeNull,
+ TypeBREDR,
+ TypeLEPublic,
+ TypeLERandom
+ };
+
GatoAddress();
- explicit GatoAddress(quint8 addr[]);
- explicit GatoAddress(quint64 addr);
- explicit GatoAddress(const QString &addr);
+ explicit GatoAddress(quint8 addr[], Type = TypeLEPublic);
+ explicit GatoAddress(quint64 addr, Type = TypeLEPublic);
+ explicit GatoAddress(const QString &addr, Type = TypeLEPublic);
GatoAddress(const GatoAddress& o);
~GatoAddress();
GatoAddress& operator=(const GatoAddress& o);
bool isNull() const;
+ Type type() const;
void toUInt8Array(quint8 addr[]) const;
quint64 toUInt64() const;
diff --git a/gatoattclient.cpp b/gatoattclient.cpp
index 00dd9d0..b8bdc17 100644
--- a/gatoattclient.cpp
+++ b/gatoattclient.cpp
@@ -75,8 +75,7 @@ static QByteArray remove_method_signature(const char *sig)
}
GatoAttClient::GatoAttClient(QObject *parent) :
- QObject(parent), socket(new GatoSocket(this)), cur_mtu(ATT_DEFAULT_LE_MTU), next_id(1),
- required_sec(GatoSocket::SecurityLow)
+ QObject(parent), socket(new GatoSocket(this)), cur_mtu(ATT_DEFAULT_LE_MTU), next_id(1)
{
connect(socket, SIGNAL(connected()), SLOT(handleSocketConnected()));
connect(socket, SIGNAL(disconnected()), SLOT(handleSocketDisconnected()));
@@ -92,9 +91,8 @@ GatoSocket::State GatoAttClient::state() const
return socket->state();
}
-bool GatoAttClient::connectTo(const GatoAddress &addr, GatoSocket::SecurityLevel sec_level)
+bool GatoAttClient::connectTo(const GatoAddress &addr)
{
- required_sec = sec_level;
return socket->connectTo(addr, ATT_CID);
}
@@ -110,7 +108,6 @@ GatoSocket::SecurityLevel GatoAttClient::securityLevel() const
bool GatoAttClient::setSecurityLevel(GatoSocket::SecurityLevel level)
{
- required_sec = level;
return socket->setSecurityLevel(level);
}
@@ -563,10 +560,6 @@ QList<GatoAttClient::AttributeGroupData> GatoAttClient::parseAttributeGroupData(
void GatoAttClient::handleSocketConnected()
{
- if (socket->securityLevel() < required_sec) {
- socket->setSecurityLevel(required_sec);
- }
-
requestExchangeMTU(ATT_MAX_LE_MTU, this, SLOT(handleServerMTU(quint16)));
emit connected();
}
diff --git a/gatoattclient.h b/gatoattclient.h
index 764abdd..0aafc6d 100644
--- a/gatoattclient.h
+++ b/gatoattclient.h
@@ -16,7 +16,7 @@ public:
GatoSocket::State state() const;
- bool connectTo(const GatoAddress& addr, GatoSocket::SecurityLevel sec_level);
+ bool connectTo(const GatoAddress& addr);
void close();
GatoSocket::SecurityLevel securityLevel() const;
@@ -99,7 +99,6 @@ private:
quint16 cur_mtu;
uint next_id;
QQueue<Request> pending_requests;
- GatoSocket::SecurityLevel required_sec;
};
#endif // GATOATTCLIENT_H
diff --git a/gatoperipheral.cpp b/gatoperipheral.cpp
index d15bf99..a08f87a 100644
--- a/gatoperipheral.cpp
+++ b/gatoperipheral.cpp
@@ -186,20 +186,29 @@ bool GatoPeripheral::advertisesService(const GatoUUID &uuid) const
return d->service_uuids.contains(uuid);
}
-void GatoPeripheral::connectPeripheral(PeripheralConnectOptions options)
+bool GatoPeripheral::connectPeripheral(PeripheralConnectOptions options)
{
Q_D(GatoPeripheral);
if (d->att->state() != GatoSocket::StateDisconnected) {
qDebug() << "Already connecting";
- return;
+ return false;
}
- GatoSocket::SecurityLevel sec_level = GatoSocket::SecurityLow;
+ d->att->setSecurityLevel(GatoSocket::SecurityLow);
if (options & PeripheralConnectOptionRequireEncryption) {
- sec_level = GatoSocket::SecurityMedium;
+ if (!d->att->setSecurityLevel(GatoSocket::SecurityMedium)) {
+ qWarning() << "Could not set medium security level";
+ return false;
+ }
+ }
+ if (options & PeripheralConnectOptionRequirePairing) {
+ if (!d->att->setSecurityLevel(GatoSocket::SecurityHigh)) {
+ qWarning() << "Could not set medium security level";
+ return false;
+ }
}
- d->att->connectTo(d->addr, sec_level);
+ return d->att->connectTo(d->addr);
}
void GatoPeripheral::disconnectPeripheral()
@@ -785,18 +794,17 @@ void GatoPeripheralPrivate::handleDescriptors(uint req, const QList<GatoAttClien
GatoHandle last_handle = 0;
foreach (const GatoAttClient::InformationData &data, list) {
- // Skip the value attribute itself.
- if (data.handle == characteristic.valueHandle()) continue;
-
- GatoDescriptor descriptor;
+ // Only add attributtes other than the value itself
+ if (data.handle != characteristic.valueHandle()) {
+ GatoDescriptor descriptor;
+ descriptor.setHandle(data.handle);
+ descriptor.setUuid(data.uuid);
- descriptor.setHandle(data.handle);
- descriptor.setUuid(data.uuid);
+ characteristic.addDescriptor(descriptor);
- characteristic.addDescriptor(descriptor);
-
- service.addCharacteristic(characteristic);
- descriptor_to_characteristic.insert(data.handle, char_handle);
+ service.addCharacteristic(characteristic);
+ descriptor_to_characteristic.insert(data.handle, char_handle);
+ }
last_handle = data.handle;
}
@@ -808,6 +816,9 @@ void GatoPeripheralPrivate::handleDescriptors(uint req, const QList<GatoAttClien
finishSetNotifyOperations(characteristic);
emit q->descriptorsDiscovered(characteristic);
return;
+ } else if (last_handle == 0) {
+ qWarning() << "Invalid handle while enumerating characteristics";
+ return;
}
// Fetch following attributes
diff --git a/gatoperipheral.h b/gatoperipheral.h
index 6b7ab5b..67c03a5 100644
--- a/gatoperipheral.h
+++ b/gatoperipheral.h
@@ -27,7 +27,8 @@ public:
~GatoPeripheral();
enum PeripheralConnectOption {
- PeripheralConnectOptionRequireEncryption = 1 << 0
+ PeripheralConnectOptionRequireEncryption = 1 << 0,
+ PeripheralConnectOptionRequirePairing = 2 << 0
};
Q_DECLARE_FLAGS(PeripheralConnectOptions, PeripheralConnectOption)
@@ -54,7 +55,7 @@ public:
bool advertisesService(const GatoUUID &uuid) const;
public slots:
- void connectPeripheral(PeripheralConnectOptions options = 0);
+ bool connectPeripheral(PeripheralConnectOptions options = 0);
void disconnectPeripheral();
void discoverServices();
diff --git a/gatosocket.cpp b/gatosocket.cpp
index da3721d..7860c9e 100644
--- a/gatosocket.cpp
+++ b/gatosocket.cpp
@@ -61,10 +61,10 @@ struct bt_le_params {
uint16_t conn_timeout;
};
-#endif
+#endif /* BT_LE_PARAMS */
GatoSocket::GatoSocket(QObject *parent)
- : QObject(parent), s(StateDisconnected), fd(-1)
+ : QObject(parent), s(StateDisconnected), fd(-1), desiredSec(SecurityLow)
{
}
@@ -95,6 +95,8 @@ bool GatoSocket::connectTo(const GatoAddress &addr, unsigned short cid)
s = StateConnecting;
+ setSecurityLevel(desiredSec);
+
readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
writeNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this);
connect(readNotifier, SIGNAL(activated(int)), SLOT(readNotify()));
@@ -106,7 +108,24 @@ bool GatoSocket::connectTo(const GatoAddress &addr, unsigned short cid)
l2addr.l2_family = AF_BLUETOOTH;
l2addr.l2_cid = htobs(cid);
#ifdef BDADDR_LE_PUBLIC
- l2addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; // TODO
+ switch (addr.type()) {
+ case GatoAddress::TypeBREDR:
+ l2addr.l2_bdaddr_type = BDADDR_BREDR;
+ break;
+ case GatoAddress::TypeLEPublic:
+ default:
+ l2addr.l2_bdaddr_type = BDADDR_LE_PUBLIC;
+ break;
+ case GatoAddress::TypeLERandom:
+ l2addr.l2_bdaddr_type = BDADDR_LE_RANDOM;
+ break;
+ }
+#else
+ // The kernel is probably too old to support this,
+ // but BLE might still work (e.g. Nokia N9).
+ if (addr.type() != GatoAddress::TypeLEPublic) {
+ qWarning() << "Kernel does not support random LE addresses!";
+ }
#endif
addr.toUInt8Array(l2addr.l2_bdaddr.b);
@@ -162,59 +181,59 @@ GatoSocket::SecurityLevel GatoSocket::securityLevel() const
bt_security bt_sec;
socklen_t len = sizeof(bt_sec);
- if (s == StateDisconnected) {
- qWarning() << "Socket not connected";
- return SecurityNone;
- }
-
- if (::getsockopt(fd, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, &len) == 0) {
- switch (bt_sec.level) {
- case BT_SECURITY_SDP:
- return SecurityNone;
- case BT_SECURITY_LOW:
- return SecurityLow;
- case BT_SECURITY_MEDIUM:
- return SecurityMedium;
- case BT_SECURITY_HIGH:
- return SecurityHigh;
+ if (s != StateDisconnected) {
+ if (::getsockopt(fd, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, &len) == 0) {
+ switch (bt_sec.level) {
+ case BT_SECURITY_SDP:
+ return SecurityNone;
+ case BT_SECURITY_LOW:
+ return SecurityLow;
+ case BT_SECURITY_MEDIUM:
+ return SecurityMedium;
+ case BT_SECURITY_HIGH:
+ return SecurityHigh;
+ }
+ } else {
+ qErrnoWarning("Could not read security level from L2 socket");
}
+
+ return SecurityNone;
} else {
- qErrnoWarning("Could not read security level from L2 socket");
+ return desiredSec;
}
-
- return SecurityNone;
}
bool GatoSocket::setSecurityLevel(SecurityLevel level)
{
- bt_security bt_sec;
- socklen_t len = sizeof(bt_sec);
+ desiredSec = level;
- if (s == StateDisconnected) {
- qWarning() << "Socket not connected";
- return false;
- }
-
- memset(&bt_sec, 0, len);
-
- switch (level) {
- case SecurityNone:
- case SecurityLow:
- bt_sec.level = BT_SECURITY_LOW;
- break;
- case SecurityMedium:
- bt_sec.level = BT_SECURITY_MEDIUM;
- break;
- case SecurityHigh:
- bt_sec.level = BT_SECURITY_HIGH;
- break;
- }
+ if (s != StateDisconnected) {
+ bt_security bt_sec;
+ socklen_t len = sizeof(bt_sec);
+
+ memset(&bt_sec, 0, len);
+
+ switch (level) {
+ case SecurityNone:
+ case SecurityLow:
+ bt_sec.level = BT_SECURITY_LOW;
+ break;
+ case SecurityMedium:
+ bt_sec.level = BT_SECURITY_MEDIUM;
+ break;
+ case SecurityHigh:
+ bt_sec.level = BT_SECURITY_HIGH;
+ break;
+ }
- if (::setsockopt(fd, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, len) == 0) {
- return true;
+ if (::setsockopt(fd, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, len) == 0) {
+ return true;
+ } else {
+ qErrnoWarning("Could not set security level in L2 socket");
+ return false;
+ }
} else {
- qErrnoWarning("Could not set security level in L2 socket");
- return false;
+ return true;
}
}
diff --git a/gatosocket.h b/gatosocket.h
index 28fd788..b7634c7 100644
--- a/gatosocket.h
+++ b/gatosocket.h
@@ -69,6 +69,7 @@ private slots:
private:
State s;
int fd;
+ SecurityLevel desiredSec;
QSocketNotifier *readNotifier;
QQueue<QByteArray> readQueue;
QSocketNotifier *writeNotifier;
diff --git a/rpm/libgato.spec b/rpm/libgato.spec
index 5b8584f..8b96fb8 100644
--- a/rpm/libgato.spec
+++ b/rpm/libgato.spec
@@ -13,7 +13,7 @@ Name: libgato
%{!?qtc_make:%define qtc_make make}
%{?qtc_builddir:%define _builddir %qtc_builddir}
Summary: A GATT library to connect with Bluetooth Smart devices
-Version: 0.1.7
+Version: 0.1.8
Release: 1
Group: Qt/Qt
License: GPL2
diff --git a/rpm/libgato.yaml b/rpm/libgato.yaml
index 3d1c092..b2b065e 100644
--- a/rpm/libgato.yaml
+++ b/rpm/libgato.yaml
@@ -1,6 +1,6 @@
Name: libgato
Summary: A GATT library to connect with Bluetooth Smart devices
-Version: 0.1.7
+Version: 0.1.8
Release: 1
Group: Qt/Qt
URL: https://gitorious.org/gato/