1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CONTEXTHUB_H_
18 #define CONTEXTHUB_H_
19 
20 #include "nanomessage.h"
21 #include "noncopyable.h"
22 
23 #include <bitset>
24 #include <functional>
25 #include <vector>
26 
27 namespace android {
28 
29 class AppToHostEvent;
30 class SensorEvent;
31 
32 // Array length helper macro
33 #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
34 
35 enum class SensorType {
36     Invalid_ = 0,
37 
38     // The order of this enum must correspond to sensor types in nanohub's
39     // sensType.h
40     Accel,
41     AnyMotion,
42     NoMotion,
43     SignificantMotion,
44     Flat,
45     Gyro,
46     GyroUncal,
47     Magnetometer,
48     MagnetometerUncal,
49     Barometer,
50     Temperature,
51     AmbientLightSensor,
52     Proximity,
53     Orientation,
54     HeartRateECG,
55     HeartRatePPG,
56     Gravity,
57     LinearAccel,
58     RotationVector,
59     GeomagneticRotationVector,
60     GameRotationVector,
61     StepCount,
62     StepDetect,
63     Gesture,
64     Tilt,
65     DoubleTwist,
66     DoubleTap,
67     WindowOrientation,
68     Hall,
69     Activity,
70     Vsync,
71     CompressedAccel,
72     WristTilt = 39,
73     CompressedMag = 59,
74     Humidity = 61,
75 
76     Max_
77 };
78 
79 // Overloaded values of rate used in sensor enable request (see sensors.h)
80 enum class SensorSpecialRate : uint32_t {
81     None     = 0,
82     OnDemand = 0xFFFFFF00,
83     OnChange = 0xFFFFFF01,
84     OneShot  = 0xFFFFFF02,
85 };
86 
87 struct SensorSpec {
88     SensorType sensor_type = SensorType::Invalid_;
89 
90     // When enabling a sensor, rate can be specified in Hz or as one of the
91     // special values
92     SensorSpecialRate special_rate = SensorSpecialRate::None;
93     float rate_hz = -1;
94     uint64_t latency_ns = 0;
95 
96     // Reference value (ground truth) used for calibration
97     bool have_cal_ref = false;
98     float cal_ref;
99 };
100 
101 /*
102  * An interface for communicating with a ContextHub.
103  */
104 class ContextHub : public NonCopyable {
105   public:
~ContextHub()106     virtual ~ContextHub() {};
107 
108     static std::string SensorTypeToAbbrevName(SensorType sensor_type);
109     static SensorType SensorAbbrevNameToType(const char *abbrev_name);
110     static SensorType SensorAbbrevNameToType(const std::string& abbrev_name);
111     static std::string ListAllSensorAbbrevNames();
112 
113     /*
114      * Performs initialization to allow commands to be sent to the context hub.
115      * Must be called before any other functions that send commands. Returns
116      * true on success, false on failure.
117      */
118     virtual bool Initialize() = 0;
119 
120     /*
121      * Configures the ContextHub to allow logs to be printed to stdout.
122      */
123     virtual void SetLoggingEnabled(bool logging_enabled) = 0;
124 
125     /*
126      * Loads a new firmware image to the ContextHub. The firmware image is
127      * specified by filename. Returns false if an error occurs.
128      */
129     bool Flash(const std::string& filename);
130 
131     /*
132      * Performs the sensor calibration routine and writes the resulting data to
133      * a file.
134      */
135     bool CalibrateSensors(const std::vector<SensorSpec>& sensors);
136 
137     /*
138      * Performs the sensor self-test routine.
139      */
140     bool TestSensors(const std::vector<SensorSpec>& sensors);
141 
142     /*
143      * Sends a sensor enable request to the context hub.
144      */
145     bool EnableSensor(const SensorSpec& sensor);
146     bool EnableSensors(const std::vector<SensorSpec>& sensors);
147 
148     /*
149      * Sends a disable sensor request to context hub. Note that this always
150      * results in sending a request, i.e. this does not check whether the sensor
151      * is currently enabled or not.
152      */
153     bool DisableSensor(SensorType sensor_type);
154     bool DisableSensors(const std::vector<SensorSpec>& sensors);
155 
156     /*
157      * Sends a disable sensor request for every sensor type we know about.
158      */
159     bool DisableAllSensors();
160 
161     /*
162      * Calls DisableSensor() on all active sensors (i.e. those which have been
163      * enabled but not yet disabled). This should be called from the destructor
164      * of derived classes before tearing down communications to ensure we don't
165      * leave sensors enabled after exiting.
166      */
167     bool DisableActiveSensors();
168 
169     /*
170      * Sends all data stored in the calibration file to the context hub.
171      */
172     virtual bool LoadCalibration();
173 
174     /*
175      * Prints up to <limit> incoming events. If limit is 0, then continues
176      * indefinitely.
177      */
178     void PrintAllEvents(unsigned int limit);
179 
180     /*
181      * Requests bridge version information
182      */
183     bool PrintBridgeVersion();
184 
185     /*
186      * Prints up to <sample_limit> incoming sensor samples corresponding to the
187      * given SensorType, ignoring other events. If sample_limit is 0, then
188      * continues indefinitely.
189      */
190     void PrintSensorEvents(SensorType sensor_type, int sample_limit);
191     void PrintSensorEvents(const std::vector<SensorSpec>& sensors,
192         int sample_limit);
193 
194   protected:
195     enum class TransportResult {
196         Success,
197         GeneralFailure,
198         Timeout,
199         ParseFailure,
200         Canceled,
201         // Add more specific error reasons as needed
202     };
203 
204     // Performs the calibration routine, but does not call SaveCalibration()
205     bool CalibrateSingleSensor(const SensorSpec& sensor);
206 
207     // Performs the self-test routine
208     bool TestSingleSensor(const SensorSpec& sensor);
209 
210     /*
211      * Iterates over sensors, invoking the given callback on each element.
212      * Returns true if all callbacks returned true. Exits early on failure.
213      */
214     bool ForEachSensor(const std::vector<SensorSpec>& sensors,
215         std::function<bool(const SensorSpec&)> callback);
216 
217     /*
218      * Parses a calibration result event and invokes the appropriate
219      * SetCalibration function with the calibration data.
220      */
221     bool HandleCalibrationResult(const SensorSpec& sensor,
222         const AppToHostEvent &event);
223 
224     /*
225      * Parses a self-test result event
226      */
227     bool HandleTestResult(const SensorSpec& sensor,
228         const AppToHostEvent &event);
229 
230     /*
231      * Same as ReadSensorEvents, but filters on AppToHostEvent instead of
232      * SensorEvent.
233      */
234     TransportResult ReadAppEvents(std::function<bool(const AppToHostEvent&)> callback,
235         int timeout_ms = 0);
236 
237     /*
238      * Calls ReadEvent in a loop, handling errors and ignoring events that
239      * didn't originate from a sensor. Valid SensorEvents are passed to the
240      * callback for further processing. The callback should return a boolean
241      * indicating whether to continue (true) or exit the read loop (false).
242      */
243     void ReadSensorEvents(std::function<bool(const SensorEvent&)> callback);
244 
245     /*
246      * Sends the given calibration data down to the hub
247      */
248     bool SendCalibrationData(SensorType sensor_type,
249         const std::vector<uint8_t>& cal_data);
250 
251     /*
252      * Read an event from the sensor hub. Block until a event is successfully
253      * read, no event traffic is generated for the timeout period, or an error
254      * occurs, such as a CRC check failure.
255      */
256     virtual TransportResult ReadEvent(std::vector<uint8_t>& response,
257         int timeout_ms) = 0;
258     virtual TransportResult WriteEvent(const std::vector<uint8_t>& request) = 0;
259 
260     // Implements the firmware loading functionality for the sensor hub. Returns
261     // false if an error occurs while writing the firmware to the device.
262     virtual bool FlashSensorHub(const std::vector<uint8_t>& bytes) = 0;
263 
264     // Convenience functions that build on top of the more generic byte-level
265     // interface
266     TransportResult ReadEvent(std::unique_ptr<ReadEventResponse>* response,
267         int timeout_ms = 0);
268     TransportResult WriteEvent(const WriteEventRequest& request);
269 
270     // Override these if saving calibration data to persistent storage is
271     // supported on the platform
272     virtual bool SetCalibration(SensorType sensor_type, int32_t data);
273     virtual bool SetCalibration(SensorType sensor_type, float data);
274     virtual bool SetCalibration(SensorType sensor_type, int32_t x,
275         int32_t y, int32_t z);
276     virtual bool SetCalibration(SensorType sensor_type, int32_t x,
277         int32_t y, int32_t z, int32_t w);
278     virtual bool SaveCalibration();
279 
280 private:
281     std::bitset<static_cast<int>(SensorType::Max_)> sensor_is_active_;
282 };
283 
284 }  // namespace android
285 
286 #endif  // CONTEXTHUB_H_
287