void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service) { if (!serviceList.contains(service)) { qCWarning(QT_BT_ANDROID) << "Discovery of unknown service" << service.toString() << "not possible"; return; } if (!hub) return; //cut leading { and trailing } {xxx-xxx} QString tempUuid = service.toString(); tempUuid.chop(1); //remove trailing '}' tempUuid.remove(0, 1); //remove first '{' QAndroidJniEnvironment env; QAndroidJniObject uuid = QAndroidJniObject::fromString(tempUuid); bool result = hub->javaObject().callMethod<jboolean>("discoverServiceDetails", "(Ljava/lang/String;)Z", uuid.object<jstring>()); if (!result) { QSharedPointer<QLowEnergyServicePrivate> servicePrivate = serviceList.value(service); if (!servicePrivate.isNull()) { servicePrivate->setError(QLowEnergyService::UnknownError); servicePrivate->setState(QLowEnergyService::DiscoveryRequired); } qCWarning(QT_BT_ANDROID) << "Cannot discover details for" << service.toString(); return; } qCDebug(QT_BT_ANDROID) << "Discovery of" << service << "started"; }
void tst_QBluetoothUuid::tst_assignment() { QBluetoothUuid uuid(QBluetoothUuid::PublicBrowseGroup); { QBluetoothUuid copy = uuid; QCOMPARE(uuid.toUInt16(), copy.toUInt16()); } { QBluetoothUuid copy1; QBluetoothUuid copy2; QVERIFY(copy1.isNull()); QVERIFY(copy2.isNull()); copy1 = copy2 = uuid; QVERIFY(!copy1.isNull()); QVERIFY(!copy2.isNull()); QCOMPARE(uuid.toUInt16(), copy1.toUInt16()); QCOMPARE(uuid.toUInt16(), copy2.toUInt16()); } }
/*! Returns the type of the descriptor. \sa name() */ QBluetoothUuid::DescriptorType QLowEnergyDescriptor::type() const { const QBluetoothUuid u = uuid(); bool ok = false; quint16 shortUuid = u.toUInt16(&ok); if (!ok) return QBluetoothUuid::UnknownDescriptorType; switch (shortUuid) { case QBluetoothUuid::CharacteristicExtendedProperties: case QBluetoothUuid::CharacteristicUserDescription: case QBluetoothUuid::ClientCharacteristicConfiguration: case QBluetoothUuid::ServerCharacteristicConfiguration: case QBluetoothUuid::CharacteristicPresentationFormat: case QBluetoothUuid::CharacteristicAggregateFormat: case QBluetoothUuid::ValidRange: case QBluetoothUuid::ExternalReportReference: case QBluetoothUuid::ReportReference: return (QBluetoothUuid::DescriptorType) shortUuid; default: break; } return QBluetoothUuid::UnknownDescriptorType; }
bool ppsSendControlMessage(const char *msg, int service, const QBluetoothUuid &uuid, const QString &address, const QString &serviceName, QObject *sender, const int &subtype) { pps_encoder_t *encoder = beginCtrlMessage(msg, sender); pps_encoder_start_object(encoder, "dat"); pps_encoder_add_int(encoder, "service", service); if (subtype != -1) pps_encoder_add_int(encoder, "subtype", subtype); pps_encoder_add_string(encoder, "uuid", uuid.toString().mid(1,36).toUtf8().constData()); if (!serviceName.isEmpty()) { pps_encoder_add_string(encoder, "name", serviceName.toUtf8().constData()); } if (!address.isEmpty()) { pps_encoder_add_string(encoder, "addr", address.toUtf8().constData()); } pps_encoder_error_t rese = pps_encoder_end_object(encoder); if (rese != PPS_ENCODER_OK) { errno = EPERM; return false; } return endCtrlMessage(encoder); }
void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode) { Q_Q(QBluetoothSocket); Q_UNUSED(openMode); qCDebug(QT_BT_QNX) << "Connecting socket"; m_peerAddress = address; #ifdef QT_QNX_BT_BLUETOOTH QByteArray b_uuid = uuid.toByteArray(); b_uuid = b_uuid.mid(1, b_uuid.length() - 2); socket = bt_spp_open(address.toString().toUtf8().data(), b_uuid.data(), false); if (socket == -1) { qCWarning(QT_BT_QNX) << "Could not connect to" << address.toString() << b_uuid << qt_error_string(errno); errorString = qt_error_string(errno); q->setSocketError(QBluetoothSocket::NetworkError); return; } delete readNotifier; delete connectWriteNotifier; readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read); QObject::connect(readNotifier, SIGNAL(activated(int)), this, SLOT(_q_readNotify())); connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q); QObject::connect(connectWriteNotifier, SIGNAL(activated(int)), this, SLOT(_q_writeNotify())); connecting = true; q->setOpenMode(openMode); #else m_uuid = uuid; if (isServerSocket) return; if (state != QBluetoothSocket::UnconnectedState) { qCDebug(QT_BT_QNX) << "Socket already connected"; return; } ppsSendControlMessage("connect_service", 0x1101, uuid, address.toString(), QString(), this, BT_SPP_CLIENT_SUBTYPE); ppsRegisterForEvent(QStringLiteral("service_connected"),this); ppsRegisterForEvent(QStringLiteral("get_mount_point_path"),this); #endif q->setSocketState(QBluetoothSocket::ConnectingState); }
void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QBluetoothDeviceInfo &remoteDevice, const QList<QBluetoothUuid> &uuids) { /* Android doesn't provide decent SDP data. A list of uuids is close to meaning-less * * The following approach is chosen: * - If we see an SPP service class and we see * one or more custom uuids we match them up. Such services will always be SPP services. * - If we see a custom uuid but no SPP uuid then we return * BluetoothServiceInfo instance with just a servuceUuid (no service class set) * - Any other service uuid will stand on its own. * */ Q_Q(QBluetoothServiceDiscoveryAgent); //find SPP and custom uuid QBluetoothUuid uuid; int sppIndex = -1; QVector<int> customUuids; for (int i = 0; i < uuids.count(); i++) { uuid = uuids.at(i); if (uuid.isNull()) continue; //check for SPP protocol bool ok = false; quint16 uuid16 = uuid.toUInt16(&ok); if (ok && uuid16 == QBluetoothUuid::SerialPort) sppIndex = i; //check for custom uuid if (uuid.minimumSize() == 16) customUuids.append(i); } for (int i = 0; i < uuids.count(); i++) { if (i == sppIndex && !customUuids.isEmpty()) continue; QBluetoothServiceInfo serviceInfo; serviceInfo.setDevice(remoteDevice); QBluetoothServiceInfo::Sequence protocolDescriptorList; { QBluetoothServiceInfo::Sequence protocol; protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap)); protocolDescriptorList.append(QVariant::fromValue(protocol)); } if (customUuids.contains(i) && sppIndex > -1) { //we have a custom uuid of service class type SPP //set rfcomm protocol QBluetoothServiceInfo::Sequence protocol; protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) << QVariant::fromValue(0); protocolDescriptorList.append(QVariant::fromValue(protocol)); //set SPP service class uuid QBluetoothServiceInfo::Sequence classId; classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort)); serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId); classId.prepend(QVariant::fromValue(uuids.at(i))); serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Serial Port Profile")); serviceInfo.setServiceUuid(uuids.at(i)); } else if (sppIndex == i && customUuids.isEmpty()) { //set rfcomm protocol QBluetoothServiceInfo::Sequence protocol; protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) << QVariant::fromValue(0); protocolDescriptorList.append(QVariant::fromValue(protocol)); QBluetoothServiceInfo::Sequence classId; classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort)); serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId); //also we need to set the custom uuid to the SPP uuid //otherwise QBluetoothSocket::connectToService() would fail due to a missing service uuid serviceInfo.setServiceUuid(uuids.at(i)); } else if (customUuids.contains(i)) { //custom uuid but no serial port serviceInfo.setServiceUuid(uuids.at(i)); } //Check if the UUID is in the uuidFilter if (!uuidFilter.isEmpty() && !uuidFilter.contains(serviceInfo.serviceUuid())) continue; serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup)); if (!customUuids.contains(i)) { //if we don't have custom uuid use it as class id as well QBluetoothServiceInfo::Sequence classId; classId << QVariant::fromValue(uuids.at(i)); serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); QBluetoothUuid::ServiceClassUuid clsId = static_cast<QBluetoothUuid::ServiceClassUuid>(uuids.at(i).toUInt16()); serviceInfo.setServiceName(QBluetoothUuid::serviceClassToString(clsId)); } //don't include the service if we already discovered it before if (!isDuplicatedService(serviceInfo)) { discoveredServices << serviceInfo; //qCDebug(QT_BT_ANDROID) << serviceInfo; emit q->serviceDiscovered(serviceInfo); } } }
static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute) { const QString unsignedFormat(QStringLiteral("0x%1")); switch (int(attribute.type())) { case QMetaType::Void: stream->writeEmptyElement(QStringLiteral("nil")); break; case QMetaType::UChar: stream->writeEmptyElement(QStringLiteral("uint8")); stream->writeAttribute(QStringLiteral("value"), unsignedFormat.arg(attribute.value<quint8>(), 2, 16, QLatin1Char('0'))); //stream->writeAttribute(QStringLiteral("name"), foo); break; case QMetaType::UShort: stream->writeEmptyElement(QStringLiteral("uint16")); stream->writeAttribute(QStringLiteral("value"), unsignedFormat.arg(attribute.value<quint16>(), 4, 16, QLatin1Char('0'))); //stream->writeAttribute(QStringLiteral("name"), foo); break; case QMetaType::UInt: stream->writeEmptyElement(QStringLiteral("uint32")); stream->writeAttribute(QStringLiteral("value"), unsignedFormat.arg(attribute.value<quint32>(), 8, 16, QLatin1Char('0'))); //stream->writeAttribute(QStringLiteral("name"), foo); break; case QMetaType::Char: stream->writeEmptyElement(QStringLiteral("int8")); stream->writeAttribute(QStringLiteral("value"), QString::number(attribute.value<uchar>(), 16)); //stream->writeAttribute(QStringLiteral("name"), foo); break; case QMetaType::Short: stream->writeEmptyElement(QStringLiteral("int16")); stream->writeAttribute(QStringLiteral("value"), QString::number(attribute.value<qint16>(), 16)); //stream->writeAttribute(QStringLiteral("name"), foo); break; case QMetaType::Int: stream->writeEmptyElement(QStringLiteral("int32")); stream->writeAttribute(QStringLiteral("value"), QString::number(attribute.value<qint32>(), 16)); //stream->writeAttribute(QStringLiteral("name"), foo); break; case QMetaType::QString: stream->writeEmptyElement(QStringLiteral("text")); if (/* require hex encoding */ false) { stream->writeAttribute(QStringLiteral("value"), QString::fromLatin1( attribute.value<QString>().toUtf8().toHex().constData())); stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("hex")); } else { stream->writeAttribute(QStringLiteral("value"), attribute.value<QString>()); stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("normal")); } //stream->writeAttribute(QStringLiteral("name"), foo); break; case QMetaType::Bool: stream->writeEmptyElement(QStringLiteral("boolean")); if (attribute.value<bool>()) stream->writeAttribute(QStringLiteral("value"), QStringLiteral("true")); else stream->writeAttribute(QStringLiteral("value"), QStringLiteral("false")); //stream->writeAttribute(QStringLiteral("name"), foo); break; case QMetaType::QUrl: stream->writeEmptyElement(QStringLiteral("url")); stream->writeAttribute(QStringLiteral("value"), attribute.value<QUrl>().toString()); //stream->writeAttribute(QStringLiteral("name"), foo); break; case QVariant::UserType: if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) { stream->writeEmptyElement(QStringLiteral("uuid")); QBluetoothUuid uuid = attribute.value<QBluetoothUuid>(); switch (uuid.minimumSize()) { case 0: stream->writeAttribute(QStringLiteral("value"), unsignedFormat.arg(quint16(0), 4, 16, QLatin1Char('0'))); break; case 2: stream->writeAttribute(QStringLiteral("value"), unsignedFormat.arg(uuid.toUInt16(), 4, 16, QLatin1Char('0'))); break; case 4: stream->writeAttribute(QStringLiteral("value"), unsignedFormat.arg(uuid.toUInt32(), 8, 16, QLatin1Char('0'))); break; case 16: stream->writeAttribute(QStringLiteral("value"), uuid.toString().mid(1, 36)); break; default: stream->writeAttribute(QStringLiteral("value"), uuid.toString().mid(1, 36)); } } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) { stream->writeStartElement(QStringLiteral("sequence")); const QBluetoothServiceInfo::Sequence *sequence = static_cast<const QBluetoothServiceInfo::Sequence *>(attribute.data()); foreach (const QVariant &v, *sequence) writeAttribute(stream, v); stream->writeEndElement(); } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode, int fallbackServiceChannel) { Q_Q(QBluetoothSocket); Q_UNUSED(openMode); qCDebug(QT_BT_ANDROID) << "connectToServiceConc()" << address.toString() << uuid.toString(); if (!adapter.isValid()) { qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth"; errorString = QBluetoothSocket::tr("Device does not support Bluetooth"); q->setSocketError(QBluetoothSocket::NetworkError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } const int state = adapter.callMethod<jint>("getState"); if (state != 12 ) { //BluetoothAdapter.STATE_ON qCWarning(QT_BT_ANDROID) << "Bt device offline"; errorString = QBluetoothSocket::tr("Device is powered off"); q->setSocketError(QBluetoothSocket::NetworkError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } QAndroidJniEnvironment env; QAndroidJniObject inputString = QAndroidJniObject::fromString(address.toString()); remoteDevice = adapter.callObjectMethod("getRemoteDevice", "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;", inputString.object<jstring>()); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); errorString = QBluetoothSocket::tr("Cannot access address %1", "%1 = Bt address e.g. 11:22:33:44:55:66").arg(address.toString()); q->setSocketError(QBluetoothSocket::HostNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } //cut leading { and trailing } {xxx-xxx} QString tempUuid = uuid.toString(); tempUuid.chop(1); //remove trailing '}' tempUuid.remove(0, 1); //remove first '{' inputString = QAndroidJniObject::fromString(tempUuid); QAndroidJniObject uuidObject = QAndroidJniObject::callStaticObjectMethod("java/util/UUID", "fromString", "(Ljava/lang/String;)Ljava/util/UUID;", inputString.object<jstring>()); socketObject = remoteDevice.callObjectMethod("createRfcommSocketToServiceRecord", "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;", uuidObject.object<jobject>()); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); socketObject = remoteDevice = QAndroidJniObject(); errorString = QBluetoothSocket::tr("Cannot connect to %1 on %2", "%1 = uuid, %2 = Bt address").arg(uuid.toString()).arg(address.toString()); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } socketObject.callMethod<void>("connect"); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); bool success = fallBackConnect(uuidObject, fallbackServiceChannel); if (!success) { errorString = QBluetoothSocket::tr("Connection to service failed"); socketObject = remoteDevice = QAndroidJniObject(); q->setSocketError(QBluetoothSocket::ServiceNotFoundError); q->setSocketState(QBluetoothSocket::UnconnectedState); env->ExceptionClear(); //just in case return; } } if (inputThread) { inputThread->deleteLater(); inputThread = 0; } inputStream = socketObject.callObjectMethod("getInputStream", "()Ljava/io/InputStream;"); outputStream = socketObject.callObjectMethod("getOutputStream", "()Ljava/io/OutputStream;"); if (env->ExceptionCheck() || !inputStream.isValid() || !outputStream.isValid()) { env->ExceptionDescribe(); env->ExceptionClear(); //close socket again socketObject.callMethod<void>("close"); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject(); errorString = QBluetoothSocket::tr("Obtaining streams for service failed"); q->setSocketError(QBluetoothSocket::NetworkError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } inputThread = new InputStreamThread(this); QObject::connect(inputThread, SIGNAL(dataAvailable()), q, SIGNAL(readyRead()), Qt::QueuedConnection); QObject::connect(inputThread, SIGNAL(error(int)), this, SLOT(inputThreadError(int)), Qt::QueuedConnection); if (!inputThread->run()) { //close socket again socketObject.callMethod<void>("close"); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject(); delete inputThread; inputThread = 0; errorString = QBluetoothSocket::tr("Input stream thread cannot be started"); q->setSocketError(QBluetoothSocket::NetworkError); q->setSocketState(QBluetoothSocket::UnconnectedState); return; } // only unbuffered behavior supported at this stage q->setOpenMode(QIODevice::ReadWrite|QIODevice::Unbuffered); q->setSocketState(QBluetoothSocket::ConnectedState); emit q->connected(); }
void tst_QBluetoothUuid::tst_construction() { { QBluetoothUuid nullUuid; QVERIFY(nullUuid.isNull()); } { QBluetoothUuid uuid(QBluetoothUuid::PublicBrowseGroup); QVERIFY(!uuid.isNull()); bool ok; quint16 uuid16; uuid16 = uuid.toUInt16(&ok); QVERIFY(ok); QCOMPARE(uuid16, static_cast<quint16>(QBluetoothUuid::PublicBrowseGroup)); } { QBluetoothUuid uuid(QBluetoothUuid::PublicBrowseGroup); QBluetoothUuid copy(uuid); QCOMPARE(uuid.toUInt16(), copy.toUInt16()); } { QBluetoothUuid uuid(QBluetoothUuid::L2cap); QVERIFY(!uuid.isNull()); bool ok; quint16 uuid16; uuid16 = uuid.toUInt16(&ok); QVERIFY(ok); QCOMPARE(uuid16, static_cast<quint16>(QBluetoothUuid::L2cap)); } { QUuid uuid(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee); QBluetoothUuid btUuid(uuid); QVERIFY(!btUuid.isNull()); QString uuidString(btUuid.toString()); QVERIFY(!uuidString.isEmpty()); QCOMPARE(uuidString, QString("{67c8770b-44f1-410a-ab9a-f9b5446f13ee}")); } { QBluetoothUuid btUuid(QString("67c8770b-44f1-410a-ab9a-f9b5446f13ee")); QVERIFY(!btUuid.isNull()); QString uuidString(btUuid.toString()); QVERIFY(!uuidString.isEmpty()); QCOMPARE(uuidString, QString("{67c8770b-44f1-410a-ab9a-f9b5446f13ee}")); } { QBluetoothUuid btUuid(QString("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")); QVERIFY(btUuid.isNull()); } }
static void dumpAttributeVariant(QDebug dbg, const QVariant &var, const QString& indent) { switch (int(var.type())) { case QMetaType::Void: dbg << QString::asprintf("%sEmpty\n", indent.toUtf8().constData()); break; case QMetaType::UChar: dbg << QString::asprintf("%suchar %u\n", indent.toUtf8().constData(), var.toUInt()); break; case QMetaType::UShort: dbg << QString::asprintf("%sushort %u\n", indent.toUtf8().constData(), var.toUInt()); break; case QMetaType::UInt: dbg << QString::asprintf("%suint %u\n", indent.toUtf8().constData(), var.toUInt()); break; case QMetaType::Char: dbg << QString::asprintf("%schar %d\n", indent.toUtf8().constData(), var.toInt()); break; case QMetaType::Short: dbg << QString::asprintf("%sshort %d\n", indent.toUtf8().constData(), var.toInt()); break; case QMetaType::Int: dbg << QString::asprintf("%sint %d\n", indent.toUtf8().constData(), var.toInt()); break; case QMetaType::QString: dbg << QString::asprintf("%sstring %s\n", indent.toUtf8().constData(), var.toString().toUtf8().constData()); break; case QMetaType::Bool: dbg << QString::asprintf("%sbool %d\n", indent.toUtf8().constData(), var.toBool()); break; case QMetaType::QUrl: dbg << QString::asprintf("%surl %s\n", indent.toUtf8().constData(), var.toUrl().toString().toUtf8().constData()); break; case QVariant::UserType: if (var.userType() == qMetaTypeId<QBluetoothUuid>()) { QBluetoothUuid uuid = var.value<QBluetoothUuid>(); switch (uuid.minimumSize()) { case 0: dbg << QString::asprintf("%suuid NULL\n", indent.toUtf8().constData()); break; case 2: dbg << QString::asprintf("%suuid2 %04x\n", indent.toUtf8().constData(), uuid.toUInt16()); break; case 4: dbg << QString::asprintf("%suuid %08x\n", indent.toUtf8().constData(), uuid.toUInt32()); break; case 16: dbg << QString::asprintf("%suuid %s\n", indent.toUtf8().constData(), QByteArray(reinterpret_cast<const char *>(uuid.toUInt128().data), 16).toHex().constData()); break; default: dbg << QString::asprintf("%suuid ???\n", indent.toUtf8().constData()); } } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) { dbg << QString::asprintf("%sSequence\n", indent.toUtf8().constData()); const QBluetoothServiceInfo::Sequence *sequence = static_cast<const QBluetoothServiceInfo::Sequence *>(var.data()); foreach (const QVariant &v, *sequence) dumpAttributeVariant(dbg, v, indent + QLatin1Char('\t')); } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {