/**************************************************************************** ** ** 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$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, 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. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qbluetoothserviceinfo.h" #include "qbluetoothserviceinfo_p.h" #include #include #include QTM_BEGIN_NAMESPACE QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() :serviceRecord(0) { } QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() { // Closing the database session will cause all // registered services removed from the SDP database. if (sdpDatabase.SubSessionHandle() != 0) sdpDatabase.Close(); if (sdpSession.Handle() != 0) sdpSession.Close(); } static void convertL(MSdpElementBuilder *list, const QList &vList) { list->StartListL(); foreach (const QVariant &v, vList) { switch (v.type()) { case QMetaType::Void: list->BuildNilL(); break; case QMetaType::UChar: list->BuildUintL(TSdpIntBuf(v.toUInt())); break; case QMetaType::UShort: list->BuildUintL(TSdpIntBuf(v.toUInt())); break; case QMetaType::UInt: list->BuildUintL(TSdpIntBuf(v.toUInt())); break; case QMetaType::Char: list->BuildIntL(TSdpIntBuf(v.toInt())); break; case QMetaType::Short: list->BuildIntL(TSdpIntBuf(v.toInt())); break; case QMetaType::Int: list->BuildIntL(TSdpIntBuf(v.toInt())); break; case QMetaType::QString: list->BuildStringL(TPtrC8(reinterpret_cast(v.toString().toLocal8Bit().constData()))); break; case QMetaType::Bool: list->BuildBooleanL(v.toBool()); break; case QMetaType::QUrl: list->BuildURLL(TPtrC8(reinterpret_cast(v.toUrl().toString().toLocal8Bit().constData()))); break; case QVariant::UserType: if (v.userType() == qMetaTypeId()) { QBluetoothUuid uuid = v.value(); switch (uuid.minimumSize()) { case 2: list->BuildUUIDL(uuid.toUInt16()); break; case 4: list->BuildUUIDL(uuid.toUInt32()); break; case 16: { TUint32 *dataPointer = (TUint32*)uuid.toUInt128().data; TUint32 hH = qToBigEndian(*(dataPointer++)); TUint32 hL = qToBigEndian(*(dataPointer++)); TUint32 lH = qToBigEndian(*(dataPointer++)); TUint32 lL = qToBigEndian(*(dataPointer)); TUUID sUuid(hH, hL, lH, lL); list->BuildUUIDL(sUuid); break; } } } else if (v.userType() == qMetaTypeId()) { convertL(list->BuildDESL(), v.value()); } else if (v.userType() == qMetaTypeId()) { convertL(list->BuildDEAL(), v.value()); } break; default: qDebug() << __FUNCTION__ << "Don't know how to handle variant type" << v.type(); } } list->EndListL(); } void QBluetoothServiceInfoPrivate::setRegisteredAttribute(quint16 attributeId, const QVariant &value) const { TRAPD(err, setRegisteredAttributeL(attributeId, value)); if (err != KErrNone) { qWarning("Could not set attributes SDP session (error %d).", err); } } void QBluetoothServiceInfoPrivate::setRegisteredAttributeL(quint16 attributeId, const QVariant &value) const { CSdpAttrValue *sdpValue = 0; switch (value.type()) { case QMetaType::Void: sdpValue = CSdpAttrValueNil::NewNilL(); break; case QMetaType::UChar: sdpValue = CSdpAttrValueUint::NewUintL(TSdpIntBuf(value.toUInt())); break; case QMetaType::UShort: sdpValue = CSdpAttrValueUint::NewUintL(TSdpIntBuf(value.toUInt())); break; case QMetaType::UInt: sdpValue = CSdpAttrValueUint::NewUintL(TSdpIntBuf(value.toUInt())); break; case QMetaType::Char: sdpValue = CSdpAttrValueInt::NewIntL(TSdpIntBuf(value.toInt())); break; case QMetaType::Short: sdpValue = CSdpAttrValueInt::NewIntL(TSdpIntBuf(value.toInt())); break; case QMetaType::Int: sdpValue = CSdpAttrValueInt::NewIntL(TSdpIntBuf(value.toInt())); break; case QMetaType::QString: sdpValue = CSdpAttrValueString::NewStringL(TPtrC8(reinterpret_cast(value.toString().toLocal8Bit().constData()))); break; case QMetaType::Bool: sdpValue = CSdpAttrValueBoolean::NewBoolL(value.toBool()); break; case QMetaType::QUrl: sdpValue = CSdpAttrValueURL::NewURLL(TPtrC8(reinterpret_cast(value.toUrl().toString().toLocal8Bit().constData()))); break; case QVariant::UserType: if (value.userType() == qMetaTypeId()) { QBluetoothUuid uuid = value.value(); switch (uuid.minimumSize()) { case 2: sdpValue = CSdpAttrValueUUID::NewUUIDL(uuid.toUInt16()); break; case 4: sdpValue = CSdpAttrValueUUID::NewUUIDL(uuid.toUInt32()); break; case 16: { TUint32 *dataPointer = (TUint32*)uuid.toUInt128().data; TUint32 hH = qToBigEndian(*(dataPointer++)); TUint32 hL = qToBigEndian(*(dataPointer++)); TUint32 lH = qToBigEndian(*(dataPointer++)); TUint32 lL = qToBigEndian(*(dataPointer)); TUUID sUuid(hH, hL, lH, lL); sdpValue = CSdpAttrValueUUID::NewUUIDL(sUuid); break; } } } else if (value.userType() == qMetaTypeId()) { CSdpAttrValueDES *sequence = CSdpAttrValueDES::NewDESL(0); CleanupStack::PushL(sequence); convertL(sequence, value.value()); sdpValue = sequence; CleanupStack::Pop(sequence); } else if (value.userType() == qMetaTypeId()) { CSdpAttrValueDEA *alternative = CSdpAttrValueDEA::NewDEAL(0); CleanupStack::PushL(alternative); convertL(alternative, value.value()); sdpValue = alternative; CleanupStack::Pop(alternative); } break; default: qDebug() << __FUNCTION__ << "Don't know how to handle variant type" << value.type(); } if (sdpValue) { CleanupStack::PushL(sdpValue); sdpDatabase.UpdateAttributeL(serviceRecord, attributeId, *sdpValue); CleanupStack::PopAndDestroy(sdpValue); } } void QBluetoothServiceInfoPrivate::removeRegisteredAttribute(quint16 attributeId) const { TRAPD(err, sdpDatabase.DeleteAttributeL(serviceRecord, attributeId)); if (err != KErrNone) { qWarning("Could not remove registered attribute (error %d).", err); } } bool QBluetoothServiceInfoPrivate::ensureSdpConnection() const { if (sdpSession.Handle() == 0) { int error = sdpSession.Connect(); if (error != KErrNone) { qWarning("Could not open connection to SDP session (error %d).", error); return false; } } if (sdpDatabase.SubSessionHandle() == 0) { int error = sdpDatabase.Open(sdpSession); if (error != KErrNone) { qWarning("Could not open connection to SDP database (error %d).", error); return false; } } return true; } bool QBluetoothServiceInfo::isRegistered() const { Q_D(const QBluetoothServiceInfo); return d->serviceRecord != 0; } bool QBluetoothServiceInfo::registerService() const { Q_D(const QBluetoothServiceInfo); if (d->serviceRecord != 0) return false; if (!d->ensureSdpConnection()) return false; TRAPD(err, d->sdpDatabase.CreateServiceRecordL(0, d->serviceRecord)); if (err != KErrNone) return false; foreach (quint16 id, d->attributes.keys()) { // Changing service record handle causes serious problems // on Symbian devices. Hence passing the value update. if (id != ServiceRecordHandle) d->setRegisteredAttribute(id, d->attributes[id]); } return true; } bool QBluetoothServiceInfo::unregisterService() const { Q_D(const QBluetoothServiceInfo); if (!d->ensureSdpConnection()) return false; TRAPD(err, d->sdpDatabase.DeleteRecordL(d->serviceRecord)); if (err != KErrNone) return false; d->serviceRecord = 0; return true; } QTM_END_NAMESPACE