Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: chromeos/accelerometer/accelerometer_reader.cc

Issue 200643005: Read and expose accelerometer values from cros-ec-accel trigger. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Virtual dtor in observer, ASH_EXPORT for tests in dependent CLs. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chromeos/accelerometer/accelerometer_reader.h ('k') | chromeos/chromeos.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chromeos/accelerometer/accelerometer_reader.h"
6
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/location.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "ui/gfx/geometry/vector3d_f.h"
15
16 namespace chromeos {
17
18 namespace {
19
20 // Paths to access necessary data from the accelerometer device.
21 const base::FilePath::CharType kAccelerometerTriggerPath[] =
22 FILE_PATH_LITERAL("/sys/bus/iio/devices/trigger0/trigger_now");
23 const base::FilePath::CharType kAccelerometerDevicePath[] =
24 FILE_PATH_LITERAL("/dev/cros-ec-accel");
25 const base::FilePath::CharType kAccelerometerIioBasePath[] =
26 FILE_PATH_LITERAL("/sys/bus/iio/devices/");
27
28 // Files within the device in kAccelerometerIioBasePath containing the scales of
29 // the accelerometers.
30 const base::FilePath::CharType kAccelerometerBaseScaleName[] =
31 FILE_PATH_LITERAL("in_accel_base_scale");
32 const base::FilePath::CharType kAccelerometerLidScaleName[] =
33 FILE_PATH_LITERAL("in_accel_lid_scale");
34
35 // The filename giving the path to read the scan index of each accelerometer
36 // axis.
37 const char kAccelerometerScanIndexPath[] =
38 "scan_elements/in_accel_%s_%s_index";
39
40 // The names of the accelerometers and axes in the order we want to read them.
41 const char kAccelerometerNames[][5] = {"base", "lid"};
42 const char kAccelerometerAxes[][2] = {"x", "y", "z"};
43 const size_t kTriggerDataValues =
44 arraysize(kAccelerometerNames) * arraysize(kAccelerometerAxes);
45 const size_t kTriggerDataLength = kTriggerDataValues * 2;
46
47 // The length required to read uint values from configuration files.
48 const size_t kMaxAsciiUintLength = 21;
49
50 // The time to wait between reading the accelerometer.
51 const int kDelayBetweenReadsMs = 100;
sadrul 2014/04/01 16:33:55 Would it make sense to use a base::FilePathWatcher
flackr 2014/04/01 17:10:55 It shouldn't trigger too frequently as it posts th
52
53 // Reads |path| to the unsigned int pointed to by |value|. Returns true on
54 // success or false on failure.
55 bool ReadFileToUint(const base::FilePath& path, unsigned int* value) {
56 std::string s;
57 DCHECK(value);
58 if (!base::ReadFileToString(path, &s, kMaxAsciiUintLength)) {
59 LOG(ERROR) << "Failed to read " << path.value();
60 return false;
61 }
62 base::TrimWhitespaceASCII(s, base::TRIM_ALL, &s);
63 if (!base::StringToUint(s, value)) {
64 LOG(ERROR) << "Failed to parse \"" << s << "\" from " << path.value();
65 return false;
66 }
67 return true;
68 }
69
70 } // namespace
71
72 AccelerometerReader::AccelerometerReader(
73 AccelerometerReader::Delegate* delegate)
74 : delegate_(delegate),
75 weak_factory_(this) {
76 DCHECK(delegate_);
77 if (Initialize())
78 TriggerRead();
79 }
80
81 AccelerometerReader::~AccelerometerReader() {
82 }
83
84 bool AccelerometerReader::Initialize() {
85 // Check for accelerometer symlink which will be created by the udev rules
86 // file on detecting the device.
87 base::FilePath device;
88 if (!base::ReadSymbolicLink(base::FilePath(kAccelerometerDevicePath),
89 &device)) {
90 return false;
91 }
92
93 if (!base::PathExists(base::FilePath(kAccelerometerTriggerPath))) {
94 LOG(ERROR) << "Accelerometer trigger does not exist at"
95 << kAccelerometerTriggerPath;
96 return false;
97 }
98
99 base::FilePath iio_path(base::FilePath(kAccelerometerIioBasePath).Append(
100 device));
101 // Read accelerometer scales
102 if (!ReadFileToUint(iio_path.Append(kAccelerometerBaseScaleName),
103 &accelerometer_base_scale_)) {
104 return false;
105 }
106 if (!ReadFileToUint(iio_path.Append(kAccelerometerLidScaleName),
107 &accelerometer_lid_scale_)) {
108 return false;
109 }
110
111 // Read indices of each accelerometer axis from each accelerometer from
112 // /sys/bus/iio/devices/iio:deviceX/scan_elements/in_accel_{x,y,z}_%s_index
113 for (size_t i = 0; i < arraysize(kAccelerometerNames); ++i) {
114 for (size_t j = 0; j < arraysize(kAccelerometerAxes); ++j) {
115 std::string accelerometer_index_path = base::StringPrintf(
116 kAccelerometerScanIndexPath, kAccelerometerAxes[j],
117 kAccelerometerNames[i]);
118 unsigned int index = 0;
119 if (!ReadFileToUint(iio_path.Append(accelerometer_index_path.c_str()),
120 &index)) {
121 return false;
122 }
123 if (index >= kTriggerDataValues) {
124 LOG(ERROR) << "Field index from " << accelerometer_index_path
125 << " out of bounds: " << index;
126 return false;
127 }
128 accelerometer_index_.push_back(index);
129 }
130 }
131 return true;
132 }
133
134 void AccelerometerReader::TriggerRead() {
135 ReadAccelerometer();
136
137 // Trigger another read after the current sampling delay.
138 base::MessageLoop::current()->PostDelayedTask(
139 FROM_HERE,
140 base::Bind(&AccelerometerReader::TriggerRead,
141 weak_factory_.GetWeakPtr()),
142 base::TimeDelta::FromMilliseconds(kDelayBetweenReadsMs));
143 }
144
145 void AccelerometerReader::ReadAccelerometer() {
146 // Initiate the trigger to read accelerometers simultaneously
147 int bytes_written = base::WriteFile(
148 base::FilePath(kAccelerometerTriggerPath), "1\n", 2);
149 if (bytes_written < 2) {
150 PLOG(ERROR) << "Accelerometer trigger failure: " << bytes_written;
151 return;
152 }
153
154 // Read resulting sample from /dev/cros-ec-accel.
155 char data[kTriggerDataLength];
156 int bytes_read = base::ReadFile(base::FilePath(kAccelerometerDevicePath),
157 data, kTriggerDataLength);
158 if (bytes_read < static_cast<int>(kTriggerDataLength)) {
159 LOG(ERROR) << "Read " << bytes_read << " byte(s), expected "
160 << kTriggerDataLength << " bytes from accelerometer";
161 return;
162 }
163
164 int16* values = reinterpret_cast<int16*>(data);
165 gfx::Vector3dF base_reading, lid_reading;
166 base_reading.set_x(values[accelerometer_index_[0]]);
167 base_reading.set_y(values[accelerometer_index_[1]]);
168 base_reading.set_z(values[accelerometer_index_[2]]);
169 base_reading.Scale(1.0f / accelerometer_base_scale_);
170
171 lid_reading.set_x(values[accelerometer_index_[3]]);
172 lid_reading.set_y(values[accelerometer_index_[4]]);
173 lid_reading.set_z(values[accelerometer_index_[5]]);
174 lid_reading.Scale(1.0f / accelerometer_lid_scale_);
175 delegate_->HandleAccelerometerReading(base_reading, lid_reading);
176 }
177
178 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/accelerometer/accelerometer_reader.h ('k') | chromeos/chromeos.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698