| // Copyright 2019 The Fuchsia 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 "input_touch.h" |
| |
| #include <ddk/debug.h> |
| #include <ddk/protocol/hidbus.h> |
| #include <fbl/algorithm.h> |
| |
| #include "src/devices/bus/lib/virtio/trace.h" |
| |
| #define LOCAL_TRACE 0 |
| |
| namespace virtio { |
| |
| zx_status_t HidTouch::GetDescriptor(uint8_t desc_type, void* out_data_buffer, size_t data_size, |
| size_t* out_data_actual) { |
| if (out_data_buffer == nullptr || out_data_actual == nullptr) { |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| if (desc_type != HID_DESCRIPTION_TYPE_REPORT) { |
| return ZX_ERR_NOT_FOUND; |
| } |
| |
| size_t buflen = 0; |
| const uint8_t* buf = get_paradise_touch_report_desc(&buflen); |
| |
| if (data_size < buflen) { |
| return ZX_ERR_BUFFER_TOO_SMALL; |
| } |
| memcpy(out_data_buffer, buf, buflen); |
| *out_data_actual = buflen; |
| return ZX_OK; |
| } |
| |
| void HidTouch::ReceiveEvent(virtio_input_event_t* event) { |
| if (event->type == VIRTIO_INPUT_EV_ABS) { |
| if (event->code == VIRTIO_INPUT_EV_MT_SLOT) { |
| if (event->value > MAX_TOUCH_POINTS) { |
| LTRACEF("ERROR: Slot is too large for touchscreen\n"); |
| mt_slot_ = -1; |
| return; |
| } |
| mt_slot_ = event->value; |
| } |
| |
| if (mt_slot_ < 0 || mt_slot_ > MAX_TOUCH_POINTS) { |
| return; |
| } |
| |
| if (event->code == VIRTIO_INPUT_EV_MT_TRACKING_ID) { |
| paradise_finger_t& finger = report_.fingers[mt_slot_]; |
| // If tracking id is -1 we have to remove the finger from being tracked. |
| if (static_cast<int>(event->value) == -1) { |
| if (finger.flags & PARADISE_FINGER_FLAGS_TSWITCH_MASK) { |
| finger.flags &= static_cast<uint8_t>(~PARADISE_FINGER_FLAGS_TSWITCH_MASK); |
| report_.contact_count--; |
| } |
| } else { |
| if (!(finger.flags & PARADISE_FINGER_FLAGS_TSWITCH_MASK)) { |
| finger.flags |= static_cast<uint8_t>(PARADISE_FINGER_FLAGS_TSWITCH_MASK); |
| report_.contact_count++; |
| } |
| } |
| finger.finger_id = static_cast<uint16_t>(event->value); |
| } else if (event->code == VIRTIO_INPUT_EV_MT_POSITION_X) { |
| report_.fingers[mt_slot_].x = |
| static_cast<uint16_t>(event->value * PARADISE_X_MAX / x_info_.max); |
| } else if (event->code == VIRTIO_INPUT_EV_MT_POSITION_Y) { |
| report_.fingers[mt_slot_].y = |
| static_cast<uint16_t>(event->value * PARADISE_Y_MAX / y_info_.max); |
| } |
| } |
| } |
| |
| const uint8_t* HidTouch::GetReport(size_t* size) { |
| *size = sizeof(report_); |
| return reinterpret_cast<const uint8_t*>(&report_); |
| } |
| |
| } // namespace virtio |