summaryrefslogtreecommitdiffstats
path: root/util/nanotool/contexthub.h
blob: 582dacb0ddee8e48d1c663962fd3e5ec5cb433b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CONTEXTHUB_H_
#define CONTEXTHUB_H_

#include "nanomessage.h"
#include "noncopyable.h"

#include <bitset>
#include <functional>
#include <vector>

namespace android {

class AppToHostEvent;
class SensorEvent;

// Array length helper macro
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))

enum class SensorType {
    Invalid_ = 0,

    // The order of this enum must correspond to sensor types in nanohub's
    // sensType.h
    Accel,
    AnyMotion,
    NoMotion,
    SignificantMotion,
    Flat,
    Gyro,
    GyroUncal,
    Magnetometer,
    MagnetometerUncal,
    Barometer,
    Temperature,
    AmbientLightSensor,
    Proximity,
    Orientation,
    HeartRateECG,
    HeartRatePPG,
    Gravity,
    LinearAccel,
    RotationVector,
    GeomagneticRotationVector,
    GameRotationVector,
    StepCount,
    StepDetect,
    Gesture,
    Tilt,
    DoubleTwist,
    DoubleTap,
    WindowOrientation,
    Hall,
    Activity,
    Vsync,
    CompressedAccel,
    WristTilt = 39,
    CompressedMag = 59,
    Humidity = 61,

    Max_
};

// Overloaded values of rate used in sensor enable request (see sensors.h)
enum class SensorSpecialRate : uint32_t {
    None     = 0,
    OnDemand = 0xFFFFFF00,
    OnChange = 0xFFFFFF01,
    OneShot  = 0xFFFFFF02,
};

struct SensorSpec {
    SensorType sensor_type = SensorType::Invalid_;

    // When enabling a sensor, rate can be specified in Hz or as one of the
    // special values
    SensorSpecialRate special_rate = SensorSpecialRate::None;
    float rate_hz = -1;
    uint64_t latency_ns = 0;

    // Reference value (ground truth) used for calibration
    bool have_cal_ref = false;
    float cal_ref;
};

/*
 * An interface for communicating with a ContextHub.
 */
class ContextHub : public NonCopyable {
  public:
    virtual ~ContextHub() {};

    static std::string SensorTypeToAbbrevName(SensorType sensor_type);
    static SensorType SensorAbbrevNameToType(const char *abbrev_name);
    static SensorType SensorAbbrevNameToType(const std::string& abbrev_name);
    static std::string ListAllSensorAbbrevNames();

    /*
     * Performs initialization to allow commands to be sent to the context hub.
     * Must be called before any other functions that send commands. Returns
     * true on success, false on failure.
     */
    virtual bool Initialize() = 0;

    /*
     * Configures the ContextHub to allow logs to be printed to stdout.
     */
    virtual void SetLoggingEnabled(bool logging_enabled) = 0;

    /*
     * Loads a new firmware image to the ContextHub. The firmware image is
     * specified by filename. Returns false if an error occurs.
     */
    bool Flash(const std::string& filename);

    /*
     * Performs the sensor calibration routine and writes the resulting data to
     * a file.
     */
    bool CalibrateSensors(const std::vector<SensorSpec>& sensors);

    /*
     * Performs the sensor self-test routine.
     */
    bool TestSensors(const std::vector<SensorSpec>& sensors);

    /*
     * Sends a sensor enable request to the context hub.
     */
    bool EnableSensor(const SensorSpec& sensor);
    bool EnableSensors(const std::vector<SensorSpec>& sensors);

    /*
     * Sends a disable sensor request to context hub. Note that this always
     * results in sending a request, i.e. this does not check whether the sensor
     * is currently enabled or not.
     */
    bool DisableSensor(SensorType sensor_type);
    bool DisableSensors(const std::vector<SensorSpec>& sensors);

    /*
     * Sends a disable sensor request for every sensor type we know about.
     */
    bool DisableAllSensors();

    /*
     * Calls DisableSensor() on all active sensors (i.e. those which have been
     * enabled but not yet disabled). This should be called from the destructor
     * of derived classes before tearing down communications to ensure we don't
     * leave sensors enabled after exiting.
     */
    bool DisableActiveSensors();

