10#include <QtCore/qloggingcategory.h>
57 &QLeAdvertiserBluez::handleCommandCompleted);
63 &QLeAdvertiserBluez::handleCommandCompleted);
77 queueReadTxPowerLevelCommand();
79 queueAdvertisingCommands();
85 toggleAdvertising(
false);
91 m_pendingCommands << Command(ocf,
data);
94void QLeAdvertiserBluez::sendNextCommand()
96 if (m_pendingCommands.
isEmpty()) {
100 const Command &
c = m_pendingCommands.
first();
107void QLeAdvertiserBluez::queueAdvertisingCommands()
109 toggleAdvertising(
false);
111 setAdvertisingParams();
112 setAdvertisingData();
113 setScanResponseData();
114 toggleAdvertising(
true);
117void QLeAdvertiserBluez::queueReadTxPowerLevelCommand()
123void QLeAdvertiserBluez::toggleAdvertising(
bool enable)
129void QLeAdvertiserBluez::setAdvertisingParams()
134 static_assert(
sizeof params == 15,
"unexpected struct size");
137 setAdvertisingInterval(
params);
142 qCWarning(QT_BT_BLUEZ) <<
"limited discoverability is incompatible with "
143 "using a white list; disabling filtering";
155 qCDebug(QT_BT_BLUEZ) <<
"advertising parameters:" << paramsData.
toHex();
166 const double multiplier = 0.625;
173 const quint16 specMaximum = 0x4000;
179void QLeAdvertiserBluez::setPowerLevel(
AdvData &advData)
181 if (m_sendPowerLevel) {
184 advData.
data[advData.
length++] = m_powerLevel;
188void QLeAdvertiserBluez::setFlags(
AdvData &advData)
207 return dataComplete ? 0x3 : 0x2;
211 return dataComplete ? 0x5 : 0x4;
215 return dataComplete ? 0x7 : 0x6;
223 constexpr auto sizeofT =
static_cast<int>(
sizeof(T));
226 const qsizetype maxServices = (std::min)((spaceAvailable - 2) / sizeofT,
services.size());
227 if (maxServices <= 0) {
228 qCWarning(QT_BT_BLUEZ) <<
"services data does not fit into advertising data packet";
231 const bool dataComplete = maxServices ==
services.size();
234 <<
"services fit into the advertising data";
236 data.data[
data.length++] = 1 + maxServices * sizeofT;
237 data.data[
data.length++] = servicesType<T>(dataComplete);
240 data.length += sizeofT;
277 if (dest.
length >=
sizeof dest.
data - 1 - 1 - 2 - manufacturerData.
size()) {
278 qCWarning(QT_BT_BLUEZ) <<
"manufacturer data does not fit into advertising data packet";
286 std::memcpy(dest.
data + dest.
length, manufacturerData.
data(), manufacturerData.
size());
292 if (
src.localName().isEmpty())
295 qCWarning(QT_BT_BLUEZ) <<
"local name does not fit into advertising data";
302 const bool isComplete =
size == fullSize;
304 const int dataType = isComplete ? 0x9 : 0x8;
310void QLeAdvertiserBluez::setData(
bool isScanResponseData)
314 static_assert(
sizeof theData == 32,
"unexpected struct size");
322 std::memcpy(theData.
data, rawData.data(), theData.
length);
325 setPowerLevel(theData);
326 if (!isScanResponseData)
331 setLocalNameData(sourceData, theData);
332 setServicesData(sourceData, theData);
333 setManufacturerData(sourceData, theData);
339 if (!isScanResponseData) {
340 qCDebug(QT_BT_BLUEZ) <<
"advertising data:" << dataToSend.
toHex();
345 qCDebug(QT_BT_BLUEZ) <<
"scan response data:" << dataToSend.
toHex();
350void QLeAdvertiserBluez::setAdvertisingData()
356void QLeAdvertiserBluez::setScanResponseData()
362void QLeAdvertiserBluez::setWhiteList()
370 for (
const auto &addressInfo : whiteListInfos) {
372 static_assert(
sizeof commandParam == 7,
"unexpected struct size");
373 commandParam.
addrType = addressInfo.type;
379void QLeAdvertiserBluez::handleCommandCompleted(
quint16 opCode,
quint8 status,
382 if (m_pendingCommands.
isEmpty())
385 const Command currentCmd = m_pendingCommands.
first();
386 if (currentCmd.ocf != ocf)
390 qCDebug(QT_BT_BLUEZ) <<
"command" << ocf
392 <<
"status code" << status;
397 qCDebug(QT_BT_BLUEZ) <<
"Advertising disable failed, ignoring";
402 qCDebug(QT_BT_BLUEZ) <<
"reading power level failed, leaving it out of the "
404 m_sendPowerLevel =
false;
410 qCDebug(QT_BT_BLUEZ) <<
"command" << ocf <<
"executed successfully";
415 if (m_sendPowerLevel) {
416 m_powerLevel =
data.at(0);
417 qCDebug(QT_BT_BLUEZ) <<
"TX power level is" << m_powerLevel;
419 queueAdvertisingCommands();
428void QLeAdvertiserBluez::handleError()
430 m_pendingCommands.
clear();
437#include "moc_qleadvertiser_bluez_p.cpp"
void putBtData(T src, void *dst)
#define ocfFromOpCode(op)
std::vector< ObjCStrongReference< CBMutableService > > services
void commandCompleted(quint16 opCode, quint8 status, const QByteArray &data)
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
QByteArray toHex(char separator='\0') const
Returns a hex encoded copy of the byte array.
void doStartAdvertising() override
void doStopAdvertising() override
~QLeAdvertiserBluez() override
QLeAdvertiserBluez(const QLowEnergyAdvertisingParameters ¶ms, const QLowEnergyAdvertisingData &advertisingData, const QLowEnergyAdvertisingData &scanResponseData, std::shared_ptr< HciManager > hciManager, QObject *parent=nullptr)
const QLowEnergyAdvertisingData & scanResponseData() const
const QLowEnergyAdvertisingParameters & parameters() const
const QLowEnergyAdvertisingData & advertisingData() const
bool isEmpty() const noexcept
The QLowEnergyAdvertisingData class represents the data to be broadcast during Bluetooth Low Energy a...
QByteArray rawData() const
Returns the user-supplied raw data to be advertised.
bool includePowerLevel() const
Returns whether to include the device's transmit power level in the advertising data.
static quint16 invalidManufacturerId()
Returns an invalid manufacturer id.
The QLowEnergyAdvertisingParameters class represents the parameters used for Bluetooth Low Energy adv...
FilterPolicy filterPolicy() const
Returns the filter policy that determines how the white list is used.
Mode mode() const
Returns the advertising mode.
int minimumInterval() const
Returns the minimum advertising interval in milliseconds.
int maximumInterval() const
Returns the maximum advertising interval in milliseconds.
QList< AddressInfo > whiteList() const
Returns the white list used for filtering scan and connection requests.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
@ OcfLeSetScanResponseData
Combined button and popup list for selecting options.
Q_CORE_EXPORT QtJniTypes::Service service()
static void convertAddress(const quint64 from, quint8(&to)[6])
constexpr T qToLittleEndian(T source)
quint8 servicesType< quint32 >(bool dataComplete)
static quint16 forceIntoRange(quint16 val, quint16 min, quint16 max)
struct AdvData __attribute__
quint8 servicesType< QUuid::Id128Bytes >(bool dataComplete)
static quint8 servicesType(bool dataComplete)
static void addServicesData(AdvData &data, const QList< T > &services)
static QByteArray byteArrayFromStruct(const T &data)
quint8 servicesType< quint16 >(bool dataComplete)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLenum GLsizei GLsizei GLint GLint GLboolean packed
myObject disconnect()
[26]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent