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