    /*
     * Sends all data stored in the calibration file to the context hub.
     */
    virtual bool LoadCalibration();

    /*
     * Prints up to <limit> incoming events. If limit is 0, then continues
     * indefinitely.
     */
    void PrintAllEvents(unsigned int limit);

    /*
     * Requests bridge version information
     */
    bool PrintBridgeVersion();

    /*
     * Prints up to <sample_limit> incoming sensor samples corresponding to the
     * given SensorType, ignoring other events. If sample_limit is 0, then
     * continues indefinitely.
     */
    void PrintSensorEvents(SensorType sensor_type, int sample_limit);
    void PrintSensorEvents(const std::vector<SensorSpec>& sensors,
        int sample_limit);

  protected:
    enum class TransportResult {
        Success,
        GeneralFailure,
        Timeout,
        ParseFailure,
        Canceled,
        // Add more specific error reasons as needed
    };

    // Performs the calibration routine, but does not call SaveCalibration()
    bool CalibrateSingleSensor(const SensorSpec& sensor);

    // Performs the self-test routine
    bool TestSingleSensor(const SensorSpec& sensor);

    /*
     * Iterates over sensors, invoking the given callback on each element.
     * Returns true if all callbacks returned true. Exits early on failure.
     */
    bool ForEachSensor(const std::vector<SensorSpec>& sensors,
        std::function<bool(const SensorSpec&)> callback);

    /*
     * Parses a calibration result event and invokes the appropriate
     * SetCalibration function with the calibration data.
     */
    bool HandleCalibrationResult(const SensorSpec& sensor,
        const AppToHostEvent &event);

    /*
     * Parses a self-test result event
     */
    bool HandleTestResult(const SensorSpec& sensor,
        const AppToHostEvent &event);

    /*
     * Same as ReadSensorEvents, but filters on AppToHostEvent instead of
     * SensorEvent.
     */
    TransportResult ReadAppEvents(std::function<bool(const AppToHostEvent&)> callback,
        int timeout_ms = 0);

    /*
     * Calls ReadEvent in a loop, handling errors and ignoring events that
     * didn't originate from a sensor. Valid SensorEvents are passed to the
     * callback for further processing. The callback should return a boolean
     * indicating whether to continue (true) or exit the read loop (false).
     */
    void ReadSensorEvents(std::function<bool(const SensorEvent&)> callback);

    /*
     * Sends the given calibration data down to the hub
     */
    bool SendCalibrationData(SensorType sensor_type,
        const std::vector<uint8_t>& cal_data);

    /*
     * Read an event from the sensor hub. Block until a event is successfully
     * read, no event traffic is generated for the timeout period, or an error
     * occurs, such as a CRC check failure.
     */
    virtual TransportResult ReadEvent(std::vector<uint8_t>& response,
        int timeout_ms) = 0;
    virtual TransportResult WriteEvent(const std::vector<uint8_t>& request) = 0;

    // Implements the firmware loading functionality for the sensor hub. Returns
    // false if an error occurs while writing the firmware to the device.
    virtual bool FlashSensorHub(const std::vector<uint8_t>& bytes) = 0;

    // Convenience functions that build on top of the more generic byte-level
    // interface
    TransportResult ReadEvent(std::unique_ptr<ReadEventResponse>* response,
        int timeout_ms = 0);
    TransportResult WriteEvent(const WriteEventRequest& request);

    // Override these if saving calibration data to persistent storage is
    // supported on the platform
    virtual bool SetCalibration(SensorType sensor_type, int32_t data);
    virtual bool SetCalibration(SensorType sensor_type, float data);
    virtual bool SetCalibration(SensorType sensor_type, int32_t x,
        int32_t y, int32_t z);
    virtual bool SetCalibration(SensorType sensor_type, int32_t x,
        int32_t y, int32_t z, int32_t w);
    virtual bool SaveCalibration();

private:
    std::bitset<static_cast<int>(SensorType::Max_)> sensor_is_active_;
};

}  // namespace android

#endif  // CONTEXTHUB_H_