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 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 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 105 SensorType ContextHub::SensorAbbrevNameToType(const std::string& abbrev_name) { 106 return ContextHub::SensorAbbrevNameToType(abbrev_name.c_str()); 107 } 108 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 486 ContextHub::TransportResult ContextHub::WriteEvent( 487 const WriteEventRequest& request) { 488 return WriteEvent(request.GetBytes()); 489 } 490 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 505 bool ContextHub::LoadCalibration() { 506 LOGE("Loading calibration data not implemented"); 507 return false; 508 } 509 510 bool ContextHub::SetCalibration(SensorType sensor_type, int32_t data) { 511 UNUSED_PARAM(sensor_type); 512 UNUSED_PARAM(data); 513 return false; 514 } 515 516 bool ContextHub::SetCalibration(SensorType sensor_type, float data) { 517 UNUSED_PARAM(sensor_type); 518 UNUSED_PARAM(data); 519 return false; 520 } 521 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 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 541 bool ContextHub::SaveCalibration() { 542 LOGE("Saving calibration data not implemented"); 543 return false; 544 } 545 546 } // namespace android 547