nanotool: add support for running sensor self-test
Bug: 28906610
Change-Id: I2c728f884db2215e981e5308eb51d90f0c7f206d
diff --git a/util/nanotool/apptohostevent.cpp b/util/nanotool/apptohostevent.cpp
index 9ab4fb3..b801475 100644
--- a/util/nanotool/apptohostevent.cpp
+++ b/util/nanotool/apptohostevent.cpp
@@ -47,11 +47,7 @@
+ sizeof(struct HostHubRawPacket));
}
-bool AppToHostEvent::IsCalibrationEventForSensor(SensorType sensor_type) const {
- if (GetDataLen() < sizeof(struct SensorAppEventHeader)) {
- return false;
- }
-
+bool AppToHostEvent::CheckAppId(SensorType sensor_type) const {
// Make sure the app ID matches what we expect for the sensor type, bail out
// early if it doesn't
switch (sensor_type) {
@@ -85,12 +81,43 @@
return false;
}
+ return true;
+}
+
+bool AppToHostEvent::CheckEventHeader(SensorType sensor_type) const {
+ if (GetDataLen() < sizeof(struct SensorAppEventHeader)) {
+ return false;
+ }
+
+ if (!CheckAppId(sensor_type)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool AppToHostEvent::IsCalibrationEventForSensor(SensorType sensor_type) const {
+ if (!CheckEventHeader(sensor_type)) {
+ return false;
+ }
+
// If we made it this far, we only need to confirm the message ID
auto header = reinterpret_cast<const struct SensorAppEventHeader *>(
GetDataPtr());
return (header->msgId == SENSOR_APP_MSG_CALIBRATION_RESULT);
}
+bool AppToHostEvent::IsTestEventForSensor(SensorType sensor_type) const {
+ if (!CheckEventHeader(sensor_type)) {
+ return false;
+ }
+
+ // If we made it this far, we only need to confirm the message ID
+ auto header = reinterpret_cast<const struct SensorAppEventHeader *>(
+ GetDataPtr());
+ return (header->msgId == SENSOR_APP_MSG_TEST_RESULT);
+}
+
bool AppToHostEvent::IsValid() const {
const HostHubRawPacket *packet = GetTypedData();
if (!packet) {
diff --git a/util/nanotool/apptohostevent.h b/util/nanotool/apptohostevent.h
index 0a8101b..f4c6b45 100644
--- a/util/nanotool/apptohostevent.h
+++ b/util/nanotool/apptohostevent.h
@@ -92,13 +92,17 @@
const uint8_t *GetDataPtr() const;
bool IsCalibrationEventForSensor(SensorType sensor_type) const;
+ bool IsTestEventForSensor(SensorType sensor_type) const;
virtual bool IsValid() const;
protected:
const HostHubRawPacket *GetTypedData() const;
+ bool CheckAppId(SensorType sensor_type) const;
+ bool CheckEventHeader(SensorType sensor_type) const;
};
#define SENSOR_APP_MSG_CALIBRATION_RESULT (0)
+#define SENSOR_APP_MSG_TEST_RESULT (1)
struct SensorAppEventHeader {
uint8_t msgId;
diff --git a/util/nanotool/contexthub.cpp b/util/nanotool/contexthub.cpp
index 5beed5e..b4fe1c2 100644
--- a/util/nanotool/contexthub.cpp
+++ b/util/nanotool/contexthub.cpp
@@ -31,6 +31,7 @@
#define UNUSED_PARAM(param) (void) (param)
constexpr int kCalibrationTimeoutMs(10000);
+constexpr int kTestTimeoutMs(10000);
constexpr int kBridgeVersionTimeoutMs(500);
struct SensorTypeNames {
@@ -174,6 +175,14 @@
return success;
}
+bool ContextHub::TestSensors(const std::vector<SensorSpec>& sensors) {
+ bool success = ForEachSensor(sensors, [this](const SensorSpec &spec) -> bool {
+ return TestSingleSensor(spec);
+ });
+
+ return success;
+}
+
bool ContextHub::EnableSensor(const SensorSpec& spec) {
ConfigureSensorRequest req;
@@ -382,6 +391,40 @@
return success;
}
+bool ContextHub::TestSingleSensor(const SensorSpec& sensor) {
+ ConfigureSensorRequest req;
+
+ req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
+ req.config.sensor_type = static_cast<uint8_t>(sensor.sensor_type);
+ req.config.command = static_cast<uint8_t>(
+ ConfigureSensorRequest::CommandType::SelfTest);
+
+ LOGI("Issuing test request to sensor %d (%s)", sensor.sensor_type,
+ ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str());
+ auto result = WriteEvent(req);
+ if (result != TransportResult::Success) {
+ LOGE("Failed to test sensor %d", sensor.sensor_type);
+ return false;
+ }
+
+ bool success = false;
+ auto test_event_handler = [this, &sensor, &success](const AppToHostEvent &event) -> bool {
+ if (event.IsTestEventForSensor(sensor.sensor_type)) {
+ success = HandleTestResult(sensor, event);
+ return false;
+ }
+ return true;
+ };
+
+ result = ReadAppEvents(test_event_handler, kTestTimeoutMs);
+ if (result != TransportResult::Success) {
+ LOGE("Error reading test response %d", static_cast<int>(result));
+ return false;
+ }
+
+ return success;
+}
+
bool ContextHub::ForEachSensor(const std::vector<SensorSpec>& sensors,
std::function<bool(const SensorSpec&)> callback) {
bool success = true;
@@ -451,6 +494,23 @@
return success;
}
+bool ContextHub::HandleTestResult(const SensorSpec& sensor,
+ const AppToHostEvent &event) {
+ auto hdr = reinterpret_cast<const SensorAppEventHeader *>(event.GetDataPtr());
+ if (!hdr->status) {
+ LOGI("Self-test of sensor %d (%s) succeeded",
+ sensor.sensor_type,
+ ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str());
+ return true;
+ } else {
+ LOGE("Self-test of sensor %d (%s) failed with status %u",
+ sensor.sensor_type,
+ ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str(),
+ hdr->status);
+ return false;
+ }
+}
+
ContextHub::TransportResult ContextHub::ReadAppEvents(
std::function<bool(const AppToHostEvent&)> callback, int timeout_ms) {
using Milliseconds = std::chrono::milliseconds;
diff --git a/util/nanotool/contexthub.h b/util/nanotool/contexthub.h
index f8eb6e7..1ea0c8a 100644
--- a/util/nanotool/contexthub.h
+++ b/util/nanotool/contexthub.h
@@ -133,6 +133,11 @@
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);
@@ -197,6 +202,9 @@
// 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.
@@ -212,6 +220,12 @@
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.
*/
diff --git a/util/nanotool/nanomessage.h b/util/nanotool/nanomessage.h
index 2276775..e11ec4b 100644
--- a/util/nanotool/nanomessage.h
+++ b/util/nanotool/nanomessage.h
@@ -165,7 +165,8 @@
Enable,
Flush,
ConfigData,
- Calibrate
+ Calibrate,
+ SelfTest
};
ConfigureSensorRequest();
diff --git a/util/nanotool/nanotool.cpp b/util/nanotool/nanotool.cpp
index cf37945..71251a5 100644
--- a/util/nanotool/nanotool.cpp
+++ b/util/nanotool/nanotool.cpp
@@ -42,6 +42,7 @@
Disable,
DisableAll,
Calibrate,
+ Test,
Read,
Poll,
LoadCalibration,
@@ -64,6 +65,7 @@
std::make_tuple("disable_all", NanotoolCommand::DisableAll),
std::make_tuple("calibrate", NanotoolCommand::Calibrate),
std::make_tuple("cal", NanotoolCommand::Calibrate),
+ std::make_tuple("test", NanotoolCommand::Test),
std::make_tuple("read", NanotoolCommand::Read),
std::make_tuple("poll", NanotoolCommand::Poll),
std::make_tuple("load_cal", NanotoolCommand::LoadCalibration),
@@ -98,6 +100,7 @@
" disable_all: send a disable request for all sensors\n"
" calibrate: disable the sensor, then perform the sensor\n"
" calibration routine\n"
+ " test: run a sensor's self-test routine\n"
#ifndef __ANDROID__
" flash: load a new firmware image to the hub\n"
#endif
@@ -159,6 +162,7 @@
if (!args->sensors.size()
&& (args->command == NanotoolCommand::Disable
|| args->command == NanotoolCommand::Calibrate
+ || args->command == NanotoolCommand::Test
|| args->command == NanotoolCommand::Poll)) {
fprintf(stderr, "%s: At least 1 sensor must be specified for this "
"command (use -s)\n",
@@ -460,6 +464,11 @@
success = hub->CalibrateSensors(args->sensors);
break;
}
+ case NanotoolCommand::Test: {
+ hub->DisableSensors(args->sensors);
+ success = hub->TestSensors(args->sensors);
+ break;
+ }
case NanotoolCommand::LoadCalibration: {
success = hub->LoadCalibration();
break;