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"; }
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); }
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(); }