Home | History | Annotate | Download | only in evdev
      1 /*
      2  * Copyright (C) 2015 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 "SwitchInputMapper"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include "SwitchInputMapper.h"
     21 
     22 #include <inttypes.h>
     23 #include <linux/input.h>
     24 #include <hardware/input.h>
     25 #include <utils/Log.h>
     26 
     27 #include "InputHost.h"
     28 #include "InputHub.h"
     29 
     30 namespace android {
     31 
     32 static struct {
     33     int32_t scancode;
     34     InputUsage usage;
     35 } codeMap[] = {
     36     {SW_LID, INPUT_USAGE_SWITCH_LID},
     37     {SW_TABLET_MODE, INPUT_USAGE_SWITCH_UNKNOWN},
     38     {SW_HEADPHONE_INSERT, INPUT_USAGE_SWITCH_HEADPHONE_INSERT},
     39     {SW_RFKILL_ALL, INPUT_USAGE_SWITCH_UNKNOWN},
     40     {SW_MICROPHONE_INSERT, INPUT_USAGE_SWITCH_MICROPHONE_INSERT},
     41     {SW_DOCK, INPUT_USAGE_SWITCH_UNKNOWN},
     42     {SW_LINEOUT_INSERT, INPUT_USAGE_SWITCH_LINEOUT_INSERT},
     43     {SW_JACK_PHYSICAL_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
     44     {SW_VIDEOOUT_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
     45     {SW_CAMERA_LENS_COVER, INPUT_USAGE_SWITCH_CAMERA_LENS_COVER},
     46     {SW_KEYPAD_SLIDE, INPUT_USAGE_SWITCH_KEYPAD_SLIDE},
     47     {SW_FRONT_PROXIMITY, INPUT_USAGE_SWITCH_UNKNOWN},
     48     {SW_ROTATE_LOCK, INPUT_USAGE_SWITCH_UNKNOWN},
     49     {SW_LINEIN_INSERT, INPUT_USAGE_SWITCH_UNKNOWN},
     50     {0x0e /* unused */, INPUT_USAGE_SWITCH_UNKNOWN},
     51     {SW_MAX, INPUT_USAGE_SWITCH_UNKNOWN},
     52 };
     53 
     54 SwitchInputMapper::SwitchInputMapper()
     55     : InputMapper() {
     56     static_assert(SW_CNT <= 32, "More than 32 switches defined in linux/input.h");
     57 }
     58 
     59 bool SwitchInputMapper::configureInputReport(InputDeviceNode* devNode,
     60         InputReportDefinition* report) {
     61     InputUsage usages[SW_CNT];
     62     int numUsages = 0;
     63     for (int32_t i = 0; i < SW_CNT; ++i) {
     64         if (devNode->hasSwitch(codeMap[i].scancode)) {
     65             usages[numUsages++] = codeMap[i].usage;
     66         }
     67     }
     68     if (numUsages == 0) {
     69         ALOGE("SwitchInputMapper found no switches for %s!", devNode->getPath().c_str());
     70         return false;
     71     }
     72     setInputReportDefinition(report);
     73     getInputReportDefinition()->addCollection(INPUT_COLLECTION_ID_SWITCH, 1);
     74     getInputReportDefinition()->declareUsages(INPUT_COLLECTION_ID_SWITCH, usages, numUsages);
     75     return true;
     76 }
     77 
     78 void SwitchInputMapper::process(const InputEvent& event) {
     79     switch (event.type) {
     80         case EV_SW:
     81             processSwitch(event.code, event.value);
     82             break;
     83         case EV_SYN:
     84             if (event.code == SYN_REPORT) {
     85                 sync(event.when);
     86             }
     87             break;
     88         default:
     89             ALOGV("unknown switch event type: %d", event.type);
     90     }
     91 }
     92 
     93 void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
     94     ALOGV("processing switch event. code=%" PRId32 ", value=%" PRId32, switchCode, switchValue);
     95     if (switchCode >= 0 && switchCode < SW_CNT) {
     96         if (switchValue) {
     97             mSwitchValues.markBit(switchCode);
     98         } else {
     99             mSwitchValues.clearBit(switchCode);
    100         }
    101         mUpdatedSwitchMask.markBit(switchCode);
    102     }
    103 }
    104 
    105 void SwitchInputMapper::sync(nsecs_t when) {
    106     if (mUpdatedSwitchMask.isEmpty()) {
    107         // Clear the values just in case.
    108         mSwitchValues.clear();
    109         return;
    110     }
    111 
    112     while (!mUpdatedSwitchMask.isEmpty()) {
    113         auto bit = mUpdatedSwitchMask.firstMarkedBit();
    114         getInputReport()->setBoolUsage(INPUT_COLLECTION_ID_SWITCH, codeMap[bit].usage,
    115                 mSwitchValues.hasBit(bit), 0);
    116         mUpdatedSwitchMask.clearBit(bit);
    117     }
    118     getInputReport()->reportEvent(getDeviceHandle());
    119     mUpdatedSwitchMask.clear();
    120     mSwitchValues.clear();
    121 }
    122 
    123 }  // namespace android
    124