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

Unified Diff: chromeos/accelerometer/accelerometer_reader.cc

Issue 236153002: Merge 261317 "Read and expose accelerometer values from cros-ec-..." (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1916/src/
Patch Set: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromeos/accelerometer/accelerometer_reader.h ('k') | chromeos/chromeos.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromeos/accelerometer/accelerometer_reader.cc
===================================================================
--- chromeos/accelerometer/accelerometer_reader.cc (revision 0)
+++ chromeos/accelerometer/accelerometer_reader.cc (revision 0)
@@ -0,0 +1,218 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/accelerometer/accelerometer_reader.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/task_runner.h"
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+
+namespace chromeos {
+
+namespace {
+
+// Paths to access necessary data from the accelerometer device.
+const base::FilePath::CharType kAccelerometerTriggerPath[] =
+ FILE_PATH_LITERAL("/sys/bus/iio/devices/trigger0/trigger_now");
+const base::FilePath::CharType kAccelerometerDevicePath[] =
+ FILE_PATH_LITERAL("/dev/cros-ec-accel");
+const base::FilePath::CharType kAccelerometerIioBasePath[] =
+ FILE_PATH_LITERAL("/sys/bus/iio/devices/");
+
+// Files within the device in kAccelerometerIioBasePath containing the scales of
+// the accelerometers.
+const base::FilePath::CharType kAccelerometerBaseScaleName[] =
+ FILE_PATH_LITERAL("in_accel_base_scale");
+const base::FilePath::CharType kAccelerometerLidScaleName[] =
+ FILE_PATH_LITERAL("in_accel_lid_scale");
+
+// The filename giving the path to read the scan index of each accelerometer
+// axis.
+const char kAccelerometerScanIndexPath[] =
+ "scan_elements/in_accel_%s_%s_index";
+
+// The names of the accelerometers and axes in the order we want to read them.
+const char kAccelerometerNames[][5] = {"base", "lid"};
+const char kAccelerometerAxes[][2] = {"x", "y", "z"};
+const size_t kTriggerDataValues =
+ arraysize(kAccelerometerNames) * arraysize(kAccelerometerAxes);
+const size_t kTriggerDataLength = kTriggerDataValues * 2;
+
+// The length required to read uint values from configuration files.
+const size_t kMaxAsciiUintLength = 21;
+
+// The time to wait between reading the accelerometer.
+const int kDelayBetweenReadsMs = 100;
+
+// Reads |path| to the unsigned int pointed to by |value|. Returns true on
+// success or false on failure.
+bool ReadFileToUint(const base::FilePath& path, unsigned int* value) {
+ std::string s;
+ DCHECK(value);
+ if (!base::ReadFileToString(path, &s, kMaxAsciiUintLength)) {
+ LOG(ERROR) << "Failed to read " << path.value();
+ return false;
+ }
+ base::TrimWhitespaceASCII(s, base::TRIM_ALL, &s);
+ if (!base::StringToUint(s, value)) {
+ LOG(ERROR) << "Failed to parse \"" << s << "\" from " << path.value();
+ return false;
+ }
+ return true;
+}
+
+bool DetectAndReadAccelerometerConfiguration(
+ scoped_refptr<AccelerometerReader::Configuration> configuration) {
+ // Check for accelerometer symlink which will be created by the udev rules
+ // file on detecting the device.
+ base::FilePath device;
+ if (!base::ReadSymbolicLink(base::FilePath(kAccelerometerDevicePath),
+ &device)) {
+ return false;
+ }
+
+ if (!base::PathExists(base::FilePath(kAccelerometerTriggerPath))) {
+ LOG(ERROR) << "Accelerometer trigger does not exist at"
+ << kAccelerometerTriggerPath;
+ return false;
+ }
+
+ base::FilePath iio_path(base::FilePath(kAccelerometerIioBasePath).Append(
+ device));
+ // Read accelerometer scales
+ if (!ReadFileToUint(iio_path.Append(kAccelerometerBaseScaleName),
+ &(configuration->data.base_scale))) {
+ return false;
+ }
+ if (!ReadFileToUint(iio_path.Append(kAccelerometerLidScaleName),
+ &(configuration->data.lid_scale))) {
+ return false;
+ }
+
+ // Read indices of each accelerometer axis from each accelerometer from
+ // /sys/bus/iio/devices/iio:deviceX/scan_elements/in_accel_{x,y,z}_%s_index
+ for (size_t i = 0; i < arraysize(kAccelerometerNames); ++i) {
+ for (size_t j = 0; j < arraysize(kAccelerometerAxes); ++j) {
+ std::string accelerometer_index_path = base::StringPrintf(
+ kAccelerometerScanIndexPath, kAccelerometerAxes[j],
+ kAccelerometerNames[i]);
+ unsigned int index = 0;
+ if (!ReadFileToUint(iio_path.Append(accelerometer_index_path.c_str()),
+ &index)) {
+ return false;
+ }
+ if (index >= kTriggerDataValues) {
+ LOG(ERROR) << "Field index from " << accelerometer_index_path
+ << " out of bounds: " << index;
+ return false;
+ }
+ configuration->data.index.push_back(index);
+ }
+ }
+ return true;
+}
+
+bool ReadAccelerometer(
+ scoped_refptr<AccelerometerReader::Reading> reading) {
+ // Initiate the trigger to read accelerometers simultaneously
+ int bytes_written = base::WriteFile(
+ base::FilePath(kAccelerometerTriggerPath), "1\n", 2);
+ if (bytes_written < 2) {
+ PLOG(ERROR) << "Accelerometer trigger failure: " << bytes_written;
+ return false;
+ }
+
+ // Read resulting sample from /dev/cros-ec-accel.
+ int bytes_read = base::ReadFile(base::FilePath(kAccelerometerDevicePath),
+ reading->data, kTriggerDataLength);
+ if (bytes_read < static_cast<int>(kTriggerDataLength)) {
+ LOG(ERROR) << "Read " << bytes_read << " byte(s), expected "
+ << kTriggerDataLength << " bytes from accelerometer";
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+AccelerometerReader::ConfigurationData::ConfigurationData() {
+}
+
+AccelerometerReader::ConfigurationData::~ConfigurationData() {
+}
+
+AccelerometerReader::AccelerometerReader(
+ base::TaskRunner* task_runner,
+ AccelerometerReader::Delegate* delegate)
+ : task_runner_(task_runner),
+ delegate_(delegate),
+ configuration_(new AccelerometerReader::Configuration()),
+ weak_factory_(this) {
+ DCHECK(task_runner_);
+ DCHECK(delegate_);
+ // Asynchronously detect and initialize the accelerometer to avoid delaying
+ // startup.
+ base::PostTaskAndReplyWithResult(task_runner_.get(), FROM_HERE,
+ base::Bind(&DetectAndReadAccelerometerConfiguration, configuration_),
+ base::Bind(&AccelerometerReader::OnInitialized,
+ weak_factory_.GetWeakPtr(), configuration_));
+}
+
+AccelerometerReader::~AccelerometerReader() {
+}
+
+void AccelerometerReader::OnInitialized(
+ scoped_refptr<AccelerometerReader::Configuration> configuration,
+ bool success) {
+ if (success)
+ TriggerRead();
+}
+
+void AccelerometerReader::TriggerRead() {
+ DCHECK(!task_runner_->RunsTasksOnCurrentThread());
+
+ scoped_refptr<AccelerometerReader::Reading> reading(
+ new AccelerometerReader::Reading());
+ base::PostTaskAndReplyWithResult(task_runner_, FROM_HERE,
+ base::Bind(&ReadAccelerometer, reading),
+ base::Bind(&AccelerometerReader::OnDataRead,
+ weak_factory_.GetWeakPtr(), reading));
+}
+
+void AccelerometerReader::OnDataRead(
+ scoped_refptr<AccelerometerReader::Reading> reading,
+ bool success) {
+ DCHECK(!task_runner_->RunsTasksOnCurrentThread());
+
+ if (success) {
+ gfx::Vector3dF base_reading, lid_reading;
+ int16* values = reinterpret_cast<int16*>(reading->data);
+ base_reading.set_x(values[configuration_->data.index[0]]);
+ base_reading.set_y(values[configuration_->data.index[1]]);
+ base_reading.set_z(values[configuration_->data.index[2]]);
+ base_reading.Scale(1.0f / configuration_->data.base_scale);
+
+ lid_reading.set_x(values[configuration_->data.index[3]]);
+ lid_reading.set_y(values[configuration_->data.index[4]]);
+ lid_reading.set_z(values[configuration_->data.index[5]]);
+ lid_reading.Scale(1.0f / configuration_->data.lid_scale);
+ delegate_->HandleAccelerometerReading(base_reading, lid_reading);
+ }
+
+ // Trigger another read after the current sampling delay.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&AccelerometerReader::TriggerRead,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kDelayBetweenReadsMs));
+}
+
+} // namespace chromeos
Property changes on: chromeos/accelerometer/accelerometer_reader.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« 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