| 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
|
|
|
|
|