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