summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/gatoperipheral.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/gatoperipheral.cpp')
-rw-r--r--src/bluetooth/gatoperipheral.cpp874
1 files changed, 0 insertions, 874 deletions
diff --git a/src/bluetooth/gatoperipheral.cpp b/src/bluetooth/gatoperipheral.cpp
deleted file mode 100644
index b44efc26..00000000
--- a/src/bluetooth/gatoperipheral.cpp
+++ /dev/null
@@ -1,874 +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:LGPL$
-** 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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $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