| // Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "touch_noise_filter/input_event_filter.h" |
| |
| #include <linux/input.h> |
| #include <stdio.h> |
| |
| #include <base/basictypes.h> |
| |
| namespace touch_noise_filter { |
| |
| InputEventFilter::InputEventFilter(NoiseFilter* next) |
| : current_frame_(0), current_touching_(0), prev_touching_(0), |
| next_(next), current_slot_(0) { |
| for (size_t i = 0; i < arraysize(frames_); i++) { |
| for (size_t j = 0; j < arraysize(frames_[i].fingers_); j++) { |
| frames_[i].fingers_[j].slot_ = j; |
| } |
| } |
| } |
| |
| namespace { |
| #define SETSTR(type_num, code_num) \ |
| do { \ |
| if ((ev)->type == type_num) { \ |
| type_str = #type_num; \ |
| if ((ev)->code == code_num) { \ |
| code_str = #code_num; \ |
| } \ |
| } \ |
| } while (0) |
| |
| double TimevalToDouble(const struct timeval& tv) { |
| // printf("%ld usec\n", tv.tv_usec); |
| return static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / |
| 1000000.0; |
| } |
| |
| void LogInputEvent(const struct input_event* ev) { |
| const char* type_str = "(unknown)"; |
| const char* code_str = "(unknown)"; |
| |
| SETSTR(EV_KEY, BTN_TOUCH); |
| |
| SETSTR(EV_ABS, ABS_X); |
| SETSTR(EV_ABS, ABS_Y); |
| SETSTR(EV_ABS, ABS_Z); |
| SETSTR(EV_ABS, ABS_RX); |
| SETSTR(EV_ABS, ABS_RY); |
| SETSTR(EV_ABS, ABS_RZ); |
| SETSTR(EV_ABS, ABS_THROTTLE); |
| SETSTR(EV_ABS, ABS_RUDDER); |
| SETSTR(EV_ABS, ABS_WHEEL); |
| SETSTR(EV_ABS, ABS_GAS); |
| SETSTR(EV_ABS, ABS_BRAKE); |
| SETSTR(EV_ABS, ABS_HAT0X); |
| SETSTR(EV_ABS, ABS_HAT0Y); |
| SETSTR(EV_ABS, ABS_HAT1X); |
| SETSTR(EV_ABS, ABS_HAT1Y); |
| SETSTR(EV_ABS, ABS_HAT2X); |
| SETSTR(EV_ABS, ABS_HAT2Y); |
| SETSTR(EV_ABS, ABS_HAT3X); |
| SETSTR(EV_ABS, ABS_HAT3Y); |
| SETSTR(EV_ABS, ABS_PRESSURE); |
| SETSTR(EV_ABS, ABS_DISTANCE); |
| SETSTR(EV_ABS, ABS_TILT_X); |
| SETSTR(EV_ABS, ABS_TILT_Y); |
| SETSTR(EV_ABS, ABS_TOOL_WIDTH); |
| |
| SETSTR(EV_ABS, ABS_MT_SLOT); |
| SETSTR(EV_ABS, ABS_MT_TOUCH_MAJOR); |
| SETSTR(EV_ABS, ABS_MT_TOUCH_MINOR); |
| SETSTR(EV_ABS, ABS_MT_WIDTH_MAJOR); |
| SETSTR(EV_ABS, ABS_MT_WIDTH_MINOR); |
| SETSTR(EV_ABS, ABS_MT_ORIENTATION); |
| SETSTR(EV_ABS, ABS_MT_POSITION_X); |
| SETSTR(EV_ABS, ABS_MT_POSITION_Y); |
| SETSTR(EV_ABS, ABS_MT_TOOL_TYPE); |
| SETSTR(EV_ABS, ABS_MT_BLOB_ID); |
| SETSTR(EV_ABS, ABS_MT_TRACKING_ID); |
| SETSTR(EV_ABS, ABS_MT_PRESSURE); |
| SETSTR(EV_ABS, ABS_MT_DISTANCE); |
| |
| if (ev->type == 0 && ev->code == 0) { |
| TouchNoiseFilterLog("INPUT: %f ---------- SYN_REPORT ----------\n", |
| TimevalToDouble(ev->time)); |
| } else { |
| TouchNoiseFilterLog("INPUT: %f %s %s %d\n", |
| TimevalToDouble(ev->time), type_str, code_str, ev->value); |
| } |
| } |
| |
| #undef SETSTR |
| } // namespace {} |
| |
| void InputEventFilter::HandleInputEvent(const struct input_event* ev) { |
| static const __u16 kMinKey = ABS_MT_TOUCH_MAJOR; |
| |
| static __s32 Finger::* const member_map[] = { |
| // The first one must correspond w/ kMinKey above, and they must be in |
| // numerical order. |
| NULL, // ABS_MT_TOUCH_MAJOR |
| NULL, // ABS_MT_TOUCH_MINOR |
| NULL, // ABS_MT_WIDTH_MAJOR |
| NULL, // ABS_MT_WIDTH_MINOR |
| NULL, // ABS_MT_ORIENTATION |
| &Finger::x_pos_, // ABS_MT_POSITION_X |
| &Finger::y_pos_, // ABS_MT_POSITION_Y |
| NULL, // ABS_MT_TOOL_TYPE |
| NULL, // ABS_MT_BLOB_ID |
| &Finger::tracking_id_, // ABS_MT_TRACKING_ID |
| NULL, // ABS_MT_PRESSURE |
| }; |
| |
| switch (ev->type) { |
| case EV_ABS: { |
| switch (ev->code) { |
| case ABS_MT_SLOT: |
| current_slot_ = ev->value; |
| break; |
| case ABS_MT_TRACKING_ID: |
| if (ev->value >= 0) |
| current_touching_ |= (1ULL << current_slot_); |
| else |
| current_touching_ &= ~(1ULL << current_slot_); |
| // fallthrough |
| default: |
| if (ev->code < kMinKey || |
| ev->code >= kMinKey + arraysize(member_map) || |
| member_map[ev->code - kMinKey] == NULL) |
| break; |
| CurrentFrame()->fingers_[ |
| current_slot_].*member_map[ev->code - kMinKey] = ev->value; |
| |
| break; |
| } |
| break; |
| } |
| case EV_SYN: { |
| for (size_t i = 0; i < arraysize(frames_[0].fingers_); i++) { |
| Finger* cur_finger = &CurrentFrame()->fingers_[i]; |
| // New fingers should have their cancelled_ bit cleared |
| if ((current_touching_ & (1ULL << i)) && |
| !(prev_touching_ & (1ULL << i))) |
| cur_finger->cancelled_ = false; |
| cur_finger->timestamp_ = TimevalToDouble(ev->time); |
| next_->FilterFinger(cur_finger); |
| } |
| prev_touching_ = current_touching_; |
| break; |
| } |
| } |
| } |
| |
| void InputEventFilter::GetCancelledTouches(uint64_t* slots_mask) { |
| for (size_t i = 0; i < arraysize(frames_[0].fingers_); i++) { |
| if (CurrentFrame()->fingers_[i].cancelled_) { |
| (*slots_mask) |= 1 << i; |
| // If the finger was released, we can lose the cancel bit |
| if (!(prev_touching_ & (1ULL << i))) |
| CurrentFrame()->fingers_[i].cancelled_ = 0; |
| } |
| } |
| } |
| |
| } // namespace touch_noise_filter |