diff options
Diffstat (limited to 'ble')
-rw-r--r-- | ble/BluetoothImpl.h | 40 | ||||
-rw-r--r-- | ble/LinuxBluetooth.cpp | 48 | ||||
-rw-r--r-- | ble/att.cpp | 15 |
3 files changed, 66 insertions, 37 deletions
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<BluetoothGattDescriptor> 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<BluetoothGattDescriptor> &&d) { + void addDescriptor(BluetoothGattDescriptorPtr &&d) { descriptors.push_back(std::move(d)); } @@ -166,17 +166,17 @@ public: return endGroupHandle; } - vector<shared_ptr<BluetoothGattCharacteristic>> getCharacteristics() const override { - vector<shared_ptr<BluetoothGattCharacteristic>> cs(characteristics.size()); + vector<BluetoothGattCharacteristicPtr> getCharacteristics() const override { + vector<BluetoothGattCharacteristicPtr> cs(characteristics.size()); std::copy(begin(characteristics), end(characteristics), begin(cs)); return cs; } - virtual void addCharacteristic(shared_ptr<BluetoothGattCharacteristic> &&characteristic) { + virtual void addCharacteristic(BluetoothGattCharacteristicPtr &&characteristic) { characteristics.emplace_back(characteristic); } - o<shared_ptr<BluetoothGattCharacteristic>> findCharacteristic(Uuid uuid) override { + o<BluetoothGattCharacteristicPtr> 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<shared_ptr<BluetoothGattCharacteristic>> characteristics; + vector<BluetoothGattCharacteristicPtr> characteristics; }; template<class _D, class _S> @@ -201,12 +201,8 @@ public: return device; } -// virtual Collection <BluetoothGattService> getServices() const { -// return CollectionImpl<BluetoothGattService, vector<_S>>(services); -// } - - vector<shared_ptr<BluetoothGattService>> getServices() const override { - vector<shared_ptr<BluetoothGattService>> ss(services.size()); + vector <BluetoothGattServicePtr> getServices() const override { + vector<BluetoothGattServicePtr> ss(services.size()); std::copy(begin(services), end(services), begin(ss)); return ss; } @@ -214,32 +210,30 @@ public: o <BluetoothGattServicePtr> findService(Uuid uuid) override { for (auto &s: services) { if (s->getUuid() == uuid) { - return o<shared_ptr<BluetoothGattService>>(s); + return o<BluetoothGattServicePtr>(s); } } - return o<shared_ptr<BluetoothGattService>>(); + 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<shared_ptr<_S>> services; + vector <std::shared_ptr<_S>> services; + BluetoothCallback *callback; }; template<class A> @@ -293,7 +287,7 @@ protected: Mac &mac; }; -shared_ptr <BluetoothAdapter> getAdapterImpl(string name); +BluetoothAdapterPtr getAdapterImpl(string name); template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; 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<BluetoothGatt> connectGatt() override; + shared_ptr<BluetoothGatt> connectGatt(BluetoothCallback* callback) override; private: LinuxBluetoothGatt *gatt; @@ -92,7 +92,7 @@ private: class LinuxBluetoothGatt final : public DefaultBluetoothGatt<LinuxBluetoothDevice, LinuxBluetoothGattService> { 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<typename clock = std::chrono::system_clock> AttVariant exchangeAndWaitFor(ByteBuffer &buffer, std::chrono::time_point<clock> time); + template<typename clock = std::chrono::system_clock> + AttVariant waitFor(ByteBuffer &buffer, std::chrono::time_point<clock> time); + template<typename T, typename clock = std::chrono::system_clock> T exchangeAndWaitFor(ByteBuffer &buffer, std::chrono::time_point<clock> time, bool fail_on_error); @@ -174,11 +179,11 @@ LinuxBluetoothDevice::~LinuxBluetoothDevice() { delete gatt; }; -shared_ptr<BluetoothGatt> LinuxBluetoothDevice::connectGatt() { +shared_ptr<BluetoothGatt> 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<LinuxBluetoothGatt>(shared_from_this(), gatt); } @@ -187,8 +192,8 @@ shared_ptr<BluetoothGatt> 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<HandleValueNotification>(v)) { + auto value = get<HandleValueNotification>(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<AttPduType>(buffer.get8(0)))); this->writeL2cap(buffer); + return waitFor(buffer, time); +} + +template<typename clock> +AttVariant LinuxBluetoothGatt::waitFor(ByteBuffer &buffer, std::chrono::time_point<clock> time) { fd_set rfds; struct timeval tv{}; @@ -638,6 +651,15 @@ void LinuxBluetoothGatt::discoverDescriptors(shared_ptr<DefaultBluetoothGattChar } } +void LinuxBluetoothGatt::process(std::chrono::system_clock::duration max_duration) { + uint8_t b[mtu]; + ByteBuffer buffer{b, mtu}; + + processAvailableMessages(buffer); + + auto variant = waitFor(buffer, std::chrono::system_clock::now() + max_duration); +} + // ----------------------------------------------------------------------- // Adapter // ----------------------------------------------------------------------- @@ -791,9 +813,9 @@ void LinuxBluetoothAdapter::runScan(std::function<void(const shared_ptr<Bluetoot stopScan(); } -} -} -} +} // namespace linux +} // namespace bluetooth +} // namespace trygvis // ----------------------------------------------------------------------- // Implementation of platform-specific method. diff --git a/ble/att.cpp b/ble/att.cpp index 301918d..4d3529a 100644 --- a/ble/att.cpp +++ b/ble/att.cpp @@ -153,7 +153,8 @@ vector<AttributeData> AttPdu::parseAttributeData(ByteBuffer &bytes) { } AttVariant AttPdu::parse(ByteBuffer &bytes) { - switch (static_cast<AttPduType>(bytes.read8())) { + auto type = static_cast<AttPduType>(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<AttPduType>(bytes.read8()); |