14f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn/*
24f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * Copyright (C) 2015 The Android Open Source Project
34f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn *
44f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * Licensed under the Apache License, Version 2.0 (the "License");
54f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * you may not use this file except in compliance with the License.
64f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * You may obtain a copy of the License at
74f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn *
84f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn *      http://www.apache.org/licenses/LICENSE-2.0
94f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn *
104f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * Unless required by applicable law or agreed to in writing, software
114f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * distributed under the License is distributed on an "AS IS" BASIS,
124f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * See the License for the specific language governing permissions and
144f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn * limitations under the License.
154f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn */
164f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
174f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn#define LOG_TAG "SwitchInputMapper"
184f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn//#define LOG_NDEBUG 0
194f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
204f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn#include "SwitchInputMapper.h"
214f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
22fdd4d81ca191ae6096e94be1bf98975d17766b1aMichael Wright#include <inttypes.h>
234f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn#include <linux/input.h>
244f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn#include <hardware/input.h>
254f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn#include <utils/Log.h>
264f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
274f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn#include "InputHost.h"
284f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn#include "InputHub.h"
294f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
304f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbournnamespace android {
314f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
324f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbournstatic struct {
334f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    int32_t scancode;
344f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    InputUsage usage;
354f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn} codeMap[] = {
364f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_LID, INPUT_USAGE_SWITCH_LID},
374f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_TABLET_MODE, INPUT_USAGE_SWITCH_UNKNOWN},
384f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_HEADPHONE_INSERT, INPUT_USAGE_SWITCH_HEADPHONE_INSERT},
394f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_RFKILL_ALL, INPUT_USAGE_SWITCH_UNKNOWN},
404f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_MICROPHONE_INSERT, INPUT_USAGE_SWITCH_MICROPHONE_INSERT},
414f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_DOCK, INPUT_USAGE_SWITCH_UNKNOWN},
424f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_LINEOUT_INSERT, INPUT_USAGE_SWITCH_LINEOUT_INSERT},
434f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_JACK_PHYSICAL_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
444f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_VIDEOOUT_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
454f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_CAMERA_LENS_COVER, INPUT_USAGE_SWITCH_CAMERA_LENS_COVER},
464f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_KEYPAD_SLIDE, INPUT_USAGE_SWITCH_KEYPAD_SLIDE},
474f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_FRONT_PROXIMITY, INPUT_USAGE_SWITCH_UNKNOWN},
484f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_ROTATE_LOCK, INPUT_USAGE_SWITCH_UNKNOWN},
494f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_LINEIN_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
504f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {0x0e /* unused */, INPUT_USAGE_SWITCH_UNKNOWN},
514f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    {SW_MAX, INPUT_USAGE_SWITCH_UNKNOWN},
524f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn};
534f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
544f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim KilbournSwitchInputMapper::SwitchInputMapper()
554f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    : InputMapper() {
564f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    static_assert(SW_CNT <= 32, "More than 32 switches defined in linux/input.h");
574f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn}
584f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
594f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbournbool SwitchInputMapper::configureInputReport(InputDeviceNode* devNode,
604f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        InputReportDefinition* report) {
614f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    InputUsage usages[SW_CNT];
624f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    int numUsages = 0;
634f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    for (int32_t i = 0; i < SW_CNT; ++i) {
644f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        if (devNode->hasSwitch(codeMap[i].scancode)) {
654f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn            usages[numUsages++] = codeMap[i].usage;
664f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        }
674f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    }
684f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    if (numUsages == 0) {
694f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        ALOGE("SwitchInputMapper found no switches for %s!", devNode->getPath().c_str());
704f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        return false;
714f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    }
724f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    setInputReportDefinition(report);
734f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    getInputReportDefinition()->addCollection(INPUT_COLLECTION_ID_SWITCH, 1);
744f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    getInputReportDefinition()->declareUsages(INPUT_COLLECTION_ID_SWITCH, usages, numUsages);
754f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    return true;
764f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn}
774f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
784f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbournvoid SwitchInputMapper::process(const InputEvent& event) {
794f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    switch (event.type) {
804f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        case EV_SW:
814f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn            processSwitch(event.code, event.value);
824f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn            break;
834f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        case EV_SYN:
844f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn            if (event.code == SYN_REPORT) {
854f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn                sync(event.when);
864f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn            }
874f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn            break;
884f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        default:
89fdd4d81ca191ae6096e94be1bf98975d17766b1aMichael Wright            ALOGV("unknown switch event type: %d", event.type);
904f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    }
914f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn}
924f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
934f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbournvoid SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
94fdd4d81ca191ae6096e94be1bf98975d17766b1aMichael Wright    ALOGV("processing switch event. code=%" PRId32 ", value=%" PRId32, switchCode, switchValue);
954f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    if (switchCode >= 0 && switchCode < SW_CNT) {
964f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        if (switchValue) {
974f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn            mSwitchValues.markBit(switchCode);
984f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        } else {
994f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn            mSwitchValues.clearBit(switchCode);
1004f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        }
1014f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        mUpdatedSwitchMask.markBit(switchCode);
1024f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    }
1034f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn}
1044f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
1054f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbournvoid SwitchInputMapper::sync(nsecs_t when) {
1064f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    if (mUpdatedSwitchMask.isEmpty()) {
1074f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        // Clear the values just in case.
1084f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        mSwitchValues.clear();
1094f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        return;
1104f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    }
1114f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
1124f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    while (!mUpdatedSwitchMask.isEmpty()) {
1134f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        auto bit = mUpdatedSwitchMask.firstMarkedBit();
1144f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        getInputReport()->setBoolUsage(INPUT_COLLECTION_ID_SWITCH, codeMap[bit].usage,
1154f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn                mSwitchValues.hasBit(bit), 0);
1164f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn        mUpdatedSwitchMask.clearBit(bit);
1174f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    }
1184f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    getInputReport()->reportEvent(getDeviceHandle());
1194f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    mUpdatedSwitchMask.clear();
1204f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    mSwitchValues.clear();
1214f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn}
1224f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn
1234f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn}  // namespace android
124