/**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSensors module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** 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 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** 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. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "sensorfwsensorbase.h" SensorManagerInterface* SensorfwSensorBase::m_remoteSensorManager = 0; //According to wikipedia link http://en.wikipedia.org/wiki/Standard_gravity const float SensorfwSensorBase::GRAVITY_EARTH_THOUSANDTH = 0.00980665; const int SensorfwSensorBase::KErrNotFound=-1; const int SensorfwSensorBase::KErrInUse=-14; QStringList SensorfwSensorBase::m_bufferingSensors = QStringList() <<"sensorfw.accelerometer"<<"sensorfw.magnetometer" <<"sensorfw.gyroscope"<<"sensorfw.rotationsensor"; SensorfwSensorBase::SensorfwSensorBase(QSensor *sensor) : QSensorBackend(sensor), m_sensorInterface(0), m_bufferSize(-1), reinitIsNeeded(false), m_prevOutputRange(0), m_efficientBufferSize(1), m_maxBufferSize(1), m_available(false), running(false) { watcher = new QDBusServiceWatcher("com.nokia.SensorService",QDBusConnection::systemBus(), QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this); connect(watcher, SIGNAL(serviceRegistered(QString)), this, SLOT(connectToSensord())); connect(watcher, SIGNAL(serviceUnregistered(QString)), this, SLOT(sensordUnregistered())); m_available = QDBusConnection::systemBus().interface()->isServiceRegistered("com.nokia.SensorService"); if (m_available) connectToSensord(); } SensorfwSensorBase::~SensorfwSensorBase() { if (m_sensorInterface) { stop(); delete m_sensorInterface, m_sensorInterface = 0; } } void SensorfwSensorBase::start() { if (m_sensorInterface) { // dataRate QByteArray type = sensor()->type(); if (type != QTapSensor::type && type != QProximitySensor::type) { int dataRate = sensor()->dataRate(); int interval = dataRate > 0 ? 1000 / dataRate : 0; // for testing maximum speed //interval = 1; //dataRate = 1000; m_sensorInterface->setInterval(interval); } // outputRange int currentRange = sensor()->outputRange(); int l = sensor()->outputRanges().size(); if (l > 1) { if (currentRange != m_prevOutputRange) { //#ifdef Q_WS_MAEMO_6 bool isOk = m_sensorInterface->setDataRangeIndex(currentRange); //NOTE THAT THE CHANGE MIGHT NOT SUCCEED, FIRST COME FIRST SERVED if (!isOk) sensorError(KErrInUse); else m_prevOutputRange = currentRange; //#else // // TODO: remove when sensord integrated, in sensorfw env there is a delay // qoutputrange range = sensor()->outputRanges().at(currentRange); // qreal correction = 1/correctionFactor(); // DataRange range1(range.minimum*correction, range.maximum*correction, range.accuracy*correction); // m_sensorInterface->requestDataRange(range1); // m_prevOutputRange = currentRange; //#endif } } // always on bool alwaysOn = sensor()->isAlwaysOn(); m_sensorInterface->setStandbyOverride(alwaysOn); // connects after buffering checks doConnectAfterCheck(); int returnCode = m_sensorInterface->start().error().type(); if (returnCode == 0) { running = true; return; } qWarning() << "m_sensorInterface did not start, error code:" << returnCode; } sensorStopped(); } void SensorfwSensorBase::stop() { if (m_sensorInterface) m_sensorInterface->stop(); running = false; } void SensorfwSensorBase::setRanges(qreal correctionFactor) { if (!m_sensorInterface) return; QList ranges = m_sensorInterface->getAvailableDataRanges(); for (int i = 0, l = ranges.size(); i < l; i++) { DataRange range = ranges.at(i); qreal rangeMin = range.min * correctionFactor; qreal rangeMax = range.max * correctionFactor; qreal resolution = range.resolution * correctionFactor; addOutputRange(rangeMin, rangeMax, resolution); } } bool SensorfwSensorBase::doConnectAfterCheck() { if (!m_sensorInterface) return false; // buffer size int size = bufferSize(); if (size == m_bufferSize) return true; if (m_bufferingSensors.contains(sensor()->identifier())) m_sensorInterface->setBufferSize(size); else size = 1; // if multiple->single or single->multiple or if uninitialized if ((m_bufferSize > 1 && size == 1) || (m_bufferSize == 1 && size > 1) || m_bufferSize == -1) { m_bufferSize = size; disconnect(this); if (!doConnect()) { qWarning() << "Unable to connect "<< sensorName(); return false; } return true; } m_bufferSize = size; return true; } int SensorfwSensorBase::bufferSize() const { int bufferSize = sensor()->bufferSize(); if (bufferSize == 1) return 1; // otherwise check validit if (bufferSize < 1) { qWarning() << "bufferSize cannot be " << bufferSize << ", must be a positive number >= 1"; return 1; } if (bufferSize > m_maxBufferSize) { qWarning() << "bufferSize cannot be " << bufferSize << ", MAX value is " << m_maxBufferSize; return m_maxBufferSize; } return bufferSize; } qreal SensorfwSensorBase::correctionFactor() const { return 1; } void SensorfwSensorBase::connectToSensord() { m_remoteSensorManager = &SensorManagerInterface::instance(); if (!m_remoteSensorManager->isValid()) { qWarning() << "SensorManagerInterface is invalid"; m_remoteSensorManager = 0; return; } if (running) { stop(); reinitIsNeeded = true; start(); reinitIsNeeded = false; } } void SensorfwSensorBase::sensordUnregistered() { m_bufferSize = -1; } bool SensorfwSensorBase::initSensorInterface(QString const &name) { if (!m_sensorInterface) { sensorError(KErrNotFound); return false; } //metadata const QList intervals = m_sensorInterface->getAvailableIntervals(); for (int i = 0, l = intervals.size(); i < l; i++) { qreal intervalMax = intervals.at(i).max; qreal intervalMin = intervals.at(i).min; if (intervalMin == 0 && intervalMax == 0) { // 0 interval has different meanings in e.g. magge/acce // magge -> best-effort // acce -> lowest possible // in Qt API setting 0 means default continue; } qreal rateMin = intervalMax < 1 ? 1 : 1 / intervalMax * 1000; rateMin = rateMin < 1 ? 1 : rateMin; intervalMin = intervalMin < 1 ? 10: intervalMin; // do not divide with 0 qreal rateMax = 1 / intervalMin * 1000; addDataRate(rateMin, rateMax); } //bufferSizes if (m_bufferingSensors.contains(sensor()->identifier())) { IntegerRangeList sizes = m_sensorInterface->getAvailableBufferSizes(); for (int i = 0; i < sizes.size(); i++) { int second = sizes.at(i).second; m_maxBufferSize = second > m_bufferSize ? second : m_maxBufferSize; } m_maxBufferSize = m_maxBufferSize < 0 ? 1 : m_maxBufferSize; //SensorFW guarantees to provide the most efficient size first //TODO: remove from comments //m_efficientBufferSize = m_sensorInterface->hwBuffering()? (l>0?sizes.at(0).first:1) : 1; } else { m_maxBufferSize = 1; } sensor()->setMaxBufferSize(m_maxBufferSize); sensor()->setEfficientBufferSize(m_efficientBufferSize); // TODO deztructor: Leaking abstraction detected. Just copied code // from initSensor<>() here, need to QByteArray type = sensor()->type(); if ((type == QAmbientLightSensor::type) // SensorFW returns lux values, plugin enumerated values || (type == QIRProximitySensor::type) // SensorFW returns raw reflectance values, plugin % of max reflectance || (name == "accelerometersensor") // SensorFW returns milliGs, plugin m/s^2 || (name == "magnetometersensor") // SensorFW returns nanoTeslas, plugin Teslas || (name == "gyroscopesensor")) // SensorFW returns DSPs, plugin milliDSPs return true; setDescription(m_sensorInterface->description()); if (name == "tapsensor") return true; setRanges(); return true; }