diff options
author | Trygve Laugstøl <trygvis@inamo.no> | 2015-02-15 23:29:17 +0100 |
---|---|---|
committer | Trygve Laugstøl <trygvis@inamo.no> | 2015-02-15 23:35:36 +0100 |
commit | 0d0543e4daeb1c6b01d4799736026b6f3aef9779 (patch) | |
tree | 0f14cac6264710700c70f18c79e41a8aaa6a8cfd /LinuxBluetooth.cpp | |
parent | 60d5440dd3514e71b87948ff5ed30ee38445b8a5 (diff) | |
download | ble-toys-0d0543e4daeb1c6b01d4799736026b6f3aef9779.tar.gz ble-toys-0d0543e4daeb1c6b01d4799736026b6f3aef9779.tar.bz2 ble-toys-0d0543e4daeb1c6b01d4799736026b6f3aef9779.tar.xz ble-toys-0d0543e4daeb1c6b01d4799736026b6f3aef9779.zip |
valgrind tests
Diffstat (limited to 'LinuxBluetooth.cpp')
-rw-r--r-- | LinuxBluetooth.cpp | 457 |
1 files changed, 236 insertions, 221 deletions
diff --git a/LinuxBluetooth.cpp b/LinuxBluetooth.cpp index c30a2b7..5a00f53 100644 --- a/LinuxBluetooth.cpp +++ b/LinuxBluetooth.cpp @@ -18,323 +18,338 @@ #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)); + void runScan(void (*callback)(BluetoothDevice &device)); - BluetoothDevice &getDevice(Mac &mac) override; + BluetoothDevice &getDevice(Mac &mac) override; - private: - void startScan(); +private: + void startScan(); - void stopScan(); + void stopScan(); - 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; - } - - void LinuxBluetoothDevice::connect() { - struct sockaddr_l2 addr; +Mac const &LinuxBluetoothDevice::mac() { + return _mac; +} - D << "connect: mac=" << _mac.str(); +LinuxBluetoothAdapter &LinuxBluetoothDevice::adapter() { + return _adapter; +} - l2cap = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); - if (l2cap < 0) { - throw BluetoothException(this, "LinuxBluetoothDevice::connect(): socket(): " + errnoAsString()); - } +void LinuxBluetoothDevice::connect() { + struct sockaddr_l2 addr; - 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; + D << "connect: mac=" << _mac.str(); - if (bind(l2cap, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - close(l2cap); - throw BluetoothException(this, "LinuxBluetoothDevice::connect(): bind(): " + errnoAsString()); - } + l2cap = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (l2cap < 0) { + throw BluetoothException(this, "LinuxBluetoothDevice::connect(): socket(): " + errnoAsString()); + } - 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_bdaddr = {{0, 0, 0, 0, 0, 0}}; + addr.l2_cid = htobs(ATT_CID); + addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; - 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, 0); +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, 0); - D << "written=" << written; + AttPdu::makeReadByGroupType(out, 0x0001, 0xffff, UUID_PRIMARY_SERVICE); - ssize_t r = read(l2cap, buffer, MAX_MTU); - ByteBuffer in = ByteBuffer(buffer, MAX_MTU, r); + D << "pdu.size()=" << out.getSize(); + ssize_t written = write(l2cap, buffer, out.getSize()); - D << "read: " << r << " bytes"; + D << "written=" << written; - vector<AttributeData> values = AttPdu::parseReadByGroupType(in); + ssize_t r = read(l2cap, buffer, MAX_MTU); + ByteBuffer in = ByteBuffer(buffer, MAX_MTU, r); - D << "READ_BY_GROUP_TYPE response has " + to_string(values.size()) + " values"; + D << "read: " << r << " bytes"; - 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 " + 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 " + 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: " + 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: " + hciDeviceId); - } + if (hci_devinfo(hciDeviceId, &di) < 0) { + throw BluetoothException(this, "hci_devinfo: " + 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=" << 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; - 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; +} - startScan(); +void LinuxBluetoothAdapter::runScan(void (*callback)(BluetoothDevice &device)) { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(hciSocket, &rfds); - while (scanning) { - // Linux can change tv, so it has to be reinitialized - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; + startScan(); - int selected = select(hciSocket + 1, &rfds, NULL, NULL, &tv); + while (scanning) { + // Linux can change tv, so it has to be reinitialized + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; - if (selected == -1) { - throw BluetoothException(this, "select() failed"); - } + int selected = select(hciSocket + 1, &rfds, NULL, NULL, &tv); - if (selected == 0) { - D << "timeout"; - // Timeout, just continue - continue; - } + if (selected == -1) { + throw BluetoothException(this, "select() failed"); + } - unsigned char hciEventBuf[HCI_MAX_EVENT_SIZE]; + if (selected == 0) { + D << "timeout"; + // Timeout, just continue + continue; + } - 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); + unsigned char hciEventBuf[HCI_MAX_EVENT_SIZE]; - D << "metaEvent->subevent = " << std::hex << (int) metaEvent->subevent; + 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); - if (metaEvent->subevent == EVT_LE_ADVERTISING_REPORT) { - le_advertising_info *advertisingInfo = (le_advertising_info *) (metaEvent->data + 1); + D << "metaEvent->subevent = " << std::hex << (int) metaEvent->subevent; - Mac mac = parseMac(advertisingInfo->bdaddr); + if (metaEvent->subevent == EVT_LE_ADVERTISING_REPORT) { + le_advertising_info *advertisingInfo = (le_advertising_info *) (metaEvent->data + 1); - BluetoothDevice &device = getDevice(mac); + Mac mac = parseMac(advertisingInfo->bdaddr); - callback(device); - } + BluetoothDevice &device = getDevice(mac); + + callback(device); } } +} + +}}} - // ----------------------------------------------------------------------- - // - // ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// Implementation of platform-specific method. +// ----------------------------------------------------------------------- - /* - map<int, LinuxBluetoothAdapter *> adapters; +namespace trygvis { +namespace bluetooth { +using namespace trygvis::bluetooth::linux; - BluetoothAdapter &getAdapter(int hciDevice) { - map<int, LinuxBluetoothAdapter *>::iterator it = adapters.find(hciDevice); +map<int, LinuxBluetoothAdapter *> adapters; - if (it == adapters.end()) { - LinuxBluetoothAdapter *adapter = new LinuxBluetoothAdapter(hciDevice); - adapters[hciDevice] = adapter; - return *adapter; - } +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; } -}; +} + +}} |