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 <utils/Errors.h>
20 #include "HidLog.h"
21 
22 #include <algorithm>
23 #include <cfloat>
24 #include <codecvt>
25 #include <iomanip>
26 #include <sstream>
27 
28 namespace android {
29 namespace SensorHalExt {
30 
31 namespace {
32 const std::string CUSTOM_TYPE_PREFIX("com.google.hardware.sensor.hid_dynamic.");
33 }
34 
HidRawSensor(SP (HidDevice)device,uint32_t usage,const std::vector<HidParser::ReportPacket> & packets)35 HidRawSensor::HidRawSensor(
36         SP(HidDevice) device, uint32_t usage, const std::vector<HidParser::ReportPacket> &packets)
37         : mReportingStateId(-1), mPowerStateId(-1), mReportIntervalId(-1), mInputReportId(-1),
38         mEnabled(false), mSamplingPeriod(1000LL*1000*1000), mBatchingPeriod(0),
39         mDevice(device), mValid(false) {
40     if (device == nullptr) {
41         return;
42     }
43     memset(&mSensor, 0, sizeof(mSensor));
44 
45     const HidDevice::HidDeviceInfo &info =  device->getDeviceInfo();
46     initFeatureValueFromHidDeviceInfo(&mFeatureInfo, info);
47 
48     if (!populateFeatureValueFromFeatureReport(&mFeatureInfo, packets)) {
49         LOG_E << "populate feature from feature report failed" << LOG_ENDL;
50         return;
51     }
52 
53     if (!findSensorControlUsage(packets)) {
54         LOG_E << "finding sensor control usage failed" << LOG_ENDL;
55         return;
56     }
57 
58     // build translation table
59     bool translationTableValid = false;
60     switch (usage) {
61         using namespace Hid::Sensor::SensorTypeUsage;
62         using namespace Hid::Sensor::ReportUsage;
63         case ACCELEROMETER_3D:
64             // Hid unit default g
65             // Android unit m/s^2
66             // 1g = 9.81 m/s^2
67             mFeatureInfo.typeString = SENSOR_STRING_TYPE_ACCELEROMETER;
68             mFeatureInfo.type = SENSOR_TYPE_ACCELEROMETER;
69             mFeatureInfo.isWakeUp = false;
70 
71             translationTableValid = processTriAxisUsage(packets,
72                                          ACCELERATION_X_AXIS,
73                                          ACCELERATION_Y_AXIS,
74                                          ACCELERATION_Z_AXIS, 9.81);
75             break;
76         case GYROMETER_3D:
77             // Hid unit default degree/s
78             // Android unit rad/s
79             // 1 degree/s = pi/180 rad/s
80             mFeatureInfo.typeString = SENSOR_STRING_TYPE_GYROSCOPE;
81             mFeatureInfo.type = SENSOR_TYPE_GYROSCOPE;
82             mFeatureInfo.isWakeUp = false;
83 
84             translationTableValid = processTriAxisUsage(packets,
85                                          ANGULAR_VELOCITY_X_AXIS,
86                                          ANGULAR_VELOCITY_Y_AXIS,
87                                          ANGULAR_VELOCITY_Z_AXIS, M_PI/180);
88             break;
89         case COMPASS_3D: {
90             // Hid unit default mGauss
91             // Android unit uT
92             // 1uT  = 0.1 nGauss
93             mFeatureInfo.typeString = SENSOR_STRING_TYPE_MAGNETIC_FIELD;
94             mFeatureInfo.type = SENSOR_TYPE_MAGNETIC_FIELD;
95 
96             if (!processTriAxisUsage(packets,
97                                      MAGNETIC_FLUX_X_AXIS,
98                                      MAGNETIC_FLUX_Y_AXIS,
99                                      MAGNETIC_FLUX_Z_AXIS, 0.1)) {
100                 break;
101             }
102             const HidParser::ReportItem *pReportAccuracy = find(packets,
103                                                                   MAGNETOMETER_ACCURACY,
104                                                                   HidParser::REPORT_TYPE_INPUT,
105                                                                   mInputReportId);
106 
107             if (pReportAccuracy == nullptr) {
108                 LOG_E << "Cannot find accuracy field in usage "
109                       << std::hex << usage << std::dec << LOG_ENDL;
110                 break;
111             }
112             if (!pReportAccuracy->isByteAligned()) {
113                 LOG_E << "Accuracy field must align to byte" << LOG_ENDL;
114                 break;
115             }
116             if (pReportAccuracy->minRaw != 0 || pReportAccuracy->maxRaw != 2) {
117                 LOG_E << "Accuracy field value range must be [0, 2]" << LOG_ENDL;
118                 break;
119             }
120             ReportTranslateRecord accuracyRecord = {
121                 .type = TYPE_ACCURACY,
122                 .maxValue = 2,
123                 .minValue = 0,
124                 .byteOffset = pReportAccuracy->bitOffset / 8,
125                 .byteSize = pReportAccuracy->bitSize / 8,
126                 .a = 1,
127                 .b = 1};
128             mTranslateTable.push_back(accuracyRecord);
129             translationTableValid = true;
130             break;
131         }
132         case DEVICE_ORIENTATION:
133             translationTableValid = processQuaternionUsage(packets);
134             break;
135         case CUSTOM: {
136             if (!mFeatureInfo.isAndroidCustom) {
137                 LOG_E << "Invalid android custom sensor" << LOG_ENDL;
138                 break;
139             }
140             const HidParser::ReportPacket *pPacket = nullptr;
141             const uint32_t usages[] = {
142                 CUSTOM_VALUE_1, CUSTOM_VALUE_2, CUSTOM_VALUE_3,
143                 CUSTOM_VALUE_4, CUSTOM_VALUE_5, CUSTOM_VALUE_6
144             };
145             for (const auto &packet : packets) {
146                 if (packet.type == HidParser::REPORT_TYPE_INPUT && std::any_of(
147                         packet.reports.begin(), packet.reports.end(),
148                         [&usages] (const HidParser::ReportItem &d) {
149                                return std::find(std::begin(usages), std::end(usages), d.usage)
150                                        != std::end(usages);
151                         })) {
152                     pPacket = &packet;
153                     break;
154                 }
155             }
156 
157             if (pPacket == nullptr) {
158                 LOG_E << "Cannot find CUSTOM_VALUE_X in custom sensor" << LOG_ENDL;
159                 break;
160             }
161 
162             double range = 0;
163             double resolution = 1;
164 
165             for (const auto &digest : pPacket->reports) {
166                 if (digest.minRaw >= digest.maxRaw) {
167                     LOG_E << "Custome usage " << digest.usage << ", min must < max" << LOG_ENDL;
168                     return;
169                 }
170 
171                 if (!digest.isByteAligned()
172                         || (digest.bitSize != 8 && digest.bitSize != 16 && digest.bitSize != 32)) {
173                     LOG_E << "Custome usage " << std::hex << digest.usage << std::hex
174                           << ", each input must be 8/16/32 bits and must align to byte boundary"
175                           << LOG_ENDL;
176                     return;
177                 }
178 
179                 ReportTranslateRecord record = {
180                     .type = TYPE_FLOAT,
181                     .maxValue = digest.maxRaw,
182                     .minValue = digest.minRaw,
183                     .byteOffset = digest.bitOffset / 8,
184                     .byteSize = digest.bitSize / 8,
185                     .a = digest.a,
186                     .b = digest.b,
187                 };
188                 // keep track of range and resolution
189                 range = std::max(std::max(std::abs((digest.maxRaw + digest.b) * digest.a),
190                                           std::abs((digest.minRaw + digest.b) * digest.a)),
191                                  range);
192                 resolution = std::min(digest.a, resolution);
193 
194                 for (size_t i = 0; i < digest.count; ++i) {
195                     if (mTranslateTable.size() == 16) {
196                         LOG_I << "Custom usage has more than 16 inputs, ignore the rest" << LOG_ENDL;
197                         break;
198                     }
199                     record.index = mTranslateTable.size();
200                     mTranslateTable.push_back(record);
201                     record.byteOffset += digest.bitSize / 8;
202                 }
203                 if (mTranslateTable.size() == 16) {
204                     break;
205                 }
206             }
207             mFeatureInfo.maxRange = range;
208             mFeatureInfo.resolution = resolution;
209             mInputReportId = pPacket->id;
210             translationTableValid = !mTranslateTable.empty();
211             break;
212         }
213         default:
214             LOG_I << "unsupported sensor usage " << usage << LOG_ENDL;
215     }
216 
217     bool sensorValid = validateFeatureValueAndBuildSensor();
218     mValid = translationTableValid && sensorValid;
219     LOG_V << "HidRawSensor init, translationTableValid: " << translationTableValid
220           << ", sensorValid: " << sensorValid << LOG_ENDL;
221 }
222 
processQuaternionUsage(const std::vector<HidParser::ReportPacket> & packets)223 bool HidRawSensor::processQuaternionUsage(const std::vector<HidParser::ReportPacket> &packets) {
224     const HidParser::ReportItem *pReportQuaternion
225             = find(packets,
226                    Hid::Sensor::ReportUsage::ORIENTATION_QUATERNION,
227                    HidParser::REPORT_TYPE_INPUT);
228 
229     if (pReportQuaternion == nullptr) {
230         return false;
231     }
232 
233     const HidParser::ReportItem &quat = *pReportQuaternion;
234     if ((quat.bitSize != 16 && quat.bitSize != 32) || !quat.isByteAligned()) {
235         LOG_E << "Quaternion usage input must be 16 or 32 bits and aligned at byte boundary" << LOG_ENDL;
236         return false;
237     }
238 
239     double min, max;
240     quat.decode(quat.mask(quat.minRaw), &min);
241     quat.decode(quat.mask(quat.maxRaw), &max);
242     if (quat.count != 4 || min > -1 || max < 1) {
243         LOG_E << "Quaternion usage need 4 inputs with range [-1, 1]" << LOG_ENDL;
244         return false;
245     }
246 
247     if (quat.minRaw > quat.maxRaw) {
248         LOG_E << "Quaternion usage min must <= max" << LOG_ENDL;
249         return false;
250     }
251 
252     ReportTranslateRecord record = {
253         .type = TYPE_FLOAT,
254         .maxValue = quat.maxRaw,
255         .minValue = quat.minRaw,
256         .byteOffset = quat.bitOffset / 8,
257         .byteSize = quat.bitSize / 8,
258         .b = quat.b,
259     };
260 
261     // Android X Y Z maps to HID X -Z Y
262     // Android order xyzw, HID order wxyz
263     // X
264     record.index = 0;
265     record.a = quat.a;
266     record.byteOffset = (quat.bitOffset + quat.bitSize) / 8;
267     mTranslateTable.push_back(record);
268     // Y
269     record.index = 1;
270     record.a = -quat.a;
271     record.byteOffset = (quat.bitOffset + 3 * quat.bitSize) / 8;
272     mTranslateTable.push_back(record);
273     // Z
274     record.index = 2;
275     record.a = quat.a;
276     record.byteOffset = (quat.bitOffset + 2 * quat.bitSize) / 8;
277     mTranslateTable.push_back(record);
278     // W
279     record.index = 3;
280     record.a = quat.a;
281     record.byteOffset = quat.bitOffset / 8;
282     mTranslateTable.push_back(record);
283 
284     mFeatureInfo.typeString = SENSOR_STRING_TYPE_ROTATION_VECTOR;
285     mFeatureInfo.type = SENSOR_TYPE_ROTATION_VECTOR;
286     mFeatureInfo.maxRange = 1;
287     mFeatureInfo.resolution = quat.a;
288     mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
289 
290     mInputReportId = quat.id;
291 
292     return true;
293 }
294 
processTriAxisUsage(const std::vector<HidParser::ReportPacket> & packets,uint32_t usageX,uint32_t usageY,uint32_t usageZ,double defaultScaling)295 bool HidRawSensor::processTriAxisUsage(const std::vector<HidParser::ReportPacket> &packets,
296         uint32_t usageX, uint32_t usageY, uint32_t usageZ, double defaultScaling) {
297     const HidParser::ReportItem *pReportX = find(packets, usageX, HidParser::REPORT_TYPE_INPUT);
298     const HidParser::ReportItem *pReportY = find(packets, usageY, HidParser::REPORT_TYPE_INPUT);
299     const HidParser::ReportItem *pReportZ = find(packets, usageZ, HidParser::REPORT_TYPE_INPUT);
300 
301     if (pReportX == nullptr || pReportY == nullptr|| pReportZ == nullptr) {
302         LOG_E << "Three axis sensor does not find all 3 axis" << LOG_ENDL;
303         return false;
304     }
305 
306     const HidParser::ReportItem &reportX = *pReportX;
307     const HidParser::ReportItem &reportY = *pReportY;
308     const HidParser::ReportItem &reportZ = *pReportZ;
309     if (reportX.id != reportY.id || reportY.id != reportZ.id) {
310         LOG_E << "All 3 axis should be in the same report" << LOG_ENDL;
311         return false;
312     }
313     if (reportX.minRaw >= reportX.maxRaw
314             || reportX.minRaw != reportY.minRaw
315             || reportX.maxRaw != reportY.maxRaw
316             || reportY.minRaw != reportZ.minRaw
317             || reportY.maxRaw != reportZ.maxRaw) {
318         LOG_E << "All 3 axis should have same min and max value and min must < max" << LOG_ENDL;
319         return false;
320     }
321     if (reportX.a != reportY.a || reportY.a != reportY.a) {
322         LOG_E << "All 3 axis should have same resolution" << LOG_ENDL;
323         return false;
324     }
325     if (reportX.count != 1 || reportY.count != 1 || reportZ.count != 1
326             || (reportX.bitSize != 16 && reportX.bitSize != 32)
327             || reportX.bitSize != reportY.bitSize || reportY.bitSize != reportZ.bitSize
328             || !reportX.isByteAligned()
329             || !reportY.isByteAligned()
330             || !reportZ.isByteAligned() ) {
331         LOG_E << "All 3 axis should have count == 1, same size == 16 or 32 "
332               "and align at byte boundary" << LOG_ENDL;
333         return false;
334     }
335 
336     if (reportX.unit != 0 || reportY.unit != 0 || reportZ.unit != 0) {
337         LOG_E << "Specified unit for usage is not supported" << LOG_ENDL;
338         return false;
339     }
340 
341     if (reportX.a != reportY.a || reportY.a != reportZ.a
342         || reportX.b != reportY.b || reportY.b != reportZ.b) {
343         LOG_W << "Scaling for 3 axis are different. It is recommended to keep them the same" << LOG_ENDL;
344     }
345 
346     // set features
347     mFeatureInfo.maxRange = std::max(
348         std::abs((reportX.maxRaw + reportX.b) * reportX.a),
349         std::abs((reportX.minRaw + reportX.b) * reportX.a));
350     mFeatureInfo.resolution = reportX.a * defaultScaling;
351     mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
352 
353     ReportTranslateRecord record = {
354         .type = TYPE_FLOAT,
355         .maxValue = reportX.maxRaw,
356         .minValue = reportX.minRaw,
357         .byteSize = reportX.bitSize / 8,
358     };
359 
360     // Reorder and swap axis
361     //
362     // HID class devices are encouraged, where possible, to use a right-handed
363     // coordinate system. If a user is facing a device, report values should increase as
364     // controls are moved from left to right (X), from far to near (Y) and from high to
365     // low (Z).
366     //
367 
368     // Android X axis = Hid X axis
369     record.index = 0;
370     record.a = reportX.a * defaultScaling;
371     record.b = reportX.b;
372     record.byteOffset = reportX.bitOffset / 8;
373     mTranslateTable.push_back(record);
374 
375     // Android Y axis = - Hid Z axis
376     record.index = 1;
377     record.a = -reportZ.a * defaultScaling;
378     record.b = reportZ.b;
379     record.byteOffset = reportZ.bitOffset / 8;
380     mTranslateTable.push_back(record);
381 
382     // Android Z axis = Hid Y axis
383     record.index = 2;
384     record.a = reportY.a * defaultScaling;
385     record.b = reportY.b;
386     record.byteOffset = reportY.bitOffset / 8;
387     mTranslateTable.push_back(record);
388 
389     mInputReportId = reportX.id;
390     return true;
391 }
392 
find(const std::vector<HidParser::ReportPacket> & packets,unsigned int usage,int type,int id)393 const HidParser::ReportItem *HidRawSensor::find(
394         const std::vector<HidParser::ReportPacket> &packets,
395         unsigned int usage, int type, int id) {
396     for (const auto &packet : packets) {
397         if (packet.type != type) {
398             continue;
399         }
400         auto i = std::find_if(
401                 packet.reports.begin(), packet.reports.end(),
402                 [usage, id](const HidParser::ReportItem &p) {
403                     return p.usage == usage
404                             && (id == -1 || p.id == static_cast<unsigned int>(id));
405                 });
406         if (i != packet.reports.end()) {
407             return &(*i);
408         }
409     }
410     return nullptr;
411 };
412 
initFeatureValueFromHidDeviceInfo(FeatureValue * featureValue,const HidDevice::HidDeviceInfo & info)413 void HidRawSensor::initFeatureValueFromHidDeviceInfo(
414         FeatureValue *featureValue, const HidDevice::HidDeviceInfo &info) {
415     featureValue->name = info.name;
416 
417     std::ostringstream ss;
418     ss << info.busType << " "
419        << std::hex << std::setfill('0') << std::setw(4) << info.vendorId
420        << ":" << std::setw(4) << info.productId;
421     featureValue->vendor = ss.str();
422 
423     featureValue->permission = "";
424     featureValue->typeString = "";
425     featureValue->type = -1; // invalid type
426     featureValue->version = 1;
427 
428     featureValue->maxRange = -1.f;
429     featureValue->resolution = FLT_MAX;
430     featureValue->power = 1.f; // default value, does not have a valid source yet
431 
432     featureValue->minDelay = 0;
433     featureValue->maxDelay = 0;
434 
435     featureValue->fifoSize = 0;
436     featureValue->fifoMaxSize = 0;
437 
438     featureValue->reportModeFlag = SENSOR_FLAG_SPECIAL_REPORTING_MODE;
439     featureValue->isWakeUp = false;
440     memset(featureValue->uuid, 0, sizeof(featureValue->uuid));
441     featureValue->isAndroidCustom = false;
442 }
443 
populateFeatureValueFromFeatureReport(FeatureValue * featureValue,const std::vector<HidParser::ReportPacket> & packets)444 bool HidRawSensor::populateFeatureValueFromFeatureReport(
445         FeatureValue *featureValue, const std::vector<HidParser::ReportPacket> &packets) {
446     SP(HidDevice) device = PROMOTE(mDevice);
447     if (device == nullptr) {
448         return false;
449     }
450 
451     std::vector<uint8_t> buffer;
452     for (const auto &packet : packets) {
453         if (packet.type != HidParser::REPORT_TYPE_FEATURE) {
454             continue;
455         }
456 
457         if (!device->getFeature(packet.id, &buffer)) {
458             continue;
459         }
460 
461         std::string str;
462         using namespace Hid::Sensor::PropertyUsage;
463         for (const auto & r : packet.reports) {
464             switch (r.usage) {
465                 case FRIENDLY_NAME:
466                     if (!r.isByteAligned() || r.bitSize != 16 || r.count < 1) {
467                         // invalid friendly name
468                         break;
469                     }
470                     if (decodeString(r, buffer, &str) && !str.empty()) {
471                         featureValue->name = str;
472                     }
473                     break;
474                 case SENSOR_MANUFACTURER:
475                     if (!r.isByteAligned() || r.bitSize != 16 || r.count < 1) {
476                         // invalid manufacturer
477                         break;
478                     }
479                     if (decodeString(r, buffer, &str) && !str.empty()) {
480                         featureValue->vendor = str;
481                     }
482                     break;
483                 case PERSISTENT_UNIQUE_ID:
484                     if (!r.isByteAligned() || r.bitSize != 16 || r.count < 1) {
485                         // invalid unique id string
486                         break;
487                     }
488                     if (decodeString(r, buffer, &str) && !str.empty()) {
489                         featureValue->uniqueId = str;
490                     }
491                     break;
492                 case SENSOR_DESCRIPTION:
493                     if (!r.isByteAligned() || r.bitSize != 16 || r.count < 1
494                             || (r.bitOffset / 8 + r.count * 2) > buffer.size() ) {
495                         // invalid description
496                         break;
497                     }
498                     if (decodeString(r, buffer, &str)) {
499                         mFeatureInfo.isAndroidCustom = detectAndroidCustomSensor(str);
500                     }
501                     break;
502                 default:
503                     // do not care about others
504                     break;
505             }
506         }
507     }
508     return true;
509 }
510 
validateFeatureValueAndBuildSensor()511 bool HidRawSensor::validateFeatureValueAndBuildSensor() {
512     if (mFeatureInfo.name.empty() || mFeatureInfo.vendor.empty() || mFeatureInfo.typeString.empty()
513             || mFeatureInfo.type <= 0 || mFeatureInfo.maxRange <= 0
514             || mFeatureInfo.resolution <= 0) {
515         return false;
516     }
517 
518     switch (mFeatureInfo.reportModeFlag) {
519         case SENSOR_FLAG_CONTINUOUS_MODE:
520         case SENSOR_FLAG_ON_CHANGE_MODE:
521             if (mFeatureInfo.minDelay < 0) {
522                 return false;
523             }
524             if (mFeatureInfo.maxDelay != 0 && mFeatureInfo.maxDelay < mFeatureInfo.minDelay) {
525                 return false;
526             }
527             break;
528         case SENSOR_FLAG_ONE_SHOT_MODE:
529             if (mFeatureInfo.minDelay != -1 && mFeatureInfo.maxDelay != 0) {
530                 return false;
531             }
532             break;
533         case SENSOR_FLAG_SPECIAL_REPORTING_MODE:
534             if (mFeatureInfo.minDelay != -1 && mFeatureInfo.maxDelay != 0) {
535                 return false;
536             }
537             break;
538         default:
539             break;
540     }
541 
542     if (mFeatureInfo.fifoMaxSize < mFeatureInfo.fifoSize) {
543         return false;
544     }
545 
546     // initialize uuid field, use name, vendor and uniqueId
547     if (mFeatureInfo.name.size() >= 4
548             && mFeatureInfo.vendor.size() >= 4
549             && mFeatureInfo.typeString.size() >= 4
550             && mFeatureInfo.uniqueId.size() >= 4) {
551         uint32_t tmp[4], h;
552         std::hash<std::string> stringHash;
553         h = stringHash(mFeatureInfo.uniqueId);
554         tmp[0] = stringHash(mFeatureInfo.name) ^ h;
555         tmp[1] = stringHash(mFeatureInfo.vendor) ^ h;
556         tmp[2] = stringHash(mFeatureInfo.typeString) ^ h;
557         tmp[3] = tmp[0] ^ tmp[1] ^ tmp[2];
558         memcpy(mFeatureInfo.uuid, tmp, sizeof(mFeatureInfo.uuid));
559     }
560 
561     mSensor = (sensor_t) {
562         mFeatureInfo.name.c_str(),                 // name
563         mFeatureInfo.vendor.c_str(),               // vendor
564         mFeatureInfo.version,                      // version
565         -1,                                        // handle, dummy number here
566         mFeatureInfo.type,
567         mFeatureInfo.maxRange,                     // maxRange
568         mFeatureInfo.resolution,                   // resolution
569         mFeatureInfo.power,                        // power
570         mFeatureInfo.minDelay,                     // minDelay
571         (uint32_t)mFeatureInfo.fifoSize,           // fifoReservedEventCount
572         (uint32_t)mFeatureInfo.fifoMaxSize,        // fifoMaxEventCount
573         mFeatureInfo.typeString.c_str(),           // type string
574         mFeatureInfo.permission.c_str(),           // requiredPermission
575         (long)mFeatureInfo.maxDelay,               // maxDelay
576         mFeatureInfo.reportModeFlag | (mFeatureInfo.isWakeUp ? 1 : 0),
577         { NULL, NULL }
578     };
579     return true;
580 }
581 
decodeString(const HidParser::ReportItem & report,const std::vector<uint8_t> & buffer,std::string * d)582 bool HidRawSensor::decodeString(
583         const HidParser::ReportItem &report, const std::vector<uint8_t> &buffer, std::string *d) {
584     if (!report.isByteAligned() || report.bitSize != 16 || report.count < 1) {
585         return false;
586     }
587 
588     size_t offset = report.bitOffset / 8;
589     if (offset + report.count * 2 > buffer.size()) {
590         return false;
591     }
592 
593     std::vector<uint16_t> data(report.count);
594     auto i = data.begin();
595     auto j = buffer.begin() + offset;
596     for ( ; i != data.end(); ++i, j += sizeof(uint16_t)) {
597         // hid specified little endian
598         *i = *j + (*(j + 1) << 8);
599     }
600     std::wstring wstr(data.begin(), data.end());
601 
602     std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
603     *d = converter.to_bytes(wstr);
604     return true;
605 }
606 
split(const std::string & text,char sep)607 std::vector<std::string> split(const std::string &text, char sep) {
608     std::vector<std::string> tokens;
609     size_t start = 0, end = 0;
610     while ((end = text.find(sep, start)) != std::string::npos) {
611         if (end != start) {
612             tokens.push_back(text.substr(start, end - start));
613         }
614         start = end + 1;
615     }
616     if (end != start) {
617         tokens.push_back(text.substr(start));
618     }
619     return tokens;
620 }
621 
detectAndroidCustomSensor(const std::string & description)622 bool HidRawSensor::detectAndroidCustomSensor(const std::string &description) {
623     size_t nullPosition = description.find('\0');
624     if (nullPosition == std::string::npos) {
625         return false;
626     }
627     const std::string prefix("#ANDROID#");
628     if (description.find(prefix, nullPosition + 1) != nullPosition + 1) {
629         return false;
630     }
631 
632     std::string str(description.c_str() + nullPosition + 1 + prefix.size());
633 
634     // Format for predefined sensor types:
635     // #ANDROID#nn,[C|X|T|S],[B|0],[W|N]
636     // Format for vendor type sensor
637     // #ANDROID#xxx.yyy.zzz,[C|X|T|S],[B|0],[W|N]
638     //
639     // C: continuous
640     // X: on-change
641     // T: one-shot
642     // S: special trigger
643     //
644     // B: body permission
645     // 0: no permission required
646     std::vector<std::string> segments;
647     size_t start = 0, end = 0;
648     while ((end = str.find(',', start)) != std::string::npos) {
649         if (end != start) {
650             segments.push_back(str.substr(start, end - start));
651         }
652         start = end + 1;
653     }
654     if (end != start) {
655         segments.push_back(str.substr(start));
656     }
657 
658     if (segments.size() < 4) {
659         LOG_E << "Not enough segments in android custom description" << LOG_ENDL;
660         return false;
661     }
662 
663     // type
664     bool typeParsed = false;
665     if (!segments[0].empty()) {
666         if (::isdigit(segments[0][0])) {
667             int type = ::atoi(segments[0].c_str());
668             // all supported types here
669             switch (type) {
670                 case SENSOR_TYPE_HEART_RATE:
671                     mFeatureInfo.type = SENSOR_TYPE_HEART_RATE;
672                     mFeatureInfo.typeString = SENSOR_STRING_TYPE_HEART_RATE;
673                     typeParsed = true;
674                     break;
675                 case SENSOR_TYPE_AMBIENT_TEMPERATURE:
676                     mFeatureInfo.type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
677                     mFeatureInfo.typeString = SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE;
678                     typeParsed = true;
679                     break;
680                 case SENSOR_TYPE_LIGHT:
681                     mFeatureInfo.type = SENSOR_TYPE_LIGHT;
682                     mFeatureInfo.typeString = SENSOR_STRING_TYPE_LIGHT;
683                     typeParsed = true;
684                     break;
685                 case SENSOR_TYPE_PRESSURE:
686                     mFeatureInfo.type = SENSOR_TYPE_PRESSURE;
687                     mFeatureInfo.typeString = SENSOR_STRING_TYPE_PRESSURE;
688                     typeParsed = true;
689                     break;
690                 default:
691                     LOG_W << "Android type " << type << " has not been supported yet" << LOG_ENDL;
692                     break;
693             }
694         } else {
695             // assume a xxx.yyy.zzz format
696             std::ostringstream s;
697             bool lastIsDot = true;
698             for (auto c : segments[0]) {
699                 if (::isalpha(c)) {
700                     s << static_cast<char>(c);
701                     lastIsDot = false;
702                 } else if (!lastIsDot && c == '.') {
703                     s << static_cast<char>(c);
704                     lastIsDot = true;
705                 } else {
706                     break;
707                 }
708             }
709             if (s.str() == segments[0]) {
710                 mFeatureInfo.type = SENSOR_TYPE_DEVICE_PRIVATE_BASE;
711                 mFeatureInfo.typeString = CUSTOM_TYPE_PREFIX + s.str();
712                 typeParsed = true;
713             }
714         }
715     }
716 
717     // reporting type
718     bool reportingModeParsed = false;
719     if (segments[1].size() == 1) {
720         switch (segments[1][0]) {
721             case 'C':
722                 mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
723                 reportingModeParsed = true;
724                 break;
725             case 'X':
726                 mFeatureInfo.reportModeFlag = SENSOR_FLAG_ON_CHANGE_MODE;
727                 reportingModeParsed = true;
728                 break;
729             case 'T':
730                 mFeatureInfo.reportModeFlag = SENSOR_FLAG_ONE_SHOT_MODE;
731                 reportingModeParsed = true;
732                 break;
733             case 'S':
734                 mFeatureInfo.reportModeFlag = SENSOR_FLAG_SPECIAL_REPORTING_MODE;
735                 reportingModeParsed = true;
736                 break;
737             default:
738                 LOG_E << "Undefined reporting mode designation " << segments[1] << LOG_ENDL;
739         }
740     }
741 
742     // permission parsed
743     bool permissionParsed = false;
744     if (segments[2].size() == 1) {
745         switch (segments[2][0]) {
746             case 'B':
747                 mFeatureInfo.permission = SENSOR_PERMISSION_BODY_SENSORS;
748                 permissionParsed = true;
749                 break;
750             case '0':
751                 mFeatureInfo.permission = "";
752                 permissionParsed = true;
753                 break;
754             default:
755                 LOG_E << "Undefined permission designation " << segments[2] << LOG_ENDL;
756         }
757     }
758 
759     // wake up
760     bool wakeUpParsed = false;
761     if (segments[3].size() == 1) {
762         switch (segments[3][0]) {
763             case 'W':
764                 mFeatureInfo.isWakeUp = true;
765                 wakeUpParsed = true;
766                 break;
767             case 'N':
768                 mFeatureInfo.isWakeUp = false;
769                 wakeUpParsed = true;
770                 break;
771             default:
772                 LOG_E << "Undefined wake up designation " << segments[3] << LOG_ENDL;
773         }
774     }
775 
776     int ret = typeParsed && reportingModeParsed && permissionParsed && wakeUpParsed;
777     if (!ret) {
778         LOG_D << "detectAndroidCustomSensor typeParsed: " << typeParsed
779               << " reportingModeParsed: "  << reportingModeParsed
780               << " permissionParsed: " << permissionParsed
781               << " wakeUpParsed: " << wakeUpParsed << LOG_ENDL;
782     }
783     return ret;
784 }
785 
findSensorControlUsage(const std::vector<HidParser::ReportPacket> & packets)786 bool HidRawSensor::findSensorControlUsage(const std::vector<HidParser::ReportPacket> &packets) {
787     using namespace Hid::Sensor::PropertyUsage;
788     using namespace Hid::Sensor::RawMinMax;
789 
790     //REPORTING_STATE
791     const HidParser::ReportItem *reportingState
792             = find(packets, REPORTING_STATE, HidParser::REPORT_TYPE_FEATURE);
793 
794     if (reportingState == nullptr
795             || !reportingState->isByteAligned()
796             || reportingState->bitSize != 8
797             || reportingState->minRaw != REPORTING_STATE_MIN
798             || reportingState->maxRaw != REPORTING_STATE_MAX) {
799         LOG_W << "Cannot find valid reporting state feature" << LOG_ENDL;
800     } else {
801         mReportingStateId = reportingState->id;
802         mReportingStateOffset = reportingState->bitOffset / 8;
803     }
804 
805     //POWER_STATE
806     const HidParser::ReportItem *powerState
807             = find(packets, POWER_STATE, HidParser::REPORT_TYPE_FEATURE);
808     if (powerState == nullptr
809             || !powerState->isByteAligned()
810             || powerState->bitSize != 8
811             || powerState->minRaw != POWER_STATE_MIN
812             || powerState->maxRaw != POWER_STATE_MAX) {
813         LOG_W << "Cannot find valid power state feature" << LOG_ENDL;
814     } else {
815         mPowerStateId = powerState->id;
816         mPowerStateOffset = powerState->bitOffset / 8;
817     }
818 
819     //REPORT_INTERVAL
820     const HidParser::ReportItem *reportInterval
821             = find(packets, REPORT_INTERVAL, HidParser::REPORT_TYPE_FEATURE);
822     if (reportInterval == nullptr
823             || !reportInterval->isByteAligned()
824             || reportInterval->minRaw < 0
825             || (reportInterval->bitSize != 16 && reportInterval->bitSize != 32)) {
826         LOG_W << "Cannot find valid report interval feature" << LOG_ENDL;
827     } else {
828         mReportIntervalId = reportInterval->id;
829         mReportIntervalOffset = reportInterval->bitOffset / 8;
830         mReportIntervalSize = reportInterval->bitSize / 8;
831 
832         mFeatureInfo.minDelay = std::max(static_cast<int64_t>(1), reportInterval->minRaw) * 1000;
833         mFeatureInfo.maxDelay = std::min(static_cast<int64_t>(1000000),
834                                     reportInterval->maxRaw) * 1000; // maximum 1000 second
835     }
836     return true;
837     return (mPowerStateId >= 0 || mReportingStateId >= 0) && mReportIntervalId >= 0;
838 }
839 
getSensor() const840 const sensor_t* HidRawSensor::getSensor() const {
841     return &mSensor;
842 }
843 
getUuid(uint8_t * uuid) const844 void HidRawSensor::getUuid(uint8_t* uuid) const {
845     memcpy(uuid, mFeatureInfo.uuid, sizeof(mFeatureInfo.uuid));
846 }
847 
enable(bool enable)848 int HidRawSensor::enable(bool enable) {
849     using namespace Hid::Sensor::StateValue;
850     SP(HidDevice) device = PROMOTE(mDevice);
851 
852     if (device == nullptr) {
853         return NO_INIT;
854     }
855 
856     if (enable == mEnabled) {
857         return NO_ERROR;
858     }
859 
860     std::vector<uint8_t> buffer;
861     bool setPowerOk = true;
862     if (mPowerStateId >= 0) {
863         setPowerOk = false;
864         uint8_t id = static_cast<uint8_t>(mPowerStateId);
865         if (device->getFeature(id, &buffer)
866                 && buffer.size() > mPowerStateOffset) {
867             buffer[mPowerStateOffset] = enable ? POWER_STATE_FULL_POWER : POWER_STATE_POWER_OFF;
868             setPowerOk = device->setFeature(id, buffer);
869         } else {
870             LOG_E << "enable: changing POWER STATE failed" << LOG_ENDL;
871         }
872     }
873 
874     bool setReportingOk = true;
875     if (mReportingStateId >= 0) {
876         setReportingOk = false;
877         uint8_t id = static_cast<uint8_t>(mReportingStateId);
878         if (device->getFeature(id, &buffer)
879                 && buffer.size() > mReportingStateOffset) {
880             buffer[mReportingStateOffset]
881                     = enable ? REPORTING_STATE_ALL_EVENT : REPORTING_STATE_NO_EVENT;
882             setReportingOk = device->setFeature(id, buffer);
883         } else {
884             LOG_E << "enable: changing REPORTING STATE failed" << LOG_ENDL;
885         }
886     }
887 
888     if (setPowerOk && setReportingOk) {
889         mEnabled = enable;
890         return NO_ERROR;
891     } else {
892         return INVALID_OPERATION;
893     }
894 }
895 
batch(int64_t samplingPeriod,int64_t batchingPeriod)896 int HidRawSensor::batch(int64_t samplingPeriod, int64_t batchingPeriod) {
897     SP(HidDevice) device = PROMOTE(mDevice);
898     if (device == nullptr) {
899         return NO_INIT;
900     }
901 
902     if (samplingPeriod < 0 || batchingPeriod < 0) {
903         return BAD_VALUE;
904     }
905 
906     bool needRefresh = mSamplingPeriod != samplingPeriod || mBatchingPeriod != batchingPeriod;
907     std::vector<uint8_t> buffer;
908 
909     bool ok = true;
910     if (needRefresh && mReportIntervalId >= 0) {
911         ok = false;
912         uint8_t id = static_cast<uint8_t>(mReportIntervalId);
913         if (device->getFeature(id, &buffer)
914                 && buffer.size() >= mReportIntervalOffset + mReportIntervalSize) {
915             int64_t periodMs = samplingPeriod / 1000000; //ns -> ms
916             switch (mReportIntervalSize) {
917                 case sizeof(uint16_t):
918                     periodMs = std::min(periodMs, static_cast<int64_t>(UINT16_MAX));
919                     buffer[mReportIntervalOffset] = periodMs & 0xFF;
920                     buffer[mReportIntervalOffset + 1] = (periodMs >> 8) & 0xFF;
921                     break;
922                 case sizeof(uint32_t):
923                     periodMs = std::min(periodMs, static_cast<int64_t>(UINT32_MAX));
924                     buffer[mReportIntervalOffset] = periodMs & 0xFF;
925                     buffer[mReportIntervalOffset + 1] = (periodMs >> 8) & 0xFF;
926                     buffer[mReportIntervalOffset + 2] = (periodMs >> 16) & 0xFF;
927                     buffer[mReportIntervalOffset + 3] = (periodMs >> 24) & 0xFF;
928                     break;
929             }
930             ok = device->setFeature(id, buffer);
931         }
932     }
933 
934     if (ok) {
935         mSamplingPeriod = samplingPeriod;
936         mBatchingPeriod = batchingPeriod;
937         return NO_ERROR;
938     } else {
939         return INVALID_OPERATION;
940     }
941 }
942 
handleInput(uint8_t id,const std::vector<uint8_t> & message)943 void HidRawSensor::handleInput(uint8_t id, const std::vector<uint8_t> &message) {
944     if (id != mInputReportId || mEnabled == false) {
945         return;
946     }
947     sensors_event_t event = {
948         .version = sizeof(event),
949         .sensor = -1,
950         .type = mSensor.type
951     };
952     bool valid = true;
953     for (const auto &rec : mTranslateTable) {
954         int64_t v = (message[rec.byteOffset + rec.byteSize - 1] & 0x80) ? -1 : 0;
955         for (int i = static_cast<int>(rec.byteSize) - 1; i >= 0; --i) {
956             v = (v << 8) | message[rec.byteOffset + i]; // HID is little endian
957         }
958 
959         switch (rec.type) {
960             case TYPE_FLOAT:
961                 if (v > rec.maxValue || v < rec.minValue) {
962                     valid = false;
963                 }
964                 event.data[rec.index] = rec.a * (v + rec.b);
965                 break;
966             case TYPE_INT64:
967                 if (v > rec.maxValue || v < rec.minValue) {
968                     valid = false;
969                 }
970                 event.u64.data[rec.index] = v + rec.b;
971                 break;
972             case TYPE_ACCURACY:
973                 event.magnetic.status = (v & 0xFF) + rec.b;
974                 break;
975         }
976     }
977     if (!valid) {
978         LOG_V << "Range error observed in decoding, discard" << LOG_ENDL;
979     }
980     event.timestamp = -1;
981     generateEvent(event);
982 }
983 
dump() const984 std::string HidRawSensor::dump() const {
985     std::ostringstream ss;
986     ss << "Feature Values " << LOG_ENDL
987           << "  name: " << mFeatureInfo.name << LOG_ENDL
988           << "  vendor: " << mFeatureInfo.vendor << LOG_ENDL
989           << "  permission: " << mFeatureInfo.permission << LOG_ENDL
990           << "  typeString: " << mFeatureInfo.typeString << LOG_ENDL
991           << "  type: " << mFeatureInfo.type << LOG_ENDL
992           << "  maxRange: " << mFeatureInfo.maxRange << LOG_ENDL
993           << "  resolution: " << mFeatureInfo.resolution << LOG_ENDL
994           << "  power: " << mFeatureInfo.power << LOG_ENDL
995           << "  minDelay: " << mFeatureInfo.minDelay << LOG_ENDL
996           << "  maxDelay: " << mFeatureInfo.maxDelay << LOG_ENDL
997           << "  fifoSize: " << mFeatureInfo.fifoSize << LOG_ENDL
998           << "  fifoMaxSize: " << mFeatureInfo.fifoMaxSize << LOG_ENDL
999           << "  reportModeFlag: " << mFeatureInfo.reportModeFlag << LOG_ENDL
1000           << "  isWakeUp: " << (mFeatureInfo.isWakeUp ? "true" : "false") << LOG_ENDL
1001           << "  uniqueId: " << mFeatureInfo.uniqueId << LOG_ENDL
1002           << "  uuid: ";
1003 
1004     ss << std::hex << std::setfill('0');
1005     for (auto d : mFeatureInfo.uuid) {
1006           ss << std::setw(2) << static_cast<int>(d) << " ";
1007     }
1008     ss << std::dec << std::setfill(' ') << LOG_ENDL;
1009 
1010     ss << "Input report id: " << mInputReportId << LOG_ENDL;
1011     for (const auto &t : mTranslateTable) {
1012         ss << "  type, index: " << t.type << ", " << t.index
1013               << "; min,max: " << t.minValue << ", " << t.maxValue
1014               << "; byte-offset,size: " << t.byteOffset << ", " << t.byteSize
1015               << "; scaling,bias: " << t.a << ", " << t.b << LOG_ENDL;
1016     }
1017 
1018     ss << "Control features: " << LOG_ENDL;
1019     ss << "  Power state ";
1020     if (mPowerStateId >= 0) {
1021         ss << "found, id: " << mPowerStateId
1022               << " offset: " << mPowerStateOffset << LOG_ENDL;
1023     } else {
1024         ss << "not found" << LOG_ENDL;
1025     }
1026 
1027     ss << "  Reporting state ";
1028     if (mReportingStateId >= 0) {
1029         ss << "found, id: " << mReportingStateId
1030               << " offset: " << mReportingStateOffset << LOG_ENDL;
1031     } else {
1032         ss << "not found" << LOG_ENDL;
1033     }
1034 
1035     ss << "  Report interval ";
1036     if (mReportIntervalId >= 0) {
1037         ss << "found, id: " << mReportIntervalId
1038               << " offset: " << mReportIntervalOffset
1039               << " size: " << mReportIntervalSize << LOG_ENDL;
1040     } else {
1041         ss << "not found" << LOG_ENDL;
1042     }
1043     return ss.str();
1044 }
1045 
1046 } // namespace SensorHalExt
1047 } // namespace android
1048