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 #include "contexthub.h"
18
19 #include <cstring>
20 #include <errno.h>
21 #include <vector>
22
23 #include "apptohostevent.h"
24 #include "log.h"
25 #include "resetreasonevent.h"
26 #include "sensorevent.h"
27 #include "util.h"
28
29 namespace android {
30
31 #define UNUSED_PARAM(param) (void) (param)
32
33 constexpr int kCalibrationTimeoutMs(10000);
34
35 struct SensorTypeNames {
36 SensorType sensor_type;
37 const char *name_abbrev;
38 };
39
40 static const SensorTypeNames sensor_names_[] = {
41 { SensorType::Accel, "accel" },
42 { SensorType::AnyMotion, "anymo" },
43 { SensorType::NoMotion, "nomo" },
44 { SensorType::SignificantMotion, "sigmo" },
45 { SensorType::Flat, "flat" },
46 { SensorType::Gyro, "gyro" },
47 //{ SensorType::GyroUncal, "gyro_uncal" },
48 { SensorType::Magnetometer, "mag" },
49 //{ SensorType::MagnetometerUncal, "mag_uncal" },
50 { SensorType::Barometer, "baro" },
51 { SensorType::Temperature, "temp" },
52 { SensorType::AmbientLightSensor, "als" },
53 { SensorType::Proximity, "prox" },
54 { SensorType::Orientation, "orien" },
55 //{ SensorType::HeartRateECG, "ecg" },
56 //{ SensorType::HeartRatePPG, "ppg" },
57 { SensorType::Gravity, "gravity" },
58 { SensorType::LinearAccel, "linear_acc" },
59 { SensorType::RotationVector, "rotation" },
60 { SensorType::GeomagneticRotationVector, "geomag" },
61 { SensorType::GameRotationVector, "game" },
62 { SensorType::StepCount, "step_cnt" },
63 { SensorType::StepDetect, "step_det" },
64 { SensorType::Gesture, "gesture" },
65 { SensorType::Tilt, "tilt" },
66 { SensorType::DoubleTwist, "twist" },
67 { SensorType::DoubleTap, "doubletap" },
68 { SensorType::WindowOrientation, "win_orien" },
69 { SensorType::Hall, "hall" },
70 { SensorType::Activity, "activity" },
71 { SensorType::Vsync, "vsync" },
72 };
73
74 struct SensorTypeAlias {
75 SensorType sensor_type;
76 SensorType sensor_alias;
77 const char *name_abbrev;
78 };
79
80 static const SensorTypeAlias sensor_aliases_[] = {
81 { SensorType::Accel, SensorType::CompressedAccel, "compressed_accel" },
82 };
83
SensorTypeIsAliasOf(SensorType sensor_type,SensorType alias)84 bool SensorTypeIsAliasOf(SensorType sensor_type, SensorType alias) {
85 for (size_t i = 0; i < ARRAY_LEN(sensor_aliases_); i++) {
86 if (sensor_aliases_[i].sensor_type == sensor_type
87 && sensor_aliases_[i].sensor_alias == alias) {
88 return true;
89 }
90 }
91
92 return false;
93 }
94
SensorAbbrevNameToType(const char * sensor_name_abbrev)95 SensorType ContextHub::SensorAbbrevNameToType(const char *sensor_name_abbrev) {
96 for (unsigned int i = 0; i < ARRAY_LEN(sensor_names_); i++) {
97 if (strcmp(sensor_names_[i].name_abbrev, sensor_name_abbrev) == 0) {
98 return sensor_names_[i].sensor_type;
99 }
100 }
101
102 return SensorType::Invalid_;
103 }
104
SensorAbbrevNameToType(const std::string & abbrev_name)105 SensorType ContextHub::SensorAbbrevNameToType(const std::string& abbrev_name) {
106 return ContextHub::SensorAbbrevNameToType(abbrev_name.c_str());
107 }
108
SensorTypeToAbbrevName(SensorType sensor_type)109 std::string ContextHub::SensorTypeToAbbrevName(SensorType sensor_type) {
110 for (unsigned int i = 0; i < ARRAY_LEN(sensor_names_); i++) {
111 if (sensor_names_[i].sensor_type == sensor_type) {
112 return std::string(sensor_names_[i].name_abbrev);
113 }
114 }
115
116 for (unsigned int i = 0; i < ARRAY_LEN(sensor_aliases_); i++) {
117 if (sensor_aliases_[i].sensor_alias == sensor_type) {
118 return std::string(sensor_aliases_[i].name_abbrev);
119 }
120 }
121
122 char buffer[24];
123 snprintf(buffer, sizeof(buffer), "unknown (%d)",
124 static_cast<int>(sensor_type));
125 return std::string(buffer);
126 }
127
ListAllSensorAbbrevNames()128 std::string ContextHub::ListAllSensorAbbrevNames() {
129 std::string sensor_list;
130 for (unsigned int i = 0; i < ARRAY_LEN(sensor_names_); i++) {
131 sensor_list += sensor_names_[i].name_abbrev;
132 if (i < ARRAY_LEN(sensor_names_) - 1) {
133 sensor_list += ", ";
134 }
135 }
136
137 return sensor_list;
138 }
139
Flash(const std::string & filename)140 bool ContextHub::Flash(const std::string& filename) {
141 FILE *firmware_file = fopen(filename.c_str(), "r");
142 if (!firmware_file) {
143 LOGE("Failed to open firmware image: %d (%s)", errno, strerror(errno));
144 return false;
145 }
146
147 fseek(firmware_file, 0, SEEK_END);
148 long file_size = ftell(firmware_file);
149 fseek(firmware_file, 0, SEEK_SET);
150
151 auto firmware_data = std::vector<uint8_t>(file_size);
152 size_t bytes_read = fread(firmware_data.data(), sizeof(uint8_t),
153 file_size, firmware_file);
154 fclose(firmware_file);
155
156 if (bytes_read != static_cast<size_t>(file_size)) {
157 LOGE("Read of firmware file returned %zu, expected %ld",
158 bytes_read, file_size);
159 return false;
160 }
161 return FlashSensorHub(firmware_data);
162 }
163
CalibrateSensors(const std::vector<SensorSpec> & sensors)164 bool ContextHub::CalibrateSensors(const std::vector<SensorSpec>& sensors) {
165 bool success = ForEachSensor(sensors, [this](const SensorSpec &spec) -> bool {
166 return CalibrateSingleSensor(spec);
167 });
168
169 if (success) {
170 success = SaveCalibration();
171 }
172 return success;
173 }
174
EnableSensor(const SensorSpec & spec)175 bool ContextHub::EnableSensor(const SensorSpec& spec) {
176 ConfigureSensorRequest req;
177
178 req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
179 req.config.sensor_type = static_cast<uint8_t>(spec.sensor_type);
180 req.config.command = static_cast<uint8_t>(
181 ConfigureSensorRequest::CommandType::Enable);
182 if (spec.special_rate != SensorSpecialRate::None) {
183 req.config.rate = static_cast<uint32_t>(spec.special_rate);
184 } else {
185 req.config.rate = ConfigureSensorRequest::FloatRateToFixedPoint(
186 spec.rate_hz);
187 }
188 req.config.latency = spec.latency_ns;
189
190 LOGI("Enabling sensor %d at rate %.0f Hz (special 0x%x) and latency %.2f ms",
191 spec.sensor_type, spec.rate_hz, spec.special_rate,
192 spec.latency_ns / 1000000.0f);
193 auto result = WriteEvent(req);
194 if (result == TransportResult::Success) {
195 sensor_is_active_[static_cast<int>(spec.sensor_type)] = true;
196 return true;
197 }
198
199 LOGE("Could not enable sensor %d", spec.sensor_type);
200 return false;
201 }
202
EnableSensors(const std::vector<SensorSpec> & sensors)203 bool ContextHub::EnableSensors(const std::vector<SensorSpec>& sensors) {
204 return ForEachSensor(sensors, [this](const SensorSpec &spec) -> bool {
205 return EnableSensor(spec);
206 });
207 }
208
DisableSensor(SensorType sensor_type)209 bool ContextHub::DisableSensor(SensorType sensor_type) {
210 ConfigureSensorRequest req;
211
212 req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
213 req.config.sensor_type = static_cast<uint8_t>(sensor_type);
214 req.config.command = static_cast<uint8_t>(
215 ConfigureSensorRequest::CommandType::Disable);
216
217 // Note that nanohub treats us as a single client, so if we call enable
218 // twice then disable once, the sensor will be disabled
219 LOGI("Disabling sensor %d", sensor_type);
220 auto result = WriteEvent(req);
221 if (result == TransportResult::Success) {
222 sensor_is_active_[static_cast<int>(sensor_type)] = false;
223 return true;
224 }
225
226 LOGE("Could not disable sensor %d", sensor_type);
227 return false;
228 }
229
DisableSensors(const std::vector<SensorSpec> & sensors)230 bool ContextHub::DisableSensors(const std::vector<SensorSpec>& sensors) {
231 return ForEachSensor(sensors, [this](const SensorSpec &spec) -> bool {
232 return DisableSensor(spec.sensor_type);
233 });
234 }
235
DisableAllSensors()236 bool ContextHub::DisableAllSensors() {
237 bool success = true;
238
239 for (int sensor_type = static_cast<int>(SensorType::Invalid_) + 1;
240 sensor_type < static_cast<int>(SensorType::Max_);
241 ++sensor_type) {
242 success &= DisableSensor(static_cast<SensorType>(sensor_type));
243 }
244
245 return success;
246 }
247
DisableActiveSensors()248 bool ContextHub::DisableActiveSensors() {
249 bool success = true;
250
251 LOGD("Disabling all active sensors");
252 for (int sensor_type = static_cast<int>(SensorType::Invalid_) + 1;
253 sensor_type < static_cast<int>(SensorType::Max_);
254 ++sensor_type) {
255 if (sensor_is_active_[sensor_type]) {
256 success &= DisableSensor(static_cast<SensorType>(sensor_type));
257 }
258 }
259
260 return success;
261 }
262
PrintAllEvents(unsigned int limit)263 void ContextHub::PrintAllEvents(unsigned int limit) {
264 bool continuous = (limit == 0);
265 auto event_printer = [&limit, continuous](const SensorEvent& event) -> bool {
266 printf("%s", event.ToString().c_str());
267 return (continuous || --limit > 0);
268 };
269 ReadSensorEvents(event_printer);
270 }
271
PrintSensorEvents(SensorType type,int limit)272 void ContextHub::PrintSensorEvents(SensorType type, int limit) {
273 bool continuous = (limit == 0);
274 auto event_printer = [type, &limit, continuous](const SensorEvent& event) -> bool {
275 SensorType event_source = event.GetSensorType();
276 if (event_source == type || SensorTypeIsAliasOf(type, event_source)) {
277 printf("%s", event.ToString().c_str());
278 limit -= event.GetNumSamples();
279 }
280 return (continuous || limit > 0);
281 };
282 ReadSensorEvents(event_printer);
283 }
284
PrintSensorEvents(const std::vector<SensorSpec> & sensors,int limit)285 void ContextHub::PrintSensorEvents(const std::vector<SensorSpec>& sensors, int limit) {
286 bool continuous = (limit == 0);
287 auto event_printer = [&sensors, &limit, continuous](const SensorEvent& event) -> bool {
288 SensorType event_source = event.GetSensorType();
289 for (unsigned int i = 0; i < sensors.size(); i++) {
290 if (sensors[i].sensor_type == event_source
291 || SensorTypeIsAliasOf(sensors[i].sensor_type, event_source)) {
292 printf("%s", event.ToString().c_str());
293 limit -= event.GetNumSamples();
294 break;
295 }
296 }
297 return (continuous || limit > 0);
298 };
299 ReadSensorEvents(event_printer);
300 }
301
302 // Protected methods -----------------------------------------------------------
303
CalibrateSingleSensor(const SensorSpec & sensor)304 bool ContextHub::CalibrateSingleSensor(const SensorSpec& sensor) {
305 ConfigureSensorRequest req;
306
307 req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
308 req.config.sensor_type = static_cast<uint8_t>(sensor.sensor_type);
309 req.config.command = static_cast<uint8_t>(
310 ConfigureSensorRequest::CommandType::Calibrate);
311
312 LOGI("Issuing calibration request to sensor %d (%s)", sensor.sensor_type,
313 ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str());
314 auto result = WriteEvent(req);
315 if (result != TransportResult::Success) {
316 LOGE("Failed to calibrate sensor %d", sensor.sensor_type);
317 return false;
318 }
319
320 bool success = false;
321 auto calEventHandler = [this, &sensor, &success](const AppToHostEvent &event) -> bool {
322 if (event.IsCalibrationEventForSensor(sensor.sensor_type)) {
323 success = HandleCalibrationResult(sensor, event);
324 return false;
325 }
326 return true;
327 };
328
329 result = ReadAppEvents(calEventHandler, kCalibrationTimeoutMs);
330 if (result != TransportResult::Success) {
331 LOGE("Error reading calibration response %d", static_cast<int>(result));
332 return false;
333 }
334
335 return success;
336 }
337
ForEachSensor(const std::vector<SensorSpec> & sensors,std::function<bool (const SensorSpec &)> callback)338 bool ContextHub::ForEachSensor(const std::vector<SensorSpec>& sensors,
339 std::function<bool(const SensorSpec&)> callback) {
340 bool success = true;
341
342 for (unsigned int i = 0; success && i < sensors.size(); i++) {
343 success &= callback(sensors[i]);
344 }
345
346 return success;
347 }
348
HandleCalibrationResult(const SensorSpec & sensor,const AppToHostEvent & event)349 bool ContextHub::HandleCalibrationResult(const SensorSpec& sensor,
350 const AppToHostEvent &event) {
351 auto hdr = reinterpret_cast<const SensorAppEventHeader *>(event.GetDataPtr());
352 if (hdr->status) {
353 LOGE("Calibration of sensor %d (%s) failed with status %u",
354 sensor.sensor_type,
355 ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str(),
356 hdr->status);
357 return false;
358 }
359
360 bool success = false;
361 switch (sensor.sensor_type) {
362 case SensorType::Accel:
363 case SensorType::Gyro: {
364 auto result = reinterpret_cast<const TripleAxisCalibrationResult *>(
365 event.GetDataPtr());
366 success = SetCalibration(sensor.sensor_type, result->xBias,
367 result->yBias, result->zBias);
368 break;
369 }
370
371 case SensorType::Barometer: {
372 auto result = reinterpret_cast<const FloatCalibrationResult *>(
373 event.GetDataPtr());
374 if (sensor.have_cal_ref) {
375 success = SetCalibration(sensor.sensor_type,
376 (sensor.cal_ref - result->value));
377 }
378 break;
379 }
380
381 case SensorType::Proximity: {
382 auto result = reinterpret_cast<const FourAxisCalibrationResult *>(
383 event.GetDataPtr());
384 success = SetCalibration(sensor.sensor_type, result->xBias,
385 result->yBias, result->zBias, result->wBias);
386 break;
387 }
388
389 case SensorType::AmbientLightSensor: {
390 auto result = reinterpret_cast<const FloatCalibrationResult *>(
391 event.GetDataPtr());
392 if (sensor.have_cal_ref && (result->value != 0.0f)) {
393 success = SetCalibration(sensor.sensor_type,
394 (sensor.cal_ref / result->value));
395 }
396 break;
397 }
398
399 default:
400 LOGE("Calibration not supported for sensor type %d",
401 static_cast<int>(sensor.sensor_type));
402 }
403
404 return success;
405 }
406
ReadAppEvents(std::function<bool (const AppToHostEvent &)> callback,int timeout_ms)407 ContextHub::TransportResult ContextHub::ReadAppEvents(
408 std::function<bool(const AppToHostEvent&)> callback, int timeout_ms) {
409 using Milliseconds = std::chrono::milliseconds;
410
411 TransportResult result;
412 bool timeout_required = timeout_ms > 0;
413 bool keep_going = true;
414
415 while (keep_going) {
416 if (timeout_required && timeout_ms <= 0) {
417 return TransportResult::Timeout;
418 }
419
420 std::unique_ptr<ReadEventResponse> event;
421
422 SteadyClock start_time = std::chrono::steady_clock::now();
423 result = ReadEvent(&event, timeout_ms);
424 SteadyClock end_time = std::chrono::steady_clock::now();
425
426 auto delta = end_time - start_time;
427 timeout_ms -= std::chrono::duration_cast<Milliseconds>(delta).count();
428
429 if (result == TransportResult::Success && event->IsAppToHostEvent()) {
430 AppToHostEvent *app_event = reinterpret_cast<AppToHostEvent*>(
431 event.get());
432 keep_going = callback(*app_event);
433 } else {
434 if (result != TransportResult::Success) {
435 LOGE("Error %d while reading", static_cast<int>(result));
436 if (result != TransportResult::ParseFailure) {
437 return result;
438 }
439 } else {
440 LOGD("Ignoring non-app-to-host event");
441 }
442 }
443 }
444
445 return TransportResult::Success;
446 }
447
ReadSensorEvents(std::function<bool (const SensorEvent &)> callback)448 void ContextHub::ReadSensorEvents(std::function<bool(const SensorEvent&)> callback) {
449 TransportResult result;
450 bool keep_going = true;
451
452 while (keep_going) {
453 std::unique_ptr<ReadEventResponse> event;
454 result = ReadEvent(&event);
455 if (result == TransportResult::Success && event->IsSensorEvent()) {
456 SensorEvent *sensor_event = reinterpret_cast<SensorEvent*>(
457 event.get());
458 keep_going = callback(*sensor_event);
459 } else {
460 if (result != TransportResult::Success) {
461 LOGE("Error %d while reading", static_cast<int>(result));
462 if (result != TransportResult::ParseFailure) {
463 break;
464 }
465 } else {
466 LOGD("Ignoring non-sensor event");
467 }
468 }
469 }
470 }
471
SendCalibrationData(SensorType sensor_type,const std::vector<uint8_t> & cal_data)472 bool ContextHub::SendCalibrationData(SensorType sensor_type,
473 const std::vector<uint8_t>& cal_data) {
474 ConfigureSensorRequest req;
475
476 req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
477 req.config.sensor_type = static_cast<uint8_t>(sensor_type);
478 req.config.command = static_cast<uint8_t>(
479 ConfigureSensorRequest::CommandType::ConfigData);
480 req.SetAdditionalData(cal_data);
481
482 auto result = WriteEvent(req);
483 return (result == TransportResult::Success);
484 }
485
WriteEvent(const WriteEventRequest & request)486 ContextHub::TransportResult ContextHub::WriteEvent(
487 const WriteEventRequest& request) {
488 return WriteEvent(request.GetBytes());
489 }
490
ReadEvent(std::unique_ptr<ReadEventResponse> * response,int timeout_ms)491 ContextHub::TransportResult ContextHub::ReadEvent(
492 std::unique_ptr<ReadEventResponse>* response, int timeout_ms) {
493 std::vector<uint8_t> responseBuf(256);
494 ContextHub::TransportResult result = ReadEvent(responseBuf, timeout_ms);
495 if (result == TransportResult::Success) {
496 *response = ReadEventResponse::FromBytes(responseBuf);
497 if (*response == nullptr) {
498 result = TransportResult::ParseFailure;
499 }
500 }
501 return result;
502 }
503
504 // Stubs for subclasses that don't implement calibration support
LoadCalibration()505 bool ContextHub::LoadCalibration() {
506 LOGE("Loading calibration data not implemented");
507 return false;
508 }
509
SetCalibration(SensorType sensor_type,int32_t data)510 bool ContextHub::SetCalibration(SensorType sensor_type, int32_t data) {
511 UNUSED_PARAM(sensor_type);
512 UNUSED_PARAM(data);
513 return false;
514 }
515
SetCalibration(SensorType sensor_type,float data)516 bool ContextHub::SetCalibration(SensorType sensor_type, float data) {
517 UNUSED_PARAM(sensor_type);
518 UNUSED_PARAM(data);
519 return false;
520 }
521
SetCalibration(SensorType sensor_type,int32_t x,int32_t y,int32_t z)522 bool ContextHub::SetCalibration(SensorType sensor_type, int32_t x,
523 int32_t y, int32_t z) {
524 UNUSED_PARAM(sensor_type);
525 UNUSED_PARAM(x);
526 UNUSED_PARAM(y);
527 UNUSED_PARAM(z);
528 return false;
529 }
530
SetCalibration(SensorType sensor_type,int32_t x,int32_t y,int32_t z,int32_t w)531 bool ContextHub::SetCalibration(SensorType sensor_type, int32_t x,
532 int32_t y, int32_t z, int32_t w) {
533 UNUSED_PARAM(sensor_type);
534 UNUSED_PARAM(x);
535 UNUSED_PARAM(y);
536 UNUSED_PARAM(z);
537 UNUSED_PARAM(w);
538 return false;
539 }
540
SaveCalibration()541 bool ContextHub::SaveCalibration() {
542 LOGE("Saving calibration data not implemented");
543 return false;
544 }
545
546 } // namespace android
547