1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtSensors module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "linuxsysaccelerometer.h"
41#include <QtCore/QDebug>
42#include <QtCore/QtGlobal>
43#include <QtCore/QFile>
44#include <QtCore/QDebug>
45#include <QtCore/QTimer>
46
47#include <QtCore/QStringList>
48
49#include <time.h>
50#include <errno.h>
51
52char const * const LinuxSysAccelerometer::id("linuxsys.accelerometer");
53
54// This plugin reads the accelerometer from a sys interface.
55
56// test machine (laptop):
57// QT_ACCEL_FILEPATH=/sys/devices/platform/lis3lv02d/position
58// QT_ACCEL_DATADIVISOR=7
59// QT_ACCEL_DELIMITER=,
60
61quint64 produceTimestamp()
62{
63 struct timespec tv;
64 int ok;
65
66#ifdef CLOCK_MONOTONIC_RAW
67 ok = clock_gettime(CLOCK_MONOTONIC_RAW, tp: &tv);
68 if (ok != 0)
69#endif
70 ok = clock_gettime(CLOCK_MONOTONIC, tp: &tv);
71 Q_ASSERT(ok == 0);
72
73 quint64 result = (tv.tv_sec * 1000000ULL) + (tv.tv_nsec * 0.001); // scale to microseconds
74 return result;
75}
76
77// TODO get output template from env and apply
78// Currently this assumes the output is like:
79// (x,y,z) or x,y,z
80
81LinuxSysAccelerometer::LinuxSysAccelerometer(QSensor *sensor)
82 : QSensorBackend(sensor)
83 , m_timerid(0)
84 , path(QString())
85 , divisor(0)
86 , delimiter(QString())
87{
88 setReading<QAccelerometerReading>(&m_reading);
89 addDataRate(min: 1, max: 100); // 100Hz
90 addOutputRange(min: -22.418, max: 22.418, accuracy: 0.17651); // 2G
91// not sure how to retrieve proper range
92
93 path = QString::fromLatin1(str: qgetenv(varName: "QT_ACCEL_FILEPATH"));
94 bool ok;
95 divisor = QString::fromLatin1(str: qgetenv(varName: "QT_ACCEL_DATADIVISOR")).toInt(ok: &ok);
96 if (divisor == 0 || !ok) {
97 divisor = 1;
98 }
99 delimiter = QString::fromLatin1(str: qgetenv(varName: "QT_ACCEL_DELIMITER"));
100 file.setFileName(path);
101}
102
103LinuxSysAccelerometer::~LinuxSysAccelerometer()
104{
105}
106
107void LinuxSysAccelerometer::start()
108{
109 if (m_timerid)
110 return;
111
112 if (!openFile())
113 return;
114
115 int dataRate = sensor()->dataRate();
116 if (dataRate == 0) {
117 if (sensor()->availableDataRates().count())
118 dataRate = sensor()->availableDataRates().first().second;
119 else
120 dataRate = 1;
121 }
122
123 int interval = 1000 / dataRate;
124
125 if (interval)
126 m_timerid = startTimer(interval);
127}
128
129void LinuxSysAccelerometer::stop()
130{
131 if (m_timerid) {
132 killTimer(id: m_timerid);
133 m_timerid = 0;
134 }
135 closeFile();
136}
137
138void LinuxSysAccelerometer::poll()
139{
140 if (!file.isOpen())
141 return;
142
143 file.seek(offset: 0);
144 QString str = file.readLine();
145 if (str.isEmpty()) {
146 return;
147 }
148 str = str.simplified();
149
150 if (!str.at(i: 0).isNumber() && str.at(i: 0) != '-') {
151 str.remove(i: 0,len: 1);
152 }
153
154 if (!str.at(i: str.size()-1).isNumber()) {
155 str.chop(n: 1);
156 }
157
158 QStringList accelDataList = str.split(sep: delimiter);
159
160 m_reading.setTimestamp(produceTimestamp());
161 m_reading.setX(-accelDataList.at(i: 0).toFloat() / divisor);
162 m_reading.setY(-accelDataList.at(i: 1).toFloat() / divisor);
163 m_reading.setZ(-accelDataList.at(i: 2).toFloat() / divisor);
164
165 newReadingAvailable();
166}
167
168void LinuxSysAccelerometer::timerEvent(QTimerEvent * /*event*/)
169{
170 poll();
171}
172
173bool LinuxSysAccelerometer::openFile()
174{
175 if (!path.isEmpty()
176 && !file.open(flags: QIODevice::ReadOnly)) {
177 qWarning() << "Could not open file" << strerror(errno);
178 return false;
179 }
180 return true;
181}
182
183void LinuxSysAccelerometer::closeFile()
184{
185 file.close();
186}
187
188
189

source code of qtsensors/src/plugins/sensors/linux/linuxsysaccelerometer.cpp