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