summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bluetooth/gatoattclient.cpp609
-rw-r--r--src/bluetooth/gatoattclient.h135
-rw-r--r--src/bluetooth/gatoperipheral.cpp866
-rw-r--r--src/bluetooth/gatoperipheral.h111
-rw-r--r--src/bluetooth/gatoperipheral_p.h108
-rw-r--r--sync.profile3
6 files changed, 0 insertions, 1832 deletions
diff --git a/src/bluetooth/gatoattclient.cpp b/src/bluetooth/gatoattclient.cpp
deleted file mode 100644
index d15e9d05..00000000
--- a/src/bluetooth/gatoattclient.cpp
+++ /dev/null
@@ -1,609 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Javier de San Pedro <dev.git@javispedro.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/QDataStream>
-#include <QtCore/QDebug>
-
-#include "gatoattclient.h"
-#include "helpers.h"
-
-#define PROTOCOL_DEBUG 0
-
-#define ATT_CID 4
-#define ATT_PSM 31
-
-#define ATT_DEFAULT_LE_MTU 23
-#define ATT_MAX_LE_MTU 0x200
-
-QT_BEGIN_NAMESPACE
-
-enum AttOpcode {
- AttOpNone = 0,
- AttOpErrorResponse = 0x1,
- AttOpExchangeMTURequest = 0x2,
- AttOpExchangeMTUResponse = 0x3,
- AttOpFindInformationRequest = 0x4,
- AttOpFindInformationResponse = 0x5,
- AttOpFindByTypeValueRequest = 0x6,
- AttOpFindByTypeValueResponse = 0x7,
- AttOpReadByTypeRequest = 0x8,
- AttOpReadByTypeResponse = 0x9,
- AttOpReadRequest = 0xA,
- AttOpReadResponse = 0xB,
- AttOpReadBlobRequest = 0xC,
- AttOpReadBlobResponse = 0xD,
- AttOpReadMultipleRequest = 0xE,
- AttOpReadMultipleResponse = 0xF,
- AttOpReadByGroupTypeRequest = 0x10,
- AttOpReadByGroupTypeResponse = 0x11,
- AttOpWriteRequest = 0x12,
- AttOpWriteResponse = 0x13,
- AttOpWriteCommand = 0x52,
- AttOpPrepareWriteRequest = 0x16,
- AttOpPrepareWriteResponse = 0x17,
- AttOpExecuteWriteRequest = 0x18,
- AttOpExecuteWriteResponse = 0x19,
- AttOpHandleValueNotification = 0x1B,
- AttOpHandleValueIndication = 0x1D,
- AttOpHandleValueConfirmation = 0x1E,
- AttOpSignedWriteCommand = 0xD2
-};
-
-static QByteArray remove_method_signature(const char *sig)
-{
- const char* bracketPosition = strchr(sig, '(');
- if (!bracketPosition || !(sig[0] >= '0' && sig[0] <= '3')) {
- qWarning("Invalid slot specification");
- return QByteArray();
- }
- return QByteArray(sig + 1, bracketPosition - 1 - sig);
-}
-
-GatoAttClient::GatoAttClient(QObject *parent) :
- 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()));
- connect(socket, SIGNAL(readyRead()), SLOT(handleSocketReadyRead()));
-}
-
-GatoAttClient::~GatoAttClient()
-{
-}
-
-GatoSocket::State GatoAttClient::state() const
-{
- return socket->state();
-}
-
-bool GatoAttClient::connectTo(const GatoAddress &addr)
-{
- return socket->connectTo(addr, ATT_CID);
-}
-
-void GatoAttClient::close()
-{
- socket->close();
-}
-
-int GatoAttClient::mtu() const
-{
- return cur_mtu;
-}
-
-uint GatoAttClient::request(int opcode, const QByteArray &data, QObject *receiver, const char *member)
-{
- Request req;
- req.id = next_id++;
- req.opcode = opcode;
- req.pkt = data;
- req.pkt.prepend(static_cast<char>(opcode));
- req.receiver = receiver;
- req.member = remove_method_signature(member);
-
- pending_requests.enqueue(req);
-
- if (pending_requests.size() == 1) {
- // So we can just send this request instead of waiting for others to complete
- sendARequest();
- }
-
- return req.id;
-}
-
-void GatoAttClient::cancelRequest(uint id)
-{
- QQueue<Request>::iterator it = pending_requests.begin();
- while (it != pending_requests.end()) {
- if (it->id == id) {
- it = pending_requests.erase(it);
- } else {
- ++it;
- }
- }
-}
-
-uint GatoAttClient::requestExchangeMTU(quint16 client_mtu, QObject *receiver, const char *member)
-{
- QByteArray data;
- QDataStream s(&data, QIODevice::WriteOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- s << client_mtu;
-
- return request(AttOpExchangeMTURequest, data, receiver, member);
-}
-
-uint GatoAttClient::requestFindInformation(GatoHandle start, GatoHandle end, QObject *receiver, const char *member)
-{
- QByteArray data;
- QDataStream s(&data, QIODevice::WriteOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- s << start << end;
-
- return request(AttOpFindInformationRequest, data, receiver, member);
-}
-
-uint GatoAttClient::requestFindByTypeValue(GatoHandle start, GatoHandle end, const GatoUUID &uuid, const QByteArray &value, QObject *receiver, const char *member)
-{
- QByteArray data;
- QDataStream s(&data, QIODevice::WriteOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- s << start << end;
-
- bool uuid16_ok;
- quint16 uuid16 = uuid.toUInt16(&uuid16_ok);
- if (uuid16_ok) {
- s << uuid16;
- } else {
- qWarning() << "FindByTypeValue does not support UUIDs other than UUID16";
- return -1;
- }
-
- s << value;
-
- return request(AttOpFindByTypeValueRequest, data, receiver, member);
-}
-
-uint GatoAttClient::requestReadByType(GatoHandle start, GatoHandle end, const GatoUUID &uuid, QObject *receiver, const char *member)
-{
- QByteArray data;
- QDataStream s(&data, QIODevice::WriteOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- s << start << end;
- write_gatouuid(s, uuid, true, false);
-
- return request(AttOpReadByTypeRequest, data, receiver, member);
-}
-
-uint GatoAttClient::requestRead(GatoHandle handle, QObject *receiver, const char *member)
-{
- QByteArray data;
- QDataStream s(&data, QIODevice::WriteOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- s << handle;
-
- return request(AttOpReadRequest, data, receiver, member);
-}
-
-uint GatoAttClient::requestReadByGroupType(GatoHandle start, GatoHandle end, const GatoUUID &uuid, QObject *receiver, const char *member)
-{
- QByteArray data;
- QDataStream s(&data, QIODevice::WriteOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- s << start << end;
- write_gatouuid(s, uuid, true, false);
-
- return request(AttOpReadByGroupTypeRequest, data, receiver, member);
-}
-
-uint GatoAttClient::requestWrite(GatoHandle handle, const QByteArray &value, QObject *receiver, const char *member)
-{
- QByteArray data;
- QDataStream s(&data, QIODevice::WriteOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- s << handle;
- s.writeRawData(value.constData(), value.length());
-
- return request(AttOpWriteRequest, data, receiver, member);
-}
-
-void GatoAttClient::command(int opcode, const QByteArray &data)
-{
- QByteArray packet = data;
- packet.prepend(static_cast<char>(opcode));
-
- socket->send(packet);
-
-#if PROTOCOL_DEBUG
- qDebug() << "Wrote" << packet.size() << "bytes (command)" << packet.toHex();
-#endif
-}
-
-void GatoAttClient::commandWrite(GatoHandle handle, const QByteArray &value)
-{
- QByteArray data;
- QDataStream s(&data, QIODevice::WriteOnly);
- s.setByteOrder(QDataStream::LittleEndian);
- s << handle;
- s.writeRawData(value.constData(), value.length());
-
- command(AttOpWriteCommand, data);
-}
-
-void GatoAttClient::sendARequest()
-{
- if (pending_requests.isEmpty()) {
- return;
- }
-
- Request &req = pending_requests.head();
- socket->send(req.pkt);
-
-#if PROTOCOL_DEBUG
- qDebug() << "Wrote" << req.pkt.size() << "bytes (request)" << req.pkt.toHex();
-#endif
-}
-
-bool GatoAttClient::handleEvent(const QByteArray &event)
-{
- const char *data = event.constData();
- quint8 opcode = event[0];
- GatoHandle handle;
-
- switch (opcode) {
- case AttOpHandleValueNotification:
- handle = read_le<GatoHandle>(&data[1]);
- emit attributeUpdated(handle, event.mid(3), false);
- return true;
- case AttOpHandleValueIndication:
- handle = read_le<GatoHandle>(&data[1]);
-
- // Send the confirmation back
- command(AttOpHandleValueConfirmation, QByteArray());
-
- emit attributeUpdated(handle, event.mid(3), true);
- return true;
- default:
- return false;
- }
-}
-
-bool GatoAttClient::handleResponse(const Request &req, const QByteArray &response)
-{
- // If we know the request, we can provide a decoded answer
- switch (req.opcode) {
- case AttOpExchangeMTURequest:
- if (response[0] == AttOpExchangeMTUResponse) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(quint16, read_le<quint16>(response.constData() + 1)));
- }
- return true;
- } else if (response[0] == AttOpErrorResponse && response[1] == AttOpExchangeMTURequest) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(quint16, 0));
- }
- return true;
- } else {
- return false;
- }
- break;
- case AttOpFindInformationRequest:
- if (response[0] == AttOpFindInformationResponse) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QList<GatoAttClient::InformationData>, parseInformationData(response.mid(1))));
- }
- return true;
- } else if (response[0] == AttOpErrorResponse && response[1] == AttOpFindInformationRequest) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QList<GatoAttClient::InformationData>, QList<InformationData>()));
- }
- return true;
- } else {
- return false;
- }
- break;
- case AttOpFindByTypeValueRequest:
- if (response[0] == AttOpFindByTypeValueResponse) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QList<GatoAttClient::HandleInformation>, parseHandleInformation(response.mid(1))));
- }
- return true;
- } else if (response[0] == AttOpErrorResponse && response[1] == AttOpFindByTypeValueRequest) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QList<GatoAttClient::HandleInformation>, QList<HandleInformation>()));
- }
- return true;
- } else {
- return false;
- }
- break;
- case AttOpReadByTypeRequest:
- if (response[0] == AttOpReadByTypeResponse) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QList<GatoAttClient::AttributeData>, parseAttributeData(response.mid(1))));
- }
- return true;
- } else if (response[0] == AttOpErrorResponse && response[1] == AttOpReadByTypeRequest) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QList<GatoAttClient::AttributeData>, QList<AttributeData>()));
- }
- return true;
- } else {
- return false;
- }
- break;
- case AttOpReadRequest:
- if (response[0] == AttOpReadResponse) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QByteArray, response.mid(1)));
- }
- return true;
- } else if (response[0] == AttOpErrorResponse && response[1] == AttOpReadRequest) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QByteArray, QByteArray()));
- }
- return true;
- } else {
- return false;
- }
- break;
- case AttOpReadByGroupTypeRequest:
- if (response[0] == AttOpReadByGroupTypeResponse) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QList<GatoAttClient::AttributeGroupData>, parseAttributeGroupData(response.mid(1))));
- }
- return true;
- } else if (response[0] == AttOpErrorResponse && response[1] == AttOpReadByGroupTypeRequest) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(QList<GatoAttClient::AttributeGroupData>, QList<AttributeGroupData>()));
- }
- return true;
- } else {
- return false;
- }
- break;
- case AttOpWriteRequest:
- if (response[0] == AttOpWriteResponse) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(bool, true));
- }
- return true;
- } else if (response[0] == AttOpErrorResponse && response[1] == AttOpWriteRequest) {
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(uint, req.id),
- Q_ARG(bool, false));
- }
- return true;
- } else {
- return false;
- }
- break;
- default: // Otherwise just send a QByteArray.
- if (req.receiver) {
- QMetaObject::invokeMethod(req.receiver, req.member.constData(),
- Q_ARG(const QByteArray&, response));
- }
- return true;
- }
-}
-
-QList<GatoAttClient::InformationData> GatoAttClient::parseInformationData(const QByteArray &data)
-{
- const int format = data[0];
- QList<InformationData> list;
- int item_len;
-
- switch (format) {
- case 1:
- item_len = 2 + 2;
- break;
- case 2:
- item_len = 2 + 16;
- break;
- default:
- qWarning() << "Unknown InformationData format!";
- return list;
- }
-
- int items = (data.size() - 1) / item_len;
- list.reserve(items);
-
- int pos = 1;
- const char *s = data.constData();
- for (int i = 0; i < items; i++) {
- InformationData d;
- QByteArray uuid;
- d.handle = read_le<GatoHandle>(&s[pos]);
- switch (format) {
- case 1:
- uuid = data.mid(pos + 2, 2);
- break;
- case 2:
- uuid = data.mid(pos + 2, 16);
- break;
- }
- d.uuid = bytearray_to_gatouuid(uuid);
-
- list.append(d);
-
- pos += item_len;
- }
-
- return list;
-}
-
-QList<GatoAttClient::HandleInformation> GatoAttClient::parseHandleInformation(const QByteArray &data)
-{
- const int item_len = 2;
- const int items = data.size() / item_len;
- QList<HandleInformation> list;
- list.reserve(items);
-
- int pos = 0;
- const char *s = data.constData();
- for (int i = 0; i < items; i++) {
- HandleInformation d;
- d.start = read_le<GatoHandle>(&s[pos]);
- d.end = read_le<GatoHandle>(&s[pos + 2]);
- list.append(d);
-
- pos += item_len;
- }
-
- return list;
-}
-
-QList<GatoAttClient::AttributeData> GatoAttClient::parseAttributeData(const QByteArray &data)
-{
- const int item_len = data[0];
- const int items = (data.size() - 1) / item_len;
- QList<AttributeData> list;
- list.reserve(items);
-
- int pos = 1;
- const char *s = data.constData();
- for (int i = 0; i < items; i++) {
- AttributeData d;
- d.handle = read_le<GatoHandle>(&s[pos]);
- d.value = data.mid(pos + 2, item_len - 2);
- list.append(d);
-
- pos += item_len;
- }
-
- return list;
-}
-
-QList<GatoAttClient::AttributeGroupData> GatoAttClient::parseAttributeGroupData(const QByteArray &data)
-{
- const int item_len = data[0];
- const int items = (data.size() - 1) / item_len;
- QList<AttributeGroupData> list;
- list.reserve(items);
-
- int pos = 1;
- const char *s = data.constData();
- for (int i = 0; i < items; i++) {
- AttributeGroupData d;
- d.start = read_le<GatoHandle>(&s[pos]);
- d.end = read_le<GatoHandle>(&s[pos + 2]);
- d.value = data.mid(pos + 4, item_len - 4);
- list.append(d);
-
- pos += item_len;
- }
-
- return list;
-}
-
-void GatoAttClient::handleSocketConnected()
-{
- requestExchangeMTU(ATT_MAX_LE_MTU, this, SLOT(handleServerMTU(quint16)));
- emit connected();
-}
-
-void GatoAttClient::handleSocketDisconnected()
-{
- emit disconnected();
-}
-
-void GatoAttClient::handleSocketReadyRead()
-{
- QByteArray pkt = socket->receive();
- if (!pkt.isEmpty()) {
-#if PROTOCOL_DEBUG
- qDebug() << "Received" << pkt.size() << "bytes" << pkt.toHex();
-#endif
-
- // Check if it is an event
- if (handleEvent(pkt)) {
- return;
- }
-
- // Otherwise, if we have a request waiting, check if this answers it
- if (!pending_requests.isEmpty()) {
- if (handleResponse(pending_requests.head(), pkt)) {
- pending_requests.dequeue();
- // Proceed to next request
- if (!pending_requests.isEmpty()) {
- sendARequest();
- }
- return;
- }
- }
-
- qDebug() << "No idea what this packet ("
- << QString("0x%1").arg(uint(pkt.at(0)), 2, 16, QLatin1Char('0'))
- << ") is";
- }
-}
-
-void GatoAttClient::handleServerMTU(uint req, quint16 server_mtu)
-{
- Q_UNUSED(req);
- if (server_mtu) {
- cur_mtu = server_mtu;
- if (cur_mtu < ATT_DEFAULT_LE_MTU) {
- cur_mtu = ATT_DEFAULT_LE_MTU;
- }
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/bluetooth/gatoattclient.h b/src/bluetooth/gatoattclient.h
deleted file mode 100644
index 6a55b308..00000000
--- a/src/bluetooth/gatoattclient.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Javier de San Pedro <dev.git@javispedro.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef GATOATTCLIENT_H
-#define GATOATTCLIENT_H
-
-#include <QtCore/QObject>
-#include <QtCore/QQueue>
-#include "gatosocket.h"
-#include "gatouuid.h"
-
-QT_BEGIN_NAMESPACE
-
-class GatoAttClient : public QObject
-{
- Q_OBJECT
-
-public:
- explicit GatoAttClient(QObject *parent = 0);
- ~GatoAttClient();
-
- GatoSocket::State state() const;
-
- bool connectTo(const GatoAddress& addr);
- void close();
-
- struct InformationData
- {
- GatoHandle handle;
- GatoUUID uuid;
- };
- struct HandleInformation
- {
- GatoHandle start;
- GatoHandle end;
- };
- struct AttributeData
- {
- GatoHandle handle;
- QByteArray value;
- };
- struct AttributeGroupData
- {
- GatoHandle start;
- GatoHandle end;
- QByteArray value;
- };
-
- int mtu() const;
-
- uint request(int opcode, const QByteArray &data, QObject *receiver, const char *member);
- uint requestExchangeMTU(quint16 client_mtu, QObject *receiver, const char *member);
- uint requestFindInformation(GatoHandle start, GatoHandle end, QObject *receiver, const char *member);
- uint requestFindByTypeValue(GatoHandle start, GatoHandle end, const GatoUUID &uuid, const QByteArray& value, QObject *receiver, const char *member);
- uint requestReadByType(GatoHandle start, GatoHandle end, const GatoUUID &uuid, QObject *receiver, const char *member);
- uint requestRead(GatoHandle handle, QObject *receiver, const char *member);
- uint requestReadByGroupType(GatoHandle start, GatoHandle end, const GatoUUID &uuid, QObject *receiver, const char *member);
- uint requestWrite(GatoHandle handle, const QByteArray &value, QObject *receiver, const char *member);
- void cancelRequest(uint id);
-
- void command(int opcode, const QByteArray &data);
- void commandWrite(GatoHandle handle, const QByteArray &value);
-
-Q_SIGNALS:
- void connected();
- void disconnected();
-
- void attributeUpdated(GatoHandle handle, const QByteArray &value, bool confirmed);
-
-private:
- struct Request
- {
- uint id;
- quint8 opcode;
- QByteArray pkt;
- QObject *receiver;
- QByteArray member;
- };
-
- void sendARequest();
- bool handleEvent(const QByteArray &event);
- bool handleResponse(const Request& req, const QByteArray &response);
-
- QList<InformationData> parseInformationData(const QByteArray &data);
- QList<HandleInformation> parseHandleInformation(const QByteArray &data);
- QList<AttributeData> parseAttributeData(const QByteArray &data);
- QList<AttributeGroupData> parseAttributeGroupData(const QByteArray &data);
-
-private Q_SLOTS:
- void handleSocketConnected();
- void handleSocketDisconnected();
- void handleSocketReadyRead();
-
- void handleServerMTU(uint req, quint16 server_mtu);
-
-private:
- GatoSocket *socket;
- quint16 cur_mtu;
- uint next_id;
- QQueue<Request> pending_requests;
-};
-
-QT_END_NAMESPACE
-
-#endif // GATOATTCLIENT_H
diff --git a/src/bluetooth/gatoperipheral.cpp b/src/bluetooth/gatoperipheral.cpp
deleted file mode 100644
index b20efbe6..00000000
--- a/src/bluetooth/gatoperipheral.cpp
+++ /dev/null
@@ -1,866 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Javier de San Pedro <dev.git@javispedro.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/QDebug>
-
-#include <assert.h>
-#include <bluetooth/bluetooth.h>
-
-#include "gatoperipheral_p.h"
-#include "gatoaddress.h"
-#include "gatouuid.h"
-#include "helpers.h"
-
-QT_BEGIN_NAMESPACE
-
-enum EIRDataFields {
- EIRFlags = 0x01,
- EIRIncompleteUUID16List = 0x02,
- EIRCompleteUUID16List = 0x03,
- EIRIncompleteUUID32List = 0x04,
- EIRCompleteUUID32List = 0x05,
- EIRIncompleteUUID128List = 0x06,
- EIRCompleteUUID128List = 0x07,
- EIRIncompleteLocalName = 0x08,
- EIRCompleteLocalName = 0x09,
- EIRTxPowerLevel = 0x0A,
- EIRDeviceClass = 0x0D,
- EIRSecurityManagerTKValue = 0x10,
- EIRSecurityManagerOutOfBandFlags = 0x11,
- EIRSolicitedUUID128List = 0x15
-};
-
-GatoPeripheral::GatoPeripheral(const GatoAddress &addr, QObject *parent) :
- QObject(parent), d_ptr(new GatoPeripheralPrivate(this))
-{
- Q_D(GatoPeripheral);
- d->addr = addr;
- d->att = new GatoAttClient(this);
-
- connect(d->att, SIGNAL(connected()), d, SLOT(handleAttConnected()));
- connect(d->att, SIGNAL(disconnected()), d, SLOT(handleAttDisconnected()));
- connect(d->att, SIGNAL(attributeUpdated(GatoHandle,QByteArray,bool)), d, SLOT(handleAttAttributeUpdated(GatoHandle,QByteArray,bool)));
-}
-
-GatoPeripheral::~GatoPeripheral()
-{
- if (state() != StateDisconnected) {
- disconnect();
- }
- delete d_ptr;
-}
-
-GatoPeripheral::State GatoPeripheral::state() const
-{
- Q_D(const GatoPeripheral);
- return static_cast<State>(d->att->state());
-}
-
-GatoAddress GatoPeripheral::address() const
-{
- Q_D(const GatoPeripheral);
- return d->addr;
-}
-
-QString GatoPeripheral::name() const
-{
- Q_D(const GatoPeripheral);
- return d->name;
-}
-
-QList<GatoService> GatoPeripheral::services() const
-{
- Q_D(const GatoPeripheral);
- return d->services.values();
-}
-
-void GatoPeripheral::parseEIR(quint8 data[], int len)
-{
- Q_D(GatoPeripheral);
-
- int pos = 0;
- while (pos < len) {
- int item_len = data[pos];
- pos++;
- if (item_len == 0) break;
- int type = data[pos];
- assert(pos + item_len <= len);
- switch (type) {
- case EIRFlags:
- d->parseEIRFlags(&data[pos + 1], item_len - 1);
- break;
- case EIRIncompleteUUID16List:
- d->parseEIRUUIDs(16/8, false, &data[pos + 1], item_len - 1);
- break;
- case EIRCompleteUUID16List:
- d->parseEIRUUIDs(16/8, true, &data[pos + 1], item_len - 1);
- break;
- case EIRIncompleteUUID32List:
- d->parseEIRUUIDs(32/8, false, &data[pos + 1], item_len - 1);
- break;
- case EIRCompleteUUID32List:
- d->parseEIRUUIDs(32/8, true, &data[pos + 1], item_len - 1);
- break;
- case EIRIncompleteUUID128List:
- d->parseEIRUUIDs(128/8, false, &data[pos + 1], item_len - 1);
- break;
- case EIRCompleteUUID128List:
- d->parseEIRUUIDs(128/8, true, &data[pos + 1], item_len - 1);
- break;
- case EIRIncompleteLocalName:
- d->parseName(false, &data[pos + 1], item_len - 1);
- break;
- case EIRCompleteLocalName:
- d->parseName(true, &data[pos + 1], item_len - 1);
- break;
- case EIRTxPowerLevel:
- case EIRSolicitedUUID128List:
- qDebug() << "Unhandled EIR data type" << type;
- break;
- default:
- qWarning() << "Unknown EIR data type" << type;
- break;
- }
-
- pos += item_len;
- }
-
- assert(pos == len);
-}
-
-bool GatoPeripheral::advertisesService(const GatoUUID &uuid) const
-{
- Q_D(const GatoPeripheral);
- return d->service_uuids.contains(uuid);
-}
-
-void GatoPeripheral::connectPeripheral()
-{
- Q_D(GatoPeripheral);
- if (d->att->state() != GatoSocket::StateDisconnected) {
- qDebug() << "Already connecting";
- return;
- }
-
- d->att->connectTo(d->addr);
-}
-
-void GatoPeripheral::disconnectPeripheral()
-{
- Q_D(GatoPeripheral);
-
- d->att->close();
-}
-
-void GatoPeripheral::discoverServices()
-{
- Q_D(GatoPeripheral);
- if (!d->complete_services && state() == StateConnected) {
- d->clearServices();
- d->att->requestReadByGroupType(0x0001, 0xFFFF, GatoUUID::GattPrimaryService,
- d, SLOT(handlePrimary(QList<GatoAttClient::AttributeGroupData>)));
- } else {
- qWarning() << "Not connected";
- }
-}
-
-void GatoPeripheral::discoverServices(const QList<GatoUUID> &serviceUUIDs)
-{
- Q_D(GatoPeripheral);
- if (serviceUUIDs.isEmpty()) return;
- if (state() == StateConnected) {
- foreach (const GatoUUID& uuid, serviceUUIDs) {
- QByteArray value = gatouuid_to_bytearray(uuid, true, false);
- uint req = d->att->requestFindByTypeValue(0x0001, 0xFFFF, GatoUUID::GattPrimaryService, value,
- d, SLOT(handlePrimaryForService(uint,QList<GatoAttClient::HandleInformation>)));
- d->pending_primary_reqs.insert(req, uuid);
- }
- } else {
- qWarning() << "Not connected";
- }
-}
-
-void GatoPeripheral::discoverCharacteristics(const GatoService &service)
-{
- Q_D(GatoPeripheral);
-
- if (!d->services.contains(service.startHandle())) {
- qWarning() << "Unknown service for this peripheral";
- return;
- }
-
- GatoService &our_service = d->services[service.startHandle()];
-
- if (our_service.startHandle() != service.startHandle() ||
- our_service.endHandle() != service.endHandle() ||
- our_service.uuid() != service.uuid()) {
- qWarning() << "Unknown service for this peripheral";
- return;
- }
-
- if (state() == StateConnected) {
- GatoHandle start = our_service.startHandle();
- GatoHandle end = our_service.endHandle();
-
- d->clearServiceCharacteristics(&our_service);
-
- uint req = d->att->requestReadByType(start, end, GatoUUID::GattCharacteristic,
- d, SLOT(handleCharacteristic(QList<GatoAttClient::AttributeData>)));
- d->pending_characteristic_reqs.insert(req, start);
- } else {
- qWarning() << "Not connected";
- }
-}
-
-void GatoPeripheral::discoverCharacteristics(const GatoService &service, const QList<GatoUUID> &characteristicUUIDs)
-{
- // TODO There seems to be no way to ask for the peripheral to filter by uuid
- Q_UNUSED(characteristicUUIDs);
- discoverCharacteristics(service);
-}
-
-void GatoPeripheral::discoverDescriptors(const GatoCharacteristic &characteristic)
-{
- Q_D(GatoPeripheral);
-
- GatoHandle char_handle = characteristic.startHandle();
- GatoHandle service_handle = d->characteristic_to_service.value(char_handle);
-
- if (!service_handle) {
- qWarning() << "Unknown characteristic for this peripheral";
- return;
- }
-
- GatoService &our_service = d->services[service_handle];
- Q_ASSERT(our_service.containsCharacteristic(char_handle));
- GatoCharacteristic our_char = our_service.getCharacteristic(char_handle);
- Q_ASSERT(our_char.startHandle() == char_handle);
-
- if (state() == StateConnected) {
- d->clearCharacteristicDescriptors(&our_char);
- our_service.addCharacteristic(our_char); // Update service with empty descriptors list
- uint req = d->att->requestFindInformation(our_char.startHandle() + 1, our_char.endHandle(),
- d, SLOT(handleDescriptors(uint,QList<GatoAttClient::InformationData>)));
- d->pending_descriptor_reqs.insert(req, char_handle);
- } else {
- qWarning() << "Not connected";
- }
-}
-
-void GatoPeripheral::readValue(const GatoCharacteristic &characteristic)
-{
- Q_D(GatoPeripheral);
-
- GatoHandle char_handle = characteristic.startHandle();
- GatoHandle service_handle = d->characteristic_to_service.value(char_handle);
-
- if (!service_handle) {
- qWarning() << "Unknown characteristic for this peripheral";
- return;
- }
-
- GatoService &our_service = d->services[service_handle];
- Q_ASSERT(our_service.containsCharacteristic(char_handle));
-
- if (state() == StateConnected) {
- uint req = d->att->requestRead(characteristic.valueHandle(),
- d, SLOT(handleCharacteristicRead(uint,QByteArray)));
- d->pending_characteristic_read_reqs.insert(req, char_handle);
- } else {
- qWarning() << "Not connected";
- }
-}
-
-void GatoPeripheral::readValue(const GatoDescriptor &descriptor)
-{
- Q_D(GatoPeripheral);
-
- GatoHandle desc_handle = descriptor.handle();
- GatoHandle char_handle = d->descriptor_to_characteristic.value(desc_handle);
-
- if (!char_handle) {
- qWarning() << "Unknown descriptor for this peripheral";
- return;
- }
-
- GatoHandle service_handle = d->characteristic_to_service.value(char_handle);
- Q_ASSERT(service_handle);
-
- GatoService &our_service = d->services[service_handle];
- Q_ASSERT(our_service.containsCharacteristic(char_handle));
-
- if (state() == StateConnected) {
- uint req = d->att->requestRead(descriptor.handle(),
- d, SLOT(handleDescriptorRead(uint,QByteArray)));
- d->pending_descriptor_read_reqs.insert(req, char_handle);
- } else {
- qWarning() << "Not connected";
- }
-}
-
-void GatoPeripheral::writeValue(const GatoCharacteristic &characteristic, const QByteArray &data, WriteType type)
-{
- Q_D(GatoPeripheral);
-
- GatoHandle char_handle = characteristic.startHandle();
- GatoHandle service_handle = d->characteristic_to_service.value(char_handle);
-
- if (!service_handle) {
- qWarning() << "Unknown characteristic for this peripheral";
- return;
- }
-
- GatoService &our_service = d->services[service_handle];
- Q_ASSERT(our_service.containsCharacteristic(char_handle));
-
- if (state() == StateConnected) {
- switch (type) {
- case WriteWithResponse:
- d->att->requestWrite(characteristic.valueHandle(), data,
- d, SLOT(handleCharacteristicWrite(uint,bool)));
- break;
- case WriteWithoutResponse:
- d->att->commandWrite(characteristic.valueHandle(), data);
- break;
- }
-
-
- } else {
- qWarning() << "Not connected";
- }
-}
-
-void GatoPeripheral::writeValue(const GatoDescriptor &descriptor, const QByteArray &data)
-{
- Q_D(GatoPeripheral);
-
- GatoHandle desc_handle = descriptor.handle();
- GatoHandle char_handle = d->descriptor_to_characteristic.value(desc_handle);
-
- if (!char_handle) {
- qWarning() << "Unknown descriptor for this peripheral";
- return;
- }
-
- GatoHandle service_handle = d->characteristic_to_service.value(char_handle);
- Q_ASSERT(service_handle);
-
- GatoService &our_service = d->services[service_handle];
- Q_ASSERT(our_service.containsCharacteristic(char_handle));
-
- if (state() == StateConnected) {
- d->att->requestWrite(descriptor.handle(), data,
- d, SLOT(handleDescriptorWrite(uint,bool)));
- } else {
- qWarning() << "Not connected";
- }
-}
-
-void GatoPeripheral::setNotification(const GatoCharacteristic &characteristic, bool enabled)
-{
- Q_D(GatoPeripheral);
-
- GatoHandle char_handle = characteristic.startHandle();
- GatoHandle service_handle = d->characteristic_to_service.value(char_handle);
-
- if (!service_handle) {
- qWarning() << "Unknown characteristic for this peripheral";
- return;
- }
-
- GatoService &our_service = d->services[service_handle];
- Q_ASSERT(our_service.containsCharacteristic(char_handle));
- GatoCharacteristic our_char = our_service.getCharacteristic(char_handle);
-
- if (!(our_char.properties() & GatoCharacteristic::PropertyNotify)) {
- qWarning() << "Characteristic does not support notifications";
- return;
- }
-
- if (state() != StateConnected) {
- qWarning() << "Not connected";
- return;
- }
-
- const GatoUUID uuid(GatoUUID::GattClientCharacteristicConfiguration);
- if (our_char.containsDescriptor(uuid)) {
- GatoDescriptor desc = our_char.getDescriptor(uuid);
- d->pending_set_notify.remove(char_handle);
- writeValue(characteristic, d->genClientCharConfiguration(true, false));
- } else {
- d->pending_set_notify[char_handle] = enabled;
- discoverDescriptors(our_char); // May need to find appropiate descriptor
- }
-}
-
-GatoPeripheralPrivate::GatoPeripheralPrivate(GatoPeripheral *parent)
- : QObject(parent), q_ptr(parent),
- complete_name(false), complete_services(false)
-{
-}
-
-GatoPeripheralPrivate::~GatoPeripheralPrivate()
-{
- delete att;
-}
-
-void GatoPeripheralPrivate::parseEIRFlags(quint8 data[], int len)
-{
- Q_UNUSED(data);
- Q_UNUSED(len);
- // Nothing to do for now.
-}
-
-void GatoPeripheralPrivate::parseEIRUUIDs(int size, bool complete, quint8 data[], int len)
-{
- Q_UNUSED(complete);
-
- if (size != 16/8 && size != 32/8 && size != 128/8) {
- qWarning() << "Unhandled UUID size: " << size;
- return;
- }
-
- for (int pos = 0; pos < len; pos += size) {
- char *ptr = reinterpret_cast<char*>(&data[pos]);
- QByteArray ba = QByteArray::fromRawData(ptr, size/8);
-
- service_uuids.insert(bytearray_to_gatouuid(ba));
- }
-}
-
-void GatoPeripheralPrivate::parseName(bool complete, quint8 data[], int len)
-{
- Q_Q(GatoPeripheral);
- if (complete || !complete_name) {
- name = QString::fromUtf8(reinterpret_cast<char*>(data), len);
- complete_name = complete;
- emit q->nameChanged();
- }
-}
-
-GatoCharacteristic GatoPeripheralPrivate::parseCharacteristicValue(const QByteArray &ba)
-{
- GatoCharacteristic characteristic;
- const char *data = ba.constData();
-
- quint8 properties = data[0];
- characteristic.setProperties(GatoCharacteristic::Properties(properties));
-
- GatoHandle handle = read_le<quint16>(&data[1]);
- characteristic.setValueHandle(handle);
-
- GatoUUID uuid = bytearray_to_gatouuid(ba.mid(3));
- characteristic.setUuid(uuid);
-
- return characteristic;
-}
-
-QByteArray GatoPeripheralPrivate::genClientCharConfiguration(bool notification, bool indication)
-{
- QByteArray ba;
- ba.resize(sizeof(quint16));
-
- quint16 val = 0;
- if (notification)
- val |= 0x1;
- if (indication)
- val |= 0x2;
-
- write_le<quint16>(val, ba.data());
-
- return ba;
-}
-
-void GatoPeripheralPrivate::clearServices()
-{
- characteristic_to_service.clear();
- value_to_characteristic.clear();
- descriptor_to_characteristic.clear();
- services.clear();
-}
-
-void GatoPeripheralPrivate::clearServiceCharacteristics(GatoService *service)
-{
- QList<GatoCharacteristic> chars = service->characteristics();
- QList<GatoCharacteristic>::iterator it;
- for (it = chars.begin(); it != chars.end(); ++it) {
- clearCharacteristicDescriptors(&*it);
- characteristic_to_service.remove(it->startHandle());
- value_to_characteristic.remove(it->valueHandle());
- }
- service->clearCharacteristics();
-}
-
-void GatoPeripheralPrivate::clearCharacteristicDescriptors(GatoCharacteristic *characteristic)
-{
- QList<GatoDescriptor> descs = characteristic->descriptors();
- foreach (const GatoDescriptor& d, descs) {
- descriptor_to_characteristic.remove(d.handle());
- }
- characteristic->clearDescriptors();
-}
-
-void GatoPeripheralPrivate::finishSetNotifyOperations(const GatoCharacteristic &characteristic)
-{
- Q_Q(GatoPeripheral);
-
- GatoHandle handle = characteristic.startHandle();
-
- if (pending_set_notify.contains(handle)) {
- const GatoUUID uuid(GatoUUID::GattClientCharacteristicConfiguration);
- bool notify = pending_set_notify.value(handle);
-
- foreach (const GatoDescriptor &descriptor, characteristic.descriptors()) {
- if (descriptor.uuid() == uuid) {
- q->writeValue(descriptor, genClientCharConfiguration(notify, false));
- }
- }
-
- pending_set_notify.remove(handle);
- }
-}
-
-void GatoPeripheralPrivate::handleAttConnected()
-{
- Q_Q(GatoPeripheral);
-
- emit q->connected();
-}
-
-void GatoPeripheralPrivate::handleAttDisconnected()
-{
- Q_Q(GatoPeripheral);
-
- // Forget about all pending requests
- pending_primary_reqs.clear();
- pending_characteristic_reqs.clear();
- pending_characteristic_read_reqs.clear();
- pending_descriptor_reqs.clear();
- pending_descriptor_read_reqs.clear();
-
- emit q->disconnected();
-}
-
-void GatoPeripheralPrivate::handleAttAttributeUpdated(GatoHandle handle, const QByteArray &value, bool confirmed)
-{
- Q_Q(GatoPeripheral);
- Q_UNUSED(confirmed);
-
- // Let's see if this is a handle we know about.
- if (value_to_characteristic.contains(handle)) {
- // Ok, it's a characteristic value.
- GatoHandle char_handle = value_to_characteristic.value(handle);
- GatoHandle service_handle = characteristic_to_service.value(char_handle);
- if (!service_handle) {
- qWarning() << "Got a notification for a characteristic I don't know about";
- return;
- }
-
- GatoService &service = services[service_handle];
- GatoCharacteristic characteristic = service.getCharacteristic(char_handle);
-
- emit q->valueUpdated(characteristic, value);
- }
-}
-
-void GatoPeripheralPrivate::handlePrimary(uint req, const QList<GatoAttClient::AttributeGroupData> &list)
-{
- Q_Q(GatoPeripheral);
- Q_UNUSED(req);
-
- if (list.isEmpty()) {
- complete_services = true;
- emit q->servicesDiscovered();
- } else {
- GatoHandle last_handle = 0;
-
- foreach (const GatoAttClient::AttributeGroupData &data, list) {
- GatoUUID uuid = bytearray_to_gatouuid(data.value);
- GatoService service;
-
- service.setUuid(uuid);
- service.setStartHandle(data.start);
- service.setEndHandle(data.end);
-
- services.insert(data.start, service);
- service_uuids.insert(uuid);
-
- last_handle = data.end;
- }
-
- // Fetch following attributes
- att->requestReadByGroupType(last_handle + 1, 0xFFFF, GatoUUID::GattPrimaryService,
- this, SLOT(handlePrimary(uint,QList<GatoAttClient::AttributeGroupData>)));
- }
-}
-
-void GatoPeripheralPrivate::handlePrimaryForService(uint req, const QList<GatoAttClient::HandleInformation> &list)
-{
- Q_Q(GatoPeripheral);
-
- GatoUUID uuid = pending_primary_reqs.value(req, GatoUUID());
- if (uuid.isNull()) {
- qDebug() << "Got primary for service response for a request I did not make";
- return;
- }
- pending_primary_reqs.remove(req);
-
- if (list.isEmpty()) {
- if (pending_primary_reqs.isEmpty()) {
- emit q->servicesDiscovered();
- }
- } else {
- GatoHandle last_handle = 0;
-
- foreach (const GatoAttClient::HandleInformation &data, list) {
- GatoService service;
-
- service.setUuid(uuid);
- service.setStartHandle(data.start);
- service.setEndHandle(data.end);
-
- services.insert(data.start, service);
- service_uuids.insert(uuid);
-
- last_handle = data.end;
- }
-
- // Fetch following attributes
- QByteArray value = gatouuid_to_bytearray(uuid, true, false);
- uint req = att->requestFindByTypeValue(last_handle + 1, 0xFFFF, GatoUUID::GattPrimaryService, value,
- this, SLOT(handlePrimaryForService(uint,QList<GatoAttClient::HandleInformation>)));
- pending_primary_reqs.insert(req, uuid);
- }
-}
-
-void GatoPeripheralPrivate::handleCharacteristic(uint req, const QList<GatoAttClient::AttributeData> &list)
-{
- Q_Q(GatoPeripheral);
-
- GatoHandle service_start = pending_characteristic_reqs.value(req, 0);
- if (!service_start) {
- qDebug() << "Got characteristics for a request I did not make";
- return;
- }
- pending_characteristic_reqs.remove(req);
-
- Q_ASSERT(services.contains(service_start));
- GatoService &service = services[service_start];
- Q_ASSERT(service.startHandle() == service_start);
-
- if (list.isEmpty()) {
- emit q->characteristicsDiscovered(service);
- } else {
- GatoHandle last_handle = 0;
-
- // If we are continuing a characteristic list, this means the
- // last service we discovered in the previous iteration was not
- // the last one, so we have to reduce its endHandle!
- QList<GatoCharacteristic> cur_chars = service.characteristics();
- if (!cur_chars.isEmpty()) {
- GatoCharacteristic &last = cur_chars.back();
- last.setEndHandle(list.front().handle - 1);
- service.addCharacteristic(last);
- }
-
- for (int i = 0; i < list.size(); i++) {
- const GatoAttClient::AttributeData &data = list.at(i);
- GatoCharacteristic characteristic = parseCharacteristicValue(data.value);
-
- characteristic.setStartHandle(data.handle);
- if (i + 1 < list.size()) {
- characteristic.setEndHandle(list.at(i + 1).handle - 1);
- } else {
- characteristic.setEndHandle(service.endHandle());
- }
-
- service.addCharacteristic(characteristic);
- characteristic_to_service.insert(data.handle, service_start);
- value_to_characteristic.insert(characteristic.valueHandle(), data.handle);
-
- last_handle = data.handle;
- }
-
- if (last_handle >= service.endHandle()) {
- // Already finished, no need to send another request
- emit q->characteristicsDiscovered(service);
- return;
- }
-
- // Fetch following attributes
- uint req = att->requestReadByType(last_handle + 1, service.endHandle(), GatoUUID::GattCharacteristic,
- this, SLOT(handleCharacteristic(uint,QList<GatoAttClient::AttributeData>)));
- pending_characteristic_reqs.insert(req, service.startHandle());
- }
-}
-
-void GatoPeripheralPrivate::handleDescriptors(uint req, const QList<GatoAttClient::InformationData> &list)
-{
- Q_Q(GatoPeripheral);
-
- GatoHandle char_handle = pending_descriptor_reqs.value(req);
- if (!char_handle) {
- qDebug() << "Got descriptor for a request I did not make";
- return;
- }
- pending_descriptor_reqs.remove(req);
- GatoHandle service_handle = characteristic_to_service.value(char_handle);
- if (!service_handle) {
- qWarning() << "Unknown characteristic during descriptor discovery: " << char_handle;
- return;
- }
-
- Q_ASSERT(services.contains(service_handle));
- GatoService &service = services[service_handle];
- Q_ASSERT(service.startHandle() == service_handle);
-
- Q_ASSERT(service.containsCharacteristic(char_handle));
- GatoCharacteristic characteristic = service.getCharacteristic(char_handle);
-
- if (list.isEmpty()) {
- finishSetNotifyOperations(characteristic);
- emit q->descriptorsDiscovered(characteristic);
- } else {
- GatoHandle last_handle = 0;
-
- foreach (const GatoAttClient::InformationData &data, list) {
- // Skip the value attribute itself.
- if (data.handle == characteristic.valueHandle()) continue;
-
- GatoDescriptor descriptor;
-
- descriptor.setHandle(data.handle);
- descriptor.setUuid(data.uuid);
-
- characteristic.addDescriptor(descriptor);
-
- service.addCharacteristic(characteristic);
- descriptor_to_characteristic.insert(data.handle, char_handle);
-
- last_handle = data.handle;
- }
-
- service.addCharacteristic(characteristic);
-
- if (last_handle >= characteristic.endHandle()) {
- // Already finished, no need to send another request
- finishSetNotifyOperations(characteristic);
- emit q->descriptorsDiscovered(characteristic);
- return;
- }
-
- // Fetch following attributes
- uint req = att->requestFindInformation(last_handle + 1, characteristic.endHandle(),
- this, SLOT(handleDescriptors(uint,QList<GatoAttClient::InformationData>)));
- pending_descriptor_reqs.insert(req, char_handle);
-
- }
-}
-
-void GatoPeripheralPrivate::handleCharacteristicRead(uint req, const QByteArray &value)
-{
- Q_Q(GatoPeripheral);
-
- GatoHandle char_handle = pending_characteristic_read_reqs.value(req);
- if (!char_handle) {
- qDebug() << "Got characteristics for a request I did not make";
- return;
- }
- pending_characteristic_read_reqs.remove(req);
- GatoHandle service_handle = characteristic_to_service.value(char_handle);
- if (!service_handle) {
- qWarning() << "Unknown characteristic during read: " << char_handle;
- return;
- }
-
- Q_ASSERT(services.contains(service_handle));
- GatoService &service = services[service_handle];
- Q_ASSERT(service.startHandle() == service_handle);
-
- Q_ASSERT(service.containsCharacteristic(char_handle));
- GatoCharacteristic characteristic = service.getCharacteristic(char_handle);
-
- emit q->valueUpdated(characteristic, value);
-}
-
-void GatoPeripheralPrivate::handleDescriptorRead(uint req, const QByteArray &value)
-{
- Q_Q(GatoPeripheral);
-
- GatoHandle desc_handle = pending_descriptor_read_reqs.value(req);
- if (!desc_handle) {
- qDebug() << "Got characteristics for a request I did not make";
- return;
- }
- pending_descriptor_read_reqs.remove(req);
- GatoHandle char_handle = descriptor_to_characteristic.value(desc_handle);
- if (!char_handle) {
- qWarning() << "Unknown characteristic during read: " << char_handle;
- return;
- }
- GatoHandle service_handle = characteristic_to_service.value(char_handle);
- if (!service_handle) {
- qWarning() << "Unknown characteristic during read: " << char_handle;
- return;
- }
-
- Q_ASSERT(services.contains(service_handle));
- GatoService &service = services[service_handle];
- Q_ASSERT(service.startHandle() == service_handle);
-
- Q_ASSERT(service.containsCharacteristic(char_handle));
- GatoCharacteristic characteristic = service.getCharacteristic(char_handle);
-
- Q_ASSERT(characteristic.containsDescriptor(desc_handle));
- GatoDescriptor descriptor = characteristic.getDescriptor(desc_handle);
-
- emit q->descriptorValueUpdated(descriptor, value);
-}
-
-void GatoPeripheralPrivate::handleCharacteristicWrite(uint req, bool ok)
-{
- Q_UNUSED(req);
- if (!ok) {
- qWarning() << "Failed to write some characteristic";
- }
-}
-
-void GatoPeripheralPrivate::handleDescriptorWrite(uint req, bool ok)
-{
- Q_UNUSED(req);
- if (!ok) {
- qWarning() << "Failed to write some characteristic";
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/bluetooth/gatoperipheral.h b/src/bluetooth/gatoperipheral.h
deleted file mode 100644
index a8850678..00000000
--- a/src/bluetooth/gatoperipheral.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Javier de San Pedro <dev.git@javispedro.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef GATOPERIPHERAL_H
-#define GATOPERIPHERAL_H
-
-#include <QtCore/QObject>
-#include "libgato_global.h"
-#include "gatouuid.h"
-#include "gatoaddress.h"
-
-QT_BEGIN_NAMESPACE
-
-class GatoService;
-class GatoCharacteristic;
-class GatoDescriptor;
-class GatoPeripheralPrivate;
-
-class LIBGATO_EXPORT GatoPeripheral : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(GatoPeripheral)
- Q_ENUMS(State)
- Q_ENUMS(WriteType)
- Q_PROPERTY(GatoAddress address READ address)
- Q_PROPERTY(QString name READ name NOTIFY nameChanged)
-
-public:
- GatoPeripheral(const GatoAddress& addr, QObject *parent = 0);
- ~GatoPeripheral();
-
- enum State {
- StateDisconnected,
- StateConnecting,
- StateConnected
- };
-
- enum WriteType {
- WriteWithResponse = 0,
- WriteWithoutResponse
- };
-
- State state() const;
- GatoAddress address() const;
- QString name() const;
- QList<GatoService> services() const;
-
- void parseEIR(quint8 data[], int len);
- bool advertisesService(const GatoUUID &uuid) const;
-
-public Q_SLOTS:
- void connectPeripheral();
- void disconnectPeripheral();
- void discoverServices();
- void discoverServices(const QList<GatoUUID>& serviceUUIDs);
- void discoverCharacteristics(const GatoService &service);
- void discoverCharacteristics(const GatoService &service, const QList<GatoUUID>& characteristicUUIDs);
- void discoverDescriptors(const GatoCharacteristic &characteristic);
- void readValue(const GatoCharacteristic &characteristic);
- void readValue(const GatoDescriptor &descriptor);
- void writeValue(const GatoCharacteristic &characteristic, const QByteArray &data, WriteType type = WriteWithResponse);
- void writeValue(const GatoDescriptor &descriptor, const QByteArray &data);
- void setNotification(const GatoCharacteristic &characteristic, bool enabled);
-
-Q_SIGNALS:
- void connected();
- void disconnected();
- void nameChanged();
- void servicesDiscovered();
- void characteristicsDiscovered(const GatoService &service);
- void descriptorsDiscovered(const GatoCharacteristic &characteristic);
- void valueUpdated(const GatoCharacteristic &characteristic, const QByteArray &value);
- void descriptorValueUpdated(const GatoDescriptor &descriptor, const QByteArray &value);
-
-private:
- GatoPeripheralPrivate *const d_ptr;
-};
-
-QT_END_NAMESPACE
-
-#endif // GATOPERIPHERAL_H
diff --git a/src/bluetooth/gatoperipheral_p.h b/src/bluetooth/gatoperipheral_p.h
deleted file mode 100644
index 663d7541..00000000
--- a/src/bluetooth/gatoperipheral_p.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Javier de San Pedro <dev.git@javispedro.com>
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef GATOPERIPHERAL_P_H
-#define GATOPERIPHERAL_P_H
-
-#include "gatoperipheral.h"
-#include "gatoservice.h"
-#include "gatocharacteristic.h"
-#include "gatodescriptor.h"
-#include "gatoattclient.h"
-
-QT_BEGIN_NAMESPACE
-
-class GatoPeripheralPrivate : public QObject
-{
- Q_OBJECT
-
- Q_DECLARE_PUBLIC(GatoPeripheral)
-
-public:
- GatoPeripheralPrivate(GatoPeripheral *parent);
- ~GatoPeripheralPrivate();
-
- GatoPeripheral *q_ptr;
- GatoAddress addr;
- QString name;
- QSet<GatoUUID> service_uuids;
- QMap<GatoHandle, GatoService> services;
-
- bool complete_name : 1;
- bool complete_services : 1;
-
- /** Maps attribute handles to service handles. */
- QMap<GatoHandle, GatoHandle> characteristic_to_service;
- QMap<GatoHandle, GatoHandle> value_to_characteristic;
- QMap<GatoHandle, GatoHandle> descriptor_to_characteristic;
-
- GatoAttClient *att;
- QMap<uint, GatoUUID> pending_primary_reqs;
- QMap<uint, GatoHandle> pending_characteristic_reqs;
- QMap<uint, GatoHandle> pending_characteristic_read_reqs;
- QMap<uint, GatoHandle> pending_descriptor_reqs;
- QMap<uint, GatoHandle> pending_descriptor_read_reqs;
-
- QMap<GatoHandle, bool> pending_set_notify;
-
- void parseEIRFlags(quint8 data[], int len);
- void parseEIRUUIDs(int size, bool complete, quint8 data[], int len);
- void parseName(bool complete, quint8 data[], int len);
-
- static GatoCharacteristic parseCharacteristicValue(const QByteArray &ba);
-
- static QByteArray genClientCharConfiguration(bool notification, bool indication);
-
- void clearServices();
- void clearServiceCharacteristics(GatoService *service);
- void clearCharacteristicDescriptors(GatoCharacteristic *characteristic);
-
- void finishSetNotifyOperations(const GatoCharacteristic &characteristic);
-
-public slots:
- void handleAttConnected();
- void handleAttDisconnected();
- void handleAttAttributeUpdated(GatoHandle handle, const QByteArray &value, bool confirmed);
- void handlePrimary(uint req, const QList<GatoAttClient::AttributeGroupData>& list);
- void handlePrimaryForService(uint req, const QList<GatoAttClient::HandleInformation>& list);
- void handleCharacteristic(uint req, const QList<GatoAttClient::AttributeData> &list);
- void handleDescriptors(uint req, const QList<GatoAttClient::InformationData> &list);
- void handleCharacteristicRead(uint req, const QByteArray &value);
- void handleDescriptorRead(uint req, const QByteArray &value);
- void handleCharacteristicWrite(uint req, bool ok);
- void handleDescriptorWrite(uint req, bool ok);
-};
-
-QT_END_NAMESPACE
-
-#endif // GATOPERIPHERAL_P_H
diff --git a/sync.profile b/sync.profile
index 0ceddf44..1204b458 100644
--- a/sync.profile
+++ b/sync.profile
@@ -17,6 +17,3 @@
"qtxmlpatterns" => "",
"qtandroidextras" => "",
);
-
-my @gato_headers = ("gatoattclient.h", "gatoperipheral.h");
-@ignore_for_master_contents = ( @gato_headers );