/*
* 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,
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_