summaryrefslogtreecommitdiff
path: root/sapbtlistener.cc
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2014-10-19 18:45:03 +0200
committerJavier <dev.git@javispedro.com>2014-10-19 18:45:03 +0200
commitd8d8fc7a0d139e7b864eee3b573bd208f823ad4f (patch)
treea9b54d6e6e6941c620f4f10cef4b5def9be86f82 /sapbtlistener.cc
downloadsapd-d8d8fc7a0d139e7b864eee3b573bd208f823ad4f.tar.gz
sapd-d8d8fc7a0d139e7b864eee3b573bd208f823ad4f.zip
initial import, no crypto
Diffstat (limited to 'sapbtlistener.cc')
-rw-r--r--sapbtlistener.cc198
1 files changed, 198 insertions, 0 deletions
diff --git a/sapbtlistener.cc b/sapbtlistener.cc
new file mode 100644
index 0000000..d5cd071
--- /dev/null
+++ b/sapbtlistener.cc
@@ -0,0 +1,198 @@
+#include <QtCore/QDebug>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include "saprotocol.h"
+#include "sapbtlistener.h"
+#include "sapbtpeer.h"
+
+#ifdef DESKTOP
+#include "hfpag.h"
+#endif
+
+namespace
+{
+void add_sdp_record(sdp_session_t *session, const QBluetoothUuid &btuuid, quint16 port)
+{
+ sdp_list_t *svclass_id, *apseq, *root;
+ uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
+ sdp_list_t *aproto, *proto[2];
+ sdp_data_t *chan;
+
+ sdp_record_t *record = sdp_record_alloc();
+
+ sdp_set_info_attr(record, "SAP", "gearbttest", "Samsung Accessory Protocol");
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(0, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ QByteArray uuid = btuuid.toRfc4122();
+ sdp_uuid128_create(&svclass_uuid, uuid.constData());
+ svclass_id = sdp_list_append(0, &svclass_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto[0] = sdp_list_append(0, &l2cap_uuid);
+ apseq = sdp_list_append(0, proto[0]);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[1] = sdp_list_append(0, &rfcomm_uuid);
+ chan = sdp_data_alloc(SDP_UINT8, &port);
+ proto[1] = sdp_list_append(proto[1], chan);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ aproto = sdp_list_append(0, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ if (sdp_record_register(session, record, 0) < 0) {
+ qWarning() << "sdp_record_register failed";
+ }
+}
+
+void add_sdp_records(quint16 port)
+{
+ bdaddr_t addr_any = {{0, 0, 0, 0, 0, 0}};
+ bdaddr_t addr_local = {{0, 0, 0, 0xFF, 0xFF, 0xFF}};
+
+ sdp_session_t *sess = sdp_connect(&addr_any, &addr_local, 0);
+ if (!sess) {
+ qWarning() << "sdp_connect failed";
+ return;
+ }
+
+ add_sdp_record(sess, SAProtocol::dataServiceUuid, port);
+}
+
+}
+
+SAPBTListener::SAPBTListener(QObject *parent) :
+ QObject(parent), _server(0)
+{
+}
+
+SAPBTListener::~SAPBTListener()
+{
+ stop();
+}
+
+void SAPBTListener::start()
+{
+ if (_server) {
+ return;
+ }
+
+ _server = new QRfcommServer(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();
+
+#if 1
+ // Basically, QBluetoothServiceInfo is not yet compatible with Bluez5,
+ // so we hack around it by doing our own SDP connection.
+ add_sdp_records(serverPort);
+#else
+
+ /*
+ 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(SAPProtocol::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";
+ }
+#endif
+}
+
+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(QBluetoothSocket::RfcommSocket, this);
+
+ qDebug() << "Nudging" << address.toString();
+
+ socket->connectToService(address, 2); //SAPProtocol::nudgeServiceUuid);
+
+#if 1
+ HfpAg *ag = new HfpAg(address, this);
+ connect(socket, SIGNAL(disconnected()), ag, SLOT(deleteLater()));
+#endif
+
+ connect(socket, SIGNAL(connected()), socket, SLOT(deleteLater()));
+ connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), socket, SLOT(deleteLater()));
+}
+
+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
+ new SAPBTPeer(SAProtocol::ClientRole, socket, this);
+}