aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Bluetooth.cpp227
-rw-r--r--Bluetooth.h179
-rw-r--r--BluetoothImpl.h14
-rw-r--r--ByteBuffer.cpp12
-rw-r--r--ByteBuffer.h6
-rw-r--r--CMakeLists.txt3
-rw-r--r--LinuxBluetooth.cpp464
-rw-r--r--main.cpp16
-rw-r--r--test/ByteBufferTest.cpp11
9 files changed, 496 insertions, 436 deletions
diff --git a/Bluetooth.cpp b/Bluetooth.cpp
index f589d1f..ebdd527 100644
--- a/Bluetooth.cpp
+++ b/Bluetooth.cpp
@@ -1,144 +1,175 @@
#include "Bluetooth.h"
+#include "BluetoothImpl.h"
#include <sstream>
#include <iomanip>
#include <string.h>
namespace trygvis {
- using namespace std;
+namespace bluetooth {
+using namespace std;
- // -----------------------------------------------------------------------
- // Mac
- // -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
+// Mac
+// -----------------------------------------------------------------------
- string Mac::str() const {
- std::ostringstream buf;
+string Mac::str() const {
+ std::ostringstream buf;
- buf
- << setw(2) << hex << setfill('0') << (int) bytes[0] << ":"
- << setw(2) << hex << setfill('0') << (int) bytes[1] << ":"
- << setw(2) << hex << setfill('0') << (int) bytes[2] << ":"
- << setw(2) << hex << setfill('0') << (int) bytes[3] << ":"
- << setw(2) << hex << setfill('0') << (int) bytes[4] << ":"
- << setw(2) << hex << setfill('0') << (int) bytes[5];
+ buf
+ << setw(2) << hex << setfill('0') << (int) bytes[0] << ":"
+ << setw(2) << hex << setfill('0') << (int) bytes[1] << ":"
+ << setw(2) << hex << setfill('0') << (int) bytes[2] << ":"
+ << setw(2) << hex << setfill('0') << (int) bytes[3] << ":"
+ << setw(2) << hex << setfill('0') << (int) bytes[4] << ":"
+ << setw(2) << hex << setfill('0') << (int) bytes[5];
- return buf.str();
- }
+ return buf.str();
+}
- bool Mac::operator==(Mac &other) const {
- const uint8_t* b = bytes;
- return memcmp(b, other.bytes, sizeof(bytes)) == 0;
- }
+bool Mac::operator==(Mac &other) const {
+ const uint8_t *b = bytes;
+ return memcmp(b, other.bytes, sizeof(bytes)) == 0;
+}
- bool Mac::operator!=(Mac &other) const {
- return !operator==(other);
- }
+bool Mac::operator!=(Mac &other) const {
+ return !operator==(other);
+}
- bool operator<(const Mac &a, const Mac &b) {
- return memcmp(a.bytes, b.bytes, sizeof(a.bytes)) < 0;
- }
+bool operator<(const Mac &a, const Mac &b) {
+ return memcmp(a.bytes, b.bytes, sizeof(a.bytes)) < 0;
+}
+
+void Mac::copy(uint8_t &_0, uint8_t &_1, uint8_t &_2, uint8_t &_3, uint8_t &_4, uint8_t &_5) const {
+ _0 = bytes[0];
+ _1 = bytes[1];
+ _2 = bytes[2];
+ _3 = bytes[3];
+ _4 = bytes[4];
+ _5 = bytes[5];
+}
- void Mac::copy(uint8_t &_0, uint8_t &_1, uint8_t &_2, uint8_t &_3, uint8_t &_4, uint8_t &_5) const {
- _0 = bytes[0];
- _1 = bytes[1];
- _2 = bytes[2];
- _3 = bytes[3];
- _4 = bytes[4];
- _5 = bytes[5];
+Mac Mac::parseMac(string s) throw(BluetoothException) {
+ unsigned int bytes[6];
+ int count = sscanf(s.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x",
+ &bytes[0], &bytes[1], &bytes[2], &bytes[3], &bytes[4], &bytes[5]);
+
+ if (count != 6) {
+ throw BluetoothException("Unable to parse mac: " + s);
}
- Mac *Mac::parseMac(string s) throw(BluetoothException) {
- unsigned int bytes[6];
- int count = sscanf(s.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x",
- &bytes[0], &bytes[1], &bytes[2], &bytes[3], &bytes[4], &bytes[5]);
+ return Mac((uint8_t) bytes[0], (uint8_t) bytes[1], (uint8_t) bytes[2], (uint8_t) bytes[3], (uint8_t) bytes[4], (uint8_t) bytes[5]);
+}
- if (count != 6) {
- throw BluetoothException("Unable to parse mac: " + s);
- }
+AttPdu::AttPdu(ByteBuffer &bytes) : bytes(bytes) {
+}
- return new Mac((uint8_t) bytes[0], (uint8_t) bytes[1], (uint8_t) bytes[2], (uint8_t) bytes[3], (uint8_t) bytes[4], (uint8_t) bytes[5]);
- }
+AttPdu::AttPdu(ByteBuffer &bytes, AttPduType type) : bytes(bytes) {
+ bytes.add8(type);
+}
- AttPdu::AttPdu(ByteBuffer &bytes) : bytes(bytes) {
- }
+AttPduType AttPdu::getType() {
+ return (AttPduType) bytes.get8(0);
+}
+
+void AttPdu::makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, uint16_t uuid) {
+ bytes.setCursor(0);
+ bytes.add8(AttPduType::READ_BY_GROUP_TYPE_REQ);
+ bytes.add16le(startHandle);
+ bytes.add16le(endHandle);
+ bytes.add16le(uuid);
+}
- AttPdu::AttPdu(ByteBuffer &bytes, AttPduType type) : bytes(bytes) {
- bytes.add8(type);
+void AttPdu::checkType(ByteBuffer &bytes, AttPduType type) {
+ if (bytes.getSize() == 0) {
+ throw BluetoothException("PDU is too small");
}
- AttPduType AttPdu::getType() {
- return (AttPduType) bytes.get8(0);
+ bytes.setCursor(0);
+ AttPduType t = (AttPduType) bytes.get8();
+
+ if (t != type) {
+ throw BluetoothException("Unexpected type: " + to_string(t));
}
+}
+
+vector<AttributeData> AttPdu::parseReadByGroupType(ByteBuffer &bytes) {
+ DF << "bytes: " << bytes.toString();
+
+ checkType(bytes, READ_BY_GROUP_TYPE_RES);
- void AttPdu::makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, uint16_t uuid) {
- bytes.setCursor(0);
- bytes.add8(AttPduType::READ_BY_GROUP_TYPE_REQ);
- bytes.add16le(startHandle);
- bytes.add16le(endHandle);
- bytes.add16le(uuid);
+ if (bytes.getSize() < 4) {
+ throw BluetoothException("Bad READ_BY_GROUP_TYPE_RES packet, expected at least 4 octets, got " + to_string(bytes.getSize()));
}
- void AttPdu::checkType(ByteBuffer &bytes, AttPduType type) {
- if (bytes.getSize() == 0) {
- throw BluetoothException("PDU is too small");
- }
+ uint8_t length = bytes.get8();
+ D << "length=" << (int) length;
- bytes.setCursor(0);
- AttPduType t = (AttPduType) bytes.get8();
+ size_t count = (bytes.getSize() - 2) / length;
+ D << "count=" << count;
- if (t != type) {
- throw BluetoothException("Unexpected type: " + to_string(t));
- }
+ vector<AttributeData> values;
+ for (int i = 0; i < count; i++) {
+ auto data = bytes.view(length);
+ D << "data, size=" << data.getSize() << ", bytes=" << data.toString();
+ bytes.skip(length);
+ values.push_back(AttributeData::fromByteBuffer(data));
}
- vector<AttributeData> AttPdu::parseReadByGroupType(ByteBuffer &bytes) {
- DF;
+ return values;
+}
- checkType(bytes, READ_BY_GROUP_TYPE_RES);
+// -----------------------------------------------------------------------
+// AttributeData
+// -----------------------------------------------------------------------
- if (bytes.getSize() < 4) {
- throw BluetoothException("Bad READ_BY_GROUP_TYPE_RES packet, expected at least 4 octets, got " + to_string(bytes.getSize()));
- }
+AttributeData AttributeData::fromByteBuffer(ByteBuffer &bytes) {
+ uint16_t handle = bytes.get16le();
+ uint16_t groupEndHandle = bytes.get16le();
- uint8_t length = bytes.get8();
- D << "length=" << (int) length;
+ return AttributeData(handle, groupEndHandle, bytes.view());
+}
- size_t count = (bytes.getSize() - 2) / length;
- D << "count=" << count;
+AttributeData::AttributeData(uint16_t handle, uint16_t groupEndHandle, ByteBuffer value) :
+ handle(handle), groupEndHandle(groupEndHandle), value(value) {
+}
- vector<AttributeData> values;
- for (int i = 0; i < count; i++) {
- auto data = bytes.view(length);
- D << "data, size=" << data.getSize() << ", bytes=" << data.toString();
- bytes.skip(length);
- values.push_back(AttributeData::fromByteBuffer(data));
- }
+AttributeData::~AttributeData() {
+}
- return values;
- }
+// -----------------------------------------------------------------------
+// Adapter
+// -----------------------------------------------------------------------
- // -----------------------------------------------------------------------
- // AttributeData
- // -----------------------------------------------------------------------
+BluetoothAdapter::BluetoothAdapter() {
+}
- AttributeData AttributeData::fromByteBuffer(ByteBuffer &bytes) {
- uint16_t handle = bytes.get16le();
- uint16_t groupEndHandle = bytes.get16le();
+BluetoothAdapter::~BluetoothAdapter() {
+}
- return AttributeData(handle, groupEndHandle, bytes.view());
- }
+/*
+map<int, LinuxBluetoothAdapter *> adapters;
- AttributeData::AttributeData(uint16_t handle, uint16_t groupEndHandle, ByteBuffer value) :
- handle(handle), groupEndHandle(groupEndHandle), value(value) {
- }
+BluetoothAdapter &getAdapter(int hciDevice) {
+ map<int, LinuxBluetoothAdapter *>::iterator it = adapters.find(hciDevice);
- AttributeData::~AttributeData() {
+ if (it == adapters.end()) {
+ LinuxBluetoothAdapter *adapter = new LinuxBluetoothAdapter(hciDevice);
+ adapters[hciDevice] = adapter;
+ return *adapter;
}
- // -----------------------------------------------------------------------
- // Adapter
- // -----------------------------------------------------------------------
+ return *it->second;
+}
+*/
- BluetoothAdapter::~BluetoothAdapter() {
- }
+BluetoothAdapter &getAdapter(int hciDevice) {
+ return getAdapterImpl(hciDevice);
+}
+
+void shutdown() {
+ shutdownImpl();
+}
+
+}
};
diff --git a/Bluetooth.h b/Bluetooth.h
index 7bc5bc3..1b5d5f0 100644
--- a/Bluetooth.h
+++ b/Bluetooth.h
@@ -10,127 +10,130 @@
#include "ByteBuffer.h"
namespace trygvis {
- using namespace std;
-
- class BluetoothAdapter;
-
- class BluetoothDevice;
-
- 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;
+namespace bluetooth {
+using namespace std;
+
+class BluetoothAdapter;
+
+class BluetoothDevice;
+
+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;
};
- 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;
- string str() const;
+ bool operator==(Mac &other) const;
- bool operator==(Mac &other) 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;
- 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) throw(BluetoothException);
- static Mac *parseMac(string s) throw(BluetoothException);
+ friend bool operator<(const Mac &a, const Mac &b);
- friend bool operator<(const Mac &a, const Mac &b);
- private:
- uint8_t bytes[6];
- };
+private:
+ uint8_t bytes[6];
+};
- class BluetoothDevice {
- public:
- virtual Mac const &mac() = 0;
+class BluetoothDevice {
+public:
+ virtual Mac const &mac() = 0;
- virtual BluetoothAdapter &adapter() = 0;
+ virtual BluetoothAdapter &adapter() = 0;
- virtual void connect() = 0;
+ virtual void connect() = 0;
- virtual void disconnect() = 0;
+ virtual void disconnect() = 0;
- virtual void discoverServices() = 0;
- };
+ virtual void discoverServices() = 0;
+};
- class BluetoothAdapter {
- public:
- BluetoothAdapter() {
- };
+class BluetoothAdapter {
+public:
+ virtual void stopScan() = 0;
- virtual ~BluetoothAdapter();
+ virtual void runScan(void (callback)(BluetoothDevice &device)) = 0;
- virtual void runScan(void (callback)(BluetoothDevice &device)) = 0;
+ virtual BluetoothDevice &getDevice(Mac &mac) = 0;
- virtual void stopScan() = 0;
+protected:
+ BluetoothAdapter();
- virtual void startScan() = 0;
+ virtual ~BluetoothAdapter();
+};
- virtual BluetoothDevice &getDevice(Mac& mac) = 0;
- };
+enum AttPduType {
+ ERROR = 0x00,
+ READ_BY_GROUP_TYPE_REQ = 0x10,
+ READ_BY_GROUP_TYPE_RES = 0x11
+};
- enum AttPduType {
- ERROR = 0x00,
- READ_BY_GROUP_TYPE_REQ = 0x10,
- READ_BY_GROUP_TYPE_RES = 0x11
- };
+class AttributeData;
- class AttributeData;
+class AttPdu {
+public:
+ AttPdu(ByteBuffer &bytes);
- class AttPdu {
- public:
- AttPdu(ByteBuffer &bytes);
+ AttPdu(ByteBuffer &bytes, AttPduType type);
- AttPdu(ByteBuffer &bytes, AttPduType type);
+ AttPduType getType();
- AttPduType getType();
+ static vector<AttributeData> parseReadByGroupType(ByteBuffer &bytes);
- static vector <AttributeData> parseReadByGroupType(ByteBuffer &bytes);
+ static void makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, uint16_t uuid);
- static void makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, uint16_t uuid);
+private:
+ static void checkType(ByteBuffer &bytes, AttPduType type);
- private:
- static void checkType(ByteBuffer &bytes, AttPduType type);
+ ByteBuffer &bytes;
+};
- ByteBuffer &bytes;
- };
+class AttributeData {
+public:
+ ~AttributeData();
- class AttributeData {
- public:
- ~AttributeData();
+ static AttributeData fromByteBuffer(ByteBuffer &value);
- static AttributeData fromByteBuffer(ByteBuffer &value);
+ const uint16_t handle;
+ const uint16_t groupEndHandle;
+ const ByteBuffer value;
- const uint16_t handle;
- const uint16_t groupEndHandle;
- const ByteBuffer value;
+private:
+ AttributeData(uint16_t handle, uint16_t groupEndHandle, ByteBuffer value);
+};
- private:
- AttributeData(uint16_t handle, uint16_t groupEndHandle, ByteBuffer value);
- };
+BluetoothAdapter &getAdapter(int hciDevice);
+
+void shutdown();
-// BluetoothAdapter &getAdapter(int hciDevice);
- BluetoothAdapter *getAdapter(int hciDevice);
+}
}
#endif
diff --git a/BluetoothImpl.h b/BluetoothImpl.h
new file mode 100644
index 0000000..ba44853
--- /dev/null
+++ b/BluetoothImpl.h
@@ -0,0 +1,14 @@
+#ifndef BLUETOOTH_IMPL_H
+#define BLUETOOTH_IMPL_H
+
+namespace trygvis {
+namespace bluetooth {
+
+BluetoothAdapter &getAdapterImpl(int hciDevice);
+
+void shutdownImpl();
+
+}
+};
+
+#endif
diff --git a/ByteBuffer.cpp b/ByteBuffer.cpp
index 2b2f33b..2d4a258 100644
--- a/ByteBuffer.cpp
+++ b/ByteBuffer.cpp
@@ -2,14 +2,11 @@
#include <string.h>
#include <sstream>
#include <iomanip>
-#include <cassert>
-#include <elf.h>
-#include <stdint-gcc.h>
using namespace std;
ByteBuffer::ByteBuffer(const uint8_t *bytes, size_t capacity) :
- bytes(bytes), capacity(capacity), zero(&bytes[0]), end(&bytes[0]) {
+ bytes(bytes), capacity(capacity), zero(&bytes[0]), end(&bytes[capacity]) {
ptr = (uint8_t *) &bytes[0];
}
@@ -78,10 +75,9 @@ ByteBuffer ByteBuffer::view(uint8_t *ptr, const uint8_t *end) const {
void ByteBuffer::checkAndUpdateEnd(size_t newBytes) {
uint8_t *newPtr = ptr + newBytes;
if (newPtr >= end) {
- throw ByteBufferException(string("New size is too large! cursor=") + to_string(getCursor()) + ", size=" + to_string(getSize()) + ", capacity=" + to_string(capacity));
- }
-
- if (newPtr > end) {
+ if (newPtr >= &zero[capacity]) {
+ throw ByteBufferException(string("New size is too large! cursor=") + to_string(getCursor()) + ", size=" + to_string(getSize()) + ", capacity=" + to_string(capacity));
+ }
end = newPtr;
}
}
diff --git a/ByteBuffer.h b/ByteBuffer.h
index 479a227..d1d02bb 100644
--- a/ByteBuffer.h
+++ b/ByteBuffer.h
@@ -17,8 +17,14 @@ public:
class ByteBuffer {
public:
+ /**
+ * Wrapping constructor, the size will be equal to the capacity.
+ */
ByteBuffer(const uint8_t *bytes, size_t capacity);
+ /**
+ * Wrapping constructor.
+ */
ByteBuffer(const uint8_t *bytes, size_t capacity, size_t zero, size_t size);
inline size_t getSize() const {
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 82dcfc8..5c596e8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,7 +27,10 @@ target_link_libraries(ble_toys ble)
enable_testing()
find_package(Boost COMPONENTS log unit_test_framework REQUIRED)
+
+# If we can change directory here add_definition and test-specific stuff could be moved to the test directory
file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cpp)
+add_definitions(-DBOOST_TEST_DYN_LINK)
foreach(testSrc ${TEST_SRCS})
#Extract the filename without an extension (NAME_WE)
diff --git a/LinuxBluetooth.cpp b/LinuxBluetooth.cpp
index 1399161..3efa7e5 100644
--- a/LinuxBluetooth.cpp
+++ b/LinuxBluetooth.cpp
@@ -18,329 +18,343 @@
#define MAX_MTU 256
namespace trygvis {
+namespace bluetooth {
+namespace linux {
- class LinuxBluetoothDevice;
+class LinuxBluetoothDevice;
- class LinuxBluetoothAdapter;
+class LinuxBluetoothAdapter;
- class LinuxBluetoothManager;
+class LinuxBluetoothManager;
- class LinuxBluetoothAdapter : public BluetoothAdapter {
- public:
- LinuxBluetoothAdapter(int hciDeviceId);
+class LinuxBluetoothAdapter : public BluetoothAdapter {
+public:
+ LinuxBluetoothAdapter(int hciDeviceId);
- ~LinuxBluetoothAdapter();
+ ~LinuxBluetoothAdapter();
- void runScan(void (*callback)(BluetoothDevice &device)) override;
+ void runScan(void (*callback)(BluetoothDevice &device)) override;
- BluetoothDevice &getDevice(Mac &mac) override;
+ BluetoothDevice &getDevice(Mac &mac) override;
- void startScan() override;
+private:
+ void startScan();
- void stopScan() override;
+ void stopScan();
- private:
+ int hciDeviceId;
+ int hciSocket;
+ struct hci_filter hciFilter;
+ bool scanning;
- int hciDeviceId;
- int hciSocket;
- struct hci_filter hciFilter;
- bool scanning;
- };
-
- class LinuxBluetoothDevice : public BluetoothDevice {
- public:
- LinuxBluetoothDevice(LinuxBluetoothAdapter &adapter, Mac mac);
+ map<Mac, LinuxBluetoothDevice *> devices;
+};
- Mac const &mac() override;
+class LinuxBluetoothDevice : public BluetoothDevice {
+public:
+ LinuxBluetoothDevice(LinuxBluetoothAdapter &adapter, Mac mac);
- LinuxBluetoothAdapter &adapter() override;
+ Mac const &mac() override;
- void connect() override;
+ LinuxBluetoothAdapter &adapter() override;
- void disconnect() override;
+ void connect() override;
- void discoverServices() override;
+ void disconnect() override;
- private:
- LinuxBluetoothAdapter &_adapter;
- Mac _mac;
- int l2cap;
- };
+ void discoverServices() override;
- // Utilities
+private:
+ LinuxBluetoothAdapter &_adapter;
+ Mac _mac;
+ int l2cap;
+};
- string errnoAsString() {
- return string(strerror(errno));
- };
+// Utilities
- // -----------------------------------------------------------------------
- // Mac
- // -----------------------------------------------------------------------
+string errnoAsString() {
+ return string(strerror(errno));
+};
- Mac parseMac(bdaddr_t &a) {
- return Mac(a.b[0], a.b[1], a.b[2], a.b[3], a.b[4], a.b[5]);
- }
+// -----------------------------------------------------------------------
+// Mac
+// -----------------------------------------------------------------------
- // -----------------------------------------------------------------------
- // Device
- // -----------------------------------------------------------------------
+Mac parseMac(bdaddr_t &a) {
+ return Mac(a.b[0], a.b[1], a.b[2], a.b[3], a.b[4], a.b[5]);
+}
- LinuxBluetoothDevice::LinuxBluetoothDevice(LinuxBluetoothAdapter &adapter, Mac mac) :
- _adapter(adapter), _mac(mac) {
- }
+// -----------------------------------------------------------------------
+// Device
+// -----------------------------------------------------------------------
- Mac const &LinuxBluetoothDevice::mac() {
- return _mac;
- }
+LinuxBluetoothDevice::LinuxBluetoothDevice(LinuxBluetoothAdapter &adapter, Mac mac) :
+ _adapter(adapter), _mac(mac) {
+}
- LinuxBluetoothAdapter &LinuxBluetoothDevice::adapter() {
- return _adapter;
- }
+Mac const &LinuxBluetoothDevice::mac() {
+ return _mac;
+}
- void LinuxBluetoothDevice::connect() {
- struct sockaddr_l2 addr;
+LinuxBluetoothAdapter &LinuxBluetoothDevice::adapter() {
+ return _adapter;
+}
- D << "connect: mac=" << _mac.str();
+void LinuxBluetoothDevice::connect() {
+ struct sockaddr_l2 addr;
- l2cap = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
- if (l2cap < 0) {
- throw BluetoothException(this, "LinuxBluetoothDevice::connect(): socket(): " + errnoAsString());
- }
+ D << "connect: mac=" << _mac.str();
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- addr.l2_bdaddr = {{0, 0, 0, 0, 0, 0}};
- addr.l2_cid = htobs(ATT_CID);
- addr.l2_bdaddr_type = BDADDR_LE_PUBLIC;
+ l2cap = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+ if (l2cap < 0) {
+ throw BluetoothException(this, "LinuxBluetoothDevice::connect(): socket(): " + errnoAsString());
+ }
- if (bind(l2cap, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(l2cap);
- throw BluetoothException(this, "LinuxBluetoothDevice::connect(): bind(): " + errnoAsString());
- }
+ memset(&addr, 0, sizeof(addr));
+ addr.l2_family = AF_BLUETOOTH;
+ addr.l2_bdaddr = {{0, 0, 0, 0, 0, 0}};
+ addr.l2_cid = htobs(ATT_CID);
+ addr.l2_bdaddr_type = BDADDR_LE_PUBLIC;
- struct bt_security btsec;
- memset(&btsec, 0, sizeof(btsec));
- btsec.level = BT_SECURITY_LOW;
- if (setsockopt(l2cap, SOL_BLUETOOTH, BT_SECURITY, &btsec, sizeof(btsec)) != 0) {
- close(l2cap);
- throw BluetoothException(this, "LinuxBluetoothDevice::connect(): setsockopt(): " + errnoAsString());
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- addr.l2_cid = htobs(ATT_CID);
- addr.l2_bdaddr_type = BDADDR_LE_RANDOM;
- _mac.copy(addr.l2_bdaddr.b[5],
- addr.l2_bdaddr.b[4],
- addr.l2_bdaddr.b[3],
- addr.l2_bdaddr.b[2],
- addr.l2_bdaddr.b[1],
- addr.l2_bdaddr.b[0]);
-
- if (::connect(l2cap, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(l2cap);
- throw BluetoothException(this, "LinuxBluetoothDevice::connect(): connect(): " + errnoAsString());
- }
+ if (bind(l2cap, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ close(l2cap);
+ throw BluetoothException(this, "LinuxBluetoothDevice::connect(): bind(): " + errnoAsString());
}
- void LinuxBluetoothDevice::disconnect() {
- DF << "mac=" << _mac.str();
+ struct bt_security btsec;
+ memset(&btsec, 0, sizeof(btsec));
+ btsec.level = BT_SECURITY_LOW;
+ if (setsockopt(l2cap, SOL_BLUETOOTH, BT_SECURITY, &btsec, sizeof(btsec)) != 0) {
close(l2cap);
+ throw BluetoothException(this, "LinuxBluetoothDevice::connect(): setsockopt(): " + errnoAsString());
}
- void LinuxBluetoothDevice::discoverServices() {
- DF;
+ memset(&addr, 0, sizeof(addr));
+ addr.l2_family = AF_BLUETOOTH;
+ addr.l2_cid = htobs(ATT_CID);
+ addr.l2_bdaddr_type = BDADDR_LE_RANDOM;
+ _mac.copy(addr.l2_bdaddr.b[5],
+ addr.l2_bdaddr.b[4],
+ addr.l2_bdaddr.b[3],
+ addr.l2_bdaddr.b[2],
+ addr.l2_bdaddr.b[1],
+ addr.l2_bdaddr.b[0]);
+
+ if (::connect(l2cap, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ close(l2cap);
+ throw BluetoothException(this, "LinuxBluetoothDevice::connect(): connect(): " + errnoAsString());
+ }
+}
- uint8_t buffer[MAX_MTU];
- ByteBuffer out = ByteBuffer(buffer, MAX_MTU);
+void LinuxBluetoothDevice::disconnect() {
+ DF << "mac=" << _mac.str();
+ close(l2cap);
+}
- AttPdu::makeReadByGroupType(out, 0x0001, 0xffff, UUID_PRIMARY_SERVICE);
+void LinuxBluetoothDevice::discoverServices() {
+ DF;
- D << "pdu.size()=" << out.getSize();
- ssize_t written = write(l2cap, buffer, out.getSize());
+ uint8_t buffer[MAX_MTU];
+ ByteBuffer out = ByteBuffer(buffer, MAX_MTU);
- D << "written=" << written;
+ AttPdu::makeReadByGroupType(out, 0x0001, 0xffff, UUID_PRIMARY_SERVICE);
- ssize_t r = read(l2cap, buffer, MAX_MTU);
+ D << "pdu.size()=" << out.getSize();
+ ssize_t written = write(l2cap, buffer, out.getSize());
- if (r == -1) {
- throw BluetoothException(this, "read(): " + errnoAsString());
- }
+ D << "written=" << written;
- ByteBuffer in = ByteBuffer(buffer, r);
+ ssize_t r = read(l2cap, buffer, MAX_MTU);
- D << "read: " << r << " bytes: " << in.toString();
+ if (r == -1) {
+ throw BluetoothException(this, "read(): " + errnoAsString());
+ }
- vector<AttributeData> values = AttPdu::parseReadByGroupType(in);
+ ByteBuffer in = ByteBuffer(buffer, r);
- D << "READ_BY_GROUP_TYPE response has " + to_string(values.size()) + " values";
+ D << "read: " << r << " bytes: " << in.toString();
- for (auto &data: values) {
- D << "handle: " << data.handle << ", value: " << data.value.toString();
- }
- }
+ vector<AttributeData> values = AttPdu::parseReadByGroupType(in);
- // -----------------------------------------------------------------------
- // Adapter
- // -----------------------------------------------------------------------
+ D << "READ_BY_GROUP_TYPE response has " + to_string(values.size()) + " values";
+ for (auto &data: values) {
+ D << "handle: " << data.handle << ", groupEndHandle: " << data.groupEndHandle << ", value: " << data.value.toString();
+ }
+}
- LinuxBluetoothAdapter::LinuxBluetoothAdapter(int hciDeviceId) {
- DF << "hciDeviceId=" << hciDeviceId;
+// -----------------------------------------------------------------------
+// Adapter
+// -----------------------------------------------------------------------
- this->hciDeviceId = hciDeviceId;
- hciSocket = ::hci_open_dev(hciDeviceId);
+LinuxBluetoothAdapter::LinuxBluetoothAdapter(int hciDeviceId) :
+ scanning(false) {
+ DF << "hciDeviceId=" << hciDeviceId;
- D << "HCI socket: " << hciSocket;
+ this->hciDeviceId = hciDeviceId;
+ hciSocket = ::hci_open_dev(hciDeviceId);
- if (hciSocket == -1) {
- throw BluetoothException(this, "Could not open HCI device " + to_string(hciDeviceId));
- }
+ D << "HCI socket: " << hciSocket;
- hci_filter_clear(&hciFilter);
- hci_filter_set_ptype(HCI_EVENT_PKT, &hciFilter);
- hci_filter_set_event(EVT_LE_META_EVENT, &hciFilter);
- hci_filter_set_event(EVT_LE_ADVERTISING_REPORT, &hciFilter);
- setsockopt(hciSocket, SOL_HCI, HCI_FILTER, &hciFilter, sizeof(hciFilter));
+ if (hciSocket == -1) {
+ throw BluetoothException(this, "Could not open HCI device " + to_string(hciDeviceId));
}
- LinuxBluetoothAdapter::~LinuxBluetoothAdapter() {
- DF;
+ hci_filter_clear(&hciFilter);
+ hci_filter_set_ptype(HCI_EVENT_PKT, &hciFilter);
+ hci_filter_set_event(EVT_LE_META_EVENT, &hciFilter);
+ hci_filter_set_event(EVT_LE_ADVERTISING_REPORT, &hciFilter);
+ setsockopt(hciSocket, SOL_HCI, HCI_FILTER, &hciFilter, sizeof(hciFilter));
+}
- stopScan();
+LinuxBluetoothAdapter::~LinuxBluetoothAdapter() {
+ DF;
- close(hciSocket);
- }
+ stopScan();
- void LinuxBluetoothAdapter::startScan() {
- DF;
+ close(hciSocket);
- struct hci_dev_info di;
+ D << "Depeting " << devices.size() << " devices";
- if (hci_devinfo(hciDeviceId, &di) < 0) {
- throw BluetoothException(this, "hci_devinfo: " + to_string(hciDeviceId));
- }
+ for (auto &pair : devices) {
+ delete pair.second;
+ }
+}
- D << "hciDeviceId.dev_id=" << di.dev_id;
- D << "hciDeviceId.bdaddr=" << parseMac(di.bdaddr).str();
- D << "hciDeviceId.flags=" << hex << setw(8) << setfill('0') << di.flags;
- D << "hciDeviceId.flags RUNNING = " << hci_test_bit(HCI_RUNNING, &di.flags);
- D << "hciDeviceId.flags UP = " << hci_test_bit(HCI_UP, &di.flags);
- D << "hciDeviceId.flags PSCAN = " << hci_test_bit(HCI_PSCAN, &di.flags);
- D << "hciDeviceId.flags ISCAN = " << hci_test_bit(HCI_ISCAN, &di.flags);
- D << "hciDeviceId.name=" << di.name;
+void LinuxBluetoothAdapter::startScan() {
+ DF;
- int up = hci_test_bit(HCI_UP, &di.flags);
+ struct hci_dev_info di;
- if (!up) {
- throw BluetoothException(this, "HCI adapter is not up: " + to_string(hciDeviceId));
- }
+ if (hci_devinfo(hciDeviceId, &di) < 0) {
+ throw BluetoothException(this, "HCI adapter is not up: " + to_string(hciDeviceId));
+ }
- if (hci_le_set_scan_parameters(hciSocket, 0x01, htobs(0x0010), htobs(0x0010), 0x00, 0, 1000) < 0) {
- throw BluetoothException(this, "hci_le_set_scan_parameters: " + errnoAsString());
- }
+ D << "hciDeviceId.dev_id=" << di.dev_id;
+ D << "hciDeviceId.bdaddr=" << parseMac(di.bdaddr).str();
+ D << "hciDeviceId.flags=" << setw(8) << setfill('0') << hex << di.flags;
+ D << "hciDeviceId.flags RUNNING = " << hci_test_bit(HCI_RUNNING, &di.flags);
+ D << "hciDeviceId.flags UP = " << hci_test_bit(HCI_UP, &di.flags);
+ D << "hciDeviceId.flags PSCAN = " << hci_test_bit(HCI_PSCAN, &di.flags);
+ D << "hciDeviceId.flags ISCAN = " << hci_test_bit(HCI_ISCAN, &di.flags);
+ D << "hciDeviceId.name=" << di.name;
- if (hci_le_set_scan_enable(hciSocket, 1, 0, 1000)) {
- throw BluetoothException(this, "Could not start scanning: other" + errnoAsString());
- }
+ int up = hci_test_bit(HCI_UP, &di.flags);
- scanning = true;
+ if (!up) {
+ throw BluetoothException(this, "HCI adapter is not up: " + hciDeviceId);
}
- void LinuxBluetoothAdapter::stopScan() {
- DF;
+ if (hci_le_set_scan_parameters(hciSocket, 0x01, htobs(0x0010), htobs(0x0010), 0x00, 0, 1000) < 0) {
+ throw BluetoothException(this, "hci_le_set_scan_parameters: " + errnoAsString());
+ }
- if (!scanning) {
- return;
- }
+ if (hci_le_set_scan_enable(hciSocket, 1, 0, 1000)) {
+ throw BluetoothException(this, "Could not start scanning: other" + errnoAsString());
+ }
- scanning = false;
+ scanning = true;
+}
- if (hci_le_set_scan_enable(hciSocket, 0, 0, 1000) < 0) {
- W << "stopScan: hci_le_set_scan_enable: " << errnoAsString();
- }
+void LinuxBluetoothAdapter::stopScan() {
+ DF;
+
+ if (!scanning) {
+ return;
}
- BluetoothDevice &LinuxBluetoothAdapter::getDevice(Mac &mac) {
- static map<Mac, LinuxBluetoothDevice *> devices;
+ scanning = false;
- map<Mac, LinuxBluetoothDevice *>::iterator it = devices.find(mac);
+ if (hci_le_set_scan_enable(hciSocket, 0, 0, 1000) < 0) {
+ W << "stopScan: hci_le_set_scan_enable: " << errnoAsString();
+ }
+}
- if (it == devices.end()) {
- LinuxBluetoothDevice *device = new LinuxBluetoothDevice(*this, mac);
- devices[mac] = device;
- return *device;
- }
+BluetoothDevice &LinuxBluetoothAdapter::getDevice(Mac &mac) {
+ map<Mac, LinuxBluetoothDevice *>::iterator it = devices.find(mac);
- return *it->second;
+ if (it == devices.end()) {
+ LinuxBluetoothDevice *device = new LinuxBluetoothDevice(*this, mac);
+ devices[mac] = device;
+ return *device;
}
- void LinuxBluetoothAdapter::runScan(void (*callback)(BluetoothDevice &device)) {
- fd_set rfds;
- FD_ZERO(&rfds);
- FD_SET(hciSocket, &rfds);
+ return *it->second;
+}
+
+void LinuxBluetoothAdapter::runScan(void (*callback)(BluetoothDevice &device)) {
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(hciSocket, &rfds);
- startScan();
+ startScan();
- while (scanning) {
- // Linux can change tv, so it has to be reinitialized
- struct timeval tv;
- tv.tv_sec = 1;
- tv.tv_usec = 0;
+ while (scanning) {
+ // Linux can change tv, so it has to be reinitialized
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
- int selected = select(hciSocket + 1, &rfds, NULL, NULL, &tv);
+ int selected = select(hciSocket + 1, &rfds, NULL, NULL, &tv);
- if (selected == -1) {
- throw BluetoothException(this, "select() failed");
- }
+ if (selected == -1) {
+ throw BluetoothException(this, "select() failed");
+ }
- if (selected == 0) {
- D << "timeout";
- // Timeout, just continue
- continue;
- }
+ if (selected == 0) {
+ D << "timeout";
+ // Timeout, just continue
+ continue;
+ }
- unsigned char hciEventBuf[HCI_MAX_EVENT_SIZE];
+ unsigned char hciEventBuf[HCI_MAX_EVENT_SIZE];
- ssize_t len = read(hciSocket, hciEventBuf, sizeof(hciEventBuf));
- evt_le_meta_event *metaEvent = (evt_le_meta_event *) (hciEventBuf + (1 + HCI_EVENT_HDR_SIZE));
- len -= (1 + HCI_EVENT_HDR_SIZE);
+ ssize_t len = read(hciSocket, hciEventBuf, sizeof(hciEventBuf));
+ evt_le_meta_event *metaEvent = (evt_le_meta_event *) (hciEventBuf + (1 + HCI_EVENT_HDR_SIZE));
+ len -= (1 + HCI_EVENT_HDR_SIZE);
- D << "metaEvent->subevent = " << std::hex << (int) metaEvent->subevent;
+ D << "metaEvent->subevent = " << std::hex << (int) metaEvent->subevent;
- if (metaEvent->subevent == EVT_LE_ADVERTISING_REPORT) {
- le_advertising_info *advertisingInfo = (le_advertising_info *) (metaEvent->data + 1);
+ if (metaEvent->subevent == EVT_LE_ADVERTISING_REPORT) {
+ le_advertising_info *advertisingInfo = (le_advertising_info *) (metaEvent->data + 1);
- Mac mac = parseMac(advertisingInfo->bdaddr);
+ Mac mac = parseMac(advertisingInfo->bdaddr);
- BluetoothDevice &device = getDevice(mac);
+ BluetoothDevice &device = getDevice(mac);
- callback(device);
- }
+ callback(device);
}
}
+}
- // -----------------------------------------------------------------------
- //
- // -----------------------------------------------------------------------
+}}}
- /*
- map<int, LinuxBluetoothAdapter *> adapters;
+// -----------------------------------------------------------------------
+// Implementation of platform-specific method.
+// -----------------------------------------------------------------------
- BluetoothAdapter &getAdapter(int hciDevice) {
- map<int, LinuxBluetoothAdapter *>::iterator it = adapters.find(hciDevice);
+namespace trygvis {
+namespace bluetooth {
+using namespace trygvis::bluetooth::linux;
- if (it == adapters.end()) {
- LinuxBluetoothAdapter *adapter = new LinuxBluetoothAdapter(hciDevice);
- adapters[hciDevice] = adapter;
- return *adapter;
- }
+map<int, LinuxBluetoothAdapter *> adapters;
+
+LinuxBluetoothAdapter &getAdapterImpl(int hciDevice) {
+ map<int, LinuxBluetoothAdapter *>::iterator it = adapters.find(hciDevice);
- return *it->second;
+ if (it == adapters.end()) {
+ LinuxBluetoothAdapter *adapter = new LinuxBluetoothAdapter(hciDevice);
+ adapters[hciDevice] = adapter;
+ return *adapter;
}
- */
- BluetoothAdapter *getAdapter(int hciDevice) {
- return new LinuxBluetoothAdapter(hciDevice);
+ return *it->second;
+}
+
+void shutdownImpl() {
+ for (auto &pair: adapters) {
+ delete pair.second;
}
-};
+}
+
+}}
diff --git a/main.cpp b/main.cpp
index 757db28..7ae4c1b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -3,9 +3,9 @@
#include "Bluetooth.h"
using namespace std;
-using namespace trygvis;
+using namespace trygvis::bluetooth;
-static Mac *targetMac;
+Mac *targetMac;
void scan_callback(BluetoothDevice &device) {
device.adapter().stopScan();
@@ -30,14 +30,14 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- BluetoothAdapter *adapter = nullptr;
int e;
// try {
- targetMac = Mac::parseMac(argv[1]);
+ Mac mac = Mac::parseMac(argv[1]);
+ targetMac = &mac;
- adapter = trygvis::getAdapter(0);
+ BluetoothAdapter &adapter = getAdapter(0);
- BluetoothDevice &device = adapter->getDevice(*targetMac);
+ BluetoothDevice &device = adapter.getDevice(mac);
scan_callback(device);
@@ -52,8 +52,6 @@ int main(int argc, char *argv[]) {
// e = EXIT_FAILURE;
// }
- if (adapter != nullptr) {
- delete adapter;
- }
+ shutdown();
return e;
}
diff --git a/test/ByteBufferTest.cpp b/test/ByteBufferTest.cpp
index ed842f2..2a9bb8c 100644
--- a/test/ByteBufferTest.cpp
+++ b/test/ByteBufferTest.cpp
@@ -1,8 +1,5 @@
#include "ByteBuffer.h"
-#define BOOST_TEST_DYN_LINK
-
-//Define our Module name (prints at testing)
#define BOOST_TEST_MODULE "ByteBuffer"
#include <boost/test/unit_test.hpp>
@@ -35,12 +32,11 @@ public:
size_t capacity;
};
-/*
BOOST_AUTO_TEST_CASE(empty_buffer) {
- Bytes b(1000);
- ByteBuffer buffer(b.bytes, b.capacity, 0, 0);
+ Bytes b(0);
+ ByteBuffer buffer(b.bytes, b.capacity);
- checkBuffer(buffer, 0, 1000, 0);
+ checkBuffer(buffer, 0, 0, 0);
try {
buffer.get8();
@@ -48,7 +44,6 @@ BOOST_AUTO_TEST_CASE(empty_buffer) {
} catch (ByteBufferException e) {
}
}
-*/
BOOST_AUTO_TEST_CASE(basic) {
Bytes b(1000);