Home | History | Annotate | Download | only in recovery
      1 /*
      2  * Copyright (C) 2016 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 #include "common.h"
     18 #include "wear_touch.h"
     19 
     20 #include <dirent.h>
     21 #include <fcntl.h>
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <unistd.h>
     25 #include <errno.h>
     26 #include <string.h>
     27 
     28 #include <linux/input.h>
     29 
     30 #define DEVICE_PATH "/dev/input"
     31 
     32 WearSwipeDetector::WearSwipeDetector(int low, int high, OnSwipeCallback callback, void* cookie):
     33     mLowThreshold(low),
     34     mHighThreshold(high),
     35     mCallback(callback),
     36     mCookie(cookie),
     37     mCurrentSlot(-1) {
     38     pthread_create(&mThread, NULL, touch_thread, this);
     39 }
     40 
     41 WearSwipeDetector::~WearSwipeDetector() {
     42 }
     43 
     44 void WearSwipeDetector::detect(int dx, int dy) {
     45     enum SwipeDirection direction;
     46 
     47     if (abs(dy) < mLowThreshold && abs(dx) > mHighThreshold) {
     48         direction = dx < 0 ? LEFT : RIGHT;
     49     } else if (abs(dx) < mLowThreshold && abs(dy) > mHighThreshold) {
     50         direction = dy < 0 ? UP : DOWN;
     51     } else {
     52         LOGD("Ignore %d %d\n", dx, dy);
     53         return;
     54     }
     55 
     56     LOGD("Swipe direction=%d\n", direction);
     57     mCallback(mCookie, direction);
     58 }
     59 
     60 void WearSwipeDetector::process(struct input_event *event) {
     61     if (mCurrentSlot < 0) {
     62         mCallback(mCookie, UP);
     63         mCurrentSlot = 0;
     64     }
     65 
     66     if (event->type == EV_ABS) {
     67         if (event->code == ABS_MT_SLOT)
     68             mCurrentSlot = event->value;
     69 
     70         // Ignore other fingers
     71         if (mCurrentSlot > 0) {
     72             return;
     73         }
     74 
     75         switch (event->code) {
     76         case ABS_MT_POSITION_X:
     77             mX = event->value;
     78             mFingerDown = true;
     79             break;
     80 
     81         case ABS_MT_POSITION_Y:
     82             mY = event->value;
     83             mFingerDown = true;
     84             break;
     85 
     86         case ABS_MT_TRACKING_ID:
     87             if (event->value < 0)
     88                 mFingerDown = false;
     89             break;
     90         }
     91     } else if (event->type == EV_SYN) {
     92         if (event->code == SYN_REPORT) {
     93             if (mFingerDown && !mSwiping) {
     94                 mStartX = mX;
     95                 mStartY = mY;
     96                 mSwiping = true;
     97             } else if (!mFingerDown && mSwiping) {
     98                 mSwiping = false;
     99                 detect(mX - mStartX, mY - mStartY);
    100             }
    101         }
    102     }
    103 }
    104 
    105 void WearSwipeDetector::run() {
    106     int fd = findDevice(DEVICE_PATH);
    107     if (fd < 0) {
    108         LOGE("no input devices found\n");
    109         return;
    110     }
    111 
    112     struct input_event event;
    113     while (read(fd, &event, sizeof(event)) == sizeof(event)) {
    114         process(&event);
    115     }
    116 
    117     close(fd);
    118 }
    119 
    120 void* WearSwipeDetector::touch_thread(void* cookie) {
    121     ((WearSwipeDetector*)cookie)->run();
    122     return NULL;
    123 }
    124 
    125 #define test_bit(bit, array)    (array[bit/8] & (1<<(bit%8)))
    126 
    127 int WearSwipeDetector::openDevice(const char *device) {
    128     int fd = open(device, O_RDONLY);
    129     if (fd < 0) {
    130         LOGE("could not open %s, %s\n", device, strerror(errno));
    131         return false;
    132     }
    133 
    134     char name[80];
    135     name[sizeof(name) - 1] = '\0';
    136     if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
    137         LOGE("could not get device name for %s, %s\n", device, strerror(errno));
    138         name[0] = '\0';
    139     }
    140 
    141     uint8_t bits[512];
    142     memset(bits, 0, sizeof(bits));
    143     int ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
    144     if (ret > 0) {
    145         if (test_bit(ABS_MT_POSITION_X, bits) && test_bit(ABS_MT_POSITION_Y, bits)) {
    146             LOGD("Found %s %s\n", device, name);
    147             return fd;
    148         }
    149     }
    150 
    151     close(fd);
    152     return -1;
    153 }
    154 
    155 int WearSwipeDetector::findDevice(const char* path) {
    156     DIR* dir = opendir(path);
    157     if (dir == NULL) {
    158         LOGE("Could not open directory %s", path);
    159         return false;
    160     }
    161 
    162     struct dirent* entry;
    163     int ret = -1;
    164     while (ret < 0 && (entry = readdir(dir)) != NULL) {
    165         if (entry->d_name[0] == '.') continue;
    166 
    167         char device[PATH_MAX];
    168         device[PATH_MAX-1] = '\0';
    169         snprintf(device, PATH_MAX-1, "%s/%s", path, entry->d_name);
    170 
    171         ret = openDevice(device);
    172     }
    173 
    174     closedir(dir);
    175     return ret;
    176 }
    177 
    178