blob: 7c25cda9acf459ae7a0a38e61a8b3fc80de75e5c [file] [log] [blame]
Jeff Brown5912f952013-07-01 19:10:31 -07001/*
2 * Copyright (C) 2008 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
17#define LOG_TAG "KeyLayoutMap"
18
Jeff Brown5912f952013-07-01 19:10:31 -070019#include <android/keycodes.h>
Dominik Laskowski75788452021-02-09 18:51:25 -080020#include <ftl/enum.h>
Michael Wright872db4f2014-04-22 15:03:51 -070021#include <input/InputEventLabels.h>
Jeff Brown5912f952013-07-01 19:10:31 -070022#include <input/KeyLayoutMap.h>
Chris Yef59a2f42020-10-16 12:55:26 -070023#include <input/Keyboard.h>
Jeff Brown5912f952013-07-01 19:10:31 -070024#include <utils/Errors.h>
Chris Yef59a2f42020-10-16 12:55:26 -070025#include <utils/Log.h>
Jeff Brown5912f952013-07-01 19:10:31 -070026#include <utils/Timers.h>
Chris Yef59a2f42020-10-16 12:55:26 -070027#include <utils/Tokenizer.h>
Jeff Brown5912f952013-07-01 19:10:31 -070028
Dominik Laskowski75788452021-02-09 18:51:25 -080029#include <cstdlib>
30#include <string_view>
31#include <unordered_map>
32
Jeff Brown5912f952013-07-01 19:10:31 -070033// Enables debug output for the parser.
34#define DEBUG_PARSER 0
35
36// Enables debug output for parser performance.
37#define DEBUG_PARSER_PERFORMANCE 0
38
39// Enables debug output for mapping.
40#define DEBUG_MAPPING 0
41
42
43namespace android {
Dominik Laskowski75788452021-02-09 18:51:25 -080044namespace {
Jeff Brown5912f952013-07-01 19:10:31 -070045
Dominik Laskowski75788452021-02-09 18:51:25 -080046constexpr const char* WHITESPACE = " \t\r";
Jeff Brown5912f952013-07-01 19:10:31 -070047
Dominik Laskowski75788452021-02-09 18:51:25 -080048template <InputDeviceSensorType S>
49constexpr auto sensorPair() {
50 return std::make_pair(ftl::enum_name<S>(), S);
Jeff Brown5912f952013-07-01 19:10:31 -070051}
52
Dominik Laskowski75788452021-02-09 18:51:25 -080053static const std::unordered_map<std::string_view, InputDeviceSensorType> SENSOR_LIST =
54 {sensorPair<InputDeviceSensorType::ACCELEROMETER>(),
55 sensorPair<InputDeviceSensorType::MAGNETIC_FIELD>(),
56 sensorPair<InputDeviceSensorType::ORIENTATION>(),
57 sensorPair<InputDeviceSensorType::GYROSCOPE>(),
58 sensorPair<InputDeviceSensorType::LIGHT>(),
59 sensorPair<InputDeviceSensorType::PRESSURE>(),
60 sensorPair<InputDeviceSensorType::TEMPERATURE>(),
61 sensorPair<InputDeviceSensorType::PROXIMITY>(),
62 sensorPair<InputDeviceSensorType::GRAVITY>(),
63 sensorPair<InputDeviceSensorType::LINEAR_ACCELERATION>(),
64 sensorPair<InputDeviceSensorType::ROTATION_VECTOR>(),
65 sensorPair<InputDeviceSensorType::RELATIVE_HUMIDITY>(),
66 sensorPair<InputDeviceSensorType::AMBIENT_TEMPERATURE>(),
67 sensorPair<InputDeviceSensorType::MAGNETIC_FIELD_UNCALIBRATED>(),
68 sensorPair<InputDeviceSensorType::GAME_ROTATION_VECTOR>(),
69 sensorPair<InputDeviceSensorType::GYROSCOPE_UNCALIBRATED>(),
70 sensorPair<InputDeviceSensorType::SIGNIFICANT_MOTION>()};
71
72} // namespace
73
74KeyLayoutMap::KeyLayoutMap() = default;
75KeyLayoutMap::~KeyLayoutMap() = default;
Jeff Brown5912f952013-07-01 19:10:31 -070076
Chris Ye1abffbd2020-08-18 12:50:12 -070077base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::loadContents(const std::string& filename,
78 const char* contents) {
79 Tokenizer* tokenizer;
80 status_t status = Tokenizer::fromContents(String8(filename.c_str()), contents, &tokenizer);
81 if (status) {
82 ALOGE("Error %d opening key layout map.", status);
83 return Errorf("Error {} opening key layout map file {}.", status, filename.c_str());
84 }
85 std::unique_ptr<Tokenizer> t(tokenizer);
86 auto ret = load(t.get());
Bernie Innocenti147c86e2020-12-21 21:01:45 +090087 if (ret.ok()) {
Chris Ye1abffbd2020-08-18 12:50:12 -070088 (*ret)->mLoadFileName = filename;
89 }
90 return ret;
91}
Jeff Brown5912f952013-07-01 19:10:31 -070092
Chris Ye1abffbd2020-08-18 12:50:12 -070093base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::load(const std::string& filename) {
Jeff Brown5912f952013-07-01 19:10:31 -070094 Tokenizer* tokenizer;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +010095 status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
Jeff Brown5912f952013-07-01 19:10:31 -070096 if (status) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +010097 ALOGE("Error %d opening key layout map file %s.", status, filename.c_str());
Chris Ye1abffbd2020-08-18 12:50:12 -070098 return Errorf("Error {} opening key layout map file {}.", status, filename.c_str());
Jeff Brown5912f952013-07-01 19:10:31 -070099 }
Chris Ye1abffbd2020-08-18 12:50:12 -0700100 std::unique_ptr<Tokenizer> t(tokenizer);
101 auto ret = load(t.get());
Bernie Innocenti147c86e2020-12-21 21:01:45 +0900102 if (ret.ok()) {
Chris Ye1abffbd2020-08-18 12:50:12 -0700103 (*ret)->mLoadFileName = filename;
104 }
105 return ret;
106}
107
108base::Result<std::shared_ptr<KeyLayoutMap>> KeyLayoutMap::load(Tokenizer* tokenizer) {
109 std::shared_ptr<KeyLayoutMap> map = std::shared_ptr<KeyLayoutMap>(new KeyLayoutMap());
110 status_t status = OK;
111 if (!map.get()) {
112 ALOGE("Error allocating key layout map.");
113 return Errorf("Error allocating key layout map.");
114 } else {
115#if DEBUG_PARSER_PERFORMANCE
116 nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
117#endif
118 Parser parser(map.get(), tokenizer);
119 status = parser.parse();
120#if DEBUG_PARSER_PERFORMANCE
121 nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
122 ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.",
123 tokenizer->getFilename().string(), tokenizer->getLineNumber(),
124 elapsedTime / 1000000.0);
125#endif
126 if (!status) {
127 return std::move(map);
128 }
129 }
130 return Errorf("Load KeyLayoutMap failed {}.", status);
Jeff Brown5912f952013-07-01 19:10:31 -0700131}
132
133status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode,
134 int32_t* outKeyCode, uint32_t* outFlags) const {
135 const Key* key = getKey(scanCode, usageCode);
136 if (!key) {
137#if DEBUG_MAPPING
138 ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
139#endif
140 *outKeyCode = AKEYCODE_UNKNOWN;
141 *outFlags = 0;
142 return NAME_NOT_FOUND;
143 }
144
145 *outKeyCode = key->keyCode;
146 *outFlags = key->flags;
147
148#if DEBUG_MAPPING
149 ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d, outFlags=0x%08x.",
150 scanCode, usageCode, *outKeyCode, *outFlags);
151#endif
152 return NO_ERROR;
153}
154
Chris Yef59a2f42020-10-16 12:55:26 -0700155// Return pair of sensor type and sensor data index, for the input device abs code
156base::Result<std::pair<InputDeviceSensorType, int32_t>> KeyLayoutMap::mapSensor(int32_t absCode) {
157 auto it = mSensorsByAbsCode.find(absCode);
158 if (it == mSensorsByAbsCode.end()) {
159#if DEBUG_MAPPING
160 ALOGD("mapSensor: absCode=%d, ~ Failed.", absCode);
161#endif
162 return Errorf("Can't find abs code {}.", absCode);
163 }
164 const Sensor& sensor = it->second;
165
166#if DEBUG_MAPPING
Dominik Laskowski75788452021-02-09 18:51:25 -0800167 ALOGD("mapSensor: absCode=%d, sensorType=%s, sensorDataIndex=0x%x.", absCode,
168 ftl::enum_string(sensor.sensorType).c_str(), sensor.sensorDataIndex);
Chris Yef59a2f42020-10-16 12:55:26 -0700169#endif
170 return std::make_pair(sensor.sensorType, sensor.sensorDataIndex);
171}
172
Jeff Brown5912f952013-07-01 19:10:31 -0700173const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const {
174 if (usageCode) {
175 ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
176 if (index >= 0) {
177 return &mKeysByUsageCode.valueAt(index);
178 }
179 }
180 if (scanCode) {
181 ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
182 if (index >= 0) {
183 return &mKeysByScanCode.valueAt(index);
184 }
185 }
Yi Kong5bed83b2018-07-17 12:53:47 -0700186 return nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700187}
188
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800189status_t KeyLayoutMap::findScanCodesForKey(
190 int32_t keyCode, std::vector<int32_t>* outScanCodes) const {
Jeff Brown5912f952013-07-01 19:10:31 -0700191 const size_t N = mKeysByScanCode.size();
192 for (size_t i=0; i<N; i++) {
193 if (mKeysByScanCode.valueAt(i).keyCode == keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800194 outScanCodes->push_back(mKeysByScanCode.keyAt(i));
Jeff Brown5912f952013-07-01 19:10:31 -0700195 }
196 }
197 return NO_ERROR;
198}
199
200status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const {
201 ssize_t index = mAxes.indexOfKey(scanCode);
202 if (index < 0) {
203#if DEBUG_MAPPING
204 ALOGD("mapAxis: scanCode=%d ~ Failed.", scanCode);
205#endif
206 return NAME_NOT_FOUND;
207 }
208
209 *outAxisInfo = mAxes.valueAt(index);
210
211#if DEBUG_MAPPING
212 ALOGD("mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, "
213 "splitValue=%d, flatOverride=%d.",
214 scanCode,
215 outAxisInfo->mode, outAxisInfo->axis, outAxisInfo->highAxis,
216 outAxisInfo->splitValue, outAxisInfo->flatOverride);
217#endif
218 return NO_ERROR;
219}
220
Michael Wright74bdd2e2013-10-17 17:35:53 -0700221status_t KeyLayoutMap::findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const {
222 const size_t N = mLedsByScanCode.size();
223 for (size_t i = 0; i < N; i++) {
224 if (mLedsByScanCode.valueAt(i).ledCode == ledCode) {
225 *outScanCode = mLedsByScanCode.keyAt(i);
226#if DEBUG_MAPPING
227 ALOGD("findScanCodeForLed: ledCode=%d, scanCode=%d.", ledCode, *outScanCode);
228#endif
229 return NO_ERROR;
230 }
231 }
232#if DEBUG_MAPPING
233 ALOGD("findScanCodeForLed: ledCode=%d ~ Not found.", ledCode);
234#endif
235 return NAME_NOT_FOUND;
236}
237
238status_t KeyLayoutMap::findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const {
239 const size_t N = mLedsByUsageCode.size();
240 for (size_t i = 0; i < N; i++) {
241 if (mLedsByUsageCode.valueAt(i).ledCode == ledCode) {
242 *outUsageCode = mLedsByUsageCode.keyAt(i);
243#if DEBUG_MAPPING
244 ALOGD("findUsageForLed: ledCode=%d, usage=%x.", ledCode, *outUsageCode);
245#endif
246 return NO_ERROR;
247 }
248 }
249#if DEBUG_MAPPING
250 ALOGD("findUsageForLed: ledCode=%d ~ Not found.", ledCode);
251#endif
252 return NAME_NOT_FOUND;
253}
254
Jeff Brown5912f952013-07-01 19:10:31 -0700255
256// --- KeyLayoutMap::Parser ---
257
258KeyLayoutMap::Parser::Parser(KeyLayoutMap* map, Tokenizer* tokenizer) :
259 mMap(map), mTokenizer(tokenizer) {
260}
261
262KeyLayoutMap::Parser::~Parser() {
263}
264
265status_t KeyLayoutMap::Parser::parse() {
266 while (!mTokenizer->isEof()) {
267#if DEBUG_PARSER
268 ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
269 mTokenizer->peekRemainderOfLine().string());
270#endif
271
272 mTokenizer->skipDelimiters(WHITESPACE);
273
274 if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
275 String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
276 if (keywordToken == "key") {
277 mTokenizer->skipDelimiters(WHITESPACE);
278 status_t status = parseKey();
279 if (status) return status;
280 } else if (keywordToken == "axis") {
281 mTokenizer->skipDelimiters(WHITESPACE);
282 status_t status = parseAxis();
283 if (status) return status;
Michael Wright74bdd2e2013-10-17 17:35:53 -0700284 } else if (keywordToken == "led") {
285 mTokenizer->skipDelimiters(WHITESPACE);
286 status_t status = parseLed();
287 if (status) return status;
Chris Yef59a2f42020-10-16 12:55:26 -0700288 } else if (keywordToken == "sensor") {
289 mTokenizer->skipDelimiters(WHITESPACE);
290 status_t status = parseSensor();
291 if (status) return status;
Jeff Brown5912f952013-07-01 19:10:31 -0700292 } else {
293 ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
294 keywordToken.string());
295 return BAD_VALUE;
296 }
297
298 mTokenizer->skipDelimiters(WHITESPACE);
299 if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
300 ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
301 mTokenizer->getLocation().string(),
302 mTokenizer->peekRemainderOfLine().string());
303 return BAD_VALUE;
304 }
305 }
306
307 mTokenizer->nextLine();
308 }
309 return NO_ERROR;
310}
311
312status_t KeyLayoutMap::Parser::parseKey() {
313 String8 codeToken = mTokenizer->nextToken(WHITESPACE);
314 bool mapUsage = false;
315 if (codeToken == "usage") {
316 mapUsage = true;
317 mTokenizer->skipDelimiters(WHITESPACE);
318 codeToken = mTokenizer->nextToken(WHITESPACE);
319 }
320
321 char* end;
322 int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
323 if (*end) {
324 ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
325 mapUsage ? "usage" : "scan code", codeToken.string());
326 return BAD_VALUE;
327 }
Michael Wright74bdd2e2013-10-17 17:35:53 -0700328 KeyedVector<int32_t, Key>& map = mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
Jeff Brown5912f952013-07-01 19:10:31 -0700329 if (map.indexOfKey(code) >= 0) {
330 ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
331 mapUsage ? "usage" : "scan code", codeToken.string());
332 return BAD_VALUE;
333 }
334
335 mTokenizer->skipDelimiters(WHITESPACE);
336 String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -0700337 int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
Jeff Brown5912f952013-07-01 19:10:31 -0700338 if (!keyCode) {
339 ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
340 keyCodeToken.string());
341 return BAD_VALUE;
342 }
343
344 uint32_t flags = 0;
345 for (;;) {
346 mTokenizer->skipDelimiters(WHITESPACE);
347 if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break;
348
349 String8 flagToken = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -0700350 uint32_t flag = InputEventLookup::getKeyFlagByLabel(flagToken.string());
Jeff Brown5912f952013-07-01 19:10:31 -0700351 if (!flag) {
352 ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(),
353 flagToken.string());
354 return BAD_VALUE;
355 }
356 if (flags & flag) {
357 ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(),
358 flagToken.string());
359 return BAD_VALUE;
360 }
361 flags |= flag;
362 }
363
364#if DEBUG_PARSER
365 ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.",
366 mapUsage ? "usage" : "scan code", code, keyCode, flags);
367#endif
368 Key key;
369 key.keyCode = keyCode;
370 key.flags = flags;
371 map.add(code, key);
372 return NO_ERROR;
373}
374
375status_t KeyLayoutMap::Parser::parseAxis() {
376 String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE);
377 char* end;
378 int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0));
379 if (*end) {
380 ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(),
381 scanCodeToken.string());
382 return BAD_VALUE;
383 }
384 if (mMap->mAxes.indexOfKey(scanCode) >= 0) {
385 ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(),
386 scanCodeToken.string());
387 return BAD_VALUE;
388 }
389
390 AxisInfo axisInfo;
391
392 mTokenizer->skipDelimiters(WHITESPACE);
393 String8 token = mTokenizer->nextToken(WHITESPACE);
394 if (token == "invert") {
395 axisInfo.mode = AxisInfo::MODE_INVERT;
396
397 mTokenizer->skipDelimiters(WHITESPACE);
398 String8 axisToken = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -0700399 axisInfo.axis = InputEventLookup::getAxisByLabel(axisToken.string());
Jeff Brown5912f952013-07-01 19:10:31 -0700400 if (axisInfo.axis < 0) {
401 ALOGE("%s: Expected inverted axis label, got '%s'.",
402 mTokenizer->getLocation().string(), axisToken.string());
403 return BAD_VALUE;
404 }
405 } else if (token == "split") {
406 axisInfo.mode = AxisInfo::MODE_SPLIT;
407
408 mTokenizer->skipDelimiters(WHITESPACE);
409 String8 splitToken = mTokenizer->nextToken(WHITESPACE);
410 axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0));
411 if (*end) {
412 ALOGE("%s: Expected split value, got '%s'.",
413 mTokenizer->getLocation().string(), splitToken.string());
414 return BAD_VALUE;
415 }
416
417 mTokenizer->skipDelimiters(WHITESPACE);
418 String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -0700419 axisInfo.axis = InputEventLookup::getAxisByLabel(lowAxisToken.string());
Jeff Brown5912f952013-07-01 19:10:31 -0700420 if (axisInfo.axis < 0) {
421 ALOGE("%s: Expected low axis label, got '%s'.",
422 mTokenizer->getLocation().string(), lowAxisToken.string());
423 return BAD_VALUE;
424 }
425
426 mTokenizer->skipDelimiters(WHITESPACE);
427 String8 highAxisToken = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -0700428 axisInfo.highAxis = InputEventLookup::getAxisByLabel(highAxisToken.string());
Jeff Brown5912f952013-07-01 19:10:31 -0700429 if (axisInfo.highAxis < 0) {
430 ALOGE("%s: Expected high axis label, got '%s'.",
431 mTokenizer->getLocation().string(), highAxisToken.string());
432 return BAD_VALUE;
433 }
434 } else {
Chris Ye4958d062020-08-20 13:21:10 -0700435 axisInfo.axis = InputEventLookup::getAxisByLabel(token.string());
Jeff Brown5912f952013-07-01 19:10:31 -0700436 if (axisInfo.axis < 0) {
437 ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.",
438 mTokenizer->getLocation().string(), token.string());
439 return BAD_VALUE;
440 }
441 }
442
443 for (;;) {
444 mTokenizer->skipDelimiters(WHITESPACE);
445 if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') {
446 break;
447 }
448 String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
449 if (keywordToken == "flat") {
450 mTokenizer->skipDelimiters(WHITESPACE);
451 String8 flatToken = mTokenizer->nextToken(WHITESPACE);
452 axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0));
453 if (*end) {
454 ALOGE("%s: Expected flat value, got '%s'.",
455 mTokenizer->getLocation().string(), flatToken.string());
456 return BAD_VALUE;
457 }
458 } else {
459 ALOGE("%s: Expected keyword 'flat', got '%s'.",
460 mTokenizer->getLocation().string(), keywordToken.string());
461 return BAD_VALUE;
462 }
463 }
464
465#if DEBUG_PARSER
466 ALOGD("Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, "
467 "splitValue=%d, flatOverride=%d.",
468 scanCode,
469 axisInfo.mode, axisInfo.axis, axisInfo.highAxis,
470 axisInfo.splitValue, axisInfo.flatOverride);
471#endif
472 mMap->mAxes.add(scanCode, axisInfo);
473 return NO_ERROR;
474}
475
Michael Wright74bdd2e2013-10-17 17:35:53 -0700476status_t KeyLayoutMap::Parser::parseLed() {
477 String8 codeToken = mTokenizer->nextToken(WHITESPACE);
478 bool mapUsage = false;
479 if (codeToken == "usage") {
480 mapUsage = true;
481 mTokenizer->skipDelimiters(WHITESPACE);
482 codeToken = mTokenizer->nextToken(WHITESPACE);
483 }
484 char* end;
485 int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
486 if (*end) {
487 ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(),
488 mapUsage ? "usage" : "scan code", codeToken.string());
489 return BAD_VALUE;
490 }
491
492 KeyedVector<int32_t, Led>& map = mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode;
493 if (map.indexOfKey(code) >= 0) {
494 ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(),
495 mapUsage ? "usage" : "scan code", codeToken.string());
496 return BAD_VALUE;
497 }
498
499 mTokenizer->skipDelimiters(WHITESPACE);
500 String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -0700501 int32_t ledCode = InputEventLookup::getLedByLabel(ledCodeToken.string());
Michael Wright74bdd2e2013-10-17 17:35:53 -0700502 if (ledCode < 0) {
503 ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(),
504 ledCodeToken.string());
505 return BAD_VALUE;
506 }
507
508#if DEBUG_PARSER
509 ALOGD("Parsed led %s: code=%d, ledCode=%d.",
510 mapUsage ? "usage" : "scan code", code, ledCode);
511#endif
512
513 Led led;
514 led.ledCode = ledCode;
515 map.add(code, led);
516 return NO_ERROR;
517}
Chris Yef59a2f42020-10-16 12:55:26 -0700518
519static std::optional<InputDeviceSensorType> getSensorType(const char* token) {
Dominik Laskowski75788452021-02-09 18:51:25 -0800520 auto it = SENSOR_LIST.find(token);
Chris Yef59a2f42020-10-16 12:55:26 -0700521 if (it == SENSOR_LIST.end()) {
522 return std::nullopt;
523 }
524 return it->second;
525}
526
527static std::optional<int32_t> getSensorDataIndex(String8 token) {
528 std::string tokenStr(token.string());
529 if (tokenStr == "X") {
530 return 0;
531 } else if (tokenStr == "Y") {
532 return 1;
533 } else if (tokenStr == "Z") {
534 return 2;
535 }
536 return std::nullopt;
537}
538
539// Parse sensor type and data index mapping, as below format
540// sensor <raw abs> <sensor type> <sensor data index>
541// raw abs : the linux abs code of the axis
542// sensor type : string name of InputDeviceSensorType
543// sensor data index : the data index of sensor, out of [X, Y, Z]
544// Examples:
545// sensor 0x00 ACCELEROMETER X
546// sensor 0x01 ACCELEROMETER Y
547// sensor 0x02 ACCELEROMETER Z
548// sensor 0x03 GYROSCOPE X
549// sensor 0x04 GYROSCOPE Y
550// sensor 0x05 GYROSCOPE Z
551status_t KeyLayoutMap::Parser::parseSensor() {
552 String8 codeToken = mTokenizer->nextToken(WHITESPACE);
553 char* end;
554 int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
555 if (*end) {
556 ALOGE("%s: Expected sensor %s number, got '%s'.", mTokenizer->getLocation().string(),
557 "abs code", codeToken.string());
558 return BAD_VALUE;
559 }
560
561 std::unordered_map<int32_t, Sensor>& map = mMap->mSensorsByAbsCode;
562 if (map.find(code) != map.end()) {
563 ALOGE("%s: Duplicate entry for sensor %s '%s'.", mTokenizer->getLocation().string(),
564 "abs code", codeToken.string());
565 return BAD_VALUE;
566 }
567
568 mTokenizer->skipDelimiters(WHITESPACE);
569 String8 sensorTypeToken = mTokenizer->nextToken(WHITESPACE);
570 std::optional<InputDeviceSensorType> typeOpt = getSensorType(sensorTypeToken.string());
571 if (!typeOpt) {
572 ALOGE("%s: Expected sensor code label, got '%s'.", mTokenizer->getLocation().string(),
573 sensorTypeToken.string());
574 return BAD_VALUE;
575 }
576 InputDeviceSensorType sensorType = typeOpt.value();
577 mTokenizer->skipDelimiters(WHITESPACE);
578 String8 sensorDataIndexToken = mTokenizer->nextToken(WHITESPACE);
579 std::optional<int32_t> indexOpt = getSensorDataIndex(sensorDataIndexToken);
580 if (!indexOpt) {
581 ALOGE("%s: Expected sensor data index label, got '%s'.", mTokenizer->getLocation().string(),
582 sensorDataIndexToken.string());
583 return BAD_VALUE;
584 }
585 int32_t sensorDataIndex = indexOpt.value();
586
587#if DEBUG_PARSER
Dominik Laskowski75788452021-02-09 18:51:25 -0800588 ALOGD("Parsed sensor: abs code=%d, sensorType=%s, sensorDataIndex=%d.", code,
589 ftl::enum_string(sensorType).c_str(), sensorDataIndex);
Chris Yef59a2f42020-10-16 12:55:26 -0700590#endif
591
592 Sensor sensor;
593 sensor.sensorType = sensorType;
594 sensor.sensorDataIndex = sensorDataIndex;
595 map.emplace(code, sensor);
596 return NO_ERROR;
597}
Dominik Laskowski75788452021-02-09 18:51:25 -0800598
599} // namespace android