<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsensormanager.h"
#include <QDebug>
#include "qsensorpluginloader_p.h"
#include "qsensorplugin.h"
#include <QSettings>
#include "sensorlog_p.h"
#include <QTimer>

QTM_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(QSensorPluginLoader, pluginLoader)

typedef QHash<QByteArray,QSensorBackendFactory*> FactoryForIdentifierMap;
typedef QHash<QByteArray,FactoryForIdentifierMap> BackendIdentifiersForTypeMap;

class QSensorManagerPrivate : public QObject
{
    friend class QSensorManager;

    Q_OBJECT
public:
    QSensorManagerPrivate()
        : pluginsLoaded(false)
        , sensorsChanged(false)
    {
    }

    bool pluginsLoaded;

    QList<CreatePluginFunc> staticRegistrations;

    // Holds a mapping from type to available identifiers (and from there to the factory)
    BackendIdentifiersForTypeMap backendsByType;

    // Holds the first identifier for each type
    QHash<QByteArray, QByteArray> firstIdentifierForType;

    bool sensorsChanged;
    QList<QSensorChangesInterface*> changeListeners;

Q_SIGNALS:
    void availableSensorsChanged();

public Q_SLOTS:
    void emitSensorsChanged()
    {
        static bool alreadyRunning = false;
        if (!pluginsLoaded || alreadyRunning) {
            // We're busy.
            // Just note that a registration changed and exit.
            // Someone up the call stack will deal with this.
            sensorsChanged = true;
            return;
        }

        // Set a flag so any recursive calls doesn't cause a loop.
        alreadyRunning = true;

        // Since one [un]registration may cause other [un]registrations and since
        // the order in which we do things matters we just do a cascading update
        // until things stop changing.
        do {
            sensorsChanged = false;
            Q_FOREACH (QSensorChangesInterface *changes, changeListeners) {
                changes->sensorsChanged();
            }
        } while (sensorsChanged);

        // We're going away now so clear the flag
        alreadyRunning = false;

        // Notify the client of the changes
        Q_EMIT availableSensorsChanged();
    }
};

Q_GLOBAL_STATIC(QSensorManagerPrivate, sensorManagerPrivate)

// The unit test needs to change the behaviour of the library. It does this
// through an exported but undocumented function.
static void initPlugin(QObject *plugin);
static bool settings_use_user_scope = false;
static bool load_external_plugins = true;
Q_SENSORS_EXPORT void sensors_unit_test_hook(int index)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();

    switch (index) {
    case 0:
        Q_ASSERT(d->pluginsLoaded == false);
        settings_use_user_scope = true;
        load_external_plugins = false;
        break;
    case 1:
        Q_ASSERT(load_external_plugins == false);
        Q_ASSERT(d->pluginsLoaded == true);
        SENSORLOG() << "initializing plugins";
        Q_FOREACH (QObject *plugin, pluginLoader()->plugins()) {
            initPlugin(plugin);
        }
        break;
    default:
        break;
    }
}

static void initPlugin(QObject *o)
{
    if (!o) return;
    QSensorManagerPrivate *d = sensorManagerPrivate();

    QSensorPluginInterface *plugin = qobject_cast<QSensorPluginInterface*>(o);
    if (plugin)
        plugin->registerSensors();
    QSensorChangesInterface *changes = qobject_cast<QSensorChangesInterface*>(o);
    if (changes)
        d->changeListeners << changes;
}

static void loadPlugins()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();

    SENSORLOG() << "initializing static plugins";
    Q_FOREACH (CreatePluginFunc func, d->staticRegistrations) {
        QSensorPluginInterface *plugin = func();
        plugin->registerSensors();
    }

    if (load_external_plugins) {
        SENSORLOG() << "initializing plugins";
        Q_FOREACH (QObject *plugin, pluginLoader()->plugins()) {
            initPlugin(plugin);
        }
    }

    d->pluginsLoaded = true;

    if (d->sensorsChanged) {
        // Notify the app that the available sensor list has changed.
        // This may cause recursive calls!
        d->emitSensorsChanged();
    }
}

// =====================================================================

/*!
    \class QSensorManager
    \ingroup sensors_backend
    \inmodule QtSensors

    \brief The QSensorManager class handles registration and creation of sensor backends.

    Sensor plugins register backends using the registerBackend() function.

    When QSensor::connectToBackend() is called, the createBackend() function will be called.
*/

/*!
    Register a sensor for \a type. The \a identifier must be unique.

    The \a factory will be asked to create instances of the backend.
*/
void QSensorManager::registerBackend(const QByteArray &type, const QByteArray &identifier, QSensorBackendFactory *factory)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->backendsByType.contains(type)) {
        (void)d->backendsByType[type];
        d->firstIdentifierForType[type] = identifier;
    }
    FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[type];
    if (factoryByIdentifier.contains(identifier)) {
        qWarning() << "A backend with type" << type << "and identifier" << identifier << "has already been registered!";
        return;
    }
    SENSORLOG() << "registering backend for type" << type << "identifier" << identifier;// << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
    factoryByIdentifier[identifier] = factory;

    // Notify the app that the available sensor list has changed.
    // This may cause recursive calls!
    d->emitSensorsChanged();
}

/*!
    Unregister the backend for \a type with \a identifier.

    Note that this only prevents new instance of the backend from being created. It does not
    invalidate the existing instances of the backend. The backend code should handle the
    dissappearance of the underlying hardware itself.
*/
void QSensorManager::unregisterBackend(const QByteArray &type, const QByteArray &identifier)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->backendsByType.contains(type)) {
        qWarning() << "No backends of type" << type << "are registered";
        return;
    }
    FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[type];
    if (!factoryByIdentifier.contains(identifier)) {
        qWarning() << "Identifier" << identifier << "is not registered";
        return;
    }

    (void)factoryByIdentifier.take(identifier); // we don't own this pointer anyway
    if (d->firstIdentifierForType[type] == identifier) {
        if (factoryByIdentifier.count())
            d->firstIdentifierForType[type] == factoryByIdentifier.begin().key();
        else
            (void)d->firstIdentifierForType.take(type);
    }
    if (!factoryByIdentifier.count())
        (void)d->backendsByType.take(type);

    // Notify the app that the available sensor list has changed.
    // This may cause recursive calls!
    d->emitSensorsChanged();
}

/*!
    \internal
*/
void QSensorManager::registerStaticPlugin(CreatePluginFunc func)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    d->staticRegistrations.append(func);
}

/*!
    Create a backend for \a sensor. Returns null if no suitable backend exists.
*/
QSensorBackend *QSensorManager::createBackend(QSensor *sensor)
{
    Q_ASSERT(sensor);

    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    SENSORLOG() << "QSensorManager::createBackend" << "type" << sensor->type() << "identifier" << sensor->identifier();

    if (!d->backendsByType.contains(sensor->type())) {
        SENSORLOG() << "no backends of type" << sensor->type() << "have been registered.";
        return 0;
    }

    const FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[sensor->type()];
    QSensorBackendFactory *factory;
    QSensorBackend *backend;

    if (sensor->identifier().isEmpty()) {
        QByteArray defaultIdentifier = QSensor::defaultSensorForType(sensor->type());
        SENSORLOG() << "Trying the default" << defaultIdentifier;
        // No identifier set, try the default
        factory = factoryByIdentifier[defaultIdentifier];
        //SENSORLOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
        sensor->setIdentifier(defaultIdentifier); // the factory requires this
        backend = factory->createBackend(sensor);
        if (backend) return backend; // Got it!

        // The default failed to instantiate so try any other registered sensors for this type
        Q_FOREACH (const QByteArray &identifier, factoryByIdentifier.keys()) {
            SENSORLOG() << "Trying" << identifier;
            if (identifier == defaultIdentifier) continue; // Don't do the default one again
            factory = factoryByIdentifier[identifier];
            //SENSORLOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
            sensor->setIdentifier(identifier); // the factory requires this
            backend = factory->createBackend(sensor);
            if (backend) return backend; // Got it!
        }
        SENSORLOG() << "FAILED";
        sensor->setIdentifier(QByteArray()); // clear the identifier
    } else {
        if (!factoryByIdentifier.contains(sensor->identifier())) {
            SENSORLOG() << "no backend with identifier" << sensor->identifier() << "for type" << sensor->type();
            return 0;
        }

        // We were given an explicit identifier so don't substitute other backends if it fails to instantiate
        factory = factoryByIdentifier[sensor->identifier()];
        //SENSORLOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
        backend = factory->createBackend(sensor);
        if (backend) return backend; // Got it!
    }

    SENSORLOG() << "no suitable backend found for requested identifier" << sensor->identifier() << "and type" << sensor->type();
    return 0;
}

/*!
    Returns true if the backend identified by \a type and \a identifier is registered.

    This is a convenience method that helps out plugins doing dynamic registration.
*/
bool QSensorManager::isBackendRegistered(const QByteArray &type, const QByteArray &identifier)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    if (!d->backendsByType.contains(type))
        return false;

    const FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[type];
    if (!factoryByIdentifier.contains(identifier))
        return false;

    return true;
}

// =====================================================================

/*!
    Returns a list of all sensor types.
*/
QList<QByteArray> QSensor::sensorTypes()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    return d->backendsByType.keys();
}

/*!
    Returns a list of ids for each of the sensors for \a type.
    If there are no sensors of that type available the list will be empty.
*/
QList<QByteArray> QSensor::sensorsForType(const QByteArray &type)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    // no sensors of that type exist
    if (!d->backendsByType.contains(type))
        return QList<QByteArray>();

    return d->backendsByType[type].keys();
}

/*!
    Returns the default sensor identifier for \a type.
    This is set in a config file and can be overridden if required.
    If no default is available the system will return the first registered
    sensor for \a type.

    \sa {Determining the default sensor for a type}
*/
QByteArray QSensor::defaultSensorForType(const QByteArray &type)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    // no sensors of that type exist
    if (!d->backendsByType.contains(type))
        return QByteArray();

    // The unit test needs to modify Sensors.conf but it can't access the system directory
    QSettings::Scope scope = settings_use_user_scope ? QSettings::UserScope : QSettings::SystemScope;
    QSettings settings(scope, QLatin1String("Nokia"), QLatin1String("Sensors"));
    QVariant value = settings.value(QString(QLatin1String("Default/%1")).arg(QString::fromLatin1(type)));
    if (!value.isNull()) {
        QByteArray defaultIdentifier = value.toByteArray();
        if (d->backendsByType[type].contains(defaultIdentifier)) // Don't return a value that we can't use!
            return defaultIdentifier;
    }

    // This is our fallback
    return d->firstIdentifierForType[type];
}

void QSensor::registerInstance()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    connect(d, SIGNAL(availableSensorsChanged()), this, SIGNAL(availableSensorsChanged()));
}

// =====================================================================

/*!
    \class QSensorBackendFactory
    \ingroup sensors_backend
    \inmodule QtSensors

    \brief The QSensorBackendFactory class instantiates instances of
           QSensorBackend.

    This interface must be implemented in order to register a sensor backend.

    \sa {Creating a sensor plugin}
*/

/*!
    \fn QSensorBackendFactory::~QSensorBackendFactory()
    \internal
*/

/*!
    \fn QSensorBackendFactory::createBackend(QSensor *sensor)

    Instantiate a backend. If the factory handles multiple identifiers
    it should check with the \a sensor to see which one is requested.

    If the factory cannot create a backend it should return 0.
*/

/*!
    \macro REGISTER_STATIC_PLUGIN(pluginname)
    \relates QSensorManager

    Registers a static plugin, \a pluginname.

    Note that this macro relies on static initialization so it may not be appropriate
    for use in a library and may not work on all platforms.

    \sa {Creating a sensor plugin}
*/

#include "qsensormanager.moc"

QTM_END_NAMESPACE

<commit_msg>spelling (doc)<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsensormanager.h"
#include <QDebug>
#include "qsensorpluginloader_p.h"
#include "qsensorplugin.h"
#include <QSettings>
#include "sensorlog_p.h"
#include <QTimer>

QTM_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(QSensorPluginLoader, pluginLoader)

typedef QHash<QByteArray,QSensorBackendFactory*> FactoryForIdentifierMap;
typedef QHash<QByteArray,FactoryForIdentifierMap> BackendIdentifiersForTypeMap;

class QSensorManagerPrivate : public QObject
{
    friend class QSensorManager;

    Q_OBJECT
public:
    QSensorManagerPrivate()
        : pluginsLoaded(false)
        , sensorsChanged(false)
    {
    }

    bool pluginsLoaded;

    QList<CreatePluginFunc> staticRegistrations;

    // Holds a mapping from type to available identifiers (and from there to the factory)
    BackendIdentifiersForTypeMap backendsByType;

    // Holds the first identifier for each type
    QHash<QByteArray, QByteArray> firstIdentifierForType;

    bool sensorsChanged;
    QList<QSensorChangesInterface*> changeListeners;

Q_SIGNALS:
    void availableSensorsChanged();

public Q_SLOTS:
    void emitSensorsChanged()
    {
        static bool alreadyRunning = false;
        if (!pluginsLoaded || alreadyRunning) {
            // We're busy.
            // Just note that a registration changed and exit.
            // Someone up the call stack will deal with this.
            sensorsChanged = true;
            return;
        }

        // Set a flag so any recursive calls doesn't cause a loop.
        alreadyRunning = true;

        // Since one [un]registration may cause other [un]registrations and since
        // the order in which we do things matters we just do a cascading update
        // until things stop changing.
        do {
            sensorsChanged = false;
            Q_FOREACH (QSensorChangesInterface *changes, changeListeners) {
                changes->sensorsChanged();
            }
        } while (sensorsChanged);

        // We're going away now so clear the flag
        alreadyRunning = false;

        // Notify the client of the changes
        Q_EMIT availableSensorsChanged();
    }
};

Q_GLOBAL_STATIC(QSensorManagerPrivate, sensorManagerPrivate)

// The unit test needs to change the behaviour of the library. It does this
// through an exported but undocumented function.
static void initPlugin(QObject *plugin);
static bool settings_use_user_scope = false;
static bool load_external_plugins = true;
Q_SENSORS_EXPORT void sensors_unit_test_hook(int index)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();

    switch (index) {
    case 0:
        Q_ASSERT(d->pluginsLoaded == false);
        settings_use_user_scope = true;
        load_external_plugins = false;
        break;
    case 1:
        Q_ASSERT(load_external_plugins == false);
        Q_ASSERT(d->pluginsLoaded == true);
        SENSORLOG() << "initializing plugins";
        Q_FOREACH (QObject *plugin, pluginLoader()->plugins()) {
            initPlugin(plugin);
        }
        break;
    default:
        break;
    }
}

static void initPlugin(QObject *o)
{
    if (!o) return;
    QSensorManagerPrivate *d = sensorManagerPrivate();

    QSensorPluginInterface *plugin = qobject_cast<QSensorPluginInterface*>(o);
    if (plugin)
        plugin->registerSensors();
    QSensorChangesInterface *changes = qobject_cast<QSensorChangesInterface*>(o);
    if (changes)
        d->changeListeners << changes;
}

static void loadPlugins()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();

    SENSORLOG() << "initializing static plugins";
    Q_FOREACH (CreatePluginFunc func, d->staticRegistrations) {
        QSensorPluginInterface *plugin = func();
        plugin->registerSensors();
    }

    if (load_external_plugins) {
        SENSORLOG() << "initializing plugins";
        Q_FOREACH (QObject *plugin, pluginLoader()->plugins()) {
            initPlugin(plugin);
        }
    }

    d->pluginsLoaded = true;

    if (d->sensorsChanged) {
        // Notify the app that the available sensor list has changed.
        // This may cause recursive calls!
        d->emitSensorsChanged();
    }
}

// =====================================================================

/*!
    \class QSensorManager
    \ingroup sensors_backend
    \inmodule QtSensors

    \brief The QSensorManager class handles registration and creation of sensor backends.

    Sensor plugins register backends using the registerBackend() function.

    When QSensor::connectToBackend() is called, the createBackend() function will be called.
*/

/*!
    Register a sensor for \a type. The \a identifier must be unique.

    The \a factory will be asked to create instances of the backend.
*/
void QSensorManager::registerBackend(const QByteArray &type, const QByteArray &identifier, QSensorBackendFactory *factory)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->backendsByType.contains(type)) {
        (void)d->backendsByType[type];
        d->firstIdentifierForType[type] = identifier;
    }
    FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[type];
    if (factoryByIdentifier.contains(identifier)) {
        qWarning() << "A backend with type" << type << "and identifier" << identifier << "has already been registered!";
        return;
    }
    SENSORLOG() << "registering backend for type" << type << "identifier" << identifier;// << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
    factoryByIdentifier[identifier] = factory;

    // Notify the app that the available sensor list has changed.
    // This may cause recursive calls!
    d->emitSensorsChanged();
}

/*!
    Unregister the backend for \a type with \a identifier.

    Note that this only prevents new instance of the backend from being created. It does not
    invalidate the existing instances of the backend. The backend code should handle the
    disappearance of the underlying hardware itself.
*/
void QSensorManager::unregisterBackend(const QByteArray &type, const QByteArray &identifier)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->backendsByType.contains(type)) {
        qWarning() << "No backends of type" << type << "are registered";
        return;
    }
    FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[type];
    if (!factoryByIdentifier.contains(identifier)) {
        qWarning() << "Identifier" << identifier << "is not registered";
        return;
    }

    (void)factoryByIdentifier.take(identifier); // we don't own this pointer anyway
    if (d->firstIdentifierForType[type] == identifier) {
        if (factoryByIdentifier.count())
            d->firstIdentifierForType[type] == factoryByIdentifier.begin().key();
        else
            (void)d->firstIdentifierForType.take(type);
    }
    if (!factoryByIdentifier.count())
        (void)d->backendsByType.take(type);

    // Notify the app that the available sensor list has changed.
    // This may cause recursive calls!
    d->emitSensorsChanged();
}

/*!
    \internal
*/
void QSensorManager::registerStaticPlugin(CreatePluginFunc func)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    d->staticRegistrations.append(func);
}

/*!
    Create a backend for \a sensor. Returns null if no suitable backend exists.
*/
QSensorBackend *QSensorManager::createBackend(QSensor *sensor)
{
    Q_ASSERT(sensor);

    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    SENSORLOG() << "QSensorManager::createBackend" << "type" << sensor->type() << "identifier" << sensor->identifier();

    if (!d->backendsByType.contains(sensor->type())) {
        SENSORLOG() << "no backends of type" << sensor->type() << "have been registered.";
        return 0;
    }

    const FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[sensor->type()];
    QSensorBackendFactory *factory;
    QSensorBackend *backend;

    if (sensor->identifier().isEmpty()) {
        QByteArray defaultIdentifier = QSensor::defaultSensorForType(sensor->type());
        SENSORLOG() << "Trying the default" << defaultIdentifier;
        // No identifier set, try the default
        factory = factoryByIdentifier[defaultIdentifier];
        //SENSORLOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
        sensor->setIdentifier(defaultIdentifier); // the factory requires this
        backend = factory->createBackend(sensor);
        if (backend) return backend; // Got it!

        // The default failed to instantiate so try any other registered sensors for this type
        Q_FOREACH (const QByteArray &identifier, factoryByIdentifier.keys()) {
            SENSORLOG() << "Trying" << identifier;
            if (identifier == defaultIdentifier) continue; // Don't do the default one again
            factory = factoryByIdentifier[identifier];
            //SENSORLOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
            sensor->setIdentifier(identifier); // the factory requires this
            backend = factory->createBackend(sensor);
            if (backend) return backend; // Got it!
        }
        SENSORLOG() << "FAILED";
        sensor->setIdentifier(QByteArray()); // clear the identifier
    } else {
        if (!factoryByIdentifier.contains(sensor->identifier())) {
            SENSORLOG() << "no backend with identifier" << sensor->identifier() << "for type" << sensor->type();
            return 0;
        }

        // We were given an explicit identifier so don't substitute other backends if it fails to instantiate
        factory = factoryByIdentifier[sensor->identifier()];
        //SENSORLOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
        backend = factory->createBackend(sensor);
        if (backend) return backend; // Got it!
    }

    SENSORLOG() << "no suitable backend found for requested identifier" << sensor->identifier() << "and type" << sensor->type();
    return 0;
}

/*!
    Returns true if the backend identified by \a type and \a identifier is registered.

    This is a convenience method that helps out plugins doing dynamic registration.
*/
bool QSensorManager::isBackendRegistered(const QByteArray &type, const QByteArray &identifier)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    if (!d->backendsByType.contains(type))
        return false;

    const FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[type];
    if (!factoryByIdentifier.contains(identifier))
        return false;

    return true;
}

// =====================================================================

/*!
    Returns a list of all sensor types.
*/
QList<QByteArray> QSensor::sensorTypes()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    return d->backendsByType.keys();
}

/*!
    Returns a list of ids for each of the sensors for \a type.
    If there are no sensors of that type available the list will be empty.
*/
QList<QByteArray> QSensor::sensorsForType(const QByteArray &type)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    // no sensors of that type exist
    if (!d->backendsByType.contains(type))
        return QList<QByteArray>();

    return d->backendsByType[type].keys();
}

/*!
    Returns the default sensor identifier for \a type.
    This is set in a config file and can be overridden if required.
    If no default is available the system will return the first registered
    sensor for \a type.

    \sa {Determining the default sensor for a type}
*/
QByteArray QSensor::defaultSensorForType(const QByteArray &type)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    // no sensors of that type exist
    if (!d->backendsByType.contains(type))
        return QByteArray();

    // The unit test needs to modify Sensors.conf but it can't access the system directory
    QSettings::Scope scope = settings_use_user_scope ? QSettings::UserScope : QSettings::SystemScope;
    QSettings settings(scope, QLatin1String("Nokia"), QLatin1String("Sensors"));
    QVariant value = settings.value(QString(QLatin1String("Default/%1")).arg(QString::fromLatin1(type)));
    if (!value.isNull()) {
        QByteArray defaultIdentifier = value.toByteArray();
        if (d->backendsByType[type].contains(defaultIdentifier)) // Don't return a value that we can't use!
            return defaultIdentifier;
    }

    // This is our fallback
    return d->firstIdentifierForType[type];
}

void QSensor::registerInstance()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    connect(d, SIGNAL(availableSensorsChanged()), this, SIGNAL(availableSensorsChanged()));
}

// =====================================================================

/*!
    \class QSensorBackendFactory
    \ingroup sensors_backend
    \inmodule QtSensors

    \brief The QSensorBackendFactory class instantiates instances of
           QSensorBackend.

    This interface must be implemented in order to register a sensor backend.

    \sa {Creating a sensor plugin}
*/

/*!
    \fn QSensorBackendFactory::~QSensorBackendFactory()
    \internal
*/

/*!
    \fn QSensorBackendFactory::createBackend(QSensor *sensor)

    Instantiate a backend. If the factory handles multiple identifiers
    it should check with the \a sensor to see which one is requested.

    If the factory cannot create a backend it should return 0.
*/

/*!
    \macro REGISTER_STATIC_PLUGIN(pluginname)
    \relates QSensorManager

    Registers a static plugin, \a pluginname.

    Note that this macro relies on static initialization so it may not be appropriate
    for use in a library and may not work on all platforms.

    \sa {Creating a sensor plugin}
*/

#include "qsensormanager.moc"

QTM_END_NAMESPACE

<|endoftext|>


<commit_before>#include "deviceproxy.h"

DeviceProxyBase::DeviceProxyBase(DeviceKey key)
{
	OSDebugOut("ctor (%s)\n", key.name.c_str());
	RegisterDevice::instance().Add(key, this);
}
<commit_msg>deviceproxy.cpp: fix format string for win32<commit_after>#include "deviceproxy.h"

DeviceProxyBase::DeviceProxyBase(DeviceKey key)
{
	OSDebugOut("ctor (%" TEXT(SFMTs) ")\n", key.name.c_str());
	RegisterDevice::instance().Add(key, this);
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX グループ・RSPI I/O 制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2016, 2019 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/vect.h"

/// F_PCKx は速度パラメーター計算で必要で、設定が無いとエラーにします。
#if defined(SIG_RX24T)
#ifndef F_PCLKB
#  error "rspi_io.hpp requires F_PCLKB to be defined"
#else
#undef PCLK
#define PCLK F_PCLKB
#endif
#elif defined(SIG_RX64M) || defined(SIG_RX71M) || defined(SIG_RX65N)
#ifndef F_PCLKA
#  error "rspi_io.hpp requires F_PCLKA to be defined"
#else
#undef PCLK
#define PCLK F_PCLKA
#endif
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  RSPI 制御クラス
		@param[in]	RSPI	RSPI 定義クラス
		@param[in]	PSEL	ポート候補
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class RSPI, port_map::option PSEL = port_map::option::FIRST>
	class rspi_io {
	public:

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  データ、クロック位相タイプ型
					TYPE1(MODE0): CPOL:0 CPHA:0 @n
					TYPE2(MODE1): CPOL:0 CPHA:1 @n
					TYPE3(MODE2): CPOL:1 CPHA:0 @n
					TYPE4(MODE3): CPOL:1 CPHA:1
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class PHASE : uint8_t {
			TYPE1,  ///< タイプ１
			TYPE2,  ///< タイプ２
			TYPE3,  ///< タイプ３
			TYPE4,  ///< タイプ４ (SD カードアクセス）
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  データ長型
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class DLEN : uint8_t {
			W8  = 0b0111,	///< 8 Bits
			W9  = 0b1000,	///< 9 Bits
			W10 = 0b1001,	///< 10 Bits
			W11 = 0b1010,	///< 11 Bits
			W12 = 0b1011,	///< 12 Bits
			W13 = 0b1100,	///< 13 Bits
			W14 = 0b1101,	///< 14 Bits
			W15 = 0b1110,	///< 15 Bits
			W16 = 0b1111,	///< 16 Bits
			W20 = 0b0000,	///< 20 Bits
			W24 = 0b0001,	///< 24 Bits
			W32 = 0b0011,	///< 32 Bits
		};

	private:

		uint8_t	level_;

		// 便宜上のスリープ
		void sleep_() { asm("nop"); }

		bool clock_div_(uint32_t speed, uint8_t& brdv, uint8_t& spbr) {
///			utils::format("PCLK: %d\n") % static_cast<uint32_t>(PCLK);
			uint32_t br = static_cast<uint32_t>(PCLK) / speed;
			uint8_t dv = 0;
			while(br > 512) {
				br >>= 1;
				++dv;
				if(dv > 3) {
					brdv = 3;
					spbr = 255;
					return false;
				}
			}
			brdv = dv;
			if(br & 1) {
				br >>= 1;
				++br;
			} else {
				br >>= 1;
			}
			if(br) --br;
			spbr = br;
			return true;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		rspi_io() noexcept : level_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  設定可能な最大速度を返す @n
					・RX24T: 20MHz @n
					・RX64M: 40MHz
			@return 最大速度
		*/
		//-----------------------------------------------------------------//
		uint32_t get_max_speed() const noexcept {
			uint32_t clk = PCLK;
#ifdef SEEDA
			while(clk > 20000000) {  // 15MHz
//			while(clk > 10000000) {  // 7MHz
#else
			while(clk > 40000000) {
#endif
				clk >>= 1;
			}
			return clk;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  通信速度を設定して、CSI を有効にする
			@param[in]	speed	通信速度
			@param[in]	ctype	クロック位相タイプ
			@param[in]	dlen	データ長設定
			@param[in]	level	割り込みレベル（１～２）、０の場合はポーリング
			@return エラー（速度設定範囲外）なら「false」
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t speed, PHASE ctype, DLEN dlen, uint8_t level = 0) noexcept
		{
			level_ = level;

			power_mgr::turn(RSPI::get_peripheral());

			// デバイスを不許可
			RSPI::SPCR = 0x00;

			// ポートを有効にする
			port_map::turn(RSPI::get_peripheral(), true, PSEL);

			bool f = true;
			uint8_t brdv;
			uint8_t spbr;
			if(!clock_div_(speed, brdv, spbr)) {
				f = false;
			}

			// 設定
		    RSPI::SPBR = spbr;

			RSPI::SPPCR = 0x00;	// Fixed idle value, disable loop-back
			RSPI::SPSCR = 0x00;	// disable sequence control
			RSPI::SPDCR = 0x20;	// SPLW=1 (long word access)
///			RSPI::SPCMD0 = RSPI::SPCMD0.LSBF.b() | RSPI::SPCMD0.BRDV.b(brdv) | RSPI::SPCMD0.SPB.b(0b0100);
			bool cpol = 0;
			bool cpha = 0;
			switch(ctype) {
			case PHASE::TYPE1:
				break;
			case PHASE::TYPE2:
				cpha = 1;
				break;
			case PHASE::TYPE3:
				cpol = 1;
				break;
			case PHASE::TYPE4:
				cpol = 1;
				cpha = 1;
				break;
			default:
				break;
			}
			RSPI::SPCMD0 = RSPI::SPCMD0.BRDV.b(brdv)
				| RSPI::SPCMD0.SPB.b(static_cast<uint8_t>(dlen))
				| RSPI::SPCMD0.CPOL.b(cpol) | RSPI::SPCMD0.CPHA.b(cpha);

			RSPI::SPCR.SPMS = 1;
			RSPI::SPCR.MSTR = 1;

			RSPI::SPCR.SPE = 1;

			return f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ＳＤカード用設定を有効にする
			@param[in]	speed	通信速度
			@return エラー（速度設定範囲外）なら「false」
		*/
		//-----------------------------------------------------------------//
		bool start_sdc(uint32_t speed) noexcept
		{
			level_ = 0;

			power_mgr::turn(RSPI::get_peripheral());

			RSPI::SPCR = 0x00;

			bool f = true;
			uint8_t brdv;
			uint8_t spbr;
			if(!clock_div_(speed, brdv, spbr)) {
				f = false;
			}
			port_map::turn(RSPI::get_peripheral(), true, PSEL);
#if 0
			utils::format("RSPI Request Speed: %u [Hz]\n") % speed;
			utils::format("RSPI SPBR: %d\n") % static_cast<uint32_t>(spbr);
			utils::format("RSPI BRDV: %d\n") % static_cast<uint32_t>(brdv);
#endif
		    RSPI::SPBR = spbr;

			// 実際のクロックを表示
#if 0
			static const uint8_t n[4] = { 1, 2, 4, 8 };
			uint32_t z = static_cast<uint32_t>(PCLK)
					/ (2 * static_cast<uint32_t>(spbr + 1) * static_cast<uint32_t>(n[brdv]));
			utils::format("RSPI Real Speed: %u [Hz]\n") % z;
#endif
			RSPI::SPPCR = 0x00;	// Fixed idle value, disable loop-back
			RSPI::SPSCR = 0x00;	// disable sequence control
			RSPI::SPDCR = 0x20;	// SPLW=1 (long word access)
			RSPI::SPCMD0 = RSPI::SPCMD0.BRDV.b(brdv) | RSPI::SPCMD0.SPB.b(0b0100);
///				| RSPI::SPCMD0.CPHA.b(0) | RSPI::SPCMD0.CPOL.b(1);

			RSPI::SPCR.SPMS = 1;
			RSPI::SPCR.MSTR = 1;

			RSPI::SPCR.SPE = 1;

			return f;
		}

		//----------------------------------------------------------------//
		/*!
			@brief	リード・ライト
			@param[in]	data	書き込みデータ
			@return 読み出しデータ
		*/
		//----------------------------------------------------------------//
		uint8_t xchg(uint8_t data = 0xff) noexcept
		{
			RSPI::SPDR = static_cast<uint32_t>(data);
			while(RSPI::SPSR.SPRF() == 0) sleep_();
		    return RSPI::SPDR();
		}

		//----------------------------------------------------------------//
		/*!
			@brief	通信レジスタへ書き込み @n
					※通信幅は最大３２ビット（通信モード設定による）
			@param[in]	data	書き込みデータ
		*/
		//----------------------------------------------------------------//
		inline void xchg32_start(uint32_t data = 0) noexcept
		{
			RSPI::SPDR = static_cast<uint32_t>(data);
		}

		//----------------------------------------------------------------//
		/*!
			@brief	通信の同期とレジスタからの読み出し @n
					※通信幅は最大３２ビット（通信モード設定による）
			@return	読み出しデータ
		*/
		//----------------------------------------------------------------//
		inline uint32_t xchg32_sync() noexcept
		{
			while(RSPI::SPSR.SPRF() == 0) sleep_();
		    return RSPI::SPDR();
		}

		//----------------------------------------------------------------//
		/*!
			@brief	リード・ライト
			@param[in]	data	書き込みデータ
			@return 読み出しデータ
		*/
		//----------------------------------------------------------------//
		inline uint32_t xchg32(uint32_t data = 0) noexcept
		{
			xchg32_start(data);
			return xchg32_sync();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  シリアル送信
			@param[in]	src	送信ソース
			@param[in]	cnt	送信サイズ
		*/
		//-----------------------------------------------------------------//
		void send(const void* src, uint32_t size) noexcept
		{
			auto ptr = static_cast<const uint8_t*>(src);
			while(size > 0) {
				xchg(*ptr);
				++ptr;
				size--;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  シリアル受信
			@param[out]	dst	受信先
			@param[in]	cnt	受信サイズ
		*/
		//-----------------------------------------------------------------//
		void recv(void* dst, uint32_t size) noexcept
		{
			auto ptr = static_cast<uint8_t*>(dst);
			while(size > 0) {
				*ptr = xchg();
				++ptr;
				size--;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  RSPIを無効にして、パワーダウンする
			@param[in]	power パワーダウンをしない場合「false」
		*/
		//-----------------------------------------------------------------//
		void destroy(bool power = true) noexcept
		{
			RSPI::SPCR = 0x00;
			port_map::turn(RSPI::get_peripheral(), false);
			if(power) power_mgr::turn(RSPI::get_peripheral(), false);
		}
	};
}
<commit_msg>Update: Support RX72x<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX グループ・RSPI I/O 制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2016, 2019 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/vect.h"

/// F_PCKx は速度パラメーター計算で必要で、設定が無いとエラーにします。
#if defined(SIG_RX24T)
#ifndef F_PCLKB
#  error "rspi_io.hpp requires F_PCLKB to be defined"
#else
#undef PCLK
#define PCLK F_PCLKB
#endif
#elif defined(SIG_RX64M) || defined(SIG_RX71M) || defined(SIG_RX65N) || defined(SIG_RX72M) || defined(SIG_RX72N)
#ifndef F_PCLKA
#  error "rspi_io.hpp requires F_PCLKA to be defined"
#else
#undef PCLK
#define PCLK F_PCLKA
#endif
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  RSPI 制御クラス
		@param[in]	RSPI	RSPI 定義クラス
		@param[in]	PSEL	ポート候補
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class RSPI, port_map::option PSEL = port_map::option::FIRST>
	class rspi_io {
	public:

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  データ、クロック位相タイプ型
					TYPE1(MODE0): CPOL:0 CPHA:0 @n
					TYPE2(MODE1): CPOL:0 CPHA:1 @n
					TYPE3(MODE2): CPOL:1 CPHA:0 @n
					TYPE4(MODE3): CPOL:1 CPHA:1
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class PHASE : uint8_t {
			TYPE1,  ///< タイプ１
			TYPE2,  ///< タイプ２
			TYPE3,  ///< タイプ３
			TYPE4,  ///< タイプ４ (SD カードアクセス）
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  データ長型
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class DLEN : uint8_t {
			W8  = 0b0111,	///< 8 Bits
			W9  = 0b1000,	///< 9 Bits
			W10 = 0b1001,	///< 10 Bits
			W11 = 0b1010,	///< 11 Bits
			W12 = 0b1011,	///< 12 Bits
			W13 = 0b1100,	///< 13 Bits
			W14 = 0b1101,	///< 14 Bits
			W15 = 0b1110,	///< 15 Bits
			W16 = 0b1111,	///< 16 Bits
			W20 = 0b0000,	///< 20 Bits
			W24 = 0b0001,	///< 24 Bits
			W32 = 0b0011,	///< 32 Bits
		};

	private:

		uint8_t	level_;

		// 便宜上のスリープ
		void sleep_() { asm("nop"); }

		bool clock_div_(uint32_t speed, uint8_t& brdv, uint8_t& spbr) {
///			utils::format("PCLK: %d\n") % static_cast<uint32_t>(PCLK);
			uint32_t br = static_cast<uint32_t>(PCLK) / speed;
			uint8_t dv = 0;
			while(br > 512) {
				br >>= 1;
				++dv;
				if(dv > 3) {
					brdv = 3;
					spbr = 255;
					return false;
				}
			}
			brdv = dv;
			if(br & 1) {
				br >>= 1;
				++br;
			} else {
				br >>= 1;
			}
			if(br) --br;
			spbr = br;
			return true;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		rspi_io() noexcept : level_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  設定可能な最大速度を返す @n
					・RX24T: 20MHz @n
					・RX64M: 40MHz
			@return 最大速度
		*/
		//-----------------------------------------------------------------//
		uint32_t get_max_speed() const noexcept {
			uint32_t clk = PCLK;
#ifdef SEEDA
			while(clk > 20000000) {  // 15MHz
//			while(clk > 10000000) {  // 7MHz
#else
			while(clk > 40000000) {
#endif
				clk >>= 1;
			}
			return clk;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  通信速度を設定して、CSI を有効にする
			@param[in]	speed	通信速度
			@param[in]	ctype	クロック位相タイプ
			@param[in]	dlen	データ長設定
			@param[in]	level	割り込みレベル（１～２）、０の場合はポーリング
			@return エラー（速度設定範囲外）なら「false」
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t speed, PHASE ctype, DLEN dlen, uint8_t level = 0) noexcept
		{
			level_ = level;

			power_mgr::turn(RSPI::get_peripheral());

			// デバイスを不許可
			RSPI::SPCR = 0x00;

			// ポートを有効にする
			port_map::turn(RSPI::get_peripheral(), true, PSEL);

			bool f = true;
			uint8_t brdv;
			uint8_t spbr;
			if(!clock_div_(speed, brdv, spbr)) {
				f = false;
			}

			// 設定
		    RSPI::SPBR = spbr;

			RSPI::SPPCR = 0x00;	// Fixed idle value, disable loop-back
			RSPI::SPSCR = 0x00;	// disable sequence control
			RSPI::SPDCR = 0x20;	// SPLW=1 (long word access)
///			RSPI::SPCMD0 = RSPI::SPCMD0.LSBF.b() | RSPI::SPCMD0.BRDV.b(brdv) | RSPI::SPCMD0.SPB.b(0b0100);
			bool cpol = 0;
			bool cpha = 0;
			switch(ctype) {
			case PHASE::TYPE1:
				break;
			case PHASE::TYPE2:
				cpha = 1;
				break;
			case PHASE::TYPE3:
				cpol = 1;
				break;
			case PHASE::TYPE4:
				cpol = 1;
				cpha = 1;
				break;
			default:
				break;
			}
			RSPI::SPCMD0 = RSPI::SPCMD0.BRDV.b(brdv)
				| RSPI::SPCMD0.SPB.b(static_cast<uint8_t>(dlen))
				| RSPI::SPCMD0.CPOL.b(cpol) | RSPI::SPCMD0.CPHA.b(cpha);

			RSPI::SPCR.SPMS = 1;
			RSPI::SPCR.MSTR = 1;

			RSPI::SPCR.SPE = 1;

			return f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ＳＤカード用設定を有効にする
			@param[in]	speed	通信速度
			@return エラー（速度設定範囲外）なら「false」
		*/
		//-----------------------------------------------------------------//
		bool start_sdc(uint32_t speed) noexcept
		{
			level_ = 0;

			power_mgr::turn(RSPI::get_peripheral());

			RSPI::SPCR = 0x00;

			bool f = true;
			uint8_t brdv;
			uint8_t spbr;
			if(!clock_div_(speed, brdv, spbr)) {
				f = false;
			}
			port_map::turn(RSPI::get_peripheral(), true, PSEL);
#if 0
			utils::format("RSPI Request Speed: %u [Hz]\n") % speed;
			utils::format("RSPI SPBR: %d\n") % static_cast<uint32_t>(spbr);
			utils::format("RSPI BRDV: %d\n") % static_cast<uint32_t>(brdv);
#endif
		    RSPI::SPBR = spbr;

			// 実際のクロックを表示
#if 0
			static const uint8_t n[4] = { 1, 2, 4, 8 };
			uint32_t z = static_cast<uint32_t>(PCLK)
					/ (2 * static_cast<uint32_t>(spbr + 1) * static_cast<uint32_t>(n[brdv]));
			utils::format("RSPI Real Speed: %u [Hz]\n") % z;
#endif
			RSPI::SPPCR = 0x00;	// Fixed idle value, disable loop-back
			RSPI::SPSCR = 0x00;	// disable sequence control
			RSPI::SPDCR = 0x20;	// SPLW=1 (long word access)
			RSPI::SPCMD0 = RSPI::SPCMD0.BRDV.b(brdv) | RSPI::SPCMD0.SPB.b(0b0100);
///				| RSPI::SPCMD0.CPHA.b(0) | RSPI::SPCMD0.CPOL.b(1);

			RSPI::SPCR.SPMS = 1;
			RSPI::SPCR.MSTR = 1;

			RSPI::SPCR.SPE = 1;

			return f;
		}

		//----------------------------------------------------------------//
		/*!
			@brief	リード・ライト
			@param[in]	data	書き込みデータ
			@return 読み出しデータ
		*/
		//----------------------------------------------------------------//
		uint8_t xchg(uint8_t data = 0xff) noexcept
		{
			RSPI::SPDR = static_cast<uint32_t>(data);
			while(RSPI::SPSR.SPRF() == 0) sleep_();
		    return RSPI::SPDR();
		}

		//----------------------------------------------------------------//
		/*!
			@brief	通信レジスタへ書き込み @n
					※通信幅は最大３２ビット（通信モード設定による）
			@param[in]	data	書き込みデータ
		*/
		//----------------------------------------------------------------//
		inline void xchg32_start(uint32_t data = 0) noexcept
		{
			RSPI::SPDR = static_cast<uint32_t>(data);
		}

		//----------------------------------------------------------------//
		/*!
			@brief	通信の同期とレジスタからの読み出し @n
					※通信幅は最大３２ビット（通信モード設定による）
			@return	読み出しデータ
		*/
		//----------------------------------------------------------------//
		inline uint32_t xchg32_sync() noexcept
		{
			while(RSPI::SPSR.SPRF() == 0) sleep_();
		    return RSPI::SPDR();
		}

		//----------------------------------------------------------------//
		/*!
			@brief	リード・ライト
			@param[in]	data	書き込みデータ
			@return 読み出しデータ
		*/
		//----------------------------------------------------------------//
		inline uint32_t xchg32(uint32_t data = 0) noexcept
		{
			xchg32_start(data);
			return xchg32_sync();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  シリアル送信
			@param[in]	src	送信ソース
			@param[in]	cnt	送信サイズ
		*/
		//-----------------------------------------------------------------//
		void send(const void* src, uint32_t size) noexcept
		{
			auto ptr = static_cast<const uint8_t*>(src);
			while(size > 0) {
				xchg(*ptr);
				++ptr;
				size--;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  シリアル受信
			@param[out]	dst	受信先
			@param[in]	cnt	受信サイズ
		*/
		//-----------------------------------------------------------------//
		void recv(void* dst, uint32_t size) noexcept
		{
			auto ptr = static_cast<uint8_t*>(dst);
			while(size > 0) {
				*ptr = xchg();
				++ptr;
				size--;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  RSPIを無効にして、パワーダウンする
			@param[in]	power パワーダウンをしない場合「false」
		*/
		//-----------------------------------------------------------------//
		void destroy(bool power = true) noexcept
		{
			RSPI::SPCR = 0x00;
			port_map::turn(RSPI::get_peripheral(), false);
			if(power) power_mgr::turn(RSPI::get_peripheral(), false);
		}
	};
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsensormanager.h"
#include <QDebug>
#include "qsensorpluginloader_p.h"
#include "qsensorplugin.h"
#include <QSettings>

//#define LOG() if (1); else qDebug()

QTM_BEGIN_NAMESPACE

Q_GLOBAL_STATIC_WITH_ARGS(QSensorPluginLoader, pluginLoader, (QSensorPluginInterface_iid, QLatin1String("/sensors")))

typedef QHash<QByteArray,QSensorBackendFactory*> FactoryForIdentifierMap;
typedef QHash<QByteArray,FactoryForIdentifierMap> BackendIdentifiersForTypeMap;

class QSensorManagerPrivate
{
public:
    QSensorManagerPrivate()
        : pluginsLoaded(false)
    {
    }

    bool pluginsLoaded;

    QList<CreatePluginFunc> staticRegistrations;

    // Holds a mapping from type to available identifiers (and from there to the factory)
    BackendIdentifiersForTypeMap backendsByType;

    // Holds the first identifier for each type
    QHash<QByteArray, QByteArray> firstIdentifierForType;
};

Q_GLOBAL_STATIC(QSensorManagerPrivate, sensorManagerPrivate)

static void loadPlugins()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    d->pluginsLoaded = true;

    qDebug() << "initializing static plugins";
    Q_FOREACH (CreatePluginFunc func, d->staticRegistrations) {
        QSensorPluginInterface *plugin = func();
        plugin->registerSensors();
    }

    qDebug() << "initializing plugins";
    Q_FOREACH (QSensorPluginInterface *plugin, pluginLoader()->plugins()) {
        plugin->registerSensors();
    }
}

// =====================================================================

/*!
    \class QSensorManager
    \ingroup sensors_backend

    \preliminary
    \brief The QSensorManager class returns the sensors on a device.

    A given device will have a variety of sensors. The sensors are
    categorized by type.
*/

/*!
    Register a sensor for \a type. The \a identifier must be unique.

    The \a factory will be asked to create instances of the backend.
*/
void QSensorManager::registerBackend(const QByteArray &type, const QByteArray &identifier, QSensorBackendFactory *factory)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->backendsByType.contains(type)) {
        (void)d->backendsByType[type];
        d->firstIdentifierForType[type] = identifier;
    }
    qDebug() << "registering backend for type" << type << "identifier" << identifier;// << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
    FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[type];
    factoryByIdentifier[identifier] = factory;
}

/*!
    \internal
*/
void QSensorManager::registerStaticPlugin(CreatePluginFunc func)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    d->staticRegistrations.append(func);
}

/*!
    Create a backend for \a sensor. Returns null if no suitable backend exists.
*/
QSensorBackend *QSensorManager::createBackend(QSensor *sensor)
{
    Q_ASSERT(sensor);

    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    //LOG() << "QSensorManager::createBackend" << "type" << sensor->type() << "identifier" << sensor->identifier();

    if (!d->backendsByType.contains(sensor->type())) {
        qDebug() << "no backends of type" << sensor->type() << "have been registered.";
        return 0;
    }

    const FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[sensor->type()];
    QSensorBackendFactory *factory;
    QSensorBackend *backend;

    if (sensor->identifier().isEmpty()) {
        QByteArray defaultIdentifier = QSensor::defaultSensorForType(sensor->type());
        //LOG() << "Trying the default" << defaultIdentifier;
        // No identifier set, try the default
        factory = factoryByIdentifier[defaultIdentifier];
        //LOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
        sensor->setIdentifier(defaultIdentifier); // the factory requires this
        backend = factory->createBackend(sensor);
        if (backend) return backend; // Got it!

        // The default failed to instantiate so try any other registered sensors for this type
        Q_FOREACH (const QByteArray &identifier, factoryByIdentifier.keys()) {
            //LOG() << "Trying" << identifier;
            if (identifier == defaultIdentifier) continue; // Don't do the default one again
            factory = factoryByIdentifier[identifier];
            //LOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
            sensor->setIdentifier(identifier); // the factory requires this
            backend = factory->createBackend(sensor);
            if (backend) return backend; // Got it!
        }
        //LOG() << "FAILED";
        sensor->setIdentifier(QByteArray()); // clear the identifier
    } else {
        if (!factoryByIdentifier.contains(sensor->identifier())) {
            qDebug() << "no backend with identifier" << sensor->identifier() << "for type" << sensor->type();
            return 0;
        }

        // We were given an explicit identifier so don't substitute other backends if it fails to instantiate
        factory = factoryByIdentifier[sensor->identifier()];
        //LOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
        backend = factory->createBackend(sensor);
        if (backend) return backend; // Got it!
    }

    qDebug() << "no suitable backend found for requested identifier" << sensor->identifier() << "and type" << sensor->type();
    return 0;
}

// =====================================================================

/*!
    Returns a list of all sensor types.
*/
QList<QByteArray> QSensor::sensorTypes()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    return d->backendsByType.keys();
}

/*!
    Returns a list of ids for each of the sensors for \a type.
    If there are no sensors of that type available the list will be empty.
*/
QList<QByteArray> QSensor::sensorsForType(const QByteArray &type)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    return d->backendsByType[type].keys();
}

/*!
    Returns the default sensor identifier for \a type.
    This is set in a config file and can be overridden if required.
    If no default is available the system will return the first registered
    sensor for \a type.
*/
QByteArray QSensor::defaultSensorForType(const QByteArray &type)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    // no sensors of that type exist
    if (!d->backendsByType.contains(type))
        return QByteArray();

    QSettings settings(QLatin1String("Nokia"), QLatin1String("Sensors"));
    QVariant value = settings.value(QString(QLatin1String("Default/%1")).arg(QString::fromLatin1(type)));
    if (!value.isNull()) {
        QByteArray defaultIdentifier = value.toByteArray();
        if (d->backendsByType[type].contains(defaultIdentifier)) // Don't return a value that we can't use!
            return defaultIdentifier;
    }

    // This is our fallback
    return d->firstIdentifierForType[type];
}

// =====================================================================

/*!
    \class QSensorBackendFactory
    \ingroup sensors_backend

    \preliminary
    \brief The QSensorBackendFactory class instantiates instances of
           QSensorBackend.

    This interface must be implemented in order to register a sensor backend.

    \sa {Creating a sensor plugin}
*/

/*!
    \fn QSensorBackendFactory::~QSensorBackendFactory()
    \internal
*/

/*!
    \fn QSensorBackendFactory::createBackend(QSensor *sensor)

    Instantiate a backend. If the factory handles multiple identifiers
    it should check with the \a sensor to see which one is requested.

    If the factory cannot create a backend it should return 0.
*/

/*!
    \macro REGISTER_STATIC_PLUGIN(pluginname)
    \relates QSensorManager

    Registers a static plugin, \a pluginname.

    Note that this macro relies on static initialization so it may not be appropriate
    for use in a library and may not work on all platforms.

    \sa {Creating a sensor plugin}
*/

QTM_END_NAMESPACE

<commit_msg>Doc: describe QSensorManager properly.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsensormanager.h"
#include <QDebug>
#include "qsensorpluginloader_p.h"
#include "qsensorplugin.h"
#include <QSettings>

//#define LOG() if (1); else qDebug()

QTM_BEGIN_NAMESPACE

Q_GLOBAL_STATIC_WITH_ARGS(QSensorPluginLoader, pluginLoader, (QSensorPluginInterface_iid, QLatin1String("/sensors")))

typedef QHash<QByteArray,QSensorBackendFactory*> FactoryForIdentifierMap;
typedef QHash<QByteArray,FactoryForIdentifierMap> BackendIdentifiersForTypeMap;

class QSensorManagerPrivate
{
public:
    QSensorManagerPrivate()
        : pluginsLoaded(false)
    {
    }

    bool pluginsLoaded;

    QList<CreatePluginFunc> staticRegistrations;

    // Holds a mapping from type to available identifiers (and from there to the factory)
    BackendIdentifiersForTypeMap backendsByType;

    // Holds the first identifier for each type
    QHash<QByteArray, QByteArray> firstIdentifierForType;
};

Q_GLOBAL_STATIC(QSensorManagerPrivate, sensorManagerPrivate)

static void loadPlugins()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    d->pluginsLoaded = true;

    qDebug() << "initializing static plugins";
    Q_FOREACH (CreatePluginFunc func, d->staticRegistrations) {
        QSensorPluginInterface *plugin = func();
        plugin->registerSensors();
    }

    qDebug() << "initializing plugins";
    Q_FOREACH (QSensorPluginInterface *plugin, pluginLoader()->plugins()) {
        plugin->registerSensors();
    }
}

// =====================================================================

/*!
    \class QSensorManager
    \ingroup sensors_backend

    \preliminary
    \brief The QSensorManager class handles registration and creation of sensor backends.

    Sensor plugins register backends using the registerBackend() function.

    When QSensor::connect() is called, the createBackend() function will be called.
*/

/*!
    Register a sensor for \a type. The \a identifier must be unique.

    The \a factory will be asked to create instances of the backend.
*/
void QSensorManager::registerBackend(const QByteArray &type, const QByteArray &identifier, QSensorBackendFactory *factory)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->backendsByType.contains(type)) {
        (void)d->backendsByType[type];
        d->firstIdentifierForType[type] = identifier;
    }
    qDebug() << "registering backend for type" << type << "identifier" << identifier;// << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
    FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[type];
    factoryByIdentifier[identifier] = factory;
}

/*!
    \internal
*/
void QSensorManager::registerStaticPlugin(CreatePluginFunc func)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    d->staticRegistrations.append(func);
}

/*!
    Create a backend for \a sensor. Returns null if no suitable backend exists.
*/
QSensorBackend *QSensorManager::createBackend(QSensor *sensor)
{
    Q_ASSERT(sensor);

    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    //LOG() << "QSensorManager::createBackend" << "type" << sensor->type() << "identifier" << sensor->identifier();

    if (!d->backendsByType.contains(sensor->type())) {
        qDebug() << "no backends of type" << sensor->type() << "have been registered.";
        return 0;
    }

    const FactoryForIdentifierMap &factoryByIdentifier = d->backendsByType[sensor->type()];
    QSensorBackendFactory *factory;
    QSensorBackend *backend;

    if (sensor->identifier().isEmpty()) {
        QByteArray defaultIdentifier = QSensor::defaultSensorForType(sensor->type());
        //LOG() << "Trying the default" << defaultIdentifier;
        // No identifier set, try the default
        factory = factoryByIdentifier[defaultIdentifier];
        //LOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
        sensor->setIdentifier(defaultIdentifier); // the factory requires this
        backend = factory->createBackend(sensor);
        if (backend) return backend; // Got it!

        // The default failed to instantiate so try any other registered sensors for this type
        Q_FOREACH (const QByteArray &identifier, factoryByIdentifier.keys()) {
            //LOG() << "Trying" << identifier;
            if (identifier == defaultIdentifier) continue; // Don't do the default one again
            factory = factoryByIdentifier[identifier];
            //LOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
            sensor->setIdentifier(identifier); // the factory requires this
            backend = factory->createBackend(sensor);
            if (backend) return backend; // Got it!
        }
        //LOG() << "FAILED";
        sensor->setIdentifier(QByteArray()); // clear the identifier
    } else {
        if (!factoryByIdentifier.contains(sensor->identifier())) {
            qDebug() << "no backend with identifier" << sensor->identifier() << "for type" << sensor->type();
            return 0;
        }

        // We were given an explicit identifier so don't substitute other backends if it fails to instantiate
        factory = factoryByIdentifier[sensor->identifier()];
        //LOG() << "factory" << QString().sprintf("0x%08x", (unsigned int)factory);
        backend = factory->createBackend(sensor);
        if (backend) return backend; // Got it!
    }

    qDebug() << "no suitable backend found for requested identifier" << sensor->identifier() << "and type" << sensor->type();
    return 0;
}

// =====================================================================

/*!
    Returns a list of all sensor types.
*/
QList<QByteArray> QSensor::sensorTypes()
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    return d->backendsByType.keys();
}

/*!
    Returns a list of ids for each of the sensors for \a type.
    If there are no sensors of that type available the list will be empty.
*/
QList<QByteArray> QSensor::sensorsForType(const QByteArray &type)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    return d->backendsByType[type].keys();
}

/*!
    Returns the default sensor identifier for \a type.
    This is set in a config file and can be overridden if required.
    If no default is available the system will return the first registered
    sensor for \a type.
*/
QByteArray QSensor::defaultSensorForType(const QByteArray &type)
{
    QSensorManagerPrivate *d = sensorManagerPrivate();
    if (!d->pluginsLoaded)
        loadPlugins();

    // no sensors of that type exist
    if (!d->backendsByType.contains(type))
        return QByteArray();

    QSettings settings(QLatin1String("Nokia"), QLatin1String("Sensors"));
    QVariant value = settings.value(QString(QLatin1String("Default/%1")).arg(QString::fromLatin1(type)));
    if (!value.isNull()) {
        QByteArray defaultIdentifier = value.toByteArray();
        if (d->backendsByType[type].contains(defaultIdentifier)) // Don't return a value that we can't use!
            return defaultIdentifier;
    }

    // This is our fallback
    return d->firstIdentifierForType[type];
}

// =====================================================================

/*!
    \class QSensorBackendFactory
    \ingroup sensors_backend

    \preliminary
    \brief The QSensorBackendFactory class instantiates instances of
           QSensorBackend.

    This interface must be implemented in order to register a sensor backend.

    \sa {Creating a sensor plugin}
*/

/*!
    \fn QSensorBackendFactory::~QSensorBackendFactory()
    \internal
*/

/*!
    \fn QSensorBackendFactory::createBackend(QSensor *sensor)

    Instantiate a backend. If the factory handles multiple identifiers
    it should check with the \a sensor to see which one is requested.

    If the factory cannot create a backend it should return 0.
*/

/*!
    \macro REGISTER_STATIC_PLUGIN(pluginname)
    \relates QSensorManager

    Registers a static plugin, \a pluginname.

    Note that this macro relies on static initialization so it may not be appropriate
    for use in a library and may not work on all platforms.

    \sa {Creating a sensor plugin}
*/

QTM_END_NAMESPACE

<|endoftext|>


<commit_before>#include "storage.h"

namespace Epyx
{
namespace DHT
{

    Storage::Storage(){};

    bool Storage::has(const std::string& key){
        lock.lock();
        bool result = data.count(key) != 0;
        lock.unlock();
        return result;
    }

    bool Storage::get(const std::string& key, Value& res){
        bool result = false;
        lock.lock();
        std::map<std::string, Value>::iterator it = data.find(key);
        if (it != data.end()) {
            res = (*it).second;
            result = true;
        }
        lock.unlock();
        return result;
    }

    void Storage::set(const std::string& key, const std::string& datum){
        lock.lock();
        Value v(datum);
        data.insert(std::make_pair(key, datum));
        lock.unlock();
    }

}
}
<commit_msg>DHT: now we can update values in the DHT<commit_after>#include "storage.h"

namespace Epyx
{
namespace DHT
{

    Storage::Storage(){};

    bool Storage::has(const std::string& key){
        lock.lock();
        bool result = data.count(key) != 0;
        lock.unlock();
        return result;
    }

    bool Storage::get(const std::string& key, Value& res){
        bool result = false;
        lock.lock();
        std::map<std::string, Value>::iterator it = data.find(key);
        if (it != data.end()) {
            res = (*it).second;
            result = true;
        }
        lock.unlock();
        return result;
    }

    void Storage::set(const std::string& key, const std::string& datum){
        lock.lock();
        Value v(datum);
        if(data.find(key) == data.end()) {
            data.insert(std::make_pair(key, datum));
        } else {
            (*data.find(key)).second = datum;
        }
        lock.unlock();
    }

}
}
<|endoftext|>


<commit_before>#include "transactionrecord.h"
#include "wallet.h"
#include "base58.h"

std::string GetTxProject(uint256 hash, int& out_blocknumber, int& out_blocktype, double& out_rac);

/* Return positive answer if transaction should be shown in list. */
bool TransactionRecord::showTransaction(const CWalletTx &wtx)
{

	std::string ShowOrphans = GetArg("-showorphans", "false");

	//R Halford - POS Transactions - If Orphaned follow showorphans directive:
	if (wtx.IsCoinStake() && !wtx.IsInMainChain())
	{
	       //Orphaned tx
		   return (ShowOrphans=="true" ? true : false);
    }

    if (wtx.IsCoinBase())
    {
        // Ensures we show generated coins / mined transactions at depth 1
        if (!wtx.IsInMainChain())
        {
            return false;
        }
    }

    // Suppress OP_RETURN transactions if they did not originate from you.
    // This is not "very" taxing but necessary since the transaction is in the wallet already.
    if (!wtx.IsFromMe())
    {
        for (auto const& txout : wtx.vout)
        {
            if (txout.scriptPubKey == (CScript() << OP_RETURN))
                return false;
        }
    }
    return true;
}

	int64_t GetMyValueOut(const CWallet *wallet,const CWalletTx &wtx)
    {
        int64_t nValueOut = 0;
        for (auto const& txout : wtx.vout)
        {
	       if (wallet->IsMine(txout))
		   {
				nValueOut += txout.nValue;
		   }
        }
        return nValueOut;
    }

/*
 * Decompose CWallet transaction to model transaction records.
 */
QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{
    QList<TransactionRecord> parts;
    int64_t nTime = wtx.GetTxTime();
    int64_t nCredit = wtx.GetCredit(true);
    int64_t nDebit = wtx.GetDebit();
    int64_t nNet = nCredit - nDebit;
    uint256 hash = wtx.GetHash(), hashPrev = 0;
    std::map<std::string, std::string> mapValue = wtx.mapValue;

    if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake())
    {
        // Cannot use range based loop anymore
        for (unsigned int t = 0; t < wtx.vout.size(); t++)
        //for (auto const& txout : wtx.vout)
        {
            if(wallet->IsMine(wtx.vout[t]))
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number
                sub.credit = wtx.vout[t].nValue;
                sub.vout = t;

                if (ExtractDestination(wtx.vout[t].scriptPubKey, address) && IsMine(*wallet, address))
                {
                    // Received by Bitcoin Address
                    sub.type = TransactionRecord::RecvWithAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
                    sub.type = TransactionRecord::RecvFromOther;
                    sub.address = mapValue["from"];
                }
                if (wtx.IsCoinBase())
                {
                    // Generated (proof-of-work)
                    sub.type = TransactionRecord::Generated;
                }
                if (wtx.IsCoinStake())
                {
                    // Generated (proof-of-stake)
                    if (hashPrev == hash)
                        continue; // last coinstake output

                    if (wtx.vout.size() >= 2)
                    {
                        //Standard POR/POS CoinStake
                        sub.type = TransactionRecord::Generated;
                        sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit;
                        hashPrev = hash;
                    }
                }

                parts.append(sub);
            }
        }
    }
    else
    {
        bool fAllFromMe = true;
        for (auto const& txin : wtx.vin)
            fAllFromMe = fAllFromMe && wallet->IsMine(txin);

        bool fAllToMe = true;
        for (auto const& txout : wtx.vout)
            fAllToMe = fAllToMe && wallet->IsMine(txout);

        if (fAllFromMe && fAllToMe)
        {
            // Payment to self
            int64_t nChange = wtx.GetChange();

            parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
                            -(nDebit - nChange), nCredit - nChange, 0));
        }
        else if (fAllFromMe)
        {
            //
            // Debit
            //
            int64_t nTxFee = nDebit - wtx.GetValueOut();

            for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
            {
                const CTxOut& txout = wtx.vout[nOut];
                TransactionRecord sub(hash, nTime);
                sub.idx = parts.size();

                if(wallet->IsMine(txout))
                {
                    // Ignore parts sent to self, as this is usually the change
                    // from a transaction sent back to our own address.
                    continue;
                }

                CTxDestination address;
                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    // Sent to Bitcoin Address
                    sub.type = TransactionRecord::SendToAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Sent to IP, or other non-address transaction like OP_EVAL
                    sub.type = TransactionRecord::SendToOther;
                    sub.address = mapValue["to"];
                }

                int64_t nValue = txout.nValue;
                /* Add fee to first output */
                if (nTxFee > 0)
                {
                    nValue += nTxFee;
                    nTxFee = 0;
                }
                sub.debit = -nValue;

                parts.append(sub);
            }
        }
        else
        {
            //
            // Mixed debit transaction, can't break down payees
            //
            parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0, 0));
        }
    }

    return parts;
}

void TransactionRecord::updateStatus(const CWalletTx &wtx)
{
    AssertLockHeld(cs_main);
    // Determine transaction status

    // Find the block the tx is in
    CBlockIndex* pindex = NULL;
    BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
    if (mi != mapBlockIndex.end())
        pindex = (*mi).second;

    // Sort order, unrecorded transactions sort to the top
    status.sortKey = strprintf("%010d-%01d-%010u-%03d",
        (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
        (wtx.IsCoinBase() ? 1 : 0),
        wtx.nTimeReceived,
        idx);
    status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
    status.depth = wtx.GetDepthInMainChain();
    status.cur_num_blocks = nBestHeight;

    if (!IsFinalTx(wtx, nBestHeight + 1))
    {
        if (wtx.nLockTime < LOCKTIME_THRESHOLD)
        {
            status.status = TransactionStatus::OpenUntilBlock;
            status.open_for = wtx.nLockTime - nBestHeight;
        }
        else
        {
            status.status = TransactionStatus::OpenUntilDate;
            status.open_for = wtx.nLockTime;
        }
    }

    // For generated transactions, determine maturity
    else if(type == TransactionRecord::Generated)
    {
        if (wtx.GetBlocksToMaturity() > 0)
        {
            status.status = TransactionStatus::Immature;

            if (wtx.IsInMainChain())
            {
                status.matures_in = wtx.GetBlocksToMaturity();

                // Check if the block was requested by anyone
                if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
                    status.status = TransactionStatus::MaturesWarning;
            }
            else
            {
                status.status = TransactionStatus::NotAccepted;
            }
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
    else
    {
        if (status.depth < 0)
        {
            status.status = TransactionStatus::Conflicted;
        }
        else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
        {
            status.status = TransactionStatus::Offline;
        }
        else if (status.depth == 0)
        {
            status.status = TransactionStatus::Unconfirmed;
        }
        else if (status.depth < RecommendedNumConfirmations)
        {
            status.status = TransactionStatus::Confirming;
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
}

bool TransactionRecord::statusUpdateNeeded()
{
    AssertLockHeld(cs_main);
    return status.cur_num_blocks != nBestHeight;
}

std::string TransactionRecord::getTxID()
{
    return hash.ToString() + strprintf("-%03d", idx);
}

<commit_msg>Correction of UTXO credit for coinstake<commit_after>#include "transactionrecord.h"
#include "wallet.h"
#include "base58.h"

std::string GetTxProject(uint256 hash, int& out_blocknumber, int& out_blocktype, double& out_rac);

/* Return positive answer if transaction should be shown in list. */
bool TransactionRecord::showTransaction(const CWalletTx &wtx)
{

	std::string ShowOrphans = GetArg("-showorphans", "false");

	//R Halford - POS Transactions - If Orphaned follow showorphans directive:
	if (wtx.IsCoinStake() && !wtx.IsInMainChain())
	{
	       //Orphaned tx
		   return (ShowOrphans=="true" ? true : false);
    }

    if (wtx.IsCoinBase())
    {
        // Ensures we show generated coins / mined transactions at depth 1
        if (!wtx.IsInMainChain())
        {
            return false;
        }
    }

    // Suppress OP_RETURN transactions if they did not originate from you.
    // This is not "very" taxing but necessary since the transaction is in the wallet already.
    if (!wtx.IsFromMe())
    {
        for (auto const& txout : wtx.vout)
        {
            if (txout.scriptPubKey == (CScript() << OP_RETURN))
                return false;
        }
    }
    return true;
}

	int64_t GetMyValueOut(const CWallet *wallet,const CWalletTx &wtx)
    {
        int64_t nValueOut = 0;
        for (auto const& txout : wtx.vout)
        {
	       if (wallet->IsMine(txout))
		   {
				nValueOut += txout.nValue;
		   }
        }
        return nValueOut;
    }

/*
 * Decompose CWallet transaction to model transaction records.
 */
QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{
    QList<TransactionRecord> parts;
    int64_t nTime = wtx.GetTxTime();
    int64_t nCredit = wtx.GetCredit(true);
    int64_t nDebit = wtx.GetDebit();
    int64_t nNet = nCredit - nDebit;
    uint256 hash = wtx.GetHash(), hashPrev = 0;
    std::map<std::string, std::string> mapValue = wtx.mapValue;

    if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake())
    {
        // Cannot use range based loop anymore
        for (unsigned int t = 0; t < wtx.vout.size(); t++)
        //for (auto const& txout : wtx.vout)
        {
            if(wallet->IsMine(wtx.vout[t]))
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number
                sub.credit = wtx.vout[t].nValue;
                sub.vout = t;

                if (ExtractDestination(wtx.vout[t].scriptPubKey, address) && IsMine(*wallet, address))
                {
                    // Received by Bitcoin Address
                    sub.type = TransactionRecord::RecvWithAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
                    sub.type = TransactionRecord::RecvFromOther;
                    sub.address = mapValue["from"];
                }
                if (wtx.IsCoinBase())
                {
                    // Generated (proof-of-work)
                    sub.type = TransactionRecord::Generated;
                }
                if (wtx.IsCoinStake())
                {
                    // Generated (proof-of-stake)
                    if (hashPrev == hash)
                        continue; // last coinstake output

                    if (wtx.vout.size() >= 2)
                    {
                        //Standard POR/POS CoinStake
                        sub.type = TransactionRecord::Generated;
                        sub.credit = nNet > 0 ? nNet : GetMyValueOut(wallet, wtx) - nDebit;
                        hashPrev = hash;
                    }
                }

                parts.append(sub);
            }
        }
    }
    else
    {
        bool fAllFromMe = true;
        for (auto const& txin : wtx.vin)
            fAllFromMe = fAllFromMe && wallet->IsMine(txin);

        bool fAllToMe = true;
        for (auto const& txout : wtx.vout)
            fAllToMe = fAllToMe && wallet->IsMine(txout);

        if (fAllFromMe && fAllToMe)
        {
            // Payment to self
            int64_t nChange = wtx.GetChange();

            parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
                            -(nDebit - nChange), nCredit - nChange, 0));
        }
        else if (fAllFromMe)
        {
            //
            // Debit
            //
            int64_t nTxFee = nDebit - wtx.GetValueOut();

            for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
            {
                const CTxOut& txout = wtx.vout[nOut];
                TransactionRecord sub(hash, nTime);
                sub.idx = parts.size();

                if(wallet->IsMine(txout))
                {
                    // Ignore parts sent to self, as this is usually the change
                    // from a transaction sent back to our own address.
                    continue;
                }

                CTxDestination address;
                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    // Sent to Bitcoin Address
                    sub.type = TransactionRecord::SendToAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Sent to IP, or other non-address transaction like OP_EVAL
                    sub.type = TransactionRecord::SendToOther;
                    sub.address = mapValue["to"];
                }

                int64_t nValue = txout.nValue;
                /* Add fee to first output */
                if (nTxFee > 0)
                {
                    nValue += nTxFee;
                    nTxFee = 0;
                }
                sub.debit = -nValue;

                parts.append(sub);
            }
        }
        else
        {
            //
            // Mixed debit transaction, can't break down payees
            //
            parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0, 0));
        }
    }

    return parts;
}

void TransactionRecord::updateStatus(const CWalletTx &wtx)
{
    AssertLockHeld(cs_main);
    // Determine transaction status

    // Find the block the tx is in
    CBlockIndex* pindex = NULL;
    BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
    if (mi != mapBlockIndex.end())
        pindex = (*mi).second;

    // Sort order, unrecorded transactions sort to the top
    status.sortKey = strprintf("%010d-%01d-%010u-%03d",
        (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
        (wtx.IsCoinBase() ? 1 : 0),
        wtx.nTimeReceived,
        idx);
    status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
    status.depth = wtx.GetDepthInMainChain();
    status.cur_num_blocks = nBestHeight;

    if (!IsFinalTx(wtx, nBestHeight + 1))
    {
        if (wtx.nLockTime < LOCKTIME_THRESHOLD)
        {
            status.status = TransactionStatus::OpenUntilBlock;
            status.open_for = wtx.nLockTime - nBestHeight;
        }
        else
        {
            status.status = TransactionStatus::OpenUntilDate;
            status.open_for = wtx.nLockTime;
        }
    }

    // For generated transactions, determine maturity
    else if(type == TransactionRecord::Generated)
    {
        if (wtx.GetBlocksToMaturity() > 0)
        {
            status.status = TransactionStatus::Immature;

            if (wtx.IsInMainChain())
            {
                status.matures_in = wtx.GetBlocksToMaturity();

                // Check if the block was requested by anyone
                if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
                    status.status = TransactionStatus::MaturesWarning;
            }
            else
            {
                status.status = TransactionStatus::NotAccepted;
            }
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
    else
    {
        if (status.depth < 0)
        {
            status.status = TransactionStatus::Conflicted;
        }
        else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
        {
            status.status = TransactionStatus::Offline;
        }
        else if (status.depth == 0)
        {
            status.status = TransactionStatus::Unconfirmed;
        }
        else if (status.depth < RecommendedNumConfirmations)
        {
            status.status = TransactionStatus::Confirming;
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
}

bool TransactionRecord::statusUpdateNeeded()
{
    AssertLockHeld(cs_main);
    return status.cur_num_blocks != nBestHeight;
}

std::string TransactionRecord::getTxID()
{
    return hash.ToString() + strprintf("-%03d", idx);
}

<|endoftext|>


<commit_before>
struct FLV_Pack {
  int len;
  int buf;
  bool isKeyframe;
  char * data;
};//FLV_Pack

char FLVHeader[13];
bool All_Hell_Broke_Loose = false;

//checks FLV Header for correctness
//returns true if everything is alright, false otherwise
bool FLV_Checkheader(char * header){
  if (header[0] != 'F') return false;
  if (header[1] != 'L') return false;
  if (header[2] != 'V') return false;
  if (header[8] != 0x09) return false;
  if (header[9] != 0) return false;
  if (header[10] != 0) return false;
  if (header[11] != 0) return false;
  if (header[12] != 0) return false;
  return true;
}//FLV_Checkheader

//returns true if header is an FLV header
bool FLV_Isheader(char * header){
  if (header[0] != 'F') return false;
  if (header[1] != 'L') return false;
  if (header[2] != 'V') return false;
  return true;
}//FLV_Isheader

bool ReadUntil(char * buffer, unsigned int count, unsigned int & sofar, int sock){
  if (count > 500000){
    All_Hell_Broke_Loose = true;
    fprintf(stderr, "ReadUntil fail: > 500kb tag? All Hell Broke Loose!\n", strerror(errno));
    return false;
  }
  if (sofar >= count){return true;}
  int r = 0;
  r = DDV_iread(buffer + sofar,count-sofar,sock);
  if (r < 0){
    if (errno != EWOULDBLOCK){
      All_Hell_Broke_Loose = true;
      fprintf(stderr, "ReadUntil fail: %s. All Hell Broke Loose!\n", strerror(errno));
    }
    return false;
  }
  sofar += r;
  if (sofar == count){return true;}
  if (sofar > count){
    All_Hell_Broke_Loose = true;
    fprintf(stderr, "ReadUntil fail: %s. Read too much. All Hell Broke Loose!\n", strerror(errno));
  }
  return false;
}

//gets a packet, storing in given FLV_Pack pointer.
//will assign pointer if null
//resizes FLV_Pack data field bigger if data doesn't fit
// (does not auto-shrink for speed!)
bool FLV_GetPacket(FLV_Pack *& p, int sock){
  static bool done = true;
  static unsigned int sofar = 0;
  if (!p){p = (FLV_Pack*)calloc(1, sizeof(FLV_Pack));}
  if (p->buf < 15){p->data = (char*)realloc(p->data, 15); p->buf = 15;}

  if (done){
    //read a header
    if (ReadUntil(p->data, 11, sofar, sock)){
      //if its a correct FLV header, throw away and read tag header
      if (FLV_Isheader(p->data)){
        if (ReadUntil(p->data, 13, sofar, sock)){
          if (FLV_Checkheader(p->data)){
            sofar = 0;
            memcpy(FLVHeader, p->data, 13);
          }else{
            All_Hell_Broke_Loose = true;
            fprintf(stderr, "Invalid FLV header. All Hell Broke Loose!\n");
          }
        }
      }else{
        //if a tag header, calculate length and read tag body
        p->len = p->data[3] + 15;
        p->len += (p->data[2] << 8);
        p->len += (p->data[1] << 16);
        //fprintf(stderr, "Tag of len %i\n", p->len);
        if (p->buf < p->len){p->data = (char*)realloc(p->data, p->len);p->buf = p->len;}
        done = false;
      }
    }
  }else{
    //read tag body
    if (ReadUntil(p->data, p->len, sofar, sock)){
      //calculate keyframeness, next time read header again, return true
      p->isKeyframe = false;
      if ((p->data[0] == 0x09) && (((p->data[11] & 0xf0) >> 4) == 1)){p->isKeyframe = true;}
      int testlen = p->data[p->len-1] + 15;
      testlen += (p->data[p->len-2] << 8);
      testlen += (p->data[p->len-3] << 16);
      fprintf(stderr, "Len: %i, testlen: %i\n", p->len, testlen);
      done = true;
      sofar = 0;
      return true;
    }
  }
  return false;
}//FLV_GetPacket

<commit_msg>Tag lengths...<commit_after>
struct FLV_Pack {
  int len;
  int buf;
  bool isKeyframe;
  char * data;
};//FLV_Pack

char FLVHeader[13];
bool All_Hell_Broke_Loose = false;

//checks FLV Header for correctness
//returns true if everything is alright, false otherwise
bool FLV_Checkheader(char * header){
  if (header[0] != 'F') return false;
  if (header[1] != 'L') return false;
  if (header[2] != 'V') return false;
  if (header[8] != 0x09) return false;
  if (header[9] != 0) return false;
  if (header[10] != 0) return false;
  if (header[11] != 0) return false;
  if (header[12] != 0) return false;
  return true;
}//FLV_Checkheader

//returns true if header is an FLV header
bool FLV_Isheader(char * header){
  if (header[0] != 'F') return false;
  if (header[1] != 'L') return false;
  if (header[2] != 'V') return false;
  return true;
}//FLV_Isheader

bool ReadUntil(char * buffer, unsigned int count, unsigned int & sofar, int sock){
  if (count > 500000){
    All_Hell_Broke_Loose = true;
    fprintf(stderr, "ReadUntil fail: > 500kb tag? All Hell Broke Loose!\n", strerror(errno));
    return false;
  }
  if (sofar >= count){return true;}
  int r = 0;
  r = DDV_iread(buffer + sofar,count-sofar,sock);
  if (r < 0){
    if (errno != EWOULDBLOCK){
      All_Hell_Broke_Loose = true;
      fprintf(stderr, "ReadUntil fail: %s. All Hell Broke Loose!\n", strerror(errno));
    }
    return false;
  }
  sofar += r;
  if (sofar == count){return true;}
  if (sofar > count){
    All_Hell_Broke_Loose = true;
    fprintf(stderr, "ReadUntil fail: %s. Read too much. All Hell Broke Loose!\n", strerror(errno));
  }
  return false;
}

//gets a packet, storing in given FLV_Pack pointer.
//will assign pointer if null
//resizes FLV_Pack data field bigger if data doesn't fit
// (does not auto-shrink for speed!)
bool FLV_GetPacket(FLV_Pack *& p, int sock){
  static bool done = true;
  static unsigned int sofar = 0;
  if (!p){p = (FLV_Pack*)calloc(1, sizeof(FLV_Pack));}
  if (p->buf < 15){p->data = (char*)realloc(p->data, 15); p->buf = 15;}

  if (done){
    //read a header
    if (ReadUntil(p->data, 11, sofar, sock)){
      //if its a correct FLV header, throw away and read tag header
      if (FLV_Isheader(p->data)){
        if (ReadUntil(p->data, 13, sofar, sock)){
          if (FLV_Checkheader(p->data)){
            sofar = 0;
            memcpy(FLVHeader, p->data, 13);
          }else{
            All_Hell_Broke_Loose = true;
            fprintf(stderr, "Invalid FLV header. All Hell Broke Loose!\n");
          }
        }
      }else{
        //if a tag header, calculate length and read tag body
        p->len = p->data[3] + 15;
        p->len += (p->data[2] << 8);
        p->len += (p->data[1] << 16);
        //fprintf(stderr, "Tag of len %i\n", p->len);
        if (p->buf < p->len){p->data = (char*)realloc(p->data, p->len);p->buf = p->len;}
        done = false;
      }
    }
  }else{
    //read tag body
    if (ReadUntil(p->data, p->len, sofar, sock)){
      //calculate keyframeness, next time read header again, return true
      p->isKeyframe = false;
      if ((p->data[0] == 0x09) && (((p->data[11] & 0xf0) >> 4) == 1)){p->isKeyframe = true;}
      int testlen = p->data[p->len-1] + 3;
      testlen += (p->data[p->len-2] << 8);
      testlen += (p->data[p->len-3] << 16);
      testlen += (p->data[p->len-4] << 24);
      fprintf(stderr, "Len: %i, testlen: %i\n", p->len, testlen);
      done = true;
      sofar = 0;
      return true;
    }
  }
  return false;
}//FLV_GetPacket

<|endoftext|>