summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qnx
diff options
context:
space:
mode:
authorFabian Bumberger <fbumberger@rim.com>2012-11-16 13:22:27 +0100
committerPeter Hartmann <phartmann@rim.com>2012-11-22 09:53:46 +0100
commitab0b1ffb6fc2ba9818f9c53b49e33eba3234e7d3 (patch)
treed60e0016f9718d87c7f04b372195a49e14677545 /src/bluetooth/qnx
parent5e228327ca510209db4ed740cdd0a8955d60f994 (diff)
Preparing the QNX bluetooth port
This commit includes a backend for processing pps commands. Change-Id: I4fb720167bbf6cecaa06a8e46d3407ea70745b28 Reviewed-by: Alex <ablasche@gmail.com>
Diffstat (limited to 'src/bluetooth/qnx')
-rw-r--r--src/bluetooth/qnx/ppshelpers.cpp361
-rw-r--r--src/bluetooth/qnx/ppshelpers_p.h134
-rw-r--r--src/bluetooth/qnx/qnx.pri6
3 files changed, 501 insertions, 0 deletions
diff --git a/src/bluetooth/qnx/ppshelpers.cpp b/src/bluetooth/qnx/ppshelpers.cpp
new file mode 100644
index 00000000..ad4c8d05
--- /dev/null
+++ b/src/bluetooth/qnx/ppshelpers.cpp
@@ -0,0 +1,361 @@
+/***************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ppshelpers_p.h"
+#include <QtCore/private/qcore_unix_p.h>
+#include <QDebug>
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+
+static int count = 0;
+
+static int ppsCtrlFD = -1;
+
+static const char btControlFDPath[] = "/pps/services/bluetooth/public/control";
+static const char btSettingsFDPath[] = "/pps/services/bluetooth/settings";
+static const char btRemoteDevFDPath[] = "/pps/services/bluetooth/remote_devices/";
+
+static const int ppsBufferSize = 1024;
+
+static int ctrlId = 20;
+
+QList<QPair<QString, QObject*> > evtRegistration;
+
+void BBSocketNotifier::distribute()
+{
+ qBBBluetoothDebug() << "Distributing";
+ ppsDecodeControlResponse();
+}
+
+QPair<int, QObject*> takeObjectInWList(int id)
+{
+ for (int i=0; i<waitingCtrlMsgs.size(); i++) {
+ if (waitingCtrlMsgs.at(i).first == id)
+ return waitingCtrlMsgs.takeAt(i);
+ }
+ return QPair<int, QObject*>(-1,0);
+}
+
+void ppsRegisterControl()
+{
+ qBBBluetoothDebug() << "Register for Control";
+ if (count == 0) {
+ ppsCtrlFD = qt_safe_open(btControlFDPath, O_RDWR | O_NONBLOCK);
+ if (ppsCtrlFD == -1) {
+ qWarning() << Q_FUNC_INFO << "ppsCtrlFD - failed to qt_safe_open" << btControlFDPath;
+ } else {
+ ppsCtrlNotifier = new QSocketNotifier(ppsCtrlFD, QSocketNotifier::Read);
+ QObject::connect(ppsCtrlNotifier, SIGNAL(activated(int)), &bbSocketNotifier, SLOT(distribute()));
+ }
+ }
+ count++;
+}
+
+void ppsUnregisterControl()
+{
+ qBBBluetoothDebug() << "Unregistering Control";
+ count--;
+ if (count == 0) {
+ qt_safe_close(ppsCtrlFD);
+ ppsCtrlFD = -1;
+ delete ppsCtrlNotifier;
+ ppsCtrlNotifier = 0;
+ }
+}
+
+pps_encoder_t *beginCtrlMessage(const char *msg, QObject *sender)
+{
+ pps_encoder_t *encoder= new pps_encoder_t;
+ pps_encoder_initialize(encoder, 0);
+ pps_encoder_add_string(encoder, "msg", msg);
+ ctrlId++;
+ pps_encoder_add_string(encoder, "id", QString::number(ctrlId).toStdString().c_str() );
+ waitingCtrlMsgs.append(QPair<int, QObject*>(ctrlId, sender));
+ return encoder;
+}
+
+void endCtrlMessage(pps_encoder_t *encoder)
+{
+ qBBBluetoothDebug() << "writing" << pps_encoder_buffer(encoder);
+ if (pps_encoder_buffer(encoder) != 0) {
+ int res = write(ppsCtrlFD, pps_encoder_buffer(encoder), pps_encoder_length(encoder));
+ if (res == -1)
+ qWarning() << Q_FUNC_INFO << "Error when writing to control FD";
+ }
+
+ pps_encoder_cleanup( encoder );
+}
+
+void ppsSendControlMessage(const char *msg, int service, const QBluetoothUuid &uuid, const QString &address, QObject *sender)
+{
+ pps_encoder_t *encoder = beginCtrlMessage(msg, sender);
+ pps_encoder_start_object(encoder, "dat");
+ pps_encoder_add_int(encoder, "service", service);
+
+ pps_encoder_add_string(encoder, "uuid", uuid.toString().mid(1,36).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;
+ }
+
+ endCtrlMessage(encoder);
+}
+
+void ppsSendControlMessage(const char *msg, const QString &dat, QObject *sender)
+{
+ pps_encoder_t *encoder = beginCtrlMessage(msg, sender);
+ pps_encoder_add_json(encoder, "dat", dat.toUtf8().constData());
+ endCtrlMessage(encoder);
+}
+
+void ppsSendControlMessage(const char *msg, QObject *sender)
+{
+ pps_encoder_t *encoder = beginCtrlMessage(msg, sender);
+ endCtrlMessage(encoder);
+}
+
+void ppsDecodeControlResponse()
+{
+ ppsResult result;
+ ResultType resType;
+
+ if (ppsCtrlFD != -1) {
+ char buf[ppsBufferSize];
+ qt_safe_read( ppsCtrlFD, &buf, sizeof(buf) );
+
+ pps_decoder_t ppsDecoder;
+ pps_decoder_initialize(&ppsDecoder, 0);
+ if (pps_decoder_parse_pps_str(&ppsDecoder, buf) == PPS_DECODER_OK) {
+ pps_decoder_push(&ppsDecoder, 0);
+ const char *buf;
+
+ //THe pps response can either be of type 'res', 'msg' or 'evt'
+ if (pps_decoder_get_string(&ppsDecoder, "res", &buf) == PPS_DECODER_OK) {
+ result.msg = QString::fromUtf8(buf);
+ resType = RESPONSE;
+ } else if (pps_decoder_get_string(&ppsDecoder, "msg", &buf) == PPS_DECODER_OK) {
+ result.msg = QString::fromUtf8(buf);
+ resType = MESSAGE;
+ } else if (pps_decoder_get_string(&ppsDecoder, "evt", &buf) == PPS_DECODER_OK) {
+ result.msg = QString::fromUtf8(buf);
+ resType = EVENT;
+ }
+
+ if (pps_decoder_get_string(&ppsDecoder, "id", &buf) == PPS_DECODER_OK)
+ result.id = QString::fromUtf8(buf).toInt();
+
+ //qt_safe_read out the error message if there is one
+ if (pps_decoder_get_string(&ppsDecoder, "errstr", &buf) == PPS_DECODER_OK)
+ result.errorMsg = QString::fromUtf8(buf);
+
+ //The dat object can be either a string or a array
+ pps_node_type_t nodeType = pps_decoder_type(&ppsDecoder,"dat");
+ if (nodeType == PPS_TYPE_STRING) {
+ pps_decoder_get_string(&ppsDecoder,"dat",&buf);
+ result.dat << QString::fromUtf8(buf);
+ } else if (nodeType == PPS_TYPE_OBJECT || nodeType == PPS_TYPE_ARRAY) {
+ pps_decoder_push(&ppsDecoder,"dat");
+ do {
+ if (pps_decoder_get_string(&ppsDecoder,0, &buf) == PPS_DECODER_OK) {
+ result.dat << QString::fromUtf8(pps_decoder_name(&ppsDecoder));
+ result.dat << QString::fromUtf8(buf);
+ }
+ } while (pps_decoder_next(&ppsDecoder) == PPS_DECODER_OK);
+ } else {
+ qBBBluetoothDebug() << "No node type";
+ }
+ }
+ pps_decoder_cleanup(&ppsDecoder);
+
+ }
+
+ if (resType == RESPONSE) {
+ QPair<int, QObject*> wMessage = takeObjectInWList(result.id);
+ if (wMessage.second!=0) {
+ wMessage.second->metaObject()->invokeMethod(wMessage.second, "controlReply", Q_ARG(ppsResult, result));
+ }
+ } else if (resType == EVENT) {
+ qBBBluetoothDebug() << "Distributing event" << result.msg << result.dat;
+ for (int i=0; i < evtRegistration.size(); i++) {
+ if (result.msg == evtRegistration.at(i).first)
+ evtRegistration.at(i).second->metaObject()->invokeMethod(evtRegistration.at(i).second, "controlEvent", Q_ARG(ppsResult, result));
+ }
+ }
+}
+
+QVariant ppsqt_safe_readSetting(const char *property)
+{
+ int settingsFD;
+ char buf[ppsBufferSize];
+ if ((settingsFD = qt_safe_open(btSettingsFDPath, O_RDONLY)) == -1) {
+ qWarning() << Q_FUNC_INFO << "failed to qt_safe_open "<< btSettingsFDPath;
+ return QVariant();
+ }
+
+ QVariant result;
+
+ qt_safe_read( settingsFD, &buf, sizeof(buf));
+ pps_decoder_t decoder;
+ pps_decoder_initialize(&decoder, 0);
+
+ if (pps_decoder_parse_pps_str(&decoder, buf) == PPS_DECODER_OK) {
+ pps_decoder_push(&decoder, 0);
+ pps_node_type_t nodeType = pps_decoder_type(&decoder, property);
+ if (nodeType == PPS_TYPE_STRING) {
+ const char *dat;
+ if (pps_decoder_get_string(&decoder, property, &dat) == PPS_DECODER_OK) {
+ result = QString::fromUtf8(dat);
+ } else {
+ qWarning() << Q_FUNC_INFO << "could not qt_safe_read"<< property;
+ return QVariant();
+ }
+ } else if (nodeType == PPS_TYPE_NUMBER) {
+ int dat;
+ if (pps_decoder_get_int(&decoder, property, &dat) == PPS_DECODER_OK) {
+ result = dat;
+ } else {
+ qWarning() << Q_FUNC_INFO << "could not qt_safe_read"<< property;
+ return QVariant();
+ }
+ } else {
+ qBBBluetoothDebug() << Q_FUNC_INFO << "unrecognized entry for settings";
+ }
+ }
+ pps_decoder_cleanup(&decoder);
+ qt_safe_close(settingsFD);
+ return result;
+}
+
+QVariant ppsRemoteDeviceStatus(const QByteArray &address, const char *property)
+{
+ int rmFD;
+ char buf[ppsBufferSize];
+ QByteArray filename = btRemoteDevFDPath;
+ filename.append(address);
+
+ if ((rmFD = qt_safe_open(filename.constData(), O_RDONLY)) < 0) {
+ qWarning() << Q_FUNC_INFO << "failed to qt_safe_open "<< btRemoteDevFDPath << address;
+ return false;
+ }
+
+ QVariant res;
+
+ qt_safe_read(rmFD, &buf, sizeof(buf));
+ pps_decoder_t ppsDecoder;
+ pps_decoder_initialize(&ppsDecoder, 0);
+ if (pps_decoder_parse_pps_str(&ppsDecoder, buf) == PPS_DECODER_OK) {
+ pps_decoder_push(&ppsDecoder, 0);
+
+ //Find out about the node type
+ pps_node_type_t nodeType = pps_decoder_type(&ppsDecoder, property);
+ if (nodeType == PPS_TYPE_STRING) {
+ const char *dat;
+ pps_decoder_get_string(&ppsDecoder,property,&dat);
+ res = QString::fromUtf8(dat);
+ } else if (nodeType == PPS_TYPE_BOOL) {
+ bool dat;
+ pps_decoder_get_bool(&ppsDecoder,property,&dat);
+ res = QVariant(dat);
+ } else {
+ qBBBluetoothDebug() << "No node type";
+ }
+ }
+ pps_decoder_cleanup(&ppsDecoder);
+ qt_safe_close(rmFD);
+ return res;
+}
+
+bool ppsqt_safe_readRemoteDevice(int fd, pps_decoder_t *decoder, QBluetoothAddress *btAddr, QString *deviceName)
+{
+ char buf[ppsBufferSize * 2];
+ char addr_buf[18];
+
+ addr_buf[17] = '\0';
+
+ if (qt_safe_read(fd, &buf, sizeof(buf)) == -1) {
+ qWarning() << Q_FUNC_INFO << "Could not qt_safe_read from pps remote device file";
+ return false;
+ }
+
+ qBBBluetoothDebug() << "Remote device" << buf;
+
+ //the address of the BT device is stored at the beginning of the qt_safe_read
+ if (buf[0] != '-') {
+ memcpy(&addr_buf, &buf[1], 17);
+ } else { //The device was removed
+ memcpy(&addr_buf, &buf[2], 17);
+ return false;
+ }
+
+ *btAddr = QBluetoothAddress(QString::fromUtf8(addr_buf));
+
+ if (pps_decoder_parse_pps_str(decoder, buf) == PPS_DECODER_OK) {
+ const char* name;
+ pps_decoder_push(decoder, 0);
+
+ if (pps_decoder_get_string(decoder, "name", &name) == PPS_DECODER_OK)
+ (*deviceName) = QString::fromUtf8(name);
+
+ return true;
+ }
+ return false;
+}
+
+void ppsRegisterForEvent(const QString &evt, QObject *obj)
+{
+ evtRegistration.append(QPair<QString, QObject*>(evt,obj));
+}
+
+void ppsUnreguisterForEvent(QObject *obj)
+{
+ for (int i=evtRegistration.size()-1; i >= 0; --i) {
+ if (evtRegistration.at(i).second == obj)
+ evtRegistration.removeAt(i);
+ }
+}
+
+QTBLUETOOTH_END_NAMESPACE
diff --git a/src/bluetooth/qnx/ppshelpers_p.h b/src/bluetooth/qnx/ppshelpers_p.h
new file mode 100644
index 00000000..68746abc
--- /dev/null
+++ b/src/bluetooth/qnx/ppshelpers_p.h
@@ -0,0 +1,134 @@
+/***************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PPSHELPERS_H
+#define PPSHELPERS_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/pps.h>
+
+#include <QSocketNotifier>
+#include <QStringList>
+
+#include <qbluetoothuuid.h>
+#include <qbluetoothaddress.h>
+
+#ifdef BT_BBPPSDEBUG
+#define qBBBluetoothDebug qDebug
+#else
+#define qBBBluetoothDebug QT_NO_QDEBUG_MACRO
+#endif
+
+QT_BEGIN_HEADER
+
+QTBLUETOOTH_BEGIN_NAMESPACE
+
+class BBSocketNotifier : public QObject
+{
+ Q_OBJECT
+public Q_SLOTS:
+ void distribute();
+};
+
+static BBSocketNotifier bbSocketNotifier;
+
+static QSocketNotifier *ppsCtrlNotifier = 0;
+
+enum ResultType {UNKNOWN, EVENT, MESSAGE, RESPONSE};
+
+struct ppsResult {
+ ppsResult() : success(false), error(0) {}
+
+ bool success;
+ int id;
+ QString msg;
+ QStringList dat;
+ QString errorMsg;
+ int error;
+};
+
+static QList<QPair<int, QObject*> > waitingCtrlMsgs;
+
+QPair<int, QObject*> takeObjectInWList(int id);
+
+void ppsRegisterControl();
+
+void ppsUnregisterControl();
+
+pps_encoder_t *beginCtrlMessage(const char *msg, QObject *sender);
+
+void endCtrlMessage(pps_encoder_t *encoder);
+
+void ppsSendControlMessage(const char *msg, int service, const QBluetoothUuid &uuid, const QString &address, QObject *sender=0);
+
+void ppsSendControlMessage(const char *msg, const QString &dat, QObject *sender=0);
+
+void ppsSendControlMessage(const char *msg, QObject *sender=0);
+
+void ppsDecodeControlResponse();
+
+QVariant ppsReadSetting(const char *property);
+
+QVariant ppsRemoteDeviceStatus(const QByteArray &address, const char *property);
+
+bool ppsReadRemoteDevice(int fd, pps_decoder_t *decoder, QBluetoothAddress *btAddr, QString *deviceName);
+
+void ppsRegisterForEvent(const QString &evt, QObject *obj);
+
+void ppsUnreguisterForEvent(QObject *obj);
+
+QTBLUETOOTH_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // PPSHELPERS_H
diff --git a/src/bluetooth/qnx/qnx.pri b/src/bluetooth/qnx/qnx.pri
new file mode 100644
index 00000000..ec0b4dab
--- /dev/null
+++ b/src/bluetooth/qnx/qnx.pri
@@ -0,0 +1,6 @@
+QT += core-private
+
+HEADERS += \
+ qnx/ppshelpers_p.h
+
+SOURCES += qnx/ppshelpers.cpp