blob: 14a12c4c8a31f48c86e33f11a81a9ba9c002e8e3 [file] [log] [blame]
// 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