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