summaryrefslogtreecommitdiff
path: root/sap/sapbtlistener.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sap/sapbtlistener.cc')
-rw-r--r--sap/sapbtlistener.cc182
1 files changed, 182 insertions, 0 deletions
diff --git a/sap/sapbtlistener.cc b/sap/sapbtlistener.cc
new file mode 100644
index 0000000..9776b59
--- /dev/null
+++ b/sap/sapbtlistener.cc
@@ -0,0 +1,182 @@
+#include <QtCore/QDebug>
+
+#include "saprotocol.h"
+#include "sapbtlistener.h"
+#include "sapbtpeer.h"
+
+#ifdef SAILFISH
+#include <bluez-qt5/bluemanager.h>
+#include <bluez-qt5/blueadapter.h>
+#include <bluez-qt5/bluedevice.h>
+#include <bluez-qt5/headset.h>
+#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<QDBusObjectPath> 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<QDBusObjectPath> 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<QBluetoothSocket*>(sender());
+ qDebug() << "Nudge connected:" << socket->peerAddress().toString();
+ new SAPBTPeer(SAProtocol::ClientRole, socket, this);
+}
+
+void SAPBTListener::handleNudgeError(QBluetoothSocket::SocketError error)
+{
+ QBluetoothSocket *socket = static_cast<QBluetoothSocket*>(sender());
+ qWarning() << "Cannot nudge:" << error << socket->errorString();
+ socket->abort();
+ socket->deleteLater();
+}