Home | History | Annotate | Download | only in nanotool
      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