1 // Copyright 2020 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 #ifndef ASH_ACCELEROMETER_ACCELEROMETER_FILE_READER_H_ 6 #define ASH_ACCELEROMETER_ACCELEROMETER_FILE_READER_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "ash/accelerometer/accelerometer_reader.h" 12 #include "ash/public/cpp/tablet_mode_observer.h" 13 #include "base/files/file_util.h" 14 #include "base/observer_list_threadsafe.h" 15 16 namespace ash { 17 18 enum class State { INITIALIZING, SUCCESS, FAILED }; 19 20 // Work that runs on a base::TaskRunner. It determines the accelerometer 21 // configuration, and reads the data. Upon a successful read it will notify 22 // all observers. 23 class AccelerometerFileReader : public AccelerometerProviderInterface, 24 public TabletModeObserver { 25 public: 26 AccelerometerFileReader(); 27 AccelerometerFileReader(const AccelerometerFileReader&) = delete; 28 AccelerometerFileReader& operator=(const AccelerometerFileReader&) = delete; 29 30 // AccelerometerProviderInterface: 31 void PrepareAndInitialize( 32 scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner) override; 33 void AddObserver(AccelerometerReader::Observer* observer) override; 34 void RemoveObserver(AccelerometerReader::Observer* observer) override; 35 void StartListenToTabletModeController() override; 36 void StopListenToTabletModeController() override; 37 void SetEmitEvents(bool emit_events) override; 38 39 // Attempts to read the accelerometer data. Upon success, converts the raw 40 // reading to an AccelerometerUpdate and notifies observers. Triggers another 41 // read at the current sampling rate. 42 void Read(); 43 44 // Controls accelerometer reading. 45 void EnableAccelerometerReading(); 46 void DisableAccelerometerReading(); 47 48 // Tracks if accelerometer initialization is completed. 49 void CheckInitStatus(); 50 51 // With ChromeOS EC lid angle driver present, accelerometer read is cancelled 52 // in clamshell mode, and triggered when entering tablet mode. 53 void TriggerRead(); 54 void CancelRead(); 55 56 // TabletModeObserver: 57 void OnTabletPhysicalStateChanged() override; 58 59 private: 60 // Represents necessary information in order to read an accelerometer device. 61 struct ReadingData { 62 ReadingData(); 63 ReadingData(const ReadingData&); 64 ~ReadingData(); 65 66 // The full path to the accelerometer device to read. 67 base::FilePath path; 68 69 // The accelerometer sources which can be read from |path|. 70 std::vector<AccelerometerSource> sources; 71 }; 72 73 // Configuration structure for accelerometer device. 74 struct ConfigurationData { 75 ConfigurationData(); 76 ~ConfigurationData(); 77 78 // Number of accelerometers on device. 79 size_t count; 80 81 // sysfs entry to trigger readings. 82 base::FilePath trigger_now; 83 84 // Which accelerometers are present on device. 85 bool has[ACCELEROMETER_SOURCE_COUNT]; 86 87 // Scale of accelerometers (i.e. raw value * scale = m/s^2). 88 float scale[ACCELEROMETER_SOURCE_COUNT][3]; 89 90 // Index of each accelerometer axis in data stream. 91 int index[ACCELEROMETER_SOURCE_COUNT][3]; 92 93 // The information for each accelerometer device to be read. In kernel 3.18 94 // there is one per ACCELEROMETER_SOURCE_COUNT. On 3.14 there is only one. 95 std::vector<ReadingData> reading_data; 96 }; 97 98 ~AccelerometerFileReader() override; 99 100 // Detects the accelerometer configuration. 101 // If an accelerometer is available, it triggers reads. 102 // This function MAY be called more than once. 103 // This function contains the actual initialization code to be run by the 104 // Initialize function. It is needed because on some devices the sensor hub 105 // isn't available at the time the call to Initialize is made. If the sensor 106 // is found to be missing we'll make a call to TryScheduleInitializeInternal. 107 void InitializeInternal(); 108 109 // Attempt to reschedule a run of InitializeInternal(). The function will be 110 // scheduled to run again if Now() < initialization_timeout_. 111 void TryScheduleInitializeInternal(); 112 113 // When accelerometers are presented as separate iio_devices this will perform 114 // the initialize for one of the devices, at the given |iio_path| and the 115 // symbolic link |name|. |location| is defined by AccelerometerSource. 116 bool InitializeAccelerometer(const base::FilePath& iio_path, 117 const base::FilePath& name, 118 const std::string& location); 119 120 // TODO(jonross): Separate the initialization into separate files. Add a gyp 121 // rule to have them built for the appropriate kernels. (crbug.com/525658) 122 // When accelerometers are presented as a single iio_device this will perform 123 // the initialization for both of them. 124 bool InitializeLegacyAccelerometers(const base::FilePath& iio_path, 125 const base::FilePath& name); 126 127 // Attempts to read the accelerometer data. Upon a success, converts the raw 128 // reading to an AccelerometerUpdate and notifies observers. 129 void ReadFileAndNotify(); 130 131 void SetEmitEventsInternal(bool emit_events); 132 133 // The current initialization state of reader. 134 State initialization_state_ = State::INITIALIZING; 135 136 // True if periodical accelerometer read is on. 137 bool accelerometer_read_on_ = false; 138 139 bool emit_events_ = true; 140 141 // The time at which initialization re-tries should stop. 142 base::TimeTicks initialization_timeout_; 143 144 // The accelerometer configuration. 145 ConfigurationData configuration_; 146 147 // The observers to notify of accelerometer updates. 148 scoped_refptr<base::ObserverListThreadSafe<AccelerometerReader::Observer>> 149 observers_; 150 151 // The task runner to use for blocking tasks. 152 scoped_refptr<base::SequencedTaskRunner> task_runner_; 153 154 // The last seen accelerometer data. 155 scoped_refptr<AccelerometerUpdate> update_; 156 }; 157 158 } // namespace ash 159 160 #endif // ASH_ACCELEROMETER_ACCELEROMETER_FILE_READER_H_ 161