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