| // 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* filter) |
| : current_touching_(0), prev_touching_(0), filter_(filter), |
| current_slot_(0) { |
| for (size_t i = 0; i < arraysize(frames_[0].fingers_); i++) { |
| PrevFrame()->fingers_[i].tracking_id_ = -1; |
| CurrentFrame()->fingers_[i].tracking_id_ = -1; |
| } |
| } |
| |
| 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; |
| } |
| #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 canceled_ bit cleared |
| if ((current_touching_ & (1ULL << i)) && |
| !(prev_touching_ & (1ULL << i))) |
| cur_finger->canceled_ = false; |
| } |
| CurrentFrame()->timestamp_ = TimevalToDouble(ev->time); |
| filter_->FilterFrame(PrevFrame(), CurrentFrame(), TOUCH_NOISE_MAX_SLOTS); |
| memcpy(PrevFrame(), CurrentFrame(), sizeof(Frame)); |
| prev_touching_ = current_touching_; |
| break; |
| } |
| } |
| } |
| |
| void InputEventFilter::GetCanceledTouches(uint64_t* slots_mask) { |
| for (size_t i = 0; i < arraysize(frames_[0].fingers_); i++) { |
| if (CurrentFrame()->fingers_[i].canceled_) { |
| __s32 tracking_id = CurrentFrame()->fingers_[i].tracking_id_; |
| if (tracking_id == -1) |
| tracking_id = PrevFrame()->fingers_[i].tracking_id_; |
| if (tracking_id != -1) |
| Log("TrackingID %d cancelled", tracking_id); |
| (*slots_mask) |= 1 << i; |
| // If the finger was released, we can lose the cancel bit |
| if (!(prev_touching_ & (1ULL << i))) |
| CurrentFrame()->fingers_[i].canceled_ = 0; |
| } |
| } |
| } |
| |
| } // namespace touch_noise_filter |