5#include <QtCore/qloggingcategory.h>
6#include <QtCore/qsocketnotifier.h>
7#include <QtCore/qtimer.h>
11#include "../qbluetoothsocketbase_p.h"
15#include <sys/syscall.h>
17#include <linux/capability.h>
27 quint16 controllerIndex;
29}
__attribute__((packed));
38}
__attribute__((packed));
42
43
44
45
46
47
48
49
50
52Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
69#define _LINUX_CAPABILITY_VERSION_3 0x20080522
73#define _LINUX_CAPABILITY_U32S_3 2
77#define CAP_NET_ADMIN 12
81#define CAP_TO_INDEX(x) ((x) >> 5
)
85#define CAP_TO_MASK(x) (1
<< ((x) & 31
))
92 return syscall(__NR_capget, header, data);
96
97
103 struct capHdr header = {};
106 header
.pid = getpid();
109 qCWarning(QT_BT_BLUEZ,
"BluetoothManangement: getCap failed with %s",
110 qPrintable(qt_error_string(errno)));
120 if (!hasPermission) {
121 qCInfo(QT_BT_BLUEZ,
"Missing CAP_NET_ADMIN permission. Cannot determine whether "
122 "a found address is of random or public type.");
128 fd = ::socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
BTPROTO_HCI);
130 qCWarning(QT_BT_BLUEZ,
"Cannot open Bluetooth Management socket: %s",
131 qPrintable(qt_error_string(errno)));
135 memset(&hciAddr, 0,
sizeof(hciAddr));
138 hciAddr.hci_family = AF_BLUETOOTH;
140 if (::bind(fd, (
struct sockaddr *)(&hciAddr),
sizeof(hciAddr)) < 0) {
141 qCWarning(QT_BT_BLUEZ,
"Cannot bind Bluetooth Management socket: %s",
142 qPrintable(qt_error_string(errno)));
148 notifier =
new QSocketNotifier(fd, QSocketNotifier::Read,
this);
149 connect(notifier, &QSocketNotifier::activated,
this, &BluetoothManagement::_q_readNotifier);
152 QTimer* timer =
new QTimer(
this);
154 timer->setTimerType(Qt::VeryCoarseTimer);
163 return bluetoothKernelManager();
172 qCWarning(QT_BT_BLUEZ,
"Management Control read error %s", qPrintable(qt_error_string(errno)));
177 if (size_t(buffer.size()) <
sizeof(MgmtHdr))
180 QByteArray data = buffer.readAll();
183 if (size_t(data.size()) <
sizeof(MgmtHdr))
186 const MgmtHdr *hdr =
reinterpret_cast<
const MgmtHdr*>(data.constData());
187 const size_t nextPackageDataSize = qFromLittleEndian(hdr->length);
188 const auto nextPackageSize = qsizetype(nextPackageDataSize +
sizeof(MgmtHdr));
189 const qsizetype remainingPackageSize = data.size() - nextPackageSize;
191 if (data.size() < nextPackageSize)
194 switch (
static_cast<EventCode>(qFromLittleEndian(hdr->cmdCode))) {
195 case EventCode::DeviceFoundEvent:
199 (data.constData() +
sizeof(MgmtHdr));
202 const bdaddr_t address = event->bdaddr;
205 convertAddress(address.b, &bdaddr);
206 const QBluetoothAddress qtAddress(bdaddr);
207 qCDebug(QT_BT_BLUEZ) <<
"BluetoothManagement: found random device"
209 processRandomAddressFlagInformation(qtAddress);
216 qCDebug(QT_BT_BLUEZ) <<
"BluetoothManagement: Ignored event:"
217 << Qt::hex << (EventCode)qFromLittleEndian(hdr->cmdCode);
221 if (data.size() > nextPackageSize)
222 data = data.right(remainingPackageSize);
231 buffer.ungetBlock(data.constData(), data.size());
234void BluetoothManagement::processRandomAddressFlagInformation(
const QBluetoothAddress &address)
237 QMutexLocker locker(&accessLock);
238 privateFlagAddresses[address] = QDateTime::currentDateTimeUtc();
242
243
246 const auto cutOffTime = QDateTime::currentDateTimeUtc().addDays(-1);
248 QMutexLocker locker(&accessLock);
250 auto i = privateFlagAddresses.begin();
251 while (i != privateFlagAddresses.end()) {
252 if (i.value() < cutOffTime)
253 i = privateFlagAddresses.erase(i);
261 if (fd == -1 || address.isNull())
264 QMutexLocker locker(&accessLock);
265 return privateFlagAddresses.contains(address);
270 return (fd == -1) ?
false :
true;
276#include "moc_bluetoothmanagement_p.cpp"
#define _LINUX_CAPABILITY_U32S_3
#define _LINUX_CAPABILITY_VERSION_3
static int sysCallCapGet(capHdr *header, capData *data)
static bool hasBtMgmtPermission()
#define QPRIVATELINEARBUFFER_BUFFERSIZE
#define HCI_CHANNEL_CONTROL
bool isAddressRandom(const QBluetoothAddress &address) const
bool isMonitoringEnabled() const
static BluetoothManagement * instance()
unsigned short hci_channel