From 672413c65685883136f4572d34f7d08f7b952641 Mon Sep 17 00:00:00 2001 From: Nedim Hadzic Date: Thu, 17 Oct 2013 15:27:45 +0200 Subject: Implemented new approach for Bluetooth service discovery Using bt_rdev_sdp_search_async function from NDK btdevice.h header. This will provide option to obtain more information about the service for 10.2.1 NDK and image versions. Change-Id: I372ebc0247a8474360ac291fe0215b6a0be59a15 Reviewed-by: Fabian Bumberger Reviewed-by: Alex Blasche --- src/bluetooth/bluetooth.pro | 1 + src/bluetooth/qbluetoothservicediscoveryagent_p.h | 5 + .../qbluetoothservicediscoveryagent_qnx.cpp | 123 ++++++++++++++++++++- 3 files changed, 128 insertions(+), 1 deletion(-) (limited to 'src/bluetooth') diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro index 98f3b3be..7c9f9f00 100644 --- a/src/bluetooth/bluetooth.pro +++ b/src/bluetooth/bluetooth.pro @@ -79,6 +79,7 @@ config_bluez:qtHaveModule(dbus) { config_btapi10_2_1 { DEFINES += QT_QNX_BT_BLUETOOTH + LIBS += -lbtapi } PRIVATE_HEADERS += \ diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h index 697fe662..2b396786 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_p.h +++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h @@ -64,6 +64,7 @@ QT_END_NAMESPACE #include #include #include +#include #endif QT_BEGIN_NAMESPACE @@ -124,11 +125,15 @@ private Q_SLOTS: void controlReply(ppsResult result); void controlEvent(ppsResult result); void queryTimeout(); +#ifdef QT_QNX_BT_BLUETOOTH + static void deviceServicesDiscoveryCallback(bt_sdp_list_t *, void *, uint8_t); +#endif private: int m_rdfd; QSocketNotifier *rdNotifier; QTimer m_queryTimer; + bool m_btInitialized; #endif public: diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_qnx.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_qnx.cpp index c271a47f..16b471da 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_qnx.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_qnx.cpp @@ -49,18 +49,94 @@ #include "qbluetoothuuid.h" #include +#ifdef QT_QNX_BT_BLUETOOTH +#include +#include +#endif #include QT_BEGIN_NAMESPACE +#ifdef QT_QNX_BT_BLUETOOTH +void QBluetoothServiceDiscoveryAgentPrivate::deviceServicesDiscoveryCallback(bt_sdp_list_t *result, void *user_data, uint8_t error) +{ + if (error != 0) + qWarning() << "Error received in callback: " << errno << strerror(errno); + QPointer *classPointer = static_cast *>(user_data); + if (classPointer->isNull()) { + qBBBluetoothDebug() << "Pointer received in callback is null"; + return; + } + QBluetoothServiceDiscoveryAgentPrivate *p = classPointer->data(); + if ( result == 0) { + qBBBluetoothDebug() << "Result received in callback is null."; + p->errorString = QBluetoothServiceDiscoveryAgent::tr("Result received in callback is null."); + p->error = QBluetoothServiceDiscoveryAgent::InputOutputError; + p->q_ptr->error(p->error); + p->_q_serviceDiscoveryFinished(); + return; + } + + for (int i = 0; i < result->num_records; i++) { + bt_sdp_record_t rec = result->record[i]; + QBluetoothServiceInfo serviceInfo; + serviceInfo.setDevice(p->discoveredDevices.at(0)); + serviceInfo.setServiceName(rec.name); + serviceInfo.setServiceDescription(rec.description); + //serviceInfo.setServiceAvailability(rec.availability); + serviceInfo.setServiceProvider(QString(rec.provider)); + QBluetoothServiceInfo::Sequence protocolDescriptorList; + for ( int j = 0; j < rec.num_protocol; j++) { + bt_sdp_prot_t protoc = rec.protocol[j]; + QString protocolUuid(protoc.uuid); + protocolUuid = QStringLiteral("0x") + protocolUuid; + QBluetoothUuid pUuid(protocolUuid.toUShort(0,0)); + protocolDescriptorList << QVariant::fromValue(pUuid); + for ( int k = 0; k < 2; k++) + protocolDescriptorList << QVariant::fromValue(QString::fromLatin1(protoc.parm[k])); + } + serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); + qBBBluetoothDebug() << "Service name " << rec.name << " Description: " << rec.description << "uuid " << rec.serviceId << "provider: " << rec.provider; + qBBBluetoothDebug() << "num protocol " << rec.num_protocol << "record handle " << rec.record_handle << "class id" << rec.num_classId << "availability " << rec.availability << rec.num_language; + + QList serviceClassId; + + for (int j = 0; j < rec.num_classId; j++) { + bt_sdp_class_t uuid = rec.classId[j]; + qBBBluetoothDebug() << "uuid: " << uuid.uuid; + QString protocolUuid(uuid.uuid); + protocolUuid = QStringLiteral("0x") + protocolUuid; + QBluetoothUuid Uuid(protocolUuid.toUShort(0,0)); + if (j == 0) { + serviceInfo.setServiceUuid(Uuid); + //Check if the UUID is in the uuidFilter + if (!p->uuidFilter.isEmpty() && !p->uuidFilter.contains(Uuid)) + continue; + } + serviceClassId << Uuid; + } + serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, QVariant::fromValue(serviceClassId)); + serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, + QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup)); + p->q_ptr->serviceDiscovered(serviceInfo); + } + p->_q_serviceDiscoveryFinished(); + //delete p; + //delete classPointer; +} +#endif + QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &deviceAdapter) - : m_rdfd(-1), rdNotifier(0), error(QBluetoothServiceDiscoveryAgent::NoError), deviceAddress(deviceAdapter), state(Inactive), + : m_rdfd(-1), rdNotifier(0), m_btInitialized(false), error(QBluetoothServiceDiscoveryAgent::NoError), deviceAddress(deviceAdapter), state(Inactive), deviceDiscoveryAgent(0), mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery) { ppsRegisterControl(); connect(&m_queryTimer, SIGNAL(timeout()), this, SLOT(queryTimeout())); ppsRegisterForEvent(QStringLiteral("service_updated"), this); + //Needed for connecting signals and slots from static function + qRegisterMetaType("QBluetoothServiceInfo"); + qRegisterMetaType("QBluetoothServiceDiscoveryAgent::Error"); } QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() @@ -72,6 +148,50 @@ QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate( void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) { Q_Q(QBluetoothServiceDiscoveryAgent); +#ifdef QT_QNX_BT_BLUETOOTH + errno = 0; + if (!m_btInitialized) { + if (bt_device_init( 0 ) < 0) { + qWarning() << "Failed to initialize bluetooth stack."; + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Failed to open to initialize bluetooth stack"); + q->error(error); + _q_serviceDiscoveryFinished(); + return; + } + } + m_btInitialized = true; + errno = 0; + bt_remote_device_t *remoteDevice = bt_rdev_get_device(address.toString().toLocal8Bit().constData()); + int deviceType = bt_rdev_get_type(remoteDevice); + if (deviceType == -1) { + qWarning() << "Could not retrieve remote device (address is 00:00:00:00:00:00)."; + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Could not retrieve remote device (address is 00:00:00:00:00:00)."); + q->error(error); + _q_serviceDiscoveryFinished(); + return; + } + /* + * In case remote device is LE device, calling bt_rdev_sdp_search_async will cause memory fault. + */ + + if ( deviceType >1) { + errno = 0; + QPointer *classPointer = new QPointer(this); + int b = bt_rdev_sdp_search_async(remoteDevice, 0, &(this->deviceServicesDiscoveryCallback), classPointer); + if ( b != 0 ) { + qWarning() << "Failed to run search on device: " << address.toString(); + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QBluetoothServiceDiscoveryAgent::tr(strerror(errno)); + q->error(error); + _q_serviceDiscoveryFinished(); + return; + } + } + else + _q_serviceDiscoveryFinished(); +#else qBBBluetoothDebug() << "Starting Service discovery for" << address.toString(); const char *filePath = QByteArray("/pps/services/bluetooth/remote_devices/").append(address.toString().toUtf8().constData()).constData(); if ((m_rdfd = qt_safe_open(filePath, O_RDONLY)) == -1) { @@ -98,6 +218,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr } m_queryTimer.start(10000); ppsSendControlMessage("service_query", QStringLiteral("{\"addr\":\"%1\"}").arg(address.toString()), this); +#endif } void QBluetoothServiceDiscoveryAgentPrivate::stop() -- cgit v1.2.3