summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp')
-rw-r--r--src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp387
1 files changed, 387 insertions, 0 deletions
diff --git a/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp b/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp
new file mode 100644
index 00000000..96fa4245
--- /dev/null
+++ b/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp
@@ -0,0 +1,387 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// INCLUDE FILES
+#include "bluetoothlinkmanagerdevicediscoverer.h"
+#include "qbluetoothaddress.h"
+#include "qbluetoothdeviceinfo.h"
+#include "qbluetoothuuid.h"
+
+#include <qstring.h>
+#ifdef EIR_SUPPORTED
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+#include "utils_symbian_p.h"
+#include <qdebug.h>
+
+/*! \internal
+ \class BluetoothLinkManagerDeviceDiscoverer
+ \brief The BluetoothLinkManagerDeviceDiscoverer class searches other bluetooth devices.
+ \since 5.0
+
+ \ingroup connectivity-bluetooth
+ \inmodule QtConnectivity
+ \internal
+
+ BluetoothLinkManagerDeviceDiscoverer is an Symbian ActiveObject derived class that discovers
+ other Bluetooth devices using "BTLinkManager" protocol.
+
+ When Bluetoothdevices are found signal deviceDiscovered(QBluetoothDeviceInfo &) is emitted. When
+ all devices are found (or none) signal deviceDiscoveryComplete() is emitted.
+
+ In case of an error signal linkManagerError(int error) is emitted. In the case of errorSignal
+ one should consider deleting this class and creating it again.
+*/
+
+_LIT(KBTLinkManagerTxt,"BTLinkManager");
+
+BluetoothLinkManagerDeviceDiscoverer::BluetoothLinkManagerDeviceDiscoverer(RSocketServ &socketServer,QObject *parent)
+ : QObject(parent)
+ , CActive(CActive::EPriorityStandard)
+ , m_socketServer(socketServer)
+ , m_pendingCancel(false), m_pendingStart(false), m_discoveryType (0)
+{
+ TInt result;
+
+ /* find Bluetooth protocol */
+ TProtocolDesc protocol;
+ result = m_socketServer.FindProtocol(KBTLinkManagerTxt(),protocol);
+ if (result == KErrNone) {
+ /* Create and initialise an RHostResolver */
+ result = m_hostResolver.Open(m_socketServer, protocol.iAddrFamily, protocol.iProtocol);
+ }
+ // check possible error
+ if (result != KErrNone) {
+ setError(result);
+ }
+
+ //add this active object to scheduler
+ CActiveScheduler::Add(this);
+}
+
+BluetoothLinkManagerDeviceDiscoverer::~BluetoothLinkManagerDeviceDiscoverer()
+{
+ // cancel active object
+ Cancel();
+ m_hostResolver.Close();
+}
+/*!
+ Starts up device discovery. When devices are discovered signal deviceDiscovered is emitted.
+ After signal deviceDiscoveryComplete() is emitted new discovery request can be made.
+*/
+void BluetoothLinkManagerDeviceDiscoverer::startDiscovery(const uint discoveryType)
+{
+ m_discoveryType = discoveryType;
+
+ if(m_pendingCancel == true) {
+ m_pendingStart = true;
+ m_pendingCancel = false;
+ return;
+ }
+ if (!IsActive()) {
+ m_addr.SetIAC( discoveryType );
+#ifdef EIR_SUPPORTED
+ m_addr.SetAction(KHostResInquiry | KHostResName | KHostResIgnoreCache | KHostResEir);
+#else
+ m_addr.SetAction(KHostResInquiry | KHostResName | KHostResIgnoreCache);
+#endif
+ m_hostResolver.GetByAddress(m_addr, m_entry, iStatus);
+ SetActive();
+ }
+}
+
+void BluetoothLinkManagerDeviceDiscoverer::stopDiscovery()
+{
+ m_pendingStart = false;
+ if (IsActive() && !m_pendingCancel) {
+ m_pendingCancel = true;
+ m_hostResolver.Cancel();
+ }
+}
+
+/*!
+ Informs that our request has been prosessed and the data is available to be used.
+*/
+void BluetoothLinkManagerDeviceDiscoverer::RunL()
+{
+ qDebug() << __PRETTY_FUNCTION__ << iStatus.Int();
+ switch (iStatus.Int()) {
+ case KErrNone: // found device
+ if (m_pendingCancel && !m_pendingStart) {
+ m_pendingCancel = false;
+ emit canceled();
+ } else {
+ m_pendingCancel = false;
+ m_pendingStart = false;
+ // get next (possible) discovered device
+ m_hostResolver.Next(m_entry, iStatus);
+ SetActive();
+ emit deviceDiscovered(currentDeviceDataToQBluetoothDeviceInfo());
+ }
+ break;
+ case KErrHostResNoMoreResults: // done with search
+ if (m_pendingCancel && !m_pendingStart){ // search was canceled prior to finishing
+ m_pendingCancel = false;
+ m_pendingStart = false;
+ emit canceled();
+ }
+ else if (m_pendingStart){ // search was restarted just prior to finishing
+ m_pendingStart = false;
+ m_pendingCancel = false;
+ startDiscovery(m_discoveryType);
+ } else { // search completed normally
+ m_pendingStart = false;
+ m_pendingCancel = false;
+ emit deviceDiscoveryComplete();
+ }
+ break;
+ case KErrCancel: // user canceled search
+ if (m_pendingStart){ // user activated search after cancel
+ m_pendingStart = false;
+ m_pendingCancel = false;
+ startDiscovery(m_discoveryType);
+ } else { // standard user cancel case
+ m_pendingCancel = false;
+ emit canceled();
+ }
+ break;
+ default:
+ m_pendingStart = false;
+ m_pendingCancel = false;
+ setError(iStatus.Int());
+ }
+}
+/*!
+ Cancel current request.
+*/
+void BluetoothLinkManagerDeviceDiscoverer::DoCancel()
+{
+ m_hostResolver.Cancel();
+}
+
+TInt BluetoothLinkManagerDeviceDiscoverer::RunError(TInt aError)
+{
+ setError(aError);
+ return KErrNone;
+}
+
+bool BluetoothLinkManagerDeviceDiscoverer::isReallyActive() const
+{
+ if(m_pendingStart)
+ return true;
+ if(m_pendingCancel)
+ return false;
+ return IsActive();
+}
+
+/*!
+ Transforms Symbian device name, address and service classes to QBluetootDeviceInfo.
+*/
+QBluetoothDeviceInfo BluetoothLinkManagerDeviceDiscoverer::currentDeviceDataToQBluetoothDeviceInfo() const
+{
+ // extract device information from results and map them to QBluetoothDeviceInfo
+#ifdef EIR_SUPPORTED
+ TBluetoothNameRecordWrapper eir(m_entry());
+ TInt bufferlength = 0;
+ TInt err = KErrNone;
+ QString deviceName;
+ bufferlength = eir.GetDeviceNameLength();
+
+ if (bufferlength > 0) {
+ TBool nameComplete;
+ HBufC *deviceNameBuffer = 0;
+ TRAP(err,deviceNameBuffer = HBufC::NewL(bufferlength));
+ if(err)
+ deviceName = QString();
+ else
+ {
+ TPtr ptr = deviceNameBuffer->Des();
+ err = eir.GetDeviceName(ptr,nameComplete);
+ if (err == KErrNone /*&& nameComplete*/)
+ {
+ if(!nameComplete)
+ qWarning() << "device name incomplete";
+ // isn't it better to get an incomplete name than getting nothing?
+ deviceName = QString::fromUtf16(ptr.Ptr(), ptr.Length()).toUpper();
+ }
+ else
+ deviceName = QString();
+ delete deviceNameBuffer;
+ }
+ }
+
+ QList<QBluetoothUuid> serviceUidList;
+ RExtendedInquiryResponseUUIDContainer uuidContainer;
+ QBluetoothDeviceInfo::DataCompleteness completenes = QBluetoothDeviceInfo::DataUnavailable;
+
+ if (eir.GetServiceClassUuids(uuidContainer) == KErrNone) {
+ TInt uuidCount = uuidContainer.UUIDs().Count();
+ if (uuidCount > 0) {
+ for (int i = 0; i < uuidCount; ++i) {
+ TPtrC8 shortFormUUid(uuidContainer.UUIDs()[i].ShortestForm());
+ if (shortFormUUid.Size() == 2) {
+ QBluetoothUuid uuid(ntohs(*reinterpret_cast<const quint16 *>(shortFormUUid.Ptr())));
+ if (uuidContainer.GetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID16))
+ completenes = QBluetoothDeviceInfo::DataComplete;
+ else
+ completenes = QBluetoothDeviceInfo::DataIncomplete;
+ serviceUidList.append(uuid);
+ }else if (shortFormUUid.Size() == 4) {
+ QBluetoothUuid uuid(ntohl(*reinterpret_cast<const quint32 *>(shortFormUUid.Ptr())));
+ if (uuidContainer.GetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID32))
+ completenes = QBluetoothDeviceInfo::DataComplete;
+ else
+ completenes = QBluetoothDeviceInfo::DataIncomplete;
+ serviceUidList.append(uuid);
+ }else if (shortFormUUid.Size() == 16) {
+ QBluetoothUuid uuid(*reinterpret_cast<const quint128 *>(shortFormUUid.Ptr()));
+ if (uuidContainer.GetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID128))
+ completenes = QBluetoothDeviceInfo::DataComplete;
+ else
+ completenes = QBluetoothDeviceInfo::DataIncomplete;
+ serviceUidList.append(uuid);
+ }
+ }
+ }
+ }
+ uuidContainer.Close();
+
+ bufferlength = 0;
+ QByteArray manufacturerData;
+ bufferlength = eir.GetVendorSpecificDataLength();
+
+ if (bufferlength > 0) {
+ HBufC8 *msd = 0;
+ TRAP(err,msd = HBufC8::NewL(bufferlength));
+ if(err)
+ manufacturerData = QByteArray();
+ else
+ {
+ TPtr8 temp = msd->Des();
+ if (eir.GetVendorSpecificData(temp))
+ manufacturerData = s60Desc8ToQByteArray(temp);
+ else
+ manufacturerData = QByteArray();
+ delete msd;
+ }
+ }
+
+ // Get transmission power level
+ TInt8 transmissionPowerLevel = 0;
+ eir.GetTxPowerLevel(transmissionPowerLevel);
+
+ // unique address of the device
+ const TBTDevAddr symbianDeviceAddress = static_cast<TBTSockAddr> (m_entry().iAddr).BTAddr();
+ QBluetoothAddress bluetoothAddress = qTBTDevAddrToQBluetoothAddress(symbianDeviceAddress);
+
+ // format symbian major/minor numbers
+ quint32 deviceClass = qTPackSymbianDeviceClass(m_addr);
+
+ QBluetoothDeviceInfo deviceInfo(bluetoothAddress, deviceName, deviceClass);
+
+ deviceInfo.setRssi(transmissionPowerLevel);
+ deviceInfo.setServiceUuids(serviceUidList, completenes);
+ deviceInfo.setManufacturerSpecificData(manufacturerData);
+#else
+ // device name
+ THostName symbianDeviceName = m_entry().iName;
+ QString deviceName = QString::fromUtf16(symbianDeviceName.Ptr(), symbianDeviceName.Length()).toUpper();
+
+ // unique address of the device
+ const TBTDevAddr symbianDeviceAddress = static_cast<TBTSockAddr> (m_entry().iAddr).BTAddr();
+ QBluetoothAddress bluetoothAddress = qTBTDevAddrToQBluetoothAddress(symbianDeviceAddress);
+
+ // format symbian major/minor numbers
+ quint32 deviceClass = qTPackSymbianDeviceClass(m_addr);
+
+ QBluetoothDeviceInfo deviceInfo(bluetoothAddress, deviceName, deviceClass);
+
+ if (m_addr.Rssi())
+ deviceInfo.setRssi(m_addr.Rssi());
+#endif
+ if (!deviceInfo.rssi())
+ deviceInfo.setRssi(1);
+
+ deviceInfo.setCached(false); //TODO cache support missing from devicediscovery API
+ //qDebug()<< "Discovered device: name="<< deviceName <<", address=" << bluetoothAddress.toString() <<", class=" << deviceClass;
+ return deviceInfo;
+}
+
+void BluetoothLinkManagerDeviceDiscoverer::setError(int errorCode)
+{
+ qDebug() << __PRETTY_FUNCTION__ << "errorCode=" << errorCode;
+ QString errorString;
+ switch (errorCode) {
+ case KLinkManagerErrBase:
+ errorString.append("Link manager base error value or Insufficient baseband resources error value");
+ emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString);
+ break;
+ case KErrProxyWriteNotAvailable:
+ errorString.append("Proxy write not available error value");
+ emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString);
+ break;
+ case KErrReflexiveBluetoothLink:
+ errorString.append("Reflexive BT link error value");
+ emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString);
+ break;
+ case KErrPendingPhysicalLink:
+ errorString.append("Physical link connection already pending when trying to connect the physical link");
+ emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString);
+ break;
+ case KErrNotReady:
+ errorString.append("KErrNotReady");
+ emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString);
+ case KErrCancel:
+ errorString.append("KErrCancel");
+ qDebug() << "emitting canceled";
+ emit canceled();
+ break;
+ case KErrNone:
+ // do nothing
+ break;
+ default:
+ errorString = QString("Symbian errorCode = %1").arg(errorCode);
+ emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString);
+ break;
+ }
+}
+#include "moc_bluetoothlinkmanagerdevicediscoverer.cpp"