10#include <QtCore/qloggingcategory.h>
15#include <sys/socket.h>
25 QObject(
nullptr), hciSocket(-1), hciDev(-1)
29 qCWarning(QT_BT_BLUEZ) <<
"Cannot open HCI socket";
33 hciDev = hciForAddress(deviceAdapter);
35 qCWarning(QT_BT_BLUEZ) <<
"Cannot find hci dev for" << deviceAdapter.toString();
44 addr.hci_dev = hciDev;
45 addr.hci_family = AF_BLUETOOTH;
47 if (
::bind(hciSocket, (
struct sockaddr *) (&
addr),
sizeof(
addr)) < 0) {
48 qCWarning(QT_BT_BLUEZ) <<
"HCI bind failed:" << strerror(errno);
50 hciSocket = hciDev = -1;
68 if (hciSocket && hciDev >= 0)
93 memset(
p.data(), 0, devListSize);
95 devRequest =
p->dev_req;
100 for (
int i = 0;
i < devRequestList->
dev_num;
i++) {
101 devInfo.
dev_id = (devRequest+
i)->dev_id;
106 int result = memcmp(&adapter, &devInfo.bdaddr,
sizeof(bdaddr_t));
107 if (
result == 0 || deviceAdapter.isNull())
108 return devInfo.dev_id;
130 qCWarning(QT_BT_BLUEZ) <<
"Cannot retrieve HCI filter settings";
139 qCWarning(QT_BT_BLUEZ) <<
"Could not set HCI socket options:" << strerror(errno);
154 qCWarning(QT_BT_BLUEZ) <<
"Cannot retrieve HCI filter settings";
162 qCWarning(QT_BT_BLUEZ) <<
"Could not set HCI socket options:" << strerror(errno);
171 qCDebug(QT_BT_BLUEZ) <<
"sending command; ogf:" << ogf <<
"ocf:" << ocf;
175 static_cast<uint8_t
>(parameters.
size())
177 static_assert(
sizeof command == 3,
"unexpected struct size");
179 iv[0].iov_base = &packetType;
181 iv[1].iov_base = &command;
182 iv[1].iov_len =
sizeof command;
185 iv[2].iov_base =
const_cast<char *
>(parameters.
constData());
186 iv[2].iov_len = parameters.
size();
189 while (writev(hciSocket, iv, ivn) < 0) {
190 if (errno == EAGAIN || errno == EINTR)
192 qCDebug(QT_BT_BLUEZ()) <<
"hci command failure:" << strerror(errno);
195 qCDebug(QT_BT_BLUEZ) <<
"command sent successfully";
211 qCWarning(QT_BT_BLUEZ) <<
"Could not clear HCI socket options:" << strerror(errno);
215 runningEvents.
clear();
226 const int maxNoOfConnections = 20;
234 p->conn_num = maxNoOfConnections;
239 qCWarning(QT_BT_BLUEZ) <<
"Cannot retrieve connection list";
259 const int maxNoOfConnections = 20;
267 p->conn_num = maxNoOfConnections;
272 qCWarning(QT_BT_BLUEZ) <<
"Cannot retrieve connection list";
292 return activeLowEnergyHandles;
297 return qMin<double>(qMax<double>(7.5, connectionInterval), 4000) / 1.25;
313 const quint16 latency = qMax<quint16>(0, qMin<quint16>(
params.latency(), 499));
316 = qMax<quint16>(100, qMin<quint16>(32000,
params.supervisionTimeout())) / 10;
324 struct CommandParams {
332 commandParams.minCeLength = 0;
335 sizeof commandParams);
345 struct SignalingPacket {
350 signalingPacket.code = 0x12;
351 signalingPacket.identifier = ++sigPacketIdentifier;
352 const quint16 sigPacketLen =
sizeof connUpdateData;
356 const quint16 l2CapHeaderLen =
sizeof signalingPacket + sigPacketLen;
369 iv[0].iov_base = &packetType;
371 iv[1].iov_base = &aclData;
372 iv[1].iov_len =
sizeof aclData;
373 iv[2].iov_base = &l2CapHeader;
374 iv[2].iov_len =
sizeof l2CapHeader;
375 iv[3].iov_base = &signalingPacket;
376 iv[3].iov_len =
sizeof signalingPacket;
377 iv[4].iov_base = &connUpdateData;
378 iv[4].iov_len =
sizeof connUpdateData;
379 while (writev(hciSocket, iv,
sizeof iv /
sizeof *iv) < 0) {
380 if (errno == EAGAIN || errno == EINTR)
382 qCDebug(QT_BT_BLUEZ()) <<
"failure writing HCI ACL packet:" << strerror(errno);
385 qCDebug(QT_BT_BLUEZ) <<
"Connection Update Request packet sent successfully";
392void HciManager::_q_readNotify()
398 if (errno != EAGAIN && errno != EINTR)
412 qCWarning(QT_BT_BLUEZ) <<
"Ignoring unexpected HCI packet type" <<
buffer[0];
416void HciManager::handleHciEventPacket(
const quint8 *
data,
int size)
419 qCWarning(QT_BT_BLUEZ) <<
"Unexpected HCI event packet size:" <<
size;
423 hci_event_hdr *
header = (hci_event_hdr *)
data;
429 qCWarning(QT_BT_BLUEZ) <<
"Invalid HCI event packet size";
438 const evt_encrypt_change *
event = (evt_encrypt_change *)
data;
439 qCDebug(QT_BT_BLUEZ) <<
"HCI Encrypt change, status:"
440 << (
event->status == 0 ?
"Success" :
"Failed")
442 <<
"encrypt:" <<
event->encrypt;
445 if (!remoteDevice.isNull())
450 static_assert(
sizeof *
event == 3,
"unexpected struct size");
455 const auto additionalData =
QByteArray(
reinterpret_cast<const char *
>(
data)
460 handleLeMetaEvent(
data);
471 qCWarning(QT_BT_BLUEZ) <<
"Unexpected HCI ACL packet size";
479 data +=
sizeof *aclData;
480 size -=
sizeof *aclData;
486 if (size < aclData->dataLen) {
488 <<
"is smaller than specified size" << aclData->
dataLen;
496 qCWarning(QT_BT_BLUEZ) <<
"Unexpected HCI ACL packet size";
502 data +=
sizeof l2CapHeader;
503 size -=
sizeof l2CapHeader;
505 qCWarning(QT_BT_BLUEZ) <<
"L2Cap payload size" <<
size <<
"is smaller than specified size"
516 qCWarning(QT_BT_BLUEZ) <<
"Unexpected key size" <<
size <<
"in Signing Information packet";
520 memcpy(&csrk,
data + 1,
sizeof csrk);
521 const bool isRemoteKey = aclData->
pbFlag == 2;
525void HciManager::handleLeMetaEvent(
const quint8 *
data)
545 const auto *
const updateData
547 if (updateData->status == 0) {
550 params.setIntervalRange(interval, interval);
564#include "moc_hcimanager_p.cpp"
static void hci_filter_all_events(struct hci_filter *f)
#define SIGNALING_CHANNEL_ID
static void hci_filter_set_ptype(int t, struct hci_filter *f)
static quint16 bt_get_le16(const void *ptr)
#define HCI_EVENT_HDR_SIZE
static void hci_filter_clear(struct hci_filter *f)
#define SECURITY_CHANNEL_ID
#define opCodePack(ogf, ocf)
static void hci_filter_set_event(int e, struct hci_filter *f)
#define HCI_MAX_EVENT_SIZE
DarwinBluetooth::LECBManagerNotifier * notifier
bool sendConnectionUpdateCommand(quint16 handle, const QLowEnergyConnectionParameters ¶ms)
bool sendCommand(QBluezConst::OpCodeGroupField ogf, QBluezConst::OpCodeCommandField ocf, const QByteArray ¶meters)
QList< quint16 > activeLowEnergyConnections() const
bool sendConnectionParameterUpdateRequest(quint16 handle, const QLowEnergyConnectionParameters ¶ms)
bool monitorEvent(HciManager::HciEvent event)
void commandCompleted(quint16 opCode, quint8 status, const QByteArray &data)
QBluetoothAddress addressForConnectionHandle(quint16 handle) const
void connectionUpdate(quint16 handle, const QLowEnergyConnectionParameters ¶meters)
void encryptionChangedEvent(const QBluetoothAddress &address, bool wasSuccess)
void connectionComplete(quint16 handle)
void signatureResolvingKeyReceived(quint16 connHandle, bool remoteKey, BluezUint128 csrk)
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
void append(parameter_type t)
The QLowEnergyConnectionParameters class is used when requesting or reporting an update of the parame...
bool contains(const T &value) const
quint16 forceIntervalIntoRange(double connectionInterval)
ConnectionUpdateData connectionUpdateData(const QLowEnergyConnectionParameters ¶ms)
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
static void convertAddress(const quint64 from, quint8(&to)[6])
static QString header(const QString &name)
constexpr T qFromLittleEndian(T source)
constexpr T qToLittleEndian(T source)
__attribute((__weak__)) extern int __ulock_wait2(uint32_t operation
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLbitfield GLuint64 timeout
[4]
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLenum GLsizei GLsizei GLint GLint GLboolean packed
ReturnedValue read(const char *data)
QFileInfo info(fileName)
[8]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
socketLayer bind(QHostAddress::Any, 4000)