summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gatoattclient.cpp21
-rw-r--r--gatoattclient.h6
-rw-r--r--gatoconnectionparameters.cpp77
-rw-r--r--gatoconnectionparameters.h52
-rw-r--r--gatoperipheral.cpp12
-rw-r--r--gatoperipheral.h4
-rw-r--r--gatosocket.cpp103
-rw-r--r--gatosocket.h4
-rw-r--r--libgato.pro8
-rw-r--r--rpm/libgato.spec2
-rw-r--r--rpm/libgato.yaml2
11 files changed, 283 insertions, 8 deletions
diff --git a/gatoattclient.cpp b/gatoattclient.cpp
index 0bf5877..00dd9d0 100644
--- a/gatoattclient.cpp
+++ b/gatoattclient.cpp
@@ -103,6 +103,27 @@ void GatoAttClient::close()
socket->close();
}
+GatoSocket::SecurityLevel GatoAttClient::securityLevel() const
+{
+ return socket->securityLevel();
+}
+
+bool GatoAttClient::setSecurityLevel(GatoSocket::SecurityLevel level)
+{
+ required_sec = level;
+ return socket->setSecurityLevel(level);
+}
+
+GatoConnectionParameters GatoAttClient::connectionParameters() const
+{
+ return socket->connectionParameters();
+}
+
+bool GatoAttClient::setConnectionParameters(const GatoConnectionParameters &params)
+{
+ return socket->setConnectionParameters(params);
+}
+
int GatoAttClient::mtu() const
{
return cur_mtu;
diff --git a/gatoattclient.h b/gatoattclient.h
index 64df313..764abdd 100644
--- a/gatoattclient.h
+++ b/gatoattclient.h
@@ -19,6 +19,12 @@ public:
bool connectTo(const GatoAddress& addr, GatoSocket::SecurityLevel sec_level);
void close();
+ GatoSocket::SecurityLevel securityLevel() const;
+ bool setSecurityLevel(GatoSocket::SecurityLevel level);
+
+ GatoConnectionParameters connectionParameters() const;
+ bool setConnectionParameters(const GatoConnectionParameters &params);
+
struct InformationData
{
GatoHandle handle;
diff --git a/gatoconnectionparameters.cpp b/gatoconnectionparameters.cpp
new file mode 100644
index 0000000..29ec37b
--- /dev/null
+++ b/gatoconnectionparameters.cpp
@@ -0,0 +1,77 @@
+#include "gatoconnectionparameters.h"
+#include <QSharedData>
+
+struct GatoConnectionParametersPrivate : public QSharedData
+{
+ int connIntervalMin;
+ int connIntervalMax;
+ int slaveLatency;
+ int supervisionTimeout;
+};
+
+GatoConnectionParameters::GatoConnectionParameters()
+ : d(new GatoConnectionParametersPrivate)
+{
+}
+
+GatoConnectionParameters::GatoConnectionParameters(const GatoConnectionParameters &o)
+ : d(o.d)
+{
+}
+
+GatoConnectionParameters::~GatoConnectionParameters()
+{
+}
+
+int GatoConnectionParameters::connectionIntervalMin() const
+{
+ return d->connIntervalMin;
+}
+
+void GatoConnectionParameters::setConnectionIntervalMin(int interval)
+{
+ d->connIntervalMin = interval;
+}
+
+int GatoConnectionParameters::connectionIntervalMax() const
+{
+ return d->connIntervalMax;
+}
+
+void GatoConnectionParameters::setConnectionIntervalMax(int interval)
+{
+ d->connIntervalMax = interval;
+}
+
+void GatoConnectionParameters::setConnectionInterval(int min, int max)
+{
+ d->connIntervalMin = min;
+ d->connIntervalMax = max;
+}
+
+int GatoConnectionParameters::slaveLatency() const
+{
+ return d->slaveLatency;
+}
+
+void GatoConnectionParameters::setSlaveLatency(int latency)
+{
+ d->slaveLatency = latency;
+}
+
+int GatoConnectionParameters::supervisionTimeout() const
+{
+ return d->supervisionTimeout;
+}
+
+void GatoConnectionParameters::setSupervisionTimeout(int timeout)
+{
+ d->supervisionTimeout = timeout;
+}
+
+GatoConnectionParameters &GatoConnectionParameters::operator=(const GatoConnectionParameters &o)
+{
+ if (this != &o)
+ d.operator=(o.d);
+ return *this;
+}
diff --git a/gatoconnectionparameters.h b/gatoconnectionparameters.h
new file mode 100644
index 0000000..1441020
--- /dev/null
+++ b/gatoconnectionparameters.h
@@ -0,0 +1,52 @@
+#ifndef GATOCONNECTIONPARAMETERS_H
+#define GATOCONNECTIONPARAMETERS_H
+
+#include <QtCore/QObject>
+#include <QtCore/QSharedDataPointer>
+
+#include "libgato_global.h"
+
+class GatoConnectionParametersPrivate;
+
+/** These parameters determine the effective throughput of a Low Energy link,
+ * enabling custom balancing between power usage, bandwidth, and latency. */
+
+class LIBGATO_EXPORT GatoConnectionParameters
+{
+ Q_GADGET
+
+public:
+ GatoConnectionParameters();
+ GatoConnectionParameters(const GatoConnectionParameters &o);
+ ~GatoConnectionParameters();
+
+ // Units for all of this: milliseconds
+ // TODO Need to document
+
+ // Connection interval: generally, lower connection interval increases throughput.
+ // Units: microseconds (µs!)
+
+ int connectionIntervalMin() const;
+ void setConnectionIntervalMin(int interval);
+
+ int connectionIntervalMax() const;
+ void setConnectionIntervalMax(int interval);
+
+ void setConnectionInterval(int min, int max);
+
+ // TODO Document
+ // Units: miliseconds (ms!)
+ int slaveLatency() const;
+ void setSlaveLatency(int latency);
+
+ // Units: miliseconds
+ int supervisionTimeout() const;
+ void setSupervisionTimeout(int timeout);
+
+ GatoConnectionParameters &operator=(const GatoConnectionParameters &o);
+
+private:
+ QSharedDataPointer<GatoConnectionParametersPrivate> d;
+};
+
+#endif // GATOCONNECTIONPARAMETERS_H
diff --git a/gatoperipheral.cpp b/gatoperipheral.cpp
index 160e302..d15bf99 100644
--- a/gatoperipheral.cpp
+++ b/gatoperipheral.cpp
@@ -97,6 +97,18 @@ QList<GatoService> GatoPeripheral::services() const
return d->services.values();
}
+GatoConnectionParameters GatoPeripheral::connectionParameters() const
+{
+ Q_D(const GatoPeripheral);
+ return d->att->connectionParameters();
+}
+
+bool GatoPeripheral::setConnectionParameters(const GatoConnectionParameters &params)
+{
+ Q_D(const GatoPeripheral);
+ return d->att->setConnectionParameters(params);
+}
+
void GatoPeripheral::parseEIR(quint8 data[], int len)
{
Q_D(GatoPeripheral);
diff --git a/gatoperipheral.h b/gatoperipheral.h
index c8c9023..6b7ab5b 100644
--- a/gatoperipheral.h
+++ b/gatoperipheral.h
@@ -5,6 +5,7 @@
#include "libgato_global.h"
#include "gatouuid.h"
#include "gatoaddress.h"
+#include "gatoconnectionparameters.h"
class GatoService;
class GatoCharacteristic;
@@ -46,6 +47,9 @@ public:
QString name() const;
QList<GatoService> services() const;
+ GatoConnectionParameters connectionParameters() const;
+ bool setConnectionParameters(const GatoConnectionParameters &params);
+
void parseEIR(quint8 data[], int len);
bool advertisesService(const GatoUUID &uuid) const;
diff --git a/gatosocket.cpp b/gatosocket.cpp
index 73567b5..19f11ff 100644
--- a/gatosocket.cpp
+++ b/gatosocket.cpp
@@ -28,6 +28,41 @@
#include <bluetooth/l2cap.h>
#include "gatosocket.h"
+#ifndef BT_LE_PARAMS
+/* Too old kernel headers. */
+#define BT_LE_PARAMS 100
+#define BT_LE_SCAN_WINDOW_MIN 0x0004
+#define BT_LE_SCAN_WINDOW_MAX 0x4000
+#define BT_LE_SCAN_WINDOW_DEF 0x0004
+#define BT_LE_SCAN_INTERVAL_MIN 0x0004
+#define BT_LE_SCAN_INTERVAL_MAX 0x4000
+#define BT_LE_SCAN_INTERVAL_DEF 0x0008
+#define BT_LE_CONN_INTERVAL_MIN 0x0006
+#define BT_LE_CONN_INTERVAL_MAX 0x0C80
+#define BT_LE_CONN_INTERVAL_MIN_DEF 0x0008
+#define BT_LE_CONN_INTERVAL_MAX_DEF 0x0100
+#define BT_LE_LATENCY_MAX 0x01F4
+#define BT_LE_LATENCY_DEF 0x0000
+#define BT_LE_SUP_TO_MIN 0x000A
+#define BT_LE_SUP_TO_MAX 0x0C80
+#define BT_LE_SUP_TO_DEFAULT 0X03E8
+
+struct bt_le_params {
+ uint8_t prohibit_remote_chg;
+ uint8_t filter_policy;
+ uint16_t scan_interval;
+ uint16_t scan_window;
+ uint16_t interval_min;
+ uint16_t interval_max;
+ uint16_t latency;
+ uint16_t supervision_timeout;
+ uint16_t min_ce_len;
+ uint16_t max_ce_len;
+ uint16_t conn_timeout;
+};
+
+#endif
+
GatoSocket::GatoSocket(QObject *parent)
: QObject(parent), s(StateDisconnected), fd(-1)
{
@@ -156,9 +191,11 @@ bool GatoSocket::setSecurityLevel(SecurityLevel level)
if (s == StateDisconnected) {
qWarning() << "Socket not connected";
- return SecurityNone;
+ return false;
}
+ memset(&bt_sec, 0, len);
+
switch (level) {
case SecurityNone:
case SecurityLow:
@@ -168,11 +205,9 @@ bool GatoSocket::setSecurityLevel(SecurityLevel level)
bt_sec.level = BT_SECURITY_MEDIUM;
break;
case SecurityHigh:
- // Will this even work in BT LE?
bt_sec.level = BT_SECURITY_HIGH;
break;
}
- bt_sec.key_size = 0;
if (::setsockopt(fd, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, len) == 0) {
return true;
@@ -182,6 +217,68 @@ bool GatoSocket::setSecurityLevel(SecurityLevel level)
}
}
+GatoConnectionParameters GatoSocket::connectionParameters() const
+{
+ GatoConnectionParameters params;
+ bt_le_params bt_params;
+ socklen_t len = sizeof(bt_params);
+
+ if (s == StateDisconnected) {
+ qWarning() << "Socket not connected";
+ return params;
+ }
+
+ if (::getsockopt(fd, SOL_BLUETOOTH, BT_LE_PARAMS, &bt_params, &len) == 0) {
+ if (bt_params.interval_min == 0 && bt_params.interval_max == 0) {
+ // Sometimes the kernel will give us this when no parameters have been set.
+ // I believe it is a bug, because in truth the kernel default parameters are in use.
+ qDebug() << "Filling in kernel defaults, since the kernel did not";
+ bt_params.interval_min = BT_LE_CONN_INTERVAL_MIN_DEF;
+ bt_params.interval_max = BT_LE_CONN_INTERVAL_MAX_DEF;
+ bt_params.latency = BT_LE_LATENCY_DEF;
+ bt_params.supervision_timeout = BT_LE_SUP_TO_DEFAULT;
+ }
+ // Kernel uses "multiples of 1.25ms", we use µs, need to convert.
+ params.setConnectionInterval(bt_params.interval_min * 1250, bt_params.interval_max * 1250);
+ // Kernel units already in ms.
+ params.setSlaveLatency(bt_params.latency);
+ // Kernel uses "multiples of 10ms", need to convert
+ params.setSupervisionTimeout(bt_params.supervision_timeout * 10);
+ } else {
+ qErrnoWarning("Could not read connection parameters from L2 socket");
+ }
+
+ return params;
+}
+
+bool GatoSocket::setConnectionParameters(const GatoConnectionParameters &params)
+{
+ bt_le_params bt_params;
+ socklen_t len = sizeof(bt_params);
+
+ if (s == StateDisconnected) {
+ qWarning() << "Socket not connected";
+ return false;
+ }
+
+ memset(&bt_params, 0, len);
+
+ // Kernel uses "multiples of 1.25ms", we use µs, need to convert
+ bt_params.interval_min = params.connectionIntervalMin() / 1250;
+ bt_params.interval_max = params.connectionIntervalMax() / 1250;
+ // Kernel units already "ms".
+ bt_params.latency = params.slaveLatency();
+ // Kernel uses "multiples of 10ms", need to convert
+ bt_params.supervision_timeout = params.supervisionTimeout() / 10;
+
+ if (::setsockopt(fd, SOL_BLUETOOTH, BT_LE_PARAMS, &bt_params, len) == 0) {
+ return true;
+ } else {
+ qErrnoWarning("Could not set connection parameters in L2 socket");
+ return false;
+ }
+}
+
bool GatoSocket::transmit(const QByteArray &pkt)
{
int written = ::write(fd, pkt.constData(), pkt.size());
diff --git a/gatosocket.h b/gatosocket.h
index 56760ee..28fd788 100644
--- a/gatosocket.h
+++ b/gatosocket.h
@@ -6,6 +6,7 @@
#include <QtCore/QSocketNotifier>
#include "gatoaddress.h"
+#include "gatoconnectionparameters.h"
/** This class encapsulates a message-oriented bluetooth L2CAP socket. */
class GatoSocket : public QObject
@@ -49,6 +50,9 @@ public:
SecurityLevel securityLevel() const;
bool setSecurityLevel(SecurityLevel level);
+ GatoConnectionParameters connectionParameters() const;
+ bool setConnectionParameters(const GatoConnectionParameters &params);
+
signals:
void connected();
void disconnected();
diff --git a/libgato.pro b/libgato.pro
index f13ebd3..a3397a4 100644
--- a/libgato.pro
+++ b/libgato.pro
@@ -19,7 +19,8 @@ SOURCES += \
gatoservice.cpp \
gatocharacteristic.cpp \
gatodescriptor.cpp \
- gatoattclient.cpp
+ gatoattclient.cpp \
+ gatoconnectionparameters.cpp
HEADERS += libgato_global.h gato.h \
gatocentralmanager.h \
@@ -33,7 +34,8 @@ HEADERS += libgato_global.h gato.h \
gatoservice.h \
gatocharacteristic.h \
gatodescriptor.h \
- gatoattclient.h
+ gatoattclient.h \
+ gatoconnectionparameters.h
target.path = /usr/lib
INSTALLS += target
@@ -41,7 +43,7 @@ INSTALLS += target
publicheaders.files = libgato_global.h gato.h \
gatocentralmanager.h gatoperipheral.h \
gatoservice.h gatocharacteristic.h gatodescriptor.h \
- gatouuid.h gatoaddress.h
+ gatouuid.h gatoaddress.h gatoconnectionparameters.h
publicheaders.path = /usr/include/gato
INSTALLS += publicheaders
diff --git a/rpm/libgato.spec b/rpm/libgato.spec
index 7ca7e60..669579b 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.4
+Version: 0.1.6
Release: 1
Group: Qt/Qt
License: GPL2
diff --git a/rpm/libgato.yaml b/rpm/libgato.yaml
index 3f603da..3b13a5c 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.4
+Version: 0.1.6
Release: 1
Group: Qt/Qt
URL: https://gitorious.org/gato/