diff options
author | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-03 08:07:09 +0000 |
---|---|---|
committer | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-03 08:07:09 +0000 |
commit | cc4fc3b26f0e902209a73bc5a65c6c45ca48c745 (patch) | |
tree | 9284aab5f63460d9a06aeb46cb9d84702d463d82 | |
parent | 8cc3d1cce54c6f3909985761d4e8ce6cb85bd2b8 (diff) | |
download | chromium_src-cc4fc3b26f0e902209a73bc5a65c6c45ca48c745.zip chromium_src-cc4fc3b26f0e902209a73bc5a65c6c45ca48c745.tar.gz chromium_src-cc4fc3b26f0e902209a73bc5a65c6c45ca48c745.tar.bz2 |
Read and expose accelerometer values from cros-ec-accel trigger.
BUG=342907
Review URL: https://codereview.chromium.org/200643005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261317 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/accelerometer/accelerometer_controller.cc | 42 | ||||
-rw-r--r-- | ash/accelerometer/accelerometer_controller.h | 71 | ||||
-rw-r--r-- | ash/accelerometer/accelerometer_observer.h | 26 | ||||
-rw-r--r-- | ash/ash.gyp | 3 | ||||
-rw-r--r-- | ash/shell.cc | 2 | ||||
-rw-r--r-- | ash/shell.h | 7 | ||||
-rw-r--r-- | chrome/browser/ui/ash/ash_init.cc | 7 | ||||
-rw-r--r-- | chromeos/DEPS | 1 | ||||
-rw-r--r-- | chromeos/accelerometer/accelerometer_reader.cc | 218 | ||||
-rw-r--r-- | chromeos/accelerometer/accelerometer_reader.h | 82 | ||||
-rw-r--r-- | chromeos/chromeos.gyp | 3 |
11 files changed, 462 insertions, 0 deletions
diff --git a/ash/accelerometer/accelerometer_controller.cc b/ash/accelerometer/accelerometer_controller.cc new file mode 100644 index 0000000..a8de559 --- /dev/null +++ b/ash/accelerometer/accelerometer_controller.cc @@ -0,0 +1,42 @@ +// 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 "ash/accelerometer/accelerometer_controller.h" + +#include "ash/accelerometer/accelerometer_observer.h" +#include "ui/gfx/geometry/vector3d_f.h" + +namespace ash { + +AccelerometerController::AccelerometerController() { +} + +AccelerometerController::~AccelerometerController() { +} + +void AccelerometerController::Initialize( + scoped_refptr<base::TaskRunner> blocking_task_runner) { +#if defined(OS_CHROMEOS) + reader_.reset(new chromeos::AccelerometerReader(blocking_task_runner, this)); +#endif +} + +void AccelerometerController::AddObserver(AccelerometerObserver* observer) { + observers_.AddObserver(observer); +} + +void AccelerometerController::RemoveObserver(AccelerometerObserver* observer) { + observers_.RemoveObserver(observer); +} + +#if defined(OS_CHROMEOS) +void AccelerometerController::HandleAccelerometerReading( + const gfx::Vector3dF& base, + const gfx::Vector3dF& lid) { + FOR_EACH_OBSERVER(AccelerometerObserver, observers_, + OnAccelerometerUpdated(base, lid)); +} +#endif + +} // namespace ash diff --git a/ash/accelerometer/accelerometer_controller.h b/ash/accelerometer/accelerometer_controller.h new file mode 100644 index 0000000..ffe9c55 --- /dev/null +++ b/ash/accelerometer/accelerometer_controller.h @@ -0,0 +1,71 @@ +// 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. + +#ifndef ASH_ACCELEROMETER_ACCELEROMETER_CONTROLLER_H_ +#define ASH_ACCELEROMETER_ACCELEROMETER_CONTROLLER_H_ + +#include "ash/ash_export.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" + +#if defined(OS_CHROMEOS) +#include "chromeos/accelerometer/accelerometer_reader.h" +#endif + +namespace base { +class TaskRunner; +} + +namespace gfx { +class Vector3dF; +} + +namespace ash { + +class AccelerometerObserver; + +// This class owns the communication interface for talking to the accelerometer +// on supporting devices. Observers will be delivered OnAccelerometerRead +// notifications if an accelerometer was detected. +class ASH_EXPORT AccelerometerController +#if defined(OS_CHROMEOS) + : public chromeos::AccelerometerReader::Delegate { +#else + { +#endif + public: + AccelerometerController(); + virtual ~AccelerometerController(); + + // Initialize the accelerometer reader. + void Initialize(scoped_refptr<base::TaskRunner> blocking_task_runner); + + // Add/remove observer. + void AddObserver(AccelerometerObserver* observer); + void RemoveObserver(AccelerometerObserver* observer); + +#if defined(OS_CHROMEOS) + // This needs to be CHROMEOS only as on other platforms it does not actually + // override a method. + // chromeos::AccelerometerReader::Delegate: + virtual void HandleAccelerometerReading(const gfx::Vector3dF& base, + const gfx::Vector3dF& lid) OVERRIDE; +#endif + + private: +#if defined(OS_CHROMEOS) + // The AccelerometerReader which directly triggers and reads from the + // accelerometer device. + scoped_ptr<chromeos::AccelerometerReader> reader_; +#endif + + ObserverList<AccelerometerObserver, true> observers_; + + DISALLOW_COPY_AND_ASSIGN(AccelerometerController); +}; + +} // namespace ash + +#endif // ASH_ACCELEROMETER_ACCELEROMETER_CONTROLLER_H_ diff --git a/ash/accelerometer/accelerometer_observer.h b/ash/accelerometer/accelerometer_observer.h new file mode 100644 index 0000000..3d70a42 --- /dev/null +++ b/ash/accelerometer/accelerometer_observer.h @@ -0,0 +1,26 @@ +// 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. + +#ifndef ASH_ACCELEROMETER_ACCELEROMETER_OBSERVER_H_ +#define ASH_ACCELEROMETER_ACCELEROMETER_OBSERVER_H_ + +namespace gfx { +class Vector3dF; +} + +namespace ash { + +// The interface for classes which observe accelerometer updates. +class AccelerometerObserver { + public: + virtual void OnAccelerometerUpdated(const gfx::Vector3dF& base, + const gfx::Vector3dF& lid) = 0; + + protected: + virtual ~AccelerometerObserver() {} +}; + +} // namespace ash + +#endif // ASH_ACCELEROMETER_ACCELEROMETER_OBSERVER_H_ diff --git a/ash/ash.gyp b/ash/ash.gyp index ebb6e60..5ec38e7 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -75,6 +75,9 @@ 'accelerators/nested_dispatcher_controller.h', 'accelerators/spoken_feedback_toggler.cc', 'accelerators/spoken_feedback_toggler.h', + 'accelerometer/accelerometer_controller.cc', + 'accelerometer/accelerometer_controller.h', + 'accelerometer/accelerometer_observer.h', 'accessibility_delegate.h', 'audio/sounds.cc', 'audio/sounds.h', diff --git a/ash/shell.cc b/ash/shell.cc index 003053e8..ad9b92c 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -11,6 +11,7 @@ #include "ash/accelerators/accelerator_filter.h" #include "ash/accelerators/focus_manager_factory.h" #include "ash/accelerators/nested_dispatcher_controller.h" +#include "ash/accelerometer/accelerometer_controller.h" #include "ash/ash_switches.h" #include "ash/autoclick/autoclick_controller.h" #include "ash/desktop_background/desktop_background_controller.h" @@ -606,6 +607,7 @@ Shell::Shell(ShellDelegate* delegate) delegate_(delegate), window_positioner_(new WindowPositioner), activation_client_(NULL), + accelerometer_controller_(new AccelerometerController()), #if defined(OS_CHROMEOS) output_configurator_(new ui::OutputConfigurator()), #endif // defined(OS_CHROMEOS) diff --git a/ash/shell.h b/ash/shell.h index 1f511db..b096e51 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -74,6 +74,7 @@ class WindowModalityController; namespace ash { class AcceleratorController; +class AccelerometerController; class AccessibilityDelegate; class AshNativeCursorManager; class AutoclickController; @@ -500,6 +501,10 @@ class ASH_EXPORT Shell // Starts the animation that occurs on first login. void DoInitialWorkspaceAnimation(); + AccelerometerController* accelerometer_controller() { + return accelerometer_controller_.get(); + } + #if defined(OS_CHROMEOS) // TODO(oshima): Move these objects to DisplayController. ui::OutputConfigurator* output_configurator() { @@ -697,6 +702,8 @@ class ASH_EXPORT Shell // The maximized window manager (if enabled). scoped_ptr<internal::MaximizeModeWindowManager> maximize_mode_window_manager_; + scoped_ptr<AccelerometerController> accelerometer_controller_; + #if defined(OS_CHROMEOS) scoped_ptr<internal::PowerEventObserver> power_event_observer_; scoped_ptr<internal::UserActivityNotifier> user_activity_notifier_; diff --git a/chrome/browser/ui/ash/ash_init.cc b/chrome/browser/ui/ash/ash_init.cc index 2af2f8a..d92d554 100644 --- a/chrome/browser/ui/ash/ash_init.cc +++ b/chrome/browser/ui/ash/ash_init.cc @@ -5,6 +5,7 @@ #include "chrome/browser/ui/ash/ash_init.h" #include "ash/accelerators/accelerator_controller.h" +#include "ash/accelerometer/accelerometer_controller.h" #include "ash/ash_switches.h" #include "ash/high_contrast/high_contrast_controller.h" #include "ash/magnifier/magnification_controller.h" @@ -16,6 +17,7 @@ #include "chrome/browser/ui/ash/chrome_shell_delegate.h" #include "chrome/browser/ui/ash/screenshot_taker.h" #include "chrome/common/chrome_switches.h" +#include "content/public/browser/browser_thread.h" #include "ui/aura/env.h" #include "ui/aura/window_tree_host.h" @@ -58,6 +60,11 @@ void OpenAsh() { ash::Shell* shell = ash::Shell::CreateInstance(new ChromeShellDelegate); shell->accelerator_controller()->SetScreenshotDelegate( scoped_ptr<ash::ScreenshotDelegate>(new ScreenshotTaker).Pass()); + // TODO(flackr): Investigate exposing a blocking pool task runner to chromeos. + shell->accelerometer_controller()->Initialize( + content::BrowserThread::GetBlockingPool()-> + GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); #if defined(OS_CHROMEOS) shell->accelerator_controller()->SetImeControlDelegate( scoped_ptr<ash::ImeControlDelegate>(new ImeController).Pass()); diff --git a/chromeos/DEPS b/chromeos/DEPS index a88fc06..82f85b3 100644 --- a/chromeos/DEPS +++ b/chromeos/DEPS @@ -3,4 +3,5 @@ include_rules = [ "+net", "+third_party/cros_system_api", "+third_party/libxml", + "+ui/gfx/geometry" ] diff --git a/chromeos/accelerometer/accelerometer_reader.cc b/chromeos/accelerometer/accelerometer_reader.cc new file mode 100644 index 0000000..f84c487 --- /dev/null +++ b/chromeos/accelerometer/accelerometer_reader.cc @@ -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 diff --git a/chromeos/accelerometer/accelerometer_reader.h b/chromeos/accelerometer/accelerometer_reader.h new file mode 100644 index 0000000..e2b85bc --- /dev/null +++ b/chromeos/accelerometer/accelerometer_reader.h @@ -0,0 +1,82 @@ +// 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. + +#ifndef CHROMEOS_ACCELEROMETER_ACCELEROMETER_READER_H_ +#define CHROMEOS_ACCELEROMETER_ACCELEROMETER_READER_H_ + +#include <vector> + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "chromeos/chromeos_export.h" +#include "ui/gfx/geometry/vector3d_f.h" + +namespace base { +class TaskRunner; +} + +namespace chromeos { + +// Reads an accelerometer device and reports data back to an +// AccelerometerDelegate. +class CHROMEOS_EXPORT AccelerometerReader { + public: + // Configuration structure for accelerometer device. + struct ConfigurationData { + ConfigurationData(); + ~ConfigurationData(); + + // Scale of accelerometers (i.e. raw value * 1.0f / scale = G's). + unsigned int base_scale; + unsigned int lid_scale; + + // Index of each accelerometer axis in data stream. + std::vector<unsigned int> index; + }; + typedef base::RefCountedData<ConfigurationData> Configuration; + typedef base::RefCountedData<char[12]> Reading; + + // An interface to receive data from the AccelerometerReader. + class Delegate { + public: + virtual void HandleAccelerometerReading(const gfx::Vector3dF& base, + const gfx::Vector3dF& lid) = 0; + }; + + AccelerometerReader(base::TaskRunner* blocking_task_runner, + Delegate* delegate); + ~AccelerometerReader(); + + private: + // Dispatched when initialization is complete. If |success|, |configuration| + // provides the details of the detected accelerometer. + void OnInitialized(scoped_refptr<Configuration> configuration, bool success); + + // Triggers an asynchronous read from the accelerometer, signalling + // OnDataRead with the result. + void TriggerRead(); + + // If |success|, converts the raw reading to a pair of Vector3dF + // values and notifies the |delegate_| with the new readings. + // Triggers another read from the accelerometer at the current sampling rate. + void OnDataRead(scoped_refptr<Reading> reading, bool success); + + // The task runner to use for blocking tasks. + scoped_refptr<base::TaskRunner> task_runner_; + + // A weak pointer to the delegate to send accelerometer readings to. + Delegate* delegate_; + + // The accelerometer configuration. + scoped_refptr<Configuration> configuration_; + + base::WeakPtrFactory<AccelerometerReader> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(AccelerometerReader); +}; + +} // namespace chromeos + +#endif // CHROMEOS_ACCELEROMETER_ACCELEROMETER_READER_H_ diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index e9fffa9..89c64fe 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -25,6 +25,7 @@ '../net/net.gyp:net', '../third_party/icu/icu.gyp:icui18n', '../third_party/libxml/libxml.gyp:libxml', + '../ui/gfx/gfx.gyp:gfx_geometry', '../url/url.gyp:url_lib', 'cryptohome_proto', 'ime/input_method.gyp:gencode', @@ -34,6 +35,8 @@ 'CHROMEOS_IMPLEMENTATION', ], 'sources': [ + 'accelerometer/accelerometer_reader.cc', + 'accelerometer/accelerometer_reader.h', 'app_mode/kiosk_oem_manifest_parser.cc', 'app_mode/kiosk_oem_manifest_parser.h', 'audio/audio_device.cc', |