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 LOG_W << "BODY_SENSORS permission has been deprecated and should not be used."
818 << LOG_ENDL;
819 mFeatureInfo.permission = SENSOR_PERMISSION_BODY_SENSORS;
820 permissionParsed = true;
821 break;
822 case '0':
823 mFeatureInfo.permission = "";
824 permissionParsed = true;
825 break;
826 default:
827 LOG_E << "Undefined permission designation " << segments[2] << LOG_ENDL;
828 }
829 }
830
831 // wake up
832 bool wakeUpParsed = false;
833 if (segments[3].size() == 1) {
834 switch (segments[3][0]) {
835 case 'W':
836 mFeatureInfo.isWakeUp = true;
837 wakeUpParsed = true;
838 break;
839 case 'N':
840 mFeatureInfo.isWakeUp = false;
841 wakeUpParsed = true;
842 break;
843 default:
844 LOG_E << "Undefined wake up designation " << segments[3] << LOG_ENDL;
845 }
846 }
847
848 int ret = typeParsed && reportingModeParsed && permissionParsed && wakeUpParsed;
849 if (!ret) {
850 LOG_D << "detectAndroidCustomSensor typeParsed: " << typeParsed
851 << " reportingModeParsed: " << reportingModeParsed
852 << " permissionParsed: " << permissionParsed
853 << " wakeUpParsed: " << wakeUpParsed << LOG_ENDL;
854 }
855 return ret;
856 }
857
findSensorControlUsage(const std::vector<HidParser::ReportPacket> & packets)858 bool HidRawSensor::findSensorControlUsage(const std::vector<HidParser::ReportPacket> &packets) {
859 using namespace Hid::Sensor::PowerStateUsage;
860 using namespace Hid::Sensor::PropertyUsage;
861 using namespace Hid::Sensor::ReportingStateUsage;
862 using namespace Hid::Sensor::LeTransportUsage;
863
864 //REPORTING_STATE
865 const HidParser::ReportItem *reportingState
866 = find(packets, REPORTING_STATE, HidParser::REPORT_TYPE_FEATURE);
867
868 if (reportingState == nullptr) {
869 LOG_W << "Cannot find valid reporting state feature" << LOG_ENDL;
870 } else {
871 mReportingStateId = reportingState->id;
872 mReportingStateBitOffset = reportingState->bitOffset;
873 mReportingStateBitSize = reportingState->bitSize;
874
875 mReportingStateDisableIndex = -1;
876 mReportingStateEnableIndex = -1;
877 for (unsigned i = 0; i < reportingState->usageVector.size(); ++i) {
878 if (reportingState->usageVector[i] == REPORTING_STATE_NO_EVENTS) {
879 mReportingStateDisableIndex = i;
880 }
881 if (reportingState->usageVector[i] == REPORTING_STATE_ALL_EVENTS) {
882 mReportingStateEnableIndex = i;
883 }
884 }
885 if (mReportingStateDisableIndex < 0) {
886 LOG_W << "Cannot find reporting state to disable sensor"
887 << LOG_ENDL;
888 mReportingStateId = -1;
889 }
890 if (mReportingStateEnableIndex < 0) {
891 LOG_W << "Cannot find reporting state to enable sensor" << LOG_ENDL;
892 mReportingStateId = -1;
893 }
894 }
895
896 //POWER_STATE
897 const HidParser::ReportItem *powerState
898 = find(packets, POWER_STATE, HidParser::REPORT_TYPE_FEATURE);
899 if (powerState == nullptr) {
900 LOG_W << "Cannot find valid power state feature" << LOG_ENDL;
901 } else {
902 mPowerStateId = powerState->id;
903 mPowerStateBitOffset = powerState->bitOffset;
904 mPowerStateBitSize = powerState->bitSize;
905
906 mPowerStateOffIndex = -1;
907 mPowerStateOnIndex = -1;
908 for (unsigned i = 0; i < powerState->usageVector.size(); ++i) {
909 if (powerState->usageVector[i] == POWER_STATE_D4_POWER_OFF) {
910 mPowerStateOffIndex = i;
911 }
912 if (powerState->usageVector[i] == POWER_STATE_D0_FULL_POWER) {
913 mPowerStateOnIndex = i;
914 }
915 }
916 if (mPowerStateOffIndex < 0) {
917 LOG_W << "Cannot find power state to power off sensor"
918 << LOG_ENDL;
919 mPowerStateId = -1;
920 }
921 if (mPowerStateOnIndex < 0) {
922 LOG_W << "Cannot find power state to power on sensor" << LOG_ENDL;
923 mPowerStateId = -1;
924 }
925 }
926
927 //REPORT_INTERVAL
928 const HidParser::ReportItem *reportInterval
929 = find(packets, REPORT_INTERVAL, HidParser::REPORT_TYPE_FEATURE);
930 if (reportInterval == nullptr
931 || reportInterval->minRaw < 0) {
932 LOG_W << "Cannot find valid report interval feature" << LOG_ENDL;
933 } else {
934 mReportIntervalId = reportInterval->id;
935 mReportIntervalBitOffset = reportInterval->bitOffset;
936 mReportIntervalBitSize = reportInterval->bitSize;
937 mReportIntervalScale = reportInterval->a;
938 mReportIntervalOffset = reportInterval->b;
939
940 mFeatureInfo.minDelay = 1000000.0
941 * (reportInterval->minRaw + reportInterval->b)
942 * reportInterval->a;
943 mFeatureInfo.minDelay = std::max(1000, mFeatureInfo.minDelay);
944 mFeatureInfo.maxDelay = 1000000.0
945 * (reportInterval->maxRaw + reportInterval->b)
946 * reportInterval->a;
947 mFeatureInfo.maxDelay = std::min(static_cast<int64_t>(1000000000),
948 mFeatureInfo.maxDelay);
949 }
950
951 bool leTransportExpected = mRequiresLeTransport;
952 if (leTransportExpected) {
953 //VENDOR_LE_TRANSPORT
954 const HidParser::ReportItem *leTransport
955 = find(packets, VENDOR_LE_TRANSPORT, HidParser::REPORT_TYPE_FEATURE);
956 if (leTransport == nullptr) {
957 LOG_W << "Cannot find valid LE transport feature" << LOG_ENDL;
958 } else {
959 mLeTransportId = leTransport->id;
960 mLeTransportBitOffset = leTransport->bitOffset;
961 mLeTransportBitSize = leTransport->bitSize;
962
963 mLeTransportAclIndex = -1;
964 mLeTransportIsoIndex = -1;
965 for (unsigned i = 0; i < leTransport->usageVector.size(); ++i) {
966 if (leTransport->usageVector[i] == LE_TRANSPORT_ACL) {
967 mLeTransportAclIndex = i;
968 }
969 if (leTransport->usageVector[i] == LE_TRANSPORT_ISO) {
970 mLeTransportIsoIndex = i;
971 }
972 }
973 if (mLeTransportAclIndex < 0) {
974 LOG_W << "Cannot find LE transport to enable ACL"
975 << LOG_ENDL;
976 mLeTransportId = -1;
977 }
978 if (mLeTransportIsoIndex < 0) {
979 LOG_W << "Cannot find LE transport to enable ISO" << LOG_ENDL;
980 mLeTransportId = -1;
981 }
982 }
983 }
984
985 return (mPowerStateId >= 0 || mReportingStateId >= 0) && mReportIntervalId >= 0 &&
986 (!leTransportExpected || mLeTransportId >= 0);
987 }
988
getSensor() const989 const sensor_t* HidRawSensor::getSensor() const {
990 return &mSensor;
991 }
992
getUuid(uint8_t * uuid) const993 void HidRawSensor::getUuid(uint8_t* uuid) const {
994 memcpy(uuid, mFeatureInfo.uuid, sizeof(mFeatureInfo.uuid));
995 }
996
enable(bool enable)997 int HidRawSensor::enable(bool enable) {
998 SP(HidDevice) device = PROMOTE(mDevice);
999
1000 if (device == nullptr) {
1001 LOG_E << "enable(" << enable << "): no device" << LOG_ENDL;
1002 return NO_INIT;
1003 }
1004
1005 if (enable == mEnabled) {
1006 LOG_D << "enable(" << enable << "): already in desired state"
1007 << LOG_ENDL;
1008 return NO_ERROR;
1009 }
1010
1011 bool setLeAudioTransportOk = setLeAudioTransport(device, enable);
1012 bool setPowerOk = setPower(device, enable);
1013 bool setReportingOk = setReportingState(device, enable);
1014 if (setPowerOk && setReportingOk && setLeAudioTransportOk) {
1015 mEnabled = enable;
1016 LOG_I << "enable(" << enable << "): success" << LOG_ENDL;
1017 return NO_ERROR;
1018 } else {
1019 LOG_E << "enable(" << enable << "): set feature failed" << LOG_ENDL;
1020 return INVALID_OPERATION;
1021 }
1022 }
1023
setLeAudioTransport(const SP (HidDevice)& device,bool enable)1024 bool HidRawSensor::setLeAudioTransport(const SP(HidDevice) &device, bool enable) {
1025 std::vector<uint8_t> buffer;
1026 bool success = true;
1027 if (mLeTransportId >= 0 && enable) {
1028 success = false;
1029 uint8_t id = static_cast<uint8_t>(mLeTransportId);
1030 if (device->getFeature(id, &buffer)
1031 && (8 * buffer.size()) >=
1032 (mLeTransportBitOffset + mLeTransportBitSize)) {
1033 // The following property, if defined, represents a comma-separated list of
1034 // transport preferences for the following types: le-acl or iso-[sw|hw],
1035 // which describes the priority list of transport selections used based on the
1036 // capabilities reported by the HID device.
1037 std::string prop = GetProperty("bluetooth.core.le.dsa_transport_preference", "");
1038 std::istringstream tokenStream(prop);
1039 std::string line;
1040 std::vector<std::string> priorityList;
1041 while (std::getline(tokenStream, line, ',')) {
1042 priorityList.push_back(line);
1043 }
1044
1045 uint16_t capability = mFeatureInfo.version & 0x0000FFFF;
1046 uint8_t index;
1047 if (capability == (kIsoBitMask | kAclBitMask)) {
1048 if (!priorityList.empty() && priorityList[0].compare("le-acl") == 0) {
1049 index = mLeTransportAclIndex;
1050 } else {
1051 index = mLeTransportIsoIndex;
1052 }
1053 } else {
1054 index = (capability & kIsoBitMask) ? mLeTransportIsoIndex : mLeTransportAclIndex;
1055 }
1056
1057 HidUtil::copyBits(&index, &(buffer[0]), buffer.size(), 0,
1058 mLeTransportBitOffset, mLeTransportBitSize);
1059 success = device->setFeature(id, buffer);
1060 if (!success) {
1061 LOG_E << "enable(" << enable << "): setFeature LE TRANSPORT failed" << LOG_ENDL;
1062 }
1063 } else {
1064 LOG_E << "enable(" << enable << "): changing LE TRANSPORT failed" << LOG_ENDL;
1065 }
1066 }
1067 return success;
1068 }
1069
setPower(const SP (HidDevice)& device,bool enable)1070 bool HidRawSensor::setPower(const SP(HidDevice) &device, bool enable) {
1071 std::vector<uint8_t> buffer;
1072 bool success = true;
1073 if (mPowerStateId >= 0) {
1074 success = false;
1075 uint8_t id = static_cast<uint8_t>(mPowerStateId);
1076 if (device->getFeature(id, &buffer)
1077 && (8 * buffer.size()) >=
1078 (mPowerStateBitOffset + mPowerStateBitSize)) {
1079 uint8_t index = enable ? mPowerStateOnIndex : mPowerStateOffIndex;
1080 HidUtil::copyBits(&index, &(buffer[0]), buffer.size(),
1081 0, mPowerStateBitOffset, mPowerStateBitSize);
1082 success = device->setFeature(id, buffer);
1083 if (!success) {
1084 LOG_E << "enable(" << enable << "): setFeature POWER STATE failed" << LOG_ENDL;
1085 }
1086 } else {
1087 LOG_E << "enable(" << enable << "): changing POWER STATE failed" << LOG_ENDL;
1088 }
1089 }
1090 return success;
1091 }
1092
setReportingState(const SP (HidDevice)& device,bool enable)1093 bool HidRawSensor::setReportingState(const SP(HidDevice) &device, bool enable) {
1094 std::vector<uint8_t> buffer;
1095 bool success = true;
1096 if (mReportingStateId >= 0) {
1097 success = false;
1098 uint8_t id = static_cast<uint8_t>(mReportingStateId);
1099 if (device->getFeature(id, &buffer)
1100 && (8 * buffer.size()) >
1101 (mReportingStateBitOffset + mReportingStateBitSize)) {
1102 uint8_t index = enable ? mReportingStateEnableIndex :
1103 mReportingStateDisableIndex;
1104 HidUtil::copyBits(&index, &(buffer[0]), buffer.size(),0,
1105 mReportingStateBitOffset, mReportingStateBitSize);
1106 success = device->setFeature(id, buffer);
1107 if (!success) {
1108 LOG_E << "enable(" << enable << "): setFeature REPORTING STATE failed" << LOG_ENDL;
1109 }
1110 } else {
1111 LOG_E << "enable(" << enable << "): changing REPORTING STATE failed" << LOG_ENDL;
1112 }
1113 }
1114 return success;
1115 }
1116
batch(int64_t samplingPeriod,int64_t batchingPeriod)1117 int HidRawSensor::batch(int64_t samplingPeriod, int64_t batchingPeriod) {
1118 SP(HidDevice) device = PROMOTE(mDevice);
1119 if (device == nullptr) {
1120 return NO_INIT;
1121 }
1122
1123 if (samplingPeriod < 0 || batchingPeriod < 0) {
1124 return BAD_VALUE;
1125 }
1126
1127 bool needRefresh = mSamplingPeriod != samplingPeriod || mBatchingPeriod != batchingPeriod;
1128 std::vector<uint8_t> buffer;
1129
1130 bool ok = true;
1131 if (needRefresh && mReportIntervalId >= 0) {
1132 ok = false;
1133 uint8_t id = static_cast<uint8_t>(mReportIntervalId);
1134 if (device->getFeature(id, &buffer)
1135 && (8 * buffer.size()) >=
1136 (mReportIntervalBitOffset + mReportIntervalBitSize)) {
1137 int64_t periodMs =
1138 (((static_cast<double>(samplingPeriod)) / 1000000000.0)
1139 / mReportIntervalScale) - mReportIntervalOffset;
1140 int64_t maxPeriodMs =
1141 (1LL << std::min(mReportIntervalBitSize, 63U)) - 1;
1142 periodMs = std::min(periodMs, maxPeriodMs);
1143 HidUtil::copyBits(&periodMs, &(buffer[0]), buffer.size(),
1144 0, mReportIntervalBitOffset,
1145 mReportIntervalBitSize);
1146 ok = device->setFeature(id, buffer);
1147 if (!ok) {
1148 LOG_E << "batch(" << samplingPeriod << ", " << batchingPeriod << "): "
1149 << "setFeature failed" << LOG_ENDL;
1150 }
1151 } else {
1152 LOG_E << "batch(" << samplingPeriod << ", " << batchingPeriod << "): "
1153 << "invalid getFeature result (buffer.size: " << buffer.size() << ")" << LOG_ENDL;
1154 }
1155 }
1156
1157 if (ok) {
1158 mSamplingPeriod = samplingPeriod;
1159 mBatchingPeriod = batchingPeriod;
1160 return NO_ERROR;
1161 } else {
1162 return INVALID_OPERATION;
1163 }
1164 }
1165
handleInput(uint8_t id,const std::vector<uint8_t> & message)1166 void HidRawSensor::handleInput(uint8_t id, const std::vector<uint8_t> &message) {
1167 if (id != mInputReportId || mEnabled == false) {
1168 return;
1169 }
1170 sensors_event_t event = {
1171 .version = sizeof(event),
1172 .sensor = -1,
1173 .type = mSensor.type
1174 };
1175 bool valid = true;
1176
1177 switch (mFeatureInfo.type) {
1178 case SENSOR_TYPE_HEAD_TRACKER:
1179 valid = getHeadTrackerEventData(message, &event);
1180 break;
1181 default:
1182 valid = getSensorEventData(message, &event);
1183 break;
1184 }
1185 if (!valid) {
1186 LOG_E << "Invalid data observed in decoding, discard" << LOG_ENDL;
1187 return;
1188 }
1189 event.timestamp = -1;
1190 generateEvent(event);
1191 }
1192
getHeadTrackerEventData(const std::vector<uint8_t> & message,sensors_event_t * event)1193 bool HidRawSensor::getHeadTrackerEventData(const std::vector<uint8_t> &message,
1194 sensors_event_t *event) {
1195 head_tracker_event_t *head_tracker;
1196
1197 head_tracker = &(event->head_tracker);
1198 if (!getReportFieldValue(message, &(mTranslateTable[0]),
1199 &(head_tracker->rx))
1200 || !getReportFieldValue(message, &(mTranslateTable[1]),
1201 &(head_tracker->ry))
1202 || !getReportFieldValue(message, &(mTranslateTable[2]),
1203 &(head_tracker->rz))
1204 || !getReportFieldValue(message, &(mTranslateTable[3]),
1205 &(head_tracker->vx))
1206 || !getReportFieldValue(message, &(mTranslateTable[4]),
1207 &(head_tracker->vy))
1208 || !getReportFieldValue(message, &(mTranslateTable[5]),
1209 &(head_tracker->vz))
1210 || !getReportFieldValue(message, &(mTranslateTable[6]),
1211 &(head_tracker->discontinuity_count))) {
1212 return false;
1213 }
1214
1215 return true;
1216 }
1217
getSensorEventData(const std::vector<uint8_t> & message,sensors_event_t * event)1218 bool HidRawSensor::getSensorEventData(const std::vector<uint8_t> &message,
1219 sensors_event_t *event) {
1220 for (const auto &rec : mTranslateTable) {
1221 int64_t v = 0;
1222 if (rec.minValue < 0) {
1223 v = (message[rec.byteOffset + rec.byteSize - 1] & 0x80) ? -1 : 0;
1224 }
1225 for (int i = static_cast<int>(rec.byteSize) - 1; i >= 0; --i) {
1226 v = (v << 8) | message[rec.byteOffset + i]; // HID is little endian
1227 }
1228
1229 switch (rec.type) {
1230 case TYPE_FLOAT:
1231 if (v > rec.maxValue || v < rec.minValue) {
1232 return false;
1233 }
1234 event->data[rec.index] = rec.a * (v + rec.b);
1235 break;
1236 case TYPE_INT64:
1237 if (v > rec.maxValue || v < rec.minValue) {
1238 return false;
1239 }
1240 event->u64.data[rec.index] = v + rec.b;
1241 break;
1242 case TYPE_ACCURACY:
1243 event->magnetic.status = (v & 0xFF) + rec.b;
1244 break;
1245 }
1246 }
1247
1248 return true;
1249 }
1250
dump() const1251 std::string HidRawSensor::dump() const {
1252 std::ostringstream ss;
1253 ss << "Feature Values " << LOG_ENDL
1254 << " name: " << mFeatureInfo.name << LOG_ENDL
1255 << " version: 0x" << std::setfill('0') << std::setw(8) << std::hex << mFeatureInfo.version << LOG_ENDL
1256 << " vendor: " << mFeatureInfo.vendor << LOG_ENDL
1257 << " permission: " << mFeatureInfo.permission << LOG_ENDL
1258 << " typeString: " << mFeatureInfo.typeString << LOG_ENDL
1259 << " type: " << mFeatureInfo.type << LOG_ENDL
1260 << " maxRange: " << mFeatureInfo.maxRange << LOG_ENDL
1261 << " resolution: " << mFeatureInfo.resolution << LOG_ENDL
1262 << " power: " << mFeatureInfo.power << LOG_ENDL
1263 << " minDelay: " << mFeatureInfo.minDelay << LOG_ENDL
1264 << " maxDelay: " << mFeatureInfo.maxDelay << LOG_ENDL
1265 << " fifoSize: " << mFeatureInfo.fifoSize << LOG_ENDL
1266 << " fifoMaxSize: " << mFeatureInfo.fifoMaxSize << LOG_ENDL
1267 << " reportModeFlag: " << mFeatureInfo.reportModeFlag << LOG_ENDL
1268 << " isWakeUp: " << (mFeatureInfo.isWakeUp ? "true" : "false") << LOG_ENDL;
1269
1270 ss << " uniqueId: " << std::hex << std::setfill('0');
1271 for (auto d : mFeatureInfo.uniqueId) {
1272 ss << std::setw(2) << static_cast<int>(d) << " ";
1273 }
1274 ss << std::dec << std::setfill(' ') << LOG_ENDL;
1275
1276 ss << " uuid: " << std::hex << std::setfill('0');
1277 for (auto d : mFeatureInfo.uuid) {
1278 ss << std::setw(2) << static_cast<int>(d) << " ";
1279 }
1280 ss << std::dec << std::setfill(' ') << LOG_ENDL;
1281
1282 ss << "Input report id: " << mInputReportId << LOG_ENDL;
1283 for (const auto &t : mTranslateTable) {
1284 ss << " type, index: " << t.type << ", " << t.index
1285 << "; min,max: " << t.minValue << ", " << t.maxValue
1286 << "; byte-offset,size: " << t.byteOffset << ", " << t.byteSize
1287 << "; scaling,bias: " << t.a << ", " << t.b << LOG_ENDL;
1288 }
1289
1290 ss << "Control features: " << LOG_ENDL;
1291 ss << " Power state ";
1292 if (mPowerStateId >= 0) {
1293 ss << "found, id: " << mPowerStateId
1294 << " bit offset: " << mPowerStateBitOffset
1295 << " bit size: " << mPowerStateBitSize
1296 << " power off index: " << mPowerStateOffIndex
1297 << " power on index: " << mPowerStateOnIndex
1298 << LOG_ENDL;
1299 } else {
1300 ss << "not found" << LOG_ENDL;
1301 }
1302
1303 ss << " Reporting state ";
1304 if (mReportingStateId >= 0) {
1305 ss << "found, id: " << mReportingStateId
1306 << " bit offset: " << mReportingStateBitOffset
1307 << " bit size: " << mReportingStateBitSize
1308 << " disable index: " << mReportingStateDisableIndex
1309 << " enable index: " << mReportingStateEnableIndex
1310 << LOG_ENDL;
1311 } else {
1312 ss << "not found" << LOG_ENDL;
1313 }
1314
1315 ss << " Report interval ";
1316 if (mReportIntervalId >= 0) {
1317 ss << "found, id: " << mReportIntervalId
1318 << " bit offset: " << mReportIntervalBitOffset
1319 << " bit size: " << mReportIntervalBitSize << LOG_ENDL;
1320 } else {
1321 ss << "not found" << LOG_ENDL;
1322 }
1323 return ss.str();
1324 }
1325
1326 } // namespace SensorHalExt
1327 } // namespace android
1328