Source

Target

Commits (7)
Showing with 379 additions and 77 deletions
examples/nfc/poster/doc/images/qml-poster-example.png

4.99 KB | W: 0px | H: 0px

examples/nfc/poster/doc/images/qml-poster-example.png

7.76 KB | W: 0px | H: 0px

examples/nfc/poster/doc/images/qml-poster-example.png
examples/nfc/poster/doc/images/qml-poster-example.png
examples/nfc/poster/doc/images/qml-poster-example.png
examples/nfc/poster/doc/images/qml-poster-example.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -31,7 +31,7 @@
\brief A QML example about reading and displaying NFC Data Exchange Format (NDEF) messages.
The QML Poster example displays the contents of specifically formatted NFC Data
Exchange Format (NDEF) messages read from an NFC Tag. The NDEF message should
Exchange Format (NDEF) messages read from an NFC Tag. The NDEF message must
contain a URI record, an optional \c image/* MIME record, and one or more
localized Text records.
......@@ -39,5 +39,24 @@ localized Text records.
\include examples-run.qdocinc
\section1 Applying NDEF Filters
The example is designed to display the content of a very specific type of NFC tag.
The tag must contain at least one URI record and one text record. If those two
record types do not exist, nothing will happen. Such filtering is applied via the
\l NearField type's filter property. The property accepts a list of \l NdefFilter objects.
\snippet poster/poster.qml QML NDEF filtering
\section1 Processing Found NDEF Messages
Once an appropriate tag is found, the \l NearField::messageRecords property reflects the content.
It transports the list of found NDEF records. The QML snippet below
demonstrates how these records can be accessed:
\snippet poster/poster.qml messageRecordsChanged 1
\snippet poster/poster.qml messageRecordsChanged 2
\snippet poster/poster.qml messageRecordsChanged 3
\sa {Qt NFC}
*/
......@@ -62,13 +62,18 @@ Rectangle {
}
}
//! [QML NDEF filtering]
filter: [
NdefFilter { type: "U"; typeNameFormat: NdefRecord.NfcRtd; maximum: 1 },
NdefFilter { type: "T"; typeNameFormat: NdefRecord.NfcRtd },
NdefFilter { typeNameFormat: NdefRecord.Mime; minimum: 0; maximum: 1 }
]
//! [QML NDEF filtering]
//! [messageRecordsChanged 1]
onMessageRecordsChanged: {
//! [messageRecordsChanged 1]
posterText.text = "";
posterImage.source = "";
posterUrl.text = "";
......@@ -76,6 +81,7 @@ Rectangle {
var currentLocaleMatch = NdefTextRecord.LocaleMatchedNone;
var i;
var found = false;
//! [messageRecordsChanged 2]
for (i = 0; i < messageRecords.length; ++i) {
switch (messageRecords[i].typeNameFormat) {
case NdefRecord.NfcRtd:
......@@ -102,18 +108,24 @@ Rectangle {
if (!found)
console.warn("Unknown NFC tag detected. Cannot display content.")
}
//! [messageRecordsChanged 2]
root.state = "show";
//! [messageRecordsChanged 3]
}
//! [messageRecordsChanged 3]
}
Text {
id: touchText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "Touch an NFC tag"
text: "Touch an NFC tag with at least one Text and one URI record."
font.bold: true
font.pointSize: 18
wrapMode: Text.WordWrap
width: root.width*0.75
horizontalAlignment: Text.AlignHCenter
}
Image {
......
......@@ -168,7 +168,6 @@ config_bluez:qtHaveModule(dbus) {
include(osx/osxbt.pri)
SOURCES += \
qbluetoothdevicediscoveryagent_p.cpp \
qbluetoothlocaldevice_p.cpp \
qbluetoothserviceinfo_p.cpp \
qbluetoothservicediscoveryagent_p.cpp \
......
......@@ -260,8 +260,24 @@ void QtBluezDiscoveryManager::PropertiesChanged(const QString &interface,
&& d->references.contains(propIface->path())
&& changed_properties.contains(QStringLiteral("Discovering"))) {
bool isDiscovering = changed_properties.value(QStringLiteral("Discovering")).toBool();
if (!isDiscovering)
removeAdapterFromMonitoring(propIface->path());
if (!isDiscovering) {
/*
Once we stop the Discovering flag will switch a few ms later. This comes through this code
path. If a new device discovery is started while we are still
waiting for the flag change signal, then the new device discovery will be aborted prematurely.
To compensate we check whether there was renewed interest.
*/
AdapterData *data = d->references[propIface->path()];
if (!data) {
removeAdapterFromMonitoring(propIface->path());
} else {
OrgBluezAdapter1Interface iface(QStringLiteral("org.bluez"), propIface->path(),
QDBusConnection::systemBus());
iface.StartDiscovery();
}
}
}
}
......
......@@ -63,6 +63,19 @@ import statement in your \c .qml file:
\section1 Related Information
\section2 Building Qt Bluetooth
Despite the fact that the module can be built for all Qt platforms,
the module is not ported to all of them. Not supported platforms such as Windows desktop
employ a fake or dummy backend which is automatically selected when the
platform is not supported. The dummy backend reports appropriate error messages
and values which allow the Qt Bluetooth developer to detect at runtime that the
current platform is not supported. The dummy backend is also selected on Linux if
BlueZ development headers are not found during build time or Qt was built without
Qt D-Bus support.
The usage of the dummy backend is highlighted via an appropriate warning while building and running.
\section2 Guides
\list
\li \l {Qt Bluetooth Overview}{Classic Bluetooth Overview}
......
......@@ -432,6 +432,10 @@ void QBluetoothDeviceDiscoveryAgentPrivate::_q_propertyChanged(const QString &na
pendingCancel = false;
start();
} else {
// happens when agent is created while other agent called StopDiscovery()
if (!adapter)
return;
if (useExtendedDiscovery) {
useExtendedDiscovery = false;
/* We don't use the Start/StopDiscovery combo here
......@@ -518,7 +522,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::_q_discoveryInterrupted(const QStrin
return;
if (path == adapterBluez5->path()) {
qCWarning(QT_BT_BLUEZ) << "Device discovery aborted due to unexpected adapter changes";
qCWarning(QT_BT_BLUEZ) << "Device discovery aborted due to unexpected adapter changes from another process.";
if (discoveryTimer)
discoveryTimer->stop();
......
......@@ -36,9 +36,7 @@
#include "qbluetoothaddress.h"
#include "qbluetoothuuid.h"
#ifndef QT_IOS_BLUETOOTH
#include "dummy/dummy_helper_p.h"
#endif
#define QT_DEVICEDISCOVERY_DEBUG
......@@ -52,9 +50,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(
q_ptr(parent)
{
Q_UNUSED(deviceAdapter);
#ifndef QT_IOS_BLUETOOTH
printDummyWarning();
#endif
}
QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
......
......@@ -214,15 +214,23 @@ void QBluetoothServiceDiscoveryAgentPrivate::runExternalSdpScan(
sdpScannerProcess = new QProcess(q);
sdpScannerProcess->setReadChannel(QProcess::StandardOutput);
if (QT_BT_BLUEZ().isDebugEnabled())
sdpScannerProcess->setProcessChannelMode(QProcess::ForwardedErrorChannel);
sdpScannerProcess->setProgram(fileInfo.canonicalFilePath());
q->connect(sdpScannerProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
q, SLOT(_q_sdpScannerDone(int,QProcess::ExitStatus)));
}
QStringList arguments;
arguments << remoteAddress.toString() << localAddress.toString();
// No filter implies PUBLIC_BROWSE_GROUP based SDP scan
if (!uuidFilter.isEmpty()) {
arguments << QLatin1String("-u"); // cmd line option for list of uuids
foreach (const QBluetoothUuid& uuid, uuidFilter)
arguments << uuid.toString();
}
sdpScannerProcess->setArguments(arguments);
sdpScannerProcess->start();
}
......
......@@ -96,7 +96,10 @@ public:
m_discoveryMode(QDeclarativeBluetoothDiscoveryModel::MinimalServiceDiscovery),
m_running(false),
m_runningRequested(true),
m_componentCompleted(false)
m_componentCompleted(false),
m_currentState(QDeclarativeBluetoothDiscoveryModel::IdleAction),
m_nextState(QDeclarativeBluetoothDiscoveryModel::IdleAction),
m_wasDirectDeviceAgentCancel(false)
{
}
~QDeclarativeBluetoothDiscoveryModelPrivate()
......@@ -122,12 +125,33 @@ public:
bool m_runningRequested;
bool m_componentCompleted;
QString m_remoteAddress;
QDeclarativeBluetoothDiscoveryModel::Action m_currentState;
QDeclarativeBluetoothDiscoveryModel::Action m_nextState;
bool m_wasDirectDeviceAgentCancel;
};
QDeclarativeBluetoothDiscoveryModel::QDeclarativeBluetoothDiscoveryModel(QObject *parent) :
QAbstractListModel(parent),
d(new QDeclarativeBluetoothDiscoveryModelPrivate)
{
d->m_deviceAgent = new QBluetoothDeviceDiscoveryAgent(this);
connect(d->m_deviceAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
connect(d->m_deviceAgent, SIGNAL(finished()), this, SLOT(finishedDiscovery()));
connect(d->m_deviceAgent, SIGNAL(canceled()), this, SLOT(finishedDiscovery()));
connect(d->m_deviceAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
this, SLOT(errorDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::Error)));
d->m_deviceAgent->setObjectName("DeviceDiscoveryAgent");
d->m_serviceAgent = new QBluetoothServiceDiscoveryAgent(this);
connect(d->m_serviceAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
connect(d->m_serviceAgent, SIGNAL(finished()), this, SLOT(finishedDiscovery()));
connect(d->m_serviceAgent, SIGNAL(canceled()), this, SLOT(finishedDiscovery()));
connect(d->m_serviceAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)),
this, SLOT(errorDiscovery(QBluetoothServiceDiscoveryAgent::Error)));
d->m_serviceAgent->setObjectName("ServiceDiscoveryAgent");
QHash<int, QByteArray> roleNames;
roleNames = QAbstractItemModel::roleNames();
......@@ -174,8 +198,8 @@ void QDeclarativeBluetoothDiscoveryModel::errorDeviceDiscovery(QBluetoothDeviceD
//QBluetoothDeviceDiscoveryAgent::finished() signal is not emitted in case of an error
//Note that this behavior is different from QBluetoothServiceDiscoveryAgent.
//This reset the models running flag.
setRunning(false);
//This resets the models running flag.
finishedDiscovery();
}
void QDeclarativeBluetoothDiscoveryModel::clearModel()
......@@ -331,7 +355,35 @@ void QDeclarativeBluetoothDiscoveryModel::deviceDiscovered(const QBluetoothDevic
void QDeclarativeBluetoothDiscoveryModel::finishedDiscovery()
{
setRunning(false);
QDeclarativeBluetoothDiscoveryModel::Action previous = d->m_currentState;
d->m_currentState = IdleAction;
switch (previous) {
case IdleAction:
// last transition didn't even start
// can happen when start() or stop() immediately returned
// usually this happens within a current transitionToNextAction call
break;
case StopAction:
qCDebug(QT_BT_QML) << "Agent cancel detected";
transitionToNextAction();
break;
default: // all other
qCDebug(QT_BT_QML) << "Discovery finished" << sender()->objectName();
//TODO Qt6 This hack below is once again due to the pendingCancel logic
// because QBluetoothDeviceDiscoveryAgent::isActive() is not reliable.
// In toggleStartStop() we need to know whether the stop() is delayed or immediate.
// isActive() cannot be used. Hence we have to wait for the canceled() signal.
// Android, WinRT and Bluez5 are immediate, Bluez4 is always delayed.
// The immediate case is what we catch here.
if (sender() == d->m_deviceAgent && d->m_nextState == StopAction) {
d->m_wasDirectDeviceAgentCancel = true;
return;
}
setRunning(false);
break;
}
}
/*!
......@@ -361,6 +413,131 @@ void QDeclarativeBluetoothDiscoveryModel::setDiscoveryMode(DiscoveryMode discove
emit discoveryModeChanged();
}
void QDeclarativeBluetoothDiscoveryModel::updateNextAction(Action action)
{
qCDebug(QT_BT_QML) << "New action queue:"
<< d->m_currentState << d->m_nextState << action;
if (action == IdleAction)
return;
switch (d->m_nextState) {
case IdleAction:
d->m_nextState = action;
return;
case StopAction:
qWarning() << "Invalid Stop state when processing new action" << action;
return;
case DeviceDiscoveryAction:
case MinimalServiceDiscoveryAction:
case FullServiceDiscoveryAction:
if (action == StopAction) // cancel out previous start call
d->m_nextState = IdleAction;
else
qWarning() << "Ignoring new DMF state while another DMF state is scheduled.";
return;
}
}
void QDeclarativeBluetoothDiscoveryModel::transitionToNextAction()
{
qCDebug(QT_BT_QML) << "Before transition change:" << d->m_currentState << d->m_nextState;
bool isRunning;
switch (d->m_currentState) {
case IdleAction:
switch (d->m_nextState) {
case IdleAction: break; // nothing to do
case StopAction: d->m_nextState = IdleAction; break; // clear, nothing to do
case DeviceDiscoveryAction:
case MinimalServiceDiscoveryAction:
case FullServiceDiscoveryAction:
Action temp = d->m_nextState;
clearModel();
isRunning = toggleStartStop(d->m_nextState);
d->m_nextState = IdleAction;
if (isRunning) {
d->m_currentState = temp;
} else {
if (temp != DeviceDiscoveryAction )
errorDiscovery(d->m_serviceAgent->error());
d->m_running = false;
}
}
break;
case StopAction:
break; // do nothing, StopAction cleared by finished()/cancelled()/error() handlers
case DeviceDiscoveryAction:
case MinimalServiceDiscoveryAction:
case FullServiceDiscoveryAction:
switch (d->m_nextState) {
case IdleAction: break;
case StopAction:
isRunning = toggleStartStop(StopAction);
(isRunning) ? d->m_currentState = StopAction : d->m_currentState = IdleAction;
d->m_nextState = IdleAction;
break;
default:
Q_ASSERT(false); // should never happen
break;
}
break;
}
qCDebug(QT_BT_QML) << "After transition change:" << d->m_currentState << d->m_nextState;
}
// Returns true if the agent is active
// this can be used to detect whether the agent still needs time to
// perform the requested action.
bool QDeclarativeBluetoothDiscoveryModel::toggleStartStop(Action action)
{
Q_ASSERT(action != IdleAction);
switch (action) {
case DeviceDiscoveryAction:
Q_ASSERT(!d->m_deviceAgent->isActive() && !d->m_serviceAgent->isActive());
d->m_deviceAgent->start();
return d->m_deviceAgent->isActive();
case MinimalServiceDiscoveryAction:
case FullServiceDiscoveryAction:
Q_ASSERT(!d->m_deviceAgent->isActive() && !d->m_serviceAgent->isActive());
d->m_serviceAgent->setRemoteAddress(QBluetoothAddress(d->m_remoteAddress));
d->m_serviceAgent->clear();
if (!d->m_uuid.isEmpty())
d->m_serviceAgent->setUuidFilter(QBluetoothUuid(d->m_uuid));
if (action == FullServiceDiscoveryAction) {
qCDebug(QT_BT_QML) << "Full Discovery";
d->m_serviceAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
} else {
qCDebug(QT_BT_QML) << "Minimal Discovery";
d->m_serviceAgent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery);
}
return d->m_serviceAgent->isActive();
case StopAction:
Q_ASSERT(d->m_currentState != StopAction && d->m_currentState != IdleAction);
if (d->m_currentState == DeviceDiscoveryAction) {
d->m_deviceAgent->stop();
// TODO Qt6 Crude hack below
// cannot use isActive() below due to pendingCancel logic
// we always wait for canceled() signal coming through or check
// for directly invoked cancel() response caused by stop() above
bool stillActive = !d->m_wasDirectDeviceAgentCancel;
d->m_wasDirectDeviceAgentCancel = false;
return stillActive;
} else {
d->m_serviceAgent->stop();
return d->m_serviceAgent->isActive();
}
default:
return true;
}
}
/*!
\qmlproperty bool BluetoothDiscoveryModel::running
......@@ -386,55 +563,23 @@ void QDeclarativeBluetoothDiscoveryModel::setRunning(bool running)
d->m_running = running;
if (!running) {
if (d->m_deviceAgent)
d->m_deviceAgent->stop();
if (d->m_serviceAgent)
d->m_serviceAgent->stop();
Action nextAction = IdleAction;
if (running) {
if (discoveryMode() == MinimalServiceDiscovery)
nextAction = MinimalServiceDiscoveryAction;
else if (discoveryMode() == FullServiceDiscovery)
nextAction = FullServiceDiscoveryAction;
else
nextAction = DeviceDiscoveryAction;
} else {
clearModel();
d->m_error = NoError;
if (d->m_discoveryMode == DeviceDiscovery) {
if (!d->m_deviceAgent) {
d->m_deviceAgent = new QBluetoothDeviceDiscoveryAgent(this);
connect(d->m_deviceAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
connect(d->m_deviceAgent, SIGNAL(finished()), this, SLOT(finishedDiscovery()));
connect(d->m_deviceAgent, SIGNAL(canceled()), this, SLOT(finishedDiscovery()));
connect(d->m_deviceAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(errorDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::Error)));
}
d->m_deviceAgent->start();
} else {
if (!d->m_serviceAgent) {
d->m_serviceAgent = new QBluetoothServiceDiscoveryAgent(this);
connect(d->m_serviceAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
connect(d->m_serviceAgent, SIGNAL(finished()), this, SLOT(finishedDiscovery()));
connect(d->m_serviceAgent, SIGNAL(canceled()), this, SLOT(finishedDiscovery()));
connect(d->m_serviceAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)), this, SLOT(errorDiscovery(QBluetoothServiceDiscoveryAgent::Error)));
}
d->m_serviceAgent->setRemoteAddress(QBluetoothAddress(d->m_remoteAddress));
d->m_serviceAgent->clear();
if (!d->m_uuid.isEmpty())
d->m_serviceAgent->setUuidFilter(QBluetoothUuid(d->m_uuid));
if (discoveryMode() == FullServiceDiscovery) {
//qDebug() << "Full Discovery";
d->m_serviceAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
} else {
//qDebug() << "Minimal Discovery";
d->m_serviceAgent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery);
}
// we could not start service discovery
if (!d->m_serviceAgent->isActive()) {
d->m_running = false;
errorDiscovery(d->m_serviceAgent->error());
return;
}
}
nextAction = StopAction;
}
Q_ASSERT(nextAction != IdleAction);
updateNextAction(nextAction);
transitionToNextAction();
qCDebug(QT_BT_QML) << "Running state:" << d->m_running;
emit runningChanged();
}
......
......@@ -111,6 +111,8 @@ public:
DiscoveryMode discoveryMode() const;
void setDiscoveryMode(DiscoveryMode discovery);
// TODO Qt 6 This property behaves synchronously but should really be
// asynchronous. The agents start/stop/restart is not immediate.
bool running() const;
void setRunning(bool running);
......@@ -139,8 +141,22 @@ private slots:
private:
void clearModel();
enum Action {
IdleAction = 0,
StopAction,
DeviceDiscoveryAction,
MinimalServiceDiscoveryAction,
FullServiceDiscoveryAction
};
bool toggleStartStop(Action action);
void updateNextAction(Action action);
void transitionToNextAction();
private:
QDeclarativeBluetoothDiscoveryModelPrivate* d;
friend class QDeclarativeBluetoothDiscoveryModelPrivate;
};
#endif // QDECLARATIVECONTACTMODEL_P_H
......@@ -34,6 +34,7 @@
#include <QtCore/QByteArray>
#include <QtCore/QDebug>
#include <stdio.h>
#include <string>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
......@@ -46,11 +47,14 @@
void usage()
{
fprintf(stderr, "Usage:\n");
fprintf(stderr, "\tsdpscanner <remote bdaddr> <local bdaddr> [Options]\n\n");
fprintf(stderr, "\tsdpscanner <remote bdaddr> <local bdaddr> [Options] ({uuids})\n\n");
fprintf(stderr, "Performs an SDP scan on remote device, using the SDP server\n"
"represented by the local Bluetooth device.\n\n"
"Options:\n"
" -p Show scan results in human-readable form\n");
" -p Show scan results in human-readable form\n"
" -u [list of uuids] List of uuids which should be scanned for.\n"
" Each uuid must be enclosed in {}.\n"
" If the list is empty PUBLIC_BROWSE_GROUP scan is used.\n");
}
#define BUFFER_SIZE 1024
......@@ -269,6 +273,7 @@ int main(int argc, char **argv)
}
bool showHumanReadable = false;
std::vector<std::string> targetServices;
for (int i = 3; i < argc; i++) {
if (argv[i][0] != '-') {
......@@ -281,12 +286,56 @@ int main(int argc, char **argv)
case 'p':
showHumanReadable = true;
break;
case 'u':
i++;
for ( ; i < argc && argv[i][0] == '{'; i++)
targetServices.push_back(argv[i]);
i--; // outer loop increments again
break;
default:
fprintf(stderr, "Wrong argument: %s\n", argv[i]);
usage();
return RETURN_USAGE;
}
}
std::vector<uuid_t> uuids;
for (std::vector<std::string>::const_iterator iter = targetServices.cbegin();
iter != targetServices.cend(); ++iter) {
uint128_t temp128;
uint16_t field1, field2, field3, field5;
uint32_t field0, field4;
fprintf(stderr, "Target scan for %s\n", (*iter).c_str());
if (sscanf((*iter).c_str(), "{%08x-%04hx-%04hx-%04hx-%08x%04hx}", &field0,
&field1, &field2, &field3, &field4, &field5) != 6) {
fprintf(stderr, "Skipping invalid uuid: %s\n", ((*iter).c_str()));
continue;
}
// we need uuid_t conversion based on
// http://www.spinics.net/lists/linux-bluetooth/msg20356.html
field0 = htonl(field0);
field4 = htonl(field4);
field1 = htons(field1);
field2 = htons(field2);
field3 = htons(field3);
field5 = htons(field5);
uint8_t* temp = (uint8_t*) &temp128;
memcpy(&temp[0], &field0, 4);
memcpy(&temp[4], &field1, 2);
memcpy(&temp[6], &field2, 2);
memcpy(&temp[8], &field3, 2);
memcpy(&temp[10], &field4, 4);
memcpy(&temp[14], &field5, 2);
uuid_t sdpUuid;
sdp_uuid128_create(&sdpUuid, &temp128);
uuids.push_back(sdpUuid);
}
sdp_session_t *session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY);
......@@ -301,27 +350,52 @@ int main(int argc, char **argv)
}
// set the filter for service matches
uuid_t publicBrowseGroupUuid;
sdp_uuid16_create(&publicBrowseGroupUuid, PUBLIC_BROWSE_GROUP);
sdp_list_t *serviceFilter;
serviceFilter = sdp_list_append(0, &publicBrowseGroupUuid);
if (uuids.empty()) {
fprintf(stderr, "Using PUBLIC_BROWSE_GROUP for SDP search\n");
uuid_t publicBrowseGroupUuid;
sdp_uuid16_create(&publicBrowseGroupUuid, PUBLIC_BROWSE_GROUP);
uuids.push_back(publicBrowseGroupUuid);
}
uint32_t attributeRange = 0x0000ffff; //all attributes
sdp_list_t *attributes;
attributes = sdp_list_append(0, &attributeRange);
sdp_list_t *sdpResults, *previous;
result = sdp_service_search_attr_req(session, serviceFilter,
sdp_list_t *sdpResults, *sdpIter;
sdp_list_t *totalResults = NULL;
sdp_list_t* serviceFilter;
for (uint i = 0; i < uuids.size(); ++i) {
serviceFilter = sdp_list_append(0, &uuids[i]);
result = sdp_service_search_attr_req(session, serviceFilter,
SDP_ATTR_REQ_RANGE,
attributes, &sdpResults);
sdp_list_free(attributes, 0);
sdp_list_free(serviceFilter, 0);
sdp_list_free(serviceFilter, 0);
if (result != 0) {
fprintf(stderr, "sdp_service_search_attr_req failed\n");
sdp_list_free(attributes, 0);
sdp_close(session);
return RETURN_SDP_ERROR;
}
if (result != 0) {
fprintf(stderr, "sdp_service_search_attr_req failed\n");
sdp_close(session);
return RETURN_SDP_ERROR;
if (!sdpResults)
continue;
if (!totalResults) {
totalResults = sdpResults;
sdpIter = totalResults;
} else {
// attach each new result list to the end of totalResults
sdpIter->next = sdpResults;
}
while (sdpIter->next) // skip to end of list
sdpIter = sdpIter->next;
}
sdp_list_free(attributes, 0);
// start XML generation from the front
sdpResults = totalResults;
QByteArray total;
while (sdpResults) {
......@@ -330,9 +404,9 @@ int main(int argc, char **argv)
const QByteArray xml = parseSdpRecord(record);
total += xml;
previous = sdpResults;
sdpIter = sdpResults;
sdpResults = sdpResults->next;
free(previous);
free(sdpIter);
sdp_record_free(record);
}
......