From 2034b1bb10720a2f0e6cc97427346f2320c115bc Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Fri, 23 Nov 2018 09:40:48 +0100 Subject: o Starting to handle notifications and indications Cleaning up: o Using more of the shared_ptr typedefs. o Adding code styles used by CLion. --- ble/BluetoothImpl.h | 40 +++++++++++++++++----------------------- ble/LinuxBluetooth.cpp | 48 +++++++++++++++++++++++++++++++++++------------- ble/att.cpp | 15 ++++++++++++++- 3 files changed, 66 insertions(+), 37 deletions(-) (limited to 'ble') diff --git a/ble/BluetoothImpl.h b/ble/BluetoothImpl.h index 5b53cd4..c41712c 100644 --- a/ble/BluetoothImpl.h +++ b/ble/BluetoothImpl.h @@ -110,7 +110,7 @@ public: return valueHandle; } - shared_ptr getDescriptor(Uuid uuid) const override { + BluetoothGattDescriptorPtr getDescriptor(Uuid uuid) const override { for (auto &d: descriptors) { if (d->getUuid() == uuid) { return d; @@ -120,7 +120,7 @@ public: return {}; } - void addDescriptor(shared_ptr &&d) { + void addDescriptor(BluetoothGattDescriptorPtr &&d) { descriptors.push_back(std::move(d)); } @@ -166,17 +166,17 @@ public: return endGroupHandle; } - vector> getCharacteristics() const override { - vector> cs(characteristics.size()); + vector getCharacteristics() const override { + vector cs(characteristics.size()); std::copy(begin(characteristics), end(characteristics), begin(cs)); return cs; } - virtual void addCharacteristic(shared_ptr &&characteristic) { + virtual void addCharacteristic(BluetoothGattCharacteristicPtr &&characteristic) { characteristics.emplace_back(characteristic); } - o> findCharacteristic(Uuid uuid) override { + o findCharacteristic(Uuid uuid) override { for (auto &c: characteristics) { if (c->getUuid() == uuid) { return {c}; @@ -191,7 +191,7 @@ protected: const Uuid uuid; const uint16_t handle; const uint16_t endGroupHandle; - vector> characteristics; + vector characteristics; }; template @@ -201,12 +201,8 @@ public: return device; } -// virtual Collection getServices() const { -// return CollectionImpl>(services); -// } - - vector> getServices() const override { - vector> ss(services.size()); + vector getServices() const override { + vector ss(services.size()); std::copy(begin(services), end(services), begin(ss)); return ss; } @@ -214,32 +210,30 @@ public: o findService(Uuid uuid) override { for (auto &s: services) { if (s->getUuid() == uuid) { - return o>(s); + return o(s); } } - return o>(); + return {}; } - void addService(shared_ptr<_S> service) { + void addService(std::shared_ptr<_S> service) { services.emplace_back(service); } protected: - explicit DefaultBluetoothGatt(_D &device) : LogSetup("BluetoothGatt"), device(device) { - } + explicit DefaultBluetoothGatt(_D &device, BluetoothCallback *callback) : + LogSetup("BluetoothGatt"), device(device), callback(callback) {} ~DefaultBluetoothGatt() override = default; void removeServices() { -// for (auto s: services) { -// delete s; -// } services.clear(); } _D &device; - vector> services; + vector > services; + BluetoothCallback *callback; }; template @@ -293,7 +287,7 @@ protected: Mac &mac; }; -shared_ptr getAdapterImpl(string name); +BluetoothAdapterPtr getAdapterImpl(string name); template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; diff --git a/ble/LinuxBluetooth.cpp b/ble/LinuxBluetooth.cpp index 99762cb..9e7193f 100644 --- a/ble/LinuxBluetooth.cpp +++ b/ble/LinuxBluetooth.cpp @@ -84,7 +84,7 @@ public: LinuxBluetoothDevice &operator=(const LinuxBluetoothDevice &) = delete; - shared_ptr connectGatt() override; + shared_ptr connectGatt(BluetoothCallback* callback) override; private: LinuxBluetoothGatt *gatt; @@ -92,7 +92,7 @@ private: class LinuxBluetoothGatt final : public DefaultBluetoothGatt { public: - explicit LinuxBluetoothGatt(LinuxBluetoothDevice &device); + explicit LinuxBluetoothGatt(LinuxBluetoothDevice &device, BluetoothCallback *callback); ~LinuxBluetoothGatt() override; @@ -104,9 +104,11 @@ public: void discoverServices() override; - void writeValue(const BluetoothGattCharacteristicPtr &c, const ByteBuffer &bytes) override; + void process(std::chrono::system_clock::duration max_duration) override; - void write(const BluetoothGattDescriptorPtr &c) override; + void writeValue(const BluetoothGattCharacteristicPtr &characteristic, const ByteBuffer &bytes) override; + + void write(const BluetoothGattDescriptorPtr &descriptor) override; ByteBuffer readValue(const BluetoothGattCharacteristicPtr &c, ByteBuffer &response) override; @@ -132,6 +134,9 @@ private: template AttVariant exchangeAndWaitFor(ByteBuffer &buffer, std::chrono::time_point time); + template + AttVariant waitFor(ByteBuffer &buffer, std::chrono::time_point time); + template T exchangeAndWaitFor(ByteBuffer &buffer, std::chrono::time_point time, bool fail_on_error); @@ -174,11 +179,11 @@ LinuxBluetoothDevice::~LinuxBluetoothDevice() { delete gatt; }; -shared_ptr LinuxBluetoothDevice::connectGatt() { +shared_ptr LinuxBluetoothDevice::connectGatt(BluetoothCallback* callback) { // Make sure that we close the old connection and create a new one when the user asks for it. delete gatt; - gatt = new LinuxBluetoothGatt(*this); + gatt = new LinuxBluetoothGatt(*this, callback); return shared_ptr(shared_from_this(), gatt); } @@ -187,8 +192,8 @@ shared_ptr LinuxBluetoothDevice::connectGatt() { // Gatt // ----------------------------------------------------------------------- -LinuxBluetoothGatt::LinuxBluetoothGatt(LinuxBluetoothDevice &device) : - DefaultBluetoothGatt(device), l2cap() { +LinuxBluetoothGatt::LinuxBluetoothGatt(LinuxBluetoothDevice &device, BluetoothCallback *callback) : + DefaultBluetoothGatt(device, callback), l2cap() { connect(); } @@ -436,7 +441,7 @@ void LinuxBluetoothGatt::writeAndRead(const ByteBuffer &buffer, ByteBuffer &resp // LOG_DEBUG("written=" << written); - ssize_t r = read(l2cap, response.underlying(), response.getSize()); + ssize_t r = ::read(l2cap, response.underlying(), response.getSize()); if (r == -1) { throw BluetoothException(&device, "read(): " + errnoAsString()); @@ -465,7 +470,7 @@ AttVariant LinuxBluetoothGatt::processAvailableMessages(ByteBuffer &buffer) { // ", bytes available: " << to_string(bytes_available)); while (!ret && bytes_available) { - ssize_t r = read(l2cap, buffer.underlying(), buffer.getBytesLeft()); + ssize_t r = ::read(l2cap, buffer.underlying(), buffer.getBytesLeft()); if (r == -1) { throw BluetoothException(&device, "read(): " + errnoAsString()); } @@ -484,6 +489,9 @@ AttVariant LinuxBluetoothGatt::processAvailableMessages(ByteBuffer &buffer) { AttPdu::makeExchangeMtuRes(buffer, mtu); writeL2cap(buffer); + } else if (holds_alternative(v)) { + auto value = get(v); + LOG_DEBUG("got notification: " + to_string(value.data.getSize()) + ", pos=" + to_string(value.data.getSize())); } else { return v; } @@ -544,6 +552,11 @@ AttVariant LinuxBluetoothGatt::exchangeAndWaitFor(ByteBuffer &buffer, std::chron LOG_DEBUG("Writing message " << to_string(static_cast(buffer.get8(0)))); this->writeL2cap(buffer); + return waitFor(buffer, time); +} + +template +AttVariant LinuxBluetoothGatt::waitFor(ByteBuffer &buffer, std::chrono::time_point time) { fd_set rfds; struct timeval tv{}; @@ -638,6 +651,15 @@ void LinuxBluetoothGatt::discoverDescriptors(shared_ptr AttPdu::parseAttributeData(ByteBuffer &bytes) { } AttVariant AttPdu::parse(ByteBuffer &bytes) { - switch (static_cast(bytes.read8())) { + auto type = static_cast(bytes.read8()); + switch (type) { case AttPduType::ERROR: return ErrorRes::parse(bytes); case AttPduType::EXCHANGE_MTU_REQ: @@ -166,6 +167,10 @@ AttVariant AttPdu::parse(ByteBuffer &bytes) { return ReadByGroupTypeRes{parseAttributeData(bytes)}; case AttPduType::READ_BY_TYPE_RES: return ReadByTypeRes{parseAttributeData(bytes)}; + case AttPduType::HANDLE_VALUE_NOTIFICATION: + return parseHandleValueNotification(bytes); + case AttPduType::HANDLE_VALUE_INDICATION: + return parseHandleValueIndication(bytes); default: return {}; } @@ -196,6 +201,14 @@ FindInformationRes AttPdu::parseFindInformationRes(ByteBuffer &bytes) { return {format, information}; } +HandleValueNotification AttPdu::parseHandleValueNotification(ByteBuffer &bytes) { + return {bytes.read16le(), bytes.viewCursorToEnd()}; +} + +HandleValueIndication AttPdu::parseHandleValueIndication(ByteBuffer &bytes) { + return {bytes.read16le(), bytes.viewCursorToEnd()}; +} + void AttPdu::parseRead(ByteBuffer &bytes) { auto t = static_cast(bytes.read8()); -- cgit v1.2.3