• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 #include "HidRawSensor.h"
17 #include "HidSensorDef.h"
18 
19 #include <android-base/properties.h>
20 #include <utils/Errors.h>
21 #include <com_android_libhardware_dynamic_sensors_flags.h>
22 #include "HidLog.h"
23 
24 #include <HidUtils.h>
25 
26 #include <algorithm>
27 #include <cfloat>
28 #include <codecvt>
29 #include <iomanip>
30 #include <sstream>
31 
32 namespace android {
33 namespace SensorHalExt {
34 
35 using ::android::base::GetProperty;
36 
37 namespace dynamic_sensors_flags = com::android::libhardware::dynamic::sensors::flags;
38 
39 namespace {
40 const std::string CUSTOM_TYPE_PREFIX("com.google.hardware.sensor.hid_dynamic.");
41 
42 }
43 
HidRawSensor(SP (HidDevice)device,uint32_t usage,const std::vector<HidParser::ReportPacket> & packets)44 HidRawSensor::HidRawSensor(
45         SP(HidDevice) device, uint32_t usage, const std::vector<HidParser::ReportPacket> &packets)
46         : mReportingStateId(-1), mPowerStateId(-1), mReportIntervalId(-1), mLeTransportId(-1),
47         mRequiresLeTransport(false), mInputReportId(-1), mEnabled(false),
48         mSamplingPeriod(1000LL*1000*1000), mBatchingPeriod(0), mDevice(device), mValid(false) {
49     if (device == nullptr) {
50         return;
51     }
52     memset(&mSensor, 0, sizeof(mSensor));
53 
54     const HidDevice::HidDeviceInfo &info =  device->getDeviceInfo();
55     initFeatureValueFromHidDeviceInfo(&mFeatureInfo, info);
56 
57     if (!populateFeatureValueFromFeatureReport(&mFeatureInfo, packets)) {
58         LOG_E << "populate feature from feature report failed" << LOG_ENDL;
59         return;
60     }
61 
62     if (!findSensorControlUsage(packets)) {
63         LOG_E << "finding sensor control usage failed" << LOG_ENDL;
64         return;
65     }
66 
67     // build translation table
68     bool translationTableValid = false;
69     switch (usage) {
70         using namespace Hid::Sensor::SensorTypeUsage;
71         using namespace Hid::Sensor::ReportUsage;
72         case ACCELEROMETER_3D:
73             // Hid unit default g
74             // Android unit m/s^2
75             // 1g = 9.81 m/s^2
76             mFeatureInfo.typeString = SENSOR_STRING_TYPE_ACCELEROMETER;
77             mFeatureInfo.type = SENSOR_TYPE_ACCELEROMETER;
78             mFeatureInfo.isWakeUp = false;
79 
80             translationTableValid = processTriAxisUsage(packets,
81                                          ACCELERATION_X_AXIS,
82                                          ACCELERATION_Y_AXIS,
83                                          ACCELERATION_Z_AXIS, 9.81);
84             break;
85         case GYROMETER_3D:
86             // Hid unit default degree/s
87             // Android unit rad/s
88             // 1 degree/s = pi/180 rad/s
89             mFeatureInfo.typeString = SENSOR_STRING_TYPE_GYROSCOPE;
90             mFeatureInfo.type = SENSOR_TYPE_GYROSCOPE;
91             mFeatureInfo.isWakeUp = false;
92 
93             translationTableValid = processTriAxisUsage(packets,
94                                          ANGULAR_VELOCITY_X_AXIS,
95                                          ANGULAR_VELOCITY_Y_AXIS,
96                                          ANGULAR_VELOCITY_Z_AXIS, M_PI/180);
97             break;
98         case COMPASS_3D: {
99             // Hid unit default mGauss
100             // Android unit uT
101             // 1uT  = 0.1 nGauss
102             mFeatureInfo.typeString = SENSOR_STRING_TYPE_MAGNETIC_FIELD;
103             mFeatureInfo.type = SENSOR_TYPE_MAGNETIC_FIELD;
104 
105             if (!processTriAxisUsage(packets,
106                                      MAGNETIC_FLUX_X_AXIS,
107                                      MAGNETIC_FLUX_Y_AXIS,
108                                      MAGNETIC_FLUX_Z_AXIS, 0.1)) {
109                 break;
110             }
111             const HidParser::ReportItem *pReportAccuracy = find(packets,
112                                                                   MAGNETOMETER_ACCURACY,
113                                                                   HidParser::REPORT_TYPE_INPUT,
114                                                                   mInputReportId);
115 
116             if (pReportAccuracy == nullptr) {
117                 LOG_E << "Cannot find accuracy field in usage "
118                       << std::hex << usage << std::dec << LOG_ENDL;
119                 break;
120             }
121             if (!pReportAccuracy->isByteAligned()) {
122                 LOG_E << "Accuracy field must align to byte" << LOG_ENDL;
123                 break;
124             }
125             if (pReportAccuracy->minRaw != 0 || pReportAccuracy->maxRaw != 2) {
126                 LOG_E << "Accuracy field value range must be [0, 2]" << LOG_ENDL;
127                 break;
128             }
129             ReportTranslateRecord accuracyRecord = {
130                 .type = TYPE_ACCURACY,
131                 .maxValue = 2,
132                 .minValue = 0,
133                 .byteOffset = pReportAccuracy->bitOffset / 8,
134                 .byteSize = pReportAccuracy->bitSize / 8,
135                 .a = 1,
136                 .b = 1};
137             mTranslateTable.push_back(accuracyRecord);
138             translationTableValid = true;
139             break;
140         }
141         case DEVICE_ORIENTATION:
142             translationTableValid = processQuaternionUsage(packets);
143             break;
144         case CUSTOM: {
145             if (!mFeatureInfo.isAndroidCustom) {
146                 LOG_E << "Invalid android custom sensor" << LOG_ENDL;
147                 break;
148             }
149             const HidParser::ReportPacket *pPacket = nullptr;
150             const uint32_t usages[] = {
151                 CUSTOM_VALUE_1, CUSTOM_VALUE_2, CUSTOM_VALUE_3,
152                 CUSTOM_VALUE_4, CUSTOM_VALUE_5, CUSTOM_VALUE_6
153             };
154             for (const auto &packet : packets) {
155                 if (packet.type == HidParser::REPORT_TYPE_INPUT && std::any_of(
156                         packet.reports.begin(), packet.reports.end(),
157                         [&usages] (const HidParser::ReportItem &d) {
158                                return std::find(std::begin(usages), std::end(usages), d.usage)
159                                        != std::end(usages);
160                         })) {
161                     pPacket = &packet;
162                     break;
163                 }
164             }
165 
166             if (pPacket == nullptr) {
167                 LOG_E << "Cannot find CUSTOM_VALUE_X in custom sensor" << LOG_ENDL;
168                 break;
169             }
170 
171             double range = 0;
172             double resolution = 1;
173 
174             for (const auto &digest : pPacket->reports) {
175                 if (digest.minRaw >= digest.maxRaw) {
176                     LOG_E << "Custome usage " << digest.usage << ", min must < max" << LOG_ENDL;
177                     return;
178                 }
179 
180                 if (!digest.isByteAligned()
181                         || (digest.bitSize != 8 && digest.bitSize != 16 && digest.bitSize != 32)) {
182                     LOG_E << "Custome usage " << std::hex << digest.usage << std::hex
183                           << ", each input must be 8/16/32 bits and must align to byte boundary"
184                           << LOG_ENDL;
185                     return;
186                 }
187 
188                 ReportTranslateRecord record = {
189                     .type = TYPE_FLOAT,
190                     .maxValue = digest.maxRaw,
191                     .minValue = digest.minRaw,
192                     .byteOffset = digest.bitOffset / 8,
193                     .byteSize = digest.bitSize / 8,
194                     .a = digest.a,
195                     .b = digest.b,
196                 };
197                 // keep track of range and resolution
198                 range = std::max(std::max(std::abs((digest.maxRaw + digest.b) * digest.a),
199                                           std::abs((digest.minRaw + digest.b) * digest.a)),
200                                  range);
201                 resolution = std::min(digest.a, resolution);
202 
203                 for (size_t i = 0; i < digest.count; ++i) {
204                     if (mTranslateTable.size() == 16) {
205                         LOG_I << "Custom usage has more than 16 inputs, ignore the rest" << LOG_ENDL;
206                         break;
207                     }
208                     record.index = mTranslateTable.size();
209                     mTranslateTable.push_back(record);
210                     record.byteOffset += digest.bitSize / 8;
211                 }
212                 if (mTranslateTable.size() == 16) {
213                     break;
214                 }
215             }
216             mFeatureInfo.maxRange = range;
217             mFeatureInfo.resolution = resolution;
218             mInputReportId = pPacket->id;
219             translationTableValid = !mTranslateTable.empty();
220             break;
221         }
222         default:
223             LOG_I << "unsupported sensor usage " << usage << LOG_ENDL;
224     }
225 
226     bool sensorValid = validateFeatureValueAndBuildSensor();
227     mValid = translationTableValid && sensorValid;
228     LOG_V << "HidRawSensor init, translationTableValid: " << translationTableValid
229           << ", sensorValid: " << sensorValid << LOG_ENDL;
230 }
231 
processQuaternionUsage(const std::vector<HidParser::ReportPacket> & packets)232 bool HidRawSensor::processQuaternionUsage(const std::vector<HidParser::ReportPacket> &packets) {
233     const HidParser::ReportItem *pReportQuaternion
234             = find(packets,
235                    Hid::Sensor::ReportUsage::ORIENTATION_QUATERNION,
236                    HidParser::REPORT_TYPE_INPUT);
237 
238     if (pReportQuaternion == nullptr) {
239         return false;
240     }
241 
242     const HidParser::ReportItem &quat = *pReportQuaternion;
243     if ((quat.bitSize != 16 && quat.bitSize != 32) || !quat.isByteAligned()) {
244         LOG_E << "Quaternion usage input must be 16 or 32 bits and aligned at byte boundary" << LOG_ENDL;
245         return false;
246     }
247 
248     double min, max;
249     quat.decode(quat.mask(quat.minRaw), &min);
250     quat.decode(quat.mask(quat.maxRaw), &max);
251     if (quat.count != 4 || min > -1 || max < 1) {
252         LOG_E << "Quaternion usage need 4 inputs with range [-1, 1]" << LOG_ENDL;
253         return false;
254     }
255 
256     if (quat.minRaw > quat.maxRaw) {
257         LOG_E << "Quaternion usage min must <= max" << LOG_ENDL;
258         return false;
259     }
260 
261     ReportTranslateRecord record = {
262         .type = TYPE_FLOAT,
263         .maxValue = quat.maxRaw,
264         .minValue = quat.minRaw,
265         .byteOffset = quat.bitOffset / 8,
266         .byteSize = quat.bitSize / 8,
267         .b = quat.b,
268     };
269 
270     // Android X Y Z maps to HID X -Z Y
271     // Android order xyzw, HID order wxyz
272     // X
273     record.index = 0;
274     record.a = quat.a;
275     record.byteOffset = (quat.bitOffset + quat.bitSize) / 8;
276     mTranslateTable.push_back(record);
277     // Y
278     record.index = 1;
279     record.a = -quat.a;
280     record.byteOffset = (quat.bitOffset + 3 * quat.bitSize) / 8;
281     mTranslateTable.push_back(record);
282     // Z
283     record.index = 2;
284     record.a = quat.a;
285     record.byteOffset = (quat.bitOffset + 2 * quat.bitSize) / 8;
286     mTranslateTable.push_back(record);
287     // W
288     record.index = 3;
289     record.a = quat.a;
290     record.byteOffset = quat.bitOffset / 8;
291     mTranslateTable.push_back(record);
292 
293     mFeatureInfo.typeString = SENSOR_STRING_TYPE_ROTATION_VECTOR;
294     mFeatureInfo.type = SENSOR_TYPE_ROTATION_VECTOR;
295     mFeatureInfo.maxRange = 1;
296     mFeatureInfo.resolution = quat.a;
297     mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
298 
299     mInputReportId = quat.id;
300 
301     return true;
302 }
303 
processTriAxisUsage(const std::vector<HidParser::ReportPacket> & packets,uint32_t usageX,uint32_t usageY,uint32_t usageZ,double defaultScaling)304 bool HidRawSensor::processTriAxisUsage(const std::vector<HidParser::ReportPacket> &packets,
305         uint32_t usageX, uint32_t usageY, uint32_t usageZ, double defaultScaling) {
306     const HidParser::ReportItem *pReportX = find(packets, usageX, HidParser::REPORT_TYPE_INPUT);
307     const HidParser::ReportItem *pReportY = find(packets, usageY, HidParser::REPORT_TYPE_INPUT);
308     const HidParser::ReportItem *pReportZ = find(packets, usageZ, HidParser::REPORT_TYPE_INPUT);
309 
310     if (pReportX == nullptr || pReportY == nullptr|| pReportZ == nullptr) {
311         LOG_E << "Three axis sensor does not find all 3 axis" << LOG_ENDL;
312         return false;
313     }
314 
315     const HidParser::ReportItem &reportX = *pReportX;
316     const HidParser::ReportItem &reportY = *pReportY;
317     const HidParser::ReportItem &reportZ = *pReportZ;
318     if (reportX.id != reportY.id || reportY.id != reportZ.id) {
319         LOG_E << "All 3 axis should be in the same report" << LOG_ENDL;
320         return false;
321     }
322     if (reportX.minRaw >= reportX.maxRaw
323             || reportX.minRaw != reportY.minRaw
324             || reportX.maxRaw != reportY.maxRaw
325             || reportY.minRaw != reportZ.minRaw
326             || reportY.maxRaw != reportZ.maxRaw) {
327         LOG_E << "All 3 axis should have same min and max value and min must < max" << LOG_ENDL;
328         return false;
329     }
330     if (reportX.a != reportY.a || reportY.a != reportY.a) {
331         LOG_E << "All 3 axis should have same resolution" << LOG_ENDL;
332         return false;
333     }
334     if (reportX.count != 1 || reportY.count != 1 || reportZ.count != 1
335             || (reportX.bitSize != 16 && reportX.bitSize != 32)
336             || reportX.bitSize != reportY.bitSize || reportY.bitSize != reportZ.bitSize
337             || !reportX.isByteAligned()
338             || !reportY.isByteAligned()
339             || !reportZ.isByteAligned() ) {
340         LOG_E << "All 3 axis should have count == 1, same size == 16 or 32 "
341               "and align at byte boundary" << LOG_ENDL;
342         return false;
343     }
344 
345     if (reportX.unit != 0 || reportY.unit != 0 || reportZ.unit != 0) {
346         LOG_E << "Specified unit for usage is not supported" << LOG_ENDL;
347         return false;
348     }
349 
350     if (reportX.a != reportY.a || reportY.a != reportZ.a
351         || reportX.b != reportY.b || reportY.b != reportZ.b) {
352         LOG_W << "Scaling for 3 axis are different. It is recommended to keep them the same" << LOG_ENDL;
353     }
354 
355     // set features
356     mFeatureInfo.maxRange = std::max(
357         std::abs((reportX.maxRaw + reportX.b) * reportX.a),
358         std::abs((reportX.minRaw + reportX.b) * reportX.a));
359     mFeatureInfo.resolution = reportX.a * defaultScaling;
360     mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
361 
362     ReportTranslateRecord record = {
363         .type = TYPE_FLOAT,
364         .maxValue = reportX.maxRaw,
365         .minValue = reportX.minRaw,
366         .byteSize = reportX.bitSize / 8,
367     };
368 
369     // Reorder and swap axis
370     //
371     // HID class devices are encouraged, where possible, to use a right-handed
372     // coordinate system. If a user is facing a device, report values should increase as
373     // controls are moved from left to right (X), from far to near (Y) and from high to
374     // low (Z).
375     //
376 
377     // Android X axis = Hid X axis
378     record.index = 0;
379     record.a = reportX.a * defaultScaling;
380     record.b = reportX.b;
381     record.byteOffset = reportX.bitOffset / 8;
382     mTranslateTable.push_back(record);
383 
384     // Android Y axis = - Hid Z axis
385     record.index = 1;
386     record.a = -reportZ.a * defaultScaling;
387     record.b = reportZ.b;
388     record.byteOffset = reportZ.bitOffset / 8;
389     mTranslateTable.push_back(record);
390 
391     // Android Z axis = Hid Y axis
392     record.index = 2;
393     record.a = reportY.a * defaultScaling;
394     record.b = reportY.b;
395     record.byteOffset = reportY.bitOffset / 8;
396     mTranslateTable.push_back(record);
397 
398     mInputReportId = reportX.id;
399     return true;
400 }
401 
find(const std::vector<HidParser::ReportPacket> & packets,unsigned int usage,int type,int id)402 const HidParser::ReportItem *HidRawSensor::find(
403         const std::vector<HidParser::ReportPacket> &packets,
404         unsigned int usage, int type, int id) {
405     for (const auto &packet : packets) {
406         if (packet.type != type) {
407             continue;
408         }
409         auto i = std::find_if(
410                 packet.reports.begin(), packet.reports.end(),
411                 [usage, id](const HidParser::ReportItem &p) {
412                     return p.usage == usage
413                             && (id == -1 || p.id == static_cast<unsigned int>(id));
414                 });
415         if (i != packet.reports.end()) {
416             return &(*i);
417         }
418     }
419     return nullptr;
420 };
421 
initFeatureValueFromHidDeviceInfo(FeatureValue * featureValue,const HidDevice::HidDeviceInfo & info)422 void HidRawSensor::initFeatureValueFromHidDeviceInfo(
423         FeatureValue *featureValue, const HidDevice::HidDeviceInfo &info) {
424     featureValue->name = info.name;
425 
426     std::ostringstream ss;
427     ss << info.busType << " "
428        << std::hex << std::setfill('0') << std::setw(4) << info.vendorId
429        << ":" << std::setw(4) << info.productId;
430     featureValue->vendor = ss.str();
431 
432     featureValue->permission = "";
433     featureValue->typeString = "";
434     featureValue->type = -1; // invalid type
435     featureValue->version = 1;
436 
437     featureValue->maxRange = -1.f;
438     featureValue->resolution = FLT_MAX;
439     featureValue->power = 1.f; // default value, does not have a valid source yet
440 
441     featureValue->minDelay = 0;
442     featureValue->maxDelay = 0;
443 
444     featureValue->fifoSize = 0;
445     featureValue->fifoMaxSize = 0;
446 
447     featureValue->reportModeFlag = SENSOR_FLAG_SPECIAL_REPORTING_MODE;
448     featureValue->isWakeUp = false;
449     featureValue->useUniqueIdForUuid = false;
450     memset(featureValue->uuid, 0, sizeof(featureValue->uuid));
451     featureValue->isAndroidCustom = false;
452 }
453 
populateFeatureValueFromFeatureReport(FeatureValue * featureValue,const std::vector<HidParser::ReportPacket> & packets)454 bool HidRawSensor::populateFeatureValueFromFeatureReport(
455         FeatureValue *featureValue, const std::vector<HidParser::ReportPacket> &packets) {
456     SP(HidDevice) device = PROMOTE(mDevice);
457     if (device == nullptr) {
458         return false;
459     }
460 
461     std::vector<uint8_t> buffer;
462     for (const auto &packet : packets) {
463         if (packet.type != HidParser::REPORT_TYPE_FEATURE) {
464             continue;
465         }
466 
467         if (!device->getFeature(packet.id, &buffer)) {
468             continue;
469         }
470 
471         std::string str;
472         using namespace Hid::Sensor::PropertyUsage;
473         for (const auto & r : packet.reports) {
474             switch (r.usage) {
475                 case FRIENDLY_NAME:
476                     if (decodeString(r, buffer, &str) && !str.empty()) {
477                         featureValue->name = str;
478                     }
479                     break;
480                 case SENSOR_MANUFACTURER:
481                     if (decodeString(r, buffer, &str) && !str.empty()) {
482                         featureValue->vendor = str;
483                     }
484                     break;
485                 case PERSISTENT_UNIQUE_ID:
486                     if (decodeString(r, buffer, &str) && !str.empty()) {
487                         featureValue->uniqueId = str;
488                     }
489                     break;
490                 case SENSOR_DESCRIPTION:
491                     if (decodeString(r, buffer, &str)) {
492                         detectSensorFromDescription(str);
493                     }
494                     break;
495                 default:
496                     // do not care about others
497                     break;
498             }
499         }
500     }
501     return true;
502 }
503 
validateFeatureValueAndBuildSensor()504 bool HidRawSensor::validateFeatureValueAndBuildSensor() {
505     if (mFeatureInfo.name.empty() || mFeatureInfo.vendor.empty() || mFeatureInfo.typeString.empty()
506             || mFeatureInfo.type <= 0 || mFeatureInfo.maxRange <= 0
507             || mFeatureInfo.resolution <= 0) {
508         return false;
509     }
510 
511     switch (mFeatureInfo.reportModeFlag) {
512         case SENSOR_FLAG_CONTINUOUS_MODE:
513         case SENSOR_FLAG_ON_CHANGE_MODE:
514             if (mFeatureInfo.minDelay < 0) {
515                 return false;
516             }
517             if (mFeatureInfo.maxDelay != 0 && mFeatureInfo.maxDelay < mFeatureInfo.minDelay) {
518                 return false;
519             }
520             break;
521         case SENSOR_FLAG_ONE_SHOT_MODE:
522             if (mFeatureInfo.minDelay != -1 && mFeatureInfo.maxDelay != 0) {
523                 return false;
524             }
525             break;
526         case SENSOR_FLAG_SPECIAL_REPORTING_MODE:
527             if (mFeatureInfo.minDelay != -1 && mFeatureInfo.maxDelay != 0) {
528                 return false;
529             }
530             break;
531         default:
532             break;
533     }
534 
535     if (mFeatureInfo.fifoMaxSize < mFeatureInfo.fifoSize) {
536         return false;
537     }
538 
539     // initialize uuid field, use name, vendor and uniqueId
540     // initialize uuid field using one of the following methods:
541     //
542     // 1. use uniqueId
543     // 2. use name, vendor and uniqueId
544     if (mFeatureInfo.useUniqueIdForUuid) {
545         if (mFeatureInfo.uniqueId.size() == sizeof(mFeatureInfo.uuid)) {
546             memcpy(mFeatureInfo.uuid, mFeatureInfo.uniqueId.c_str(),
547                    sizeof(mFeatureInfo.uuid));
548         }
549     } else if (mFeatureInfo.name.size() >= 4
550                    && mFeatureInfo.vendor.size() >= 4
551                    && mFeatureInfo.typeString.size() >= 4
552                    && mFeatureInfo.uniqueId.size() >= 4) {
553         uint32_t tmp[4], h;
554         std::hash<std::string> stringHash;
555         h = stringHash(mFeatureInfo.uniqueId);
556         tmp[0] = stringHash(mFeatureInfo.name) ^ h;
557         tmp[1] = stringHash(mFeatureInfo.vendor) ^ h;
558         tmp[2] = stringHash(mFeatureInfo.typeString) ^ h;
559         tmp[3] = tmp[0] ^ tmp[1] ^ tmp[2];
560         memcpy(mFeatureInfo.uuid, tmp, sizeof(mFeatureInfo.uuid));
561     }
562 
563     mSensor = (sensor_t) {
564         mFeatureInfo.name.c_str(),                 // name
565         mFeatureInfo.vendor.c_str(),               // vendor
566         mFeatureInfo.version,                      // version
567         -1,                                        // handle, dummy number here
568         mFeatureInfo.type,
569         mFeatureInfo.maxRange,                     // maxRange
570         mFeatureInfo.resolution,                   // resolution
571         mFeatureInfo.power,                        // power
572         mFeatureInfo.minDelay,                     // minDelay
573         (uint32_t)mFeatureInfo.fifoSize,           // fifoReservedEventCount
574         (uint32_t)mFeatureInfo.fifoMaxSize,        // fifoMaxEventCount
575         mFeatureInfo.typeString.c_str(),           // type string
576         mFeatureInfo.permission.c_str(),           // requiredPermission
577         (long)mFeatureInfo.maxDelay,               // maxDelay
578         mFeatureInfo.reportModeFlag | (mFeatureInfo.isWakeUp ? 1 : 0),
579         { NULL, NULL }
580     };
581     return true;
582 }
583 
decodeString(const HidParser::ReportItem & report,const std::vector<uint8_t> & buffer,std::string * d)584 bool HidRawSensor::decodeString(
585         const HidParser::ReportItem &report, const std::vector<uint8_t> &buffer, std::string *d) {
586     if (!report.isByteAligned() ||
587         (report.bitSize != 8 && report.bitSize != 16) || report.count < 1) {
588         return false;
589     }
590 
591     size_t charSize = report.bitSize / 8;
592     size_t offset = report.bitOffset / 8;
593     if (offset + report.count * charSize > buffer.size()) {
594         return false;
595     }
596 
597     if (charSize == 1) {
598         *d = std::string(buffer.begin() + offset,
599                          buffer.begin() + offset + report.count);
600     } else {
601         std::vector<uint16_t> data(report.count);
602         auto i = data.begin();
603         auto j = buffer.begin() + offset;
604         for ( ; i != data.end(); ++i, j += sizeof(uint16_t)) {
605             // hid specified little endian
606             *i = *j + (*(j + 1) << 8);
607         }
608         std::wstring wstr(data.begin(), data.end());
609 
610         std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
611         *d = converter.to_bytes(wstr);
612     }
613 
614     return true;
615 }
616 
split(const std::string & text,char sep)617 std::vector<std::string> split(const std::string &text, char sep) {
618     std::vector<std::string> tokens;
619     size_t start = 0, end = 0;
620     while ((end = text.find(sep, start)) != std::string::npos) {
621         if (end != start) {
622             tokens.push_back(text.substr(start, end - start));
623         }
624         start = end + 1;
625     }
626     if (end != start) {
627         tokens.push_back(text.substr(start));
628     }
629     return tokens;
630 }
631 
detectSensorFromDescription(const std::string & description)632 void HidRawSensor::detectSensorFromDescription(const std::string &description) {
633     if (detectAndroidHeadTrackerSensor(description) ||
634         detectAndroidCustomSensor(description)) {
635         mFeatureInfo.isAndroidCustom = true;
636     }
637 }
638 
detectAndroidHeadTrackerSensor(const std::string & description)639 bool HidRawSensor::detectAndroidHeadTrackerSensor(
640         const std::string &description) {
641     bool leAudioFlagEnabled = dynamic_sensors_flags::dynamic_sensors_le_audio();
642     LOG_I << "detectAndroidHeadTrackerSensor: " << description << LOG_ENDL;
643     if (!description.starts_with("#AndroidHeadTracker#1.")
644         && (!leAudioFlagEnabled || !description.starts_with("#AndroidHeadTracker#2."))) {
645         return false;
646     }
647 
648     // #AndroidHeadTracker#<major version>.<minor version>#<capability>
649     // We encode the major, minor, and capabilities in the following format:
650     // 0xMMmmcccc (Major, minor, capability bits)
651     if (leAudioFlagEnabled) {
652         uint32_t majorVersion = 0, minorVersion = 0, capability = 0;
653         mFeatureInfo.version = 0;
654         int ret = sscanf(description.c_str(), "#AndroidHeadTracker#%d.%d#%d",
655                         &majorVersion, &minorVersion, &capability);
656         if (ret > 0) {
657             mRequiresLeTransport = (majorVersion == kLeAudioCapabilitiesMajorVersion);
658             mFeatureInfo.version = (majorVersion & 0xFF) << 24;
659         }
660         if (ret > 1) {
661             mFeatureInfo.version |= (minorVersion & 0xFF) << 16;
662         }
663         if (ret > 2) {
664             mFeatureInfo.version |= (capability & 0xFFFF);
665         }
666     } else {
667         mFeatureInfo.version = 1;
668     }
669 
670     mFeatureInfo.type = SENSOR_TYPE_HEAD_TRACKER;
671     mFeatureInfo.typeString = SENSOR_STRING_TYPE_HEAD_TRACKER;
672     mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
673     mFeatureInfo.permission = "";
674     mFeatureInfo.isWakeUp = false;
675 
676     // HID head tracker sensors must use the HID unique ID for the sensor UUID
677     // to permit association between the sensor and audio device (see
678     // specification for HEAD_TRACKER in SensorType).
679     mFeatureInfo.useUniqueIdForUuid = true;
680 
681     return true;
682 }
683 
detectAndroidCustomSensor(const std::string & description)684 bool HidRawSensor::detectAndroidCustomSensor(const std::string &description) {
685     size_t nullPosition = description.find('\0');
686     if (nullPosition == std::string::npos) {
687         return false;
688     }
689     const std::string prefix("#ANDROID#");
690     if (description.find(prefix, nullPosition + 1) != nullPosition + 1) {
691         return false;
692     }
693 
694     std::string str(description.c_str() + nullPosition + 1 + prefix.size());
695 
696     // Format for predefined sensor types:
697     // #ANDROID#nn,[C|X|T|S],[B|0],[W|N]
698     // Format for vendor type sensor
699     // #ANDROID#xxx.yyy.zzz,[C|X|T|S],[B|0],[W|N]
700     //
701     // C: continuous
702     // X: on-change
703     // T: one-shot
704     // S: special trigger
705     //
706     // B: body permission
707     // 0: no permission required
708     std::vector<std::string> segments;
709     size_t start = 0, end = 0;
710     while ((end = str.find(',', start)) != std::string::npos) {
711         if (end != start) {
712             segments.push_back(str.substr(start, end - start));
713         }
714         start = end + 1;
715     }
716     if (end != start) {
717         segments.push_back(str.substr(start));
718     }
719 
720     if (segments.size() < 4) {
721         LOG_E << "Not enough segments in android custom description" << LOG_ENDL;
722         return false;
723     }
724 
725     // type
726     bool typeParsed = false;
727     if (!segments[0].empty()) {
728         if (::isdigit(segments[0][0])) {
729             int type = ::atoi(segments[0].c_str());
730             // all supported types here
731             switch (type) {
732                 case SENSOR_TYPE_HEART_RATE:
733                     mFeatureInfo.type = SENSOR_TYPE_HEART_RATE;
734                     mFeatureInfo.typeString = SENSOR_STRING_TYPE_HEART_RATE;
735                     typeParsed = true;
736                     break;
737                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
738                     mFeatureInfo.type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
739                     mFeatureInfo.typeString = SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE;
740                     typeParsed = true;
741                     break;
742                 case SENSOR_TYPE_LIGHT:
743                     mFeatureInfo.type = SENSOR_TYPE_LIGHT;
744                     mFeatureInfo.typeString = SENSOR_STRING_TYPE_LIGHT;
745                     typeParsed = true;
746                     break;
747                 case SENSOR_TYPE_PRESSURE:
748                     mFeatureInfo.type = SENSOR_TYPE_PRESSURE;
749                     mFeatureInfo.typeString = SENSOR_STRING_TYPE_PRESSURE;
750                     typeParsed = true;
751                     break;
752                 default:
753                     LOG_W << "Android type " << type << " has not been supported yet" << LOG_ENDL;
754                     break;
755             }
756         } else {
757             // assume a xxx.yyy.zzz format
758             std::ostringstream s;
759             bool lastIsDot = true;
760             for (auto c : segments[0]) {
761                 if (::isalpha(c)) {
762                     s << static_cast<char>(c);
763                     lastIsDot = false;
764                 } else if (!lastIsDot && c == '.') {
765                     s << static_cast<char>(c);
766                     lastIsDot = true;
767                 } else {
768                     break;
769                 }
770             }
771             if (s.str() == segments[0]) {
772                 mFeatureInfo.type = SENSOR_TYPE_DEVICE_PRIVATE_BASE;
773                 mFeatureInfo.typeString = CUSTOM_TYPE_PREFIX + s.str();
774                 typeParsed = true;
775             }
776         }
777     }
778 
779     // reporting type
780     bool reportingModeParsed = false;
781     if (segments[1].size() == 1) {
782         switch (segments[1][0]) {
783             case 'C':
784                 mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
785                 reportingModeParsed = true;
786                 break;
787             case 'X':
788                 mFeatureInfo.reportModeFlag = SENSOR_FLAG_ON_CHANGE_MODE;
789                 reportingModeParsed = true;
790                 break;
791             case 'T':
792                 mFeatureInfo.reportModeFlag = SENSOR_FLAG_ONE_SHOT_MODE;
793                 reportingModeParsed = true;
794                 break;
795             case 'S':
796                 mFeatureInfo.reportModeFlag = SENSOR_FLAG_SPECIAL_REPORTING_MODE;
797                 reportingModeParsed = true;
798                 break;
799             default:
800                 LOG_E << "Undefined reporting mode designation " << segments[1] << LOG_ENDL;
801         }
802     }
803 
804     // permission parsed
805     bool permissionParsed = false;
806     if (segments[2].size() == 1) {
807         switch (segments[2][0]) {
808             case 'B':
809                 mFeatureInfo.permission = SENSOR_PERMISSION_BODY_SENSORS;
810                 permissionParsed = true;
811                 break;
812             case '0':
813                 mFeatureInfo.permission = "";
814                 permissionParsed = true;
815                 break;
816             default:
817                 LOG_E << "Undefined permission designation " << segments[2] << LOG_ENDL;
818         }
819     }
820 
821     // wake up
822     bool wakeUpParsed = false;
823     if (segments[3].size() == 1) {
824         switch (segments[3][0]) {
825             case 'W':
826                 mFeatureInfo.isWakeUp = true;
827                 wakeUpParsed = true;
828                 break;
829             case 'N':
830                 mFeatureInfo.isWakeUp = false;
831                 wakeUpParsed = true;
832                 break;
833             default:
834                 LOG_E << "Undefined wake up designation " << segments[3] << LOG_ENDL;
835         }
836     }
837 
838     int ret = typeParsed && reportingModeParsed && permissionParsed && wakeUpParsed;
839     if (!ret) {
840         LOG_D << "detectAndroidCustomSensor typeParsed: " << typeParsed
841               << " reportingModeParsed: "  << reportingModeParsed
842               << " permissionParsed: " << permissionParsed
843               << " wakeUpParsed: " << wakeUpParsed << LOG_ENDL;
844     }
845     return ret;
846 }
847 
findSensorControlUsage(const std::vector<HidParser::ReportPacket> & packets)848 bool HidRawSensor::findSensorControlUsage(const std::vector<HidParser::ReportPacket> &packets) {
849     using namespace Hid::Sensor::PowerStateUsage;
850     using namespace Hid::Sensor::PropertyUsage;
851     using namespace Hid::Sensor::ReportingStateUsage;
852     using namespace Hid::Sensor::LeTransportUsage;
853 
854     //REPORTING_STATE
855     const HidParser::ReportItem *reportingState
856             = find(packets, REPORTING_STATE, HidParser::REPORT_TYPE_FEATURE);
857 
858     if (reportingState == nullptr) {
859         LOG_W << "Cannot find valid reporting state feature" << LOG_ENDL;
860     } else {
861         mReportingStateId = reportingState->id;
862         mReportingStateBitOffset = reportingState->bitOffset;
863         mReportingStateBitSize = reportingState->bitSize;
864 
865         mReportingStateDisableIndex = -1;
866         mReportingStateEnableIndex = -1;
867         for (unsigned i = 0; i < reportingState->usageVector.size(); ++i) {
868             if (reportingState->usageVector[i] == REPORTING_STATE_NO_EVENTS) {
869                 mReportingStateDisableIndex = i;
870             }
871             if (reportingState->usageVector[i] == REPORTING_STATE_ALL_EVENTS) {
872                 mReportingStateEnableIndex = i;
873             }
874         }
875         if (mReportingStateDisableIndex < 0) {
876             LOG_W << "Cannot find reporting state to disable sensor"
877                   << LOG_ENDL;
878             mReportingStateId = -1;
879         }
880         if (mReportingStateEnableIndex < 0) {
881             LOG_W << "Cannot find reporting state to enable sensor" << LOG_ENDL;
882             mReportingStateId = -1;
883         }
884     }
885 
886     //POWER_STATE
887     const HidParser::ReportItem *powerState
888             = find(packets, POWER_STATE, HidParser::REPORT_TYPE_FEATURE);
889     if (powerState == nullptr) {
890         LOG_W << "Cannot find valid power state feature" << LOG_ENDL;
891     } else {
892         mPowerStateId = powerState->id;
893         mPowerStateBitOffset = powerState->bitOffset;
894         mPowerStateBitSize = powerState->bitSize;
895 
896         mPowerStateOffIndex = -1;
897         mPowerStateOnIndex = -1;
898         for (unsigned i = 0; i < powerState->usageVector.size(); ++i) {
899             if (powerState->usageVector[i] == POWER_STATE_D4_POWER_OFF) {
900                 mPowerStateOffIndex = i;
901             }
902             if (powerState->usageVector[i] == POWER_STATE_D0_FULL_POWER) {
903                 mPowerStateOnIndex = i;
904             }
905         }
906         if (mPowerStateOffIndex < 0) {
907             LOG_W << "Cannot find power state to power off sensor"
908                   << LOG_ENDL;
909             mPowerStateId = -1;
910         }
911         if (mPowerStateOnIndex < 0) {
912             LOG_W << "Cannot find power state to power on sensor" << LOG_ENDL;
913             mPowerStateId = -1;
914         }
915     }
916 
917     //REPORT_INTERVAL
918     const HidParser::ReportItem *reportInterval
919             = find(packets, REPORT_INTERVAL, HidParser::REPORT_TYPE_FEATURE);
920     if (reportInterval == nullptr
921             || reportInterval->minRaw < 0) {
922         LOG_W << "Cannot find valid report interval feature" << LOG_ENDL;
923     } else {
924         mReportIntervalId = reportInterval->id;
925         mReportIntervalBitOffset = reportInterval->bitOffset;
926         mReportIntervalBitSize = reportInterval->bitSize;
927         mReportIntervalScale = reportInterval->a;
928         mReportIntervalOffset = reportInterval->b;
929 
930         mFeatureInfo.minDelay = 1000000.0
931                                 * (reportInterval->minRaw + reportInterval->b)
932                                 * reportInterval->a;
933         mFeatureInfo.minDelay = std::max(1000, mFeatureInfo.minDelay);
934         mFeatureInfo.maxDelay = 1000000.0
935                                 * (reportInterval->maxRaw + reportInterval->b)
936                                 * reportInterval->a;
937         mFeatureInfo.maxDelay = std::min(static_cast<int64_t>(1000000000),
938                                          mFeatureInfo.maxDelay);
939     }
940 
941     bool leTransportExpected = mRequiresLeTransport;
942     if (leTransportExpected) {
943         //VENDOR_LE_TRANSPORT
944         const HidParser::ReportItem *leTransport
945                 = find(packets, VENDOR_LE_TRANSPORT, HidParser::REPORT_TYPE_FEATURE);
946         if (leTransport == nullptr) {
947             LOG_W << "Cannot find valid LE transport feature" << LOG_ENDL;
948         } else {
949             mLeTransportId = leTransport->id;
950             mLeTransportBitOffset = leTransport->bitOffset;
951             mLeTransportBitSize = leTransport->bitSize;
952 
953             mLeTransportAclIndex = -1;
954             mLeTransportIsoIndex = -1;
955             for (unsigned i = 0; i < leTransport->usageVector.size(); ++i) {
956                 if (leTransport->usageVector[i] == LE_TRANSPORT_ACL) {
957                     mLeTransportAclIndex = i;
958                 }
959                 if (leTransport->usageVector[i] == LE_TRANSPORT_ISO) {
960                     mLeTransportIsoIndex = i;
961                 }
962             }
963             if (mLeTransportAclIndex < 0) {
964                 LOG_W << "Cannot find LE transport to enable ACL"
965                         << LOG_ENDL;
966                 mLeTransportId = -1;
967             }
968             if (mLeTransportIsoIndex < 0) {
969                 LOG_W << "Cannot find LE transport to enable ISO" << LOG_ENDL;
970                 mLeTransportId = -1;
971             }
972         }
973     }
974 
975     return (mPowerStateId >= 0 || mReportingStateId >= 0) && mReportIntervalId >= 0 &&
976            (!leTransportExpected || mLeTransportId >= 0);
977 }
978 
getSensor() const979 const sensor_t* HidRawSensor::getSensor() const {
980     return &mSensor;
981 }
982 
getUuid(uint8_t * uuid) const983 void HidRawSensor::getUuid(uint8_t* uuid) const {
984     memcpy(uuid, mFeatureInfo.uuid, sizeof(mFeatureInfo.uuid));
985 }
986 
enable(bool enable)987 int HidRawSensor::enable(bool enable) {
988     SP(HidDevice) device = PROMOTE(mDevice);
989 
990     if (device == nullptr) {
991         LOG_E << "enable: no device" << LOG_ENDL;
992         return NO_INIT;
993     }
994 
995     if (enable == mEnabled) {
996         LOG_D << "enable: already in desired state" << LOG_ENDL;
997         return NO_ERROR;
998     }
999 
1000     bool setLeAudioTransportOk = setLeAudioTransport(device, enable);
1001     bool setPowerOk = setPower(device, enable);
1002     bool setReportingOk = setReportingState(device, enable);
1003     if (setPowerOk && setReportingOk && setLeAudioTransportOk) {
1004         mEnabled = enable;
1005         LOG_I << "enable: success" << LOG_ENDL;
1006         return NO_ERROR;
1007     } else {
1008         LOG_E << "enable: set feature failed" << LOG_ENDL;
1009         return INVALID_OPERATION;
1010     }
1011 }
1012 
setLeAudioTransport(const SP (HidDevice)& device,bool enable)1013 bool HidRawSensor::setLeAudioTransport(const SP(HidDevice) &device, bool enable) {
1014     std::vector<uint8_t> buffer;
1015     bool success = true;
1016     if (mLeTransportId >= 0 && enable) {
1017         success = false;
1018         uint8_t id = static_cast<uint8_t>(mLeTransportId);
1019         if (device->getFeature(id, &buffer)
1020                 && (8 * buffer.size()) >=
1021                         (mLeTransportBitOffset + mLeTransportBitSize)) {
1022             // The following property, if defined, represents a comma-separated list of
1023             // transport preferences for the following types: le-acl or iso-[sw|hw],
1024             // which describes the priority list of transport selections used based on the
1025             // capabilities reported by the HID device.
1026             std::string prop = GetProperty("bluetooth.core.le.dsa_transport_preference", "");
1027             std::istringstream tokenStream(prop);
1028             std::string line;
1029             std::vector<std::string> priorityList;
1030             while (std::getline(tokenStream, line, ',')) {
1031                 priorityList.push_back(line);
1032             }
1033 
1034             uint16_t capability = mFeatureInfo.version & 0x0000FFFF;
1035             uint8_t index;
1036             if (capability == (kIsoBitMask | kAclBitMask)) {
1037                 if (!priorityList.empty() && priorityList[0].compare("le-acl") == 0) {
1038                     index = mLeTransportAclIndex;
1039                 } else {
1040                     index = mLeTransportIsoIndex;
1041                 }
1042             } else {
1043                 index = (capability & kIsoBitMask) ? mLeTransportIsoIndex : mLeTransportAclIndex;
1044             }
1045 
1046             HidUtil::copyBits(&index, &(buffer[0]), buffer.size(), 0,
1047                               mLeTransportBitOffset, mLeTransportBitSize);
1048             success = device->setFeature(id, buffer);
1049             if (!success) {
1050               LOG_E << "enable: setFeature VENDOR LE TRANSPORT failed" << LOG_ENDL;
1051             }
1052         } else {
1053             LOG_E << "enable: changing VENDOR LE TRANSPORT failed" << LOG_ENDL;
1054         }
1055     }
1056     return success;
1057 }
1058 
setPower(const SP (HidDevice)& device,bool enable)1059 bool HidRawSensor::setPower(const SP(HidDevice) &device, bool enable) {
1060     std::vector<uint8_t> buffer;
1061     bool success = true;
1062     if (mPowerStateId >= 0) {
1063         success = false;
1064         uint8_t id = static_cast<uint8_t>(mPowerStateId);
1065         if (device->getFeature(id, &buffer)
1066                 && (8 * buffer.size()) >=
1067                    (mPowerStateBitOffset + mPowerStateBitSize)) {
1068             uint8_t index = enable ? mPowerStateOnIndex : mPowerStateOffIndex;
1069             HidUtil::copyBits(&index, &(buffer[0]), buffer.size(),
1070                               0, mPowerStateBitOffset, mPowerStateBitSize);
1071             success = device->setFeature(id, buffer);
1072             if (!success) {
1073               LOG_E << "enable: setFeature POWER STATE failed" << LOG_ENDL;
1074             }
1075         } else {
1076             LOG_E << "enable: changing POWER STATE failed" << LOG_ENDL;
1077         }
1078     }
1079     return success;
1080 }
1081 
setReportingState(const SP (HidDevice)& device,bool enable)1082 bool HidRawSensor::setReportingState(const SP(HidDevice) &device, bool enable) {
1083     std::vector<uint8_t> buffer;
1084     bool success = true;
1085     if (mReportingStateId >= 0) {
1086         success = false;
1087         uint8_t id = static_cast<uint8_t>(mReportingStateId);
1088         if (device->getFeature(id, &buffer)
1089                 && (8 * buffer.size()) >
1090                    (mReportingStateBitOffset + mReportingStateBitSize)) {
1091             uint8_t index = enable ? mReportingStateEnableIndex :
1092                                      mReportingStateDisableIndex;
1093             HidUtil::copyBits(&index, &(buffer[0]), buffer.size(),0,
1094                               mReportingStateBitOffset, mReportingStateBitSize);
1095             success = device->setFeature(id, buffer);
1096             if (!success) {
1097               LOG_E << "enable: setFeature REPORTING STATE failed" << LOG_ENDL;
1098             }
1099         } else {
1100             LOG_E << "enable: changing REPORTING STATE failed" << LOG_ENDL;
1101         }
1102     }
1103     return success;
1104 }
1105 
batch(int64_t samplingPeriod,int64_t batchingPeriod)1106 int HidRawSensor::batch(int64_t samplingPeriod, int64_t batchingPeriod) {
1107     SP(HidDevice) device = PROMOTE(mDevice);
1108     if (device == nullptr) {
1109         return NO_INIT;
1110     }
1111 
1112     if (samplingPeriod < 0 || batchingPeriod < 0) {
1113         return BAD_VALUE;
1114     }
1115 
1116     bool needRefresh = mSamplingPeriod != samplingPeriod || mBatchingPeriod != batchingPeriod;
1117     std::vector<uint8_t> buffer;
1118 
1119     bool ok = true;
1120     if (needRefresh && mReportIntervalId >= 0) {
1121         ok = false;
1122         uint8_t id = static_cast<uint8_t>(mReportIntervalId);
1123         if (device->getFeature(id, &buffer)
1124                 && (8 * buffer.size()) >=
1125                    (mReportIntervalBitOffset + mReportIntervalBitSize)) {
1126             int64_t periodMs =
1127                     (((static_cast<double>(samplingPeriod)) / 1000000000.0)
1128                      / mReportIntervalScale) - mReportIntervalOffset;
1129             int64_t maxPeriodMs =
1130                 (1LL << std::min(mReportIntervalBitSize, 63U)) - 1;
1131             periodMs = std::min(periodMs, maxPeriodMs);
1132             HidUtil::copyBits(&periodMs, &(buffer[0]), buffer.size(),
1133                               0, mReportIntervalBitOffset,
1134                               mReportIntervalBitSize);
1135             ok = device->setFeature(id, buffer);
1136         }
1137     }
1138 
1139     if (ok) {
1140         mSamplingPeriod = samplingPeriod;
1141         mBatchingPeriod = batchingPeriod;
1142         return NO_ERROR;
1143     } else {
1144         return INVALID_OPERATION;
1145     }
1146 }
1147 
handleInput(uint8_t id,const std::vector<uint8_t> & message)1148 void HidRawSensor::handleInput(uint8_t id, const std::vector<uint8_t> &message) {
1149     if (id != mInputReportId || mEnabled == false) {
1150         return;
1151     }
1152     sensors_event_t event = {
1153         .version = sizeof(event),
1154         .sensor = -1,
1155         .type = mSensor.type
1156     };
1157     bool valid = true;
1158 
1159     switch (mFeatureInfo.type) {
1160         case SENSOR_TYPE_HEAD_TRACKER:
1161             valid = getHeadTrackerEventData(message, &event);
1162             break;
1163         default:
1164             valid = getSensorEventData(message, &event);
1165             break;
1166     }
1167     if (!valid) {
1168         LOG_E << "Invalid data observed in decoding, discard" << LOG_ENDL;
1169         return;
1170     }
1171     event.timestamp = -1;
1172     generateEvent(event);
1173 }
1174 
getHeadTrackerEventData(const std::vector<uint8_t> & message,sensors_event_t * event)1175 bool HidRawSensor::getHeadTrackerEventData(const std::vector<uint8_t> &message,
1176                                            sensors_event_t *event) {
1177     head_tracker_event_t *head_tracker;
1178 
1179     head_tracker = &(event->head_tracker);
1180     if (!getReportFieldValue(message, &(mTranslateTable[0]),
1181                              &(head_tracker->rx))
1182             || !getReportFieldValue(message, &(mTranslateTable[1]),
1183                                     &(head_tracker->ry))
1184             || !getReportFieldValue(message, &(mTranslateTable[2]),
1185                                     &(head_tracker->rz))
1186             || !getReportFieldValue(message, &(mTranslateTable[3]),
1187                                     &(head_tracker->vx))
1188             || !getReportFieldValue(message, &(mTranslateTable[4]),
1189                                     &(head_tracker->vy))
1190             || !getReportFieldValue(message, &(mTranslateTable[5]),
1191                                     &(head_tracker->vz))
1192             || !getReportFieldValue(message, &(mTranslateTable[6]),
1193                                     &(head_tracker->discontinuity_count))) {
1194         return false;
1195     }
1196 
1197     return true;
1198 }
1199 
getSensorEventData(const std::vector<uint8_t> & message,sensors_event_t * event)1200 bool HidRawSensor::getSensorEventData(const std::vector<uint8_t> &message,
1201                                       sensors_event_t *event) {
1202     for (const auto &rec : mTranslateTable) {
1203         int64_t v = 0;
1204         if (rec.minValue < 0) {
1205             v = (message[rec.byteOffset + rec.byteSize - 1] & 0x80) ? -1 : 0;
1206         }
1207         for (int i = static_cast<int>(rec.byteSize) - 1; i >= 0; --i) {
1208             v = (v << 8) | message[rec.byteOffset + i]; // HID is little endian
1209         }
1210 
1211         switch (rec.type) {
1212             case TYPE_FLOAT:
1213                 if (v > rec.maxValue || v < rec.minValue) {
1214                     return false;
1215                 }
1216                 event->data[rec.index] = rec.a * (v + rec.b);
1217                 break;
1218             case TYPE_INT64:
1219                 if (v > rec.maxValue || v < rec.minValue) {
1220                     return false;
1221                 }
1222                 event->u64.data[rec.index] = v + rec.b;
1223                 break;
1224             case TYPE_ACCURACY:
1225                 event->magnetic.status = (v & 0xFF) + rec.b;
1226                 break;
1227         }
1228     }
1229 
1230     return true;
1231 }
1232 
dump() const1233 std::string HidRawSensor::dump() const {
1234     std::ostringstream ss;
1235     ss << "Feature Values " << LOG_ENDL
1236           << "  name: " << mFeatureInfo.name << LOG_ENDL
1237           << "  version: 0x" << std::setfill('0') << std::setw(8) << std::hex << mFeatureInfo.version << LOG_ENDL
1238           << "  vendor: " << mFeatureInfo.vendor << LOG_ENDL
1239           << "  permission: " << mFeatureInfo.permission << LOG_ENDL
1240           << "  typeString: " << mFeatureInfo.typeString << LOG_ENDL
1241           << "  type: " << mFeatureInfo.type << LOG_ENDL
1242           << "  maxRange: " << mFeatureInfo.maxRange << LOG_ENDL
1243           << "  resolution: " << mFeatureInfo.resolution << LOG_ENDL
1244           << "  power: " << mFeatureInfo.power << LOG_ENDL
1245           << "  minDelay: " << mFeatureInfo.minDelay << LOG_ENDL
1246           << "  maxDelay: " << mFeatureInfo.maxDelay << LOG_ENDL
1247           << "  fifoSize: " << mFeatureInfo.fifoSize << LOG_ENDL
1248           << "  fifoMaxSize: " << mFeatureInfo.fifoMaxSize << LOG_ENDL
1249           << "  reportModeFlag: " << mFeatureInfo.reportModeFlag << LOG_ENDL
1250           << "  isWakeUp: " << (mFeatureInfo.isWakeUp ? "true" : "false") << LOG_ENDL;
1251 
1252     ss << "  uniqueId: " << std::hex << std::setfill('0');
1253     for (auto d : mFeatureInfo.uniqueId) {
1254           ss << std::setw(2) << static_cast<int>(d) << " ";
1255     }
1256     ss << std::dec << std::setfill(' ') << LOG_ENDL;
1257 
1258     ss << "  uuid: " << std::hex << std::setfill('0');
1259     for (auto d : mFeatureInfo.uuid) {
1260           ss << std::setw(2) << static_cast<int>(d) << " ";
1261     }
1262     ss << std::dec << std::setfill(' ') << LOG_ENDL;
1263 
1264     ss << "Input report id: " << mInputReportId << LOG_ENDL;
1265     for (const auto &t : mTranslateTable) {
1266         ss << "  type, index: " << t.type << ", " << t.index
1267               << "; min,max: " << t.minValue << ", " << t.maxValue
1268               << "; byte-offset,size: " << t.byteOffset << ", " << t.byteSize
1269               << "; scaling,bias: " << t.a << ", " << t.b << LOG_ENDL;
1270     }
1271 
1272     ss << "Control features: " << LOG_ENDL;
1273     ss << "  Power state ";
1274     if (mPowerStateId >= 0) {
1275         ss << "found, id: " << mPowerStateId
1276               << " bit offset: " << mPowerStateBitOffset
1277               << " bit size: " << mPowerStateBitSize
1278               << " power off index: " << mPowerStateOffIndex
1279               << " power on index: " << mPowerStateOnIndex
1280               << LOG_ENDL;
1281     } else {
1282         ss << "not found" << LOG_ENDL;
1283     }
1284 
1285     ss << "  Reporting state ";
1286     if (mReportingStateId >= 0) {
1287         ss << "found, id: " << mReportingStateId
1288               << " bit offset: " << mReportingStateBitOffset
1289               << " bit size: " << mReportingStateBitSize
1290               << " disable index: " << mReportingStateDisableIndex
1291               << " enable index: " << mReportingStateEnableIndex
1292               << LOG_ENDL;
1293     } else {
1294         ss << "not found" << LOG_ENDL;
1295     }
1296 
1297     ss << "  Report interval ";
1298     if (mReportIntervalId >= 0) {
1299         ss << "found, id: " << mReportIntervalId
1300               << " bit offset: " << mReportIntervalBitOffset
1301               << " bit size: " << mReportIntervalBitSize << LOG_ENDL;
1302     } else {
1303         ss << "not found" << LOG_ENDL;
1304     }
1305     return ss.str();
1306 }
1307 
1308 } // namespace SensorHalExt
1309 } // namespace android
1310