aboutsummaryrefslogtreecommitdiff
path: root/include/ble
diff options
context:
space:
mode:
Diffstat (limited to 'include/ble')
-rw-r--r--include/ble/Bluetooth.h252
-rw-r--r--include/ble/ByteBuffer.h97
2 files changed, 349 insertions, 0 deletions
diff --git a/include/ble/Bluetooth.h b/include/ble/Bluetooth.h
new file mode 100644
index 0000000..1a1394e
--- /dev/null
+++ b/include/ble/Bluetooth.h
@@ -0,0 +1,252 @@
+#ifndef BLUETOOTH_H
+#define BLUETOOTH_H
+
+#include <string>
+#include <stdexcept>
+#include <boost/uuid/uuid.hpp>
+#include <boost/optional.hpp>
+
+#include "ByteBuffer.h"
+
+namespace trygvis {
+namespace bluetooth {
+
+using namespace std;
+
+struct SpecUuid {
+public:
+ SpecUuid(uint16_t value) : value(value) {
+ }
+
+ uint16_t value;
+};
+
+namespace uuids {
+const SpecUuid PRIMARY_SERVICE = SpecUuid(0x2800);
+const SpecUuid SECONDARY_SERVICE = SpecUuid(0x2801);
+const SpecUuid CHARACTERISTIC = SpecUuid(0x2803);
+}
+
+class BluetoothAdapter;
+
+class BluetoothDevice;
+
+class BluetoothGattService;
+
+class BluetoothGattCharacteristic;
+
+class BluetoothException : public runtime_error {
+public:
+ BluetoothException(const BluetoothAdapter *adapter, string const &what) :
+ runtime_error(what), adapter(adapter), device(nullptr) {
+ }
+
+ BluetoothException(const BluetoothDevice *device, string const &what) :
+ runtime_error(what), adapter(nullptr), device(device) {
+ }
+
+ BluetoothException(string const &what) :
+ runtime_error(what), adapter(nullptr), device(nullptr) {
+ }
+
+ const BluetoothAdapter *adapter;
+ const BluetoothDevice *device;
+};
+
+class Mac {
+public:
+ Mac(uint8_t _0, uint8_t _1, uint8_t _2, uint8_t _3, uint8_t _4, uint8_t _5) {
+ bytes[0] = _0;
+ bytes[1] = _1;
+ bytes[2] = _2;
+ bytes[3] = _3;
+ bytes[4] = _4;
+ bytes[5] = _5;
+ };
+
+ string str() const;
+
+ bool operator==(Mac &other) const;
+
+ bool operator!=(Mac &other) const;
+
+ void copy(uint8_t &_0, uint8_t &_1, uint8_t &_2, uint8_t &_3, uint8_t &_4, uint8_t &_5) const;
+
+ static Mac parseMac(string s);
+
+ friend bool operator<(const Mac &a, const Mac &b);
+
+private:
+ uint8_t bytes[6];
+};
+
+class BluetoothGattCharacteristic {
+public:
+ virtual ~BluetoothGattCharacteristic() {
+ };
+
+ virtual BluetoothGattService &getService() const = 0;
+
+ virtual uint16_t getHandle() const = 0;
+
+ virtual const boost::uuids::uuid getUuid() const = 0;
+
+ virtual uint8_t getProperties() const = 0;
+
+ virtual uint16_t getValueHandle() const = 0;
+};
+
+class BluetoothGattService {
+public:
+ virtual ~BluetoothGattService() {
+ };
+
+ virtual BluetoothDevice &getDevice() const = 0;
+
+ virtual boost::uuids::uuid getUuid() const = 0;
+
+ virtual uint16_t getHandle() const = 0;
+
+ virtual uint16_t getEndGroupHandle() const = 0;
+
+ virtual const vector<BluetoothGattCharacteristic *> getCharacteristics() const = 0;
+
+ virtual void addCharacteristic(BluetoothGattCharacteristic *characteristic) = 0;
+
+ virtual const boost::optional<BluetoothGattCharacteristic &> findCharacteristic(boost::uuids::uuid uuid) const = 0;
+};
+
+class BluetoothGatt {
+public:
+ BluetoothGatt();
+
+ virtual ~BluetoothGatt();
+
+ virtual BluetoothDevice &getDevice() const = 0;
+
+ virtual void connect() = 0;
+
+ virtual void disconnect() = 0;
+
+ virtual void writeValue(const BluetoothGattCharacteristic &c, const ByteBuffer &bytes) = 0;
+
+ virtual ByteBuffer readValue(const BluetoothGattCharacteristic &c) = 0;
+
+ virtual void discoverServices() = 0;
+
+ virtual const vector<BluetoothGattService *> getServices() const = 0;
+
+ virtual const boost::optional<BluetoothGattService &> findService(boost::uuids::uuid uuid) const = 0;
+};
+
+class BluetoothDevice {
+public:
+ BluetoothDevice();
+
+ virtual ~BluetoothDevice();
+
+ virtual Mac const &getMac() = 0;
+
+ virtual BluetoothAdapter &getAdapter() = 0;
+
+ virtual BluetoothGatt &connectGatt() = 0;
+};
+
+class BluetoothAdapter {
+public:
+ virtual void startScan() = 0;
+
+ virtual void stopScan() = 0;
+
+ virtual void runScan(void (callback)(BluetoothDevice &device)) = 0;
+
+ virtual BluetoothDevice &getDevice(Mac &mac) = 0;
+
+protected:
+ BluetoothAdapter();
+
+ virtual ~BluetoothAdapter();
+};
+
+/**
+* Right this is only RAII support to properly call shutdown().
+*
+* TODO: move getAdapter() here. Make this control all shutdowns.
+*/
+class BluetoothSystem {
+public:
+ BluetoothSystem();
+
+ ~BluetoothSystem();
+};
+
+enum AttPduType {
+ ERROR = 0x00,
+ INVALID_HANDLE = 0x01,
+ READ_BY_TYPE_REQ = 0x08,
+ READ_BY_TYPE_RES = 0x09,
+ READ_REQ = 0x0a,
+ READ_RES = 0x0b,
+ READ_BY_GROUP_TYPE_REQ = 0x10,
+ READ_BY_GROUP_TYPE_RES = 0x11,
+ WRITE_REQ = 0x12,
+ WRITE_RES = 0x13,
+};
+
+class AttributeData;
+
+class AttPdu {
+public:
+ AttPdu(ByteBuffer &bytes);
+
+ AttPdu(ByteBuffer &bytes, AttPduType type);
+
+ AttPduType getType();
+
+ static vector<AttributeData> parseReadByGroupType(ByteBuffer &bytes);
+
+ static vector<AttributeData> parseReadByType(ByteBuffer &bytes);
+
+ static void parseRead(ByteBuffer &bytes);
+
+ static void parseWrite(ByteBuffer &bytes);
+
+ static void makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, SpecUuid uuid);
+
+ static void makeReadByType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, SpecUuid uuid);
+
+ static void makeRead(ByteBuffer &bytes, uint16_t handle);
+
+ static void makeWrite(ByteBuffer &req, uint16_t handle, const ByteBuffer &bytes);
+
+private:
+ static void checkType(ByteBuffer &bytes, AttPduType type);
+
+ static vector<AttributeData> parse(ByteBuffer &bytes, AttPduType type);
+
+ ByteBuffer &bytes;
+};
+
+class AttributeData {
+public:
+ ~AttributeData();
+
+ static AttributeData fromByteBuffer(ByteBuffer &value);
+
+ const uint16_t handle;
+ ByteBuffer value;
+
+private:
+ AttributeData(uint16_t handle, ByteBuffer value);
+};
+
+BluetoothAdapter &getAdapter(int hciDevice);
+
+void shutdown();
+
+boost::uuids::uuid makeUuid(const boost::uuids::uuid base, uint8_t a, uint8_t b);
+
+}
+}
+
+#endif
diff --git a/include/ble/ByteBuffer.h b/include/ble/ByteBuffer.h
new file mode 100644
index 0000000..f884d6e
--- /dev/null
+++ b/include/ble/ByteBuffer.h
@@ -0,0 +1,97 @@
+#ifndef BYTE_STREAM_WRAPPER_H
+#define BYTE_STREAM_WRAPPER_H
+
+#include <cstdint>
+#include <cstdlib>
+#include <string>
+#include <stdexcept>
+#include <memory>
+
+class ByteBufferException : public std::runtime_error {
+public:
+ ByteBufferException(std::string const &what) : std::runtime_error(what) {
+ }
+};
+
+class ByteBuffer {
+public:
+ static ByteBuffer alloc(std::size_t capacity);
+
+ ByteBuffer(const std::shared_ptr<uint8_t> bytes, size_t capacity);
+
+ ByteBuffer(const std::shared_ptr<uint8_t> bytes, size_t capacity, size_t size);
+
+ ByteBuffer(const std::shared_ptr<uint8_t> bytes, size_t capacity, size_t size, size_t zero);
+
+ inline size_t getSize() const {
+ return end - zero;
+ }
+
+ inline size_t getCapacity() const {
+ return capacity;
+ }
+
+ inline size_t getCursor() const {
+ return ptr - zero;
+ }
+
+ inline size_t getBytesLeft() const {
+ return end - ptr;
+ }
+
+ inline void setCursor(size_t newCursor) {
+ ptr = (uint8_t *) &zero[newCursor];
+ }
+
+ inline void skip(size_t length) {
+ ptr += length;
+ }
+
+ ByteBuffer &write8(uint8_t value);
+
+ ByteBuffer &write16le(uint16_t value);
+
+ /**
+ * Appends the entire buffer. Make a view if you want to write a part of it.
+ */
+ ByteBuffer &write(const ByteBuffer &value);
+
+ ByteBuffer &write(const uint8_t *bytes, size_t len);
+
+ uint8_t get8(size_t index) const;
+
+ uint8_t read8();
+
+ uint16_t read16le();
+
+ void copy(uint8_t *bytes, size_t length) const;
+
+ /**
+ * Creates a view from cursor to size.
+ */
+ ByteBuffer view() const;
+
+ // TODO: should return const
+ ByteBuffer view(size_t length) const;
+
+ std::string toString() const;
+
+private:
+ ByteBuffer(const std::shared_ptr<uint8_t> bytes, size_t capacity, const uint8_t *zero, const uint8_t *end);
+
+ ByteBuffer view(uint8_t *ptr, const uint8_t *end) const;
+
+ void checkAndUpdateEnd(size_t count);
+
+ void assertCanAccessRelative(size_t diff) const;
+
+ void assertCanAccessIndex(uint8_t *p) const;
+
+ const std::shared_ptr<uint8_t> bytes;
+ const size_t capacity;
+ const uint8_t *zero;
+ const uint8_t *end;
+ uint8_t *ptr;
+};
+
+#endif