#include #include "saprotocol.h" #include "sapbtlistener.h" #include "sapbtpeer.h" #ifdef SAILFISH #include #include #include #include #endif #ifdef DESKTOP #include "hfpag.h" #endif SAPBTListener::SAPBTListener(QObject *parent) : QObject(parent), _server(0) { } SAPBTListener::~SAPBTListener() { stop(); } void SAPBTListener::start() { if (_server) { qWarning() << "Already started"; return; } _server = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this); connect(_server, SIGNAL(newConnection()), this, SLOT(acceptConnection())); if (!_server->listen(QBluetoothAddress(), 0)) { qWarning() << "Failed to start Bluetooth listener socket"; stop(); return; } quint8 serverPort = _server->serverPort(); /* Service Name: SAP Service RecHandle: 0x1000b Service Class ID List: UUID 128: a49eb41e-cb06-495c-9f4f-bb80a90cdf00 Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 5 Service Name: SAP Service RecHandle: 0x1000c Service Class ID List: UUID 128: a49eb41e-cb06-495c-9f4f-aa80a90cdf4a Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 6 */ _service.setServiceName("SAP"); _service.setServiceDescription("Samsung Accessory Profile"); _service.setServiceProvider("gearbtteest"); QBluetoothServiceInfo::Sequence classIds; classIds.append(QVariant::fromValue(SAProtocol::dataServiceUuid)); _service.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classIds); QBluetoothServiceInfo::Sequence browseGroupList; browseGroupList.append(QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup))); _service.setAttribute(QBluetoothServiceInfo::BrowseGroupList, browseGroupList); QBluetoothServiceInfo::Sequence protocolDescriptorList; QBluetoothServiceInfo::Sequence protocol; protocol.append(QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap))); protocolDescriptorList.append(QVariant::fromValue(protocol)); protocol.clear(); protocol.append(QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))); protocol.append(QVariant::fromValue(serverPort)); protocolDescriptorList.append(QVariant::fromValue(protocol)); protocol.clear(); _service.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); if (!_service.registerService()) { qWarning() << "Failed to register the SAP service"; } } void SAPBTListener::stop() { if (!_server) { return; } if (!_service.unregisterService()) { qWarning() << "Failed to unregister SAP service"; } delete _server; _server = 0; } void SAPBTListener::nudge(const QBluetoothAddress &address) { QBluetoothSocket *socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this); connect(socket, SIGNAL(connected()), this, SLOT(handleNudgeConnected())); connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(handleNudgeError(QBluetoothSocket::SocketError))); qDebug() << "Nudging" << address.toString(); // First, set up HFP/Headset connection to watch #if SAILFISH QDBusConnection bus = QDBusConnection::systemBus(); OrgBluezManagerInterface manager("org.bluez", "/", bus); QDBusReply defaultAdapter = manager.DefaultAdapter(); if (!defaultAdapter.isValid()) { qWarning() << "Could not get default Bluez adapter:" << defaultAdapter.error().message(); } OrgBluezAdapterInterface adapter("org.bluez", defaultAdapter.value().path(), bus); QList list = adapter.ListDevices(); foreach (QDBusObjectPath item, list) { OrgBluezDeviceInterface device("org.bluez", item.path(), bus); QVariantMap properties = device.GetProperties(); QBluetoothAddress devAddress(properties["Address"].toString()); if (devAddress == address) { OrgBluezHeadsetInterface headset("org.bluez", item.path(), bus); qDebug() << "Creating HFP connection to" << devAddress.toString(); headset.Connect(); } } #elif DESKTOP new HfpAg(address, this); #endif // After that, start normal connection. #if SAILFISH // For some reason, using UUIDs here fails on SailfishOS socket->connectToService(address, 1); #else socket->connectToService(address, SAProtocol::nudgeServiceUuid); #endif } void SAPBTListener::acceptConnection() { qDebug() << "Incoming BT connection"; QBluetoothSocket *socket = _server->nextPendingConnection(); if (!socket) { qWarning() << "Actually, no incoming connection"; return; } qDebug() << "Got connection"; // TODO Why am I hardcoding the role here SAPBTPeer *peer = new SAPBTPeer(SAProtocol::ClientRole, socket, this); connect(peer, SIGNAL(disconnected()), peer, SLOT(deleteLater())); } void SAPBTListener::handleNudgeConnected() { QBluetoothSocket *socket = static_cast(sender()); qDebug() << "Nudge connected:" << socket->peerAddress().toString(); new SAPBTPeer(SAProtocol::ClientRole, socket, this); } void SAPBTListener::handleNudgeError(QBluetoothSocket::SocketError error) { QBluetoothSocket *socket = static_cast(sender()); qWarning() << "Cannot nudge:" << error << socket->errorString(); socket->abort(); socket->deleteLater(); }