| // Copyright 2020 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 <zircon/status.h> |
| |
| #include <cstdint> |
| #include <iterator> |
| |
| #include <ddk/debug.h> |
| #include <fbl/algorithm.h> |
| #include <virtio/input.h> |
| |
| #include "src/devices/bus/lib/virtio/trace.h" |
| #include "src/ui/input/drivers/virtio/input.h" |
| |
| #define LOCAL_TRACE 0 |
| |
| namespace virtio { |
| |
| namespace { |
| |
| constexpr uint16_t kKeyCodeBtnLeft = 0x110; // BTN_LEFT |
| constexpr uint16_t kKeyCodeBtnRight = 0x111; // BTN_RIGHT |
| constexpr uint16_t kKeyCodeBtnMiddle = 0x112; // BTN_MIDDLE |
| |
| constexpr uint8_t kButtonIndexLeft = 1; |
| constexpr uint8_t kButtonIndexRight = 2; |
| constexpr uint8_t kButtonIndexMid = 3; |
| |
| } // namespace |
| |
| zx_status_t HidMouse::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 report_size = 0u; |
| const uint8_t* report_descriptor = get_virtio_scroll_mouse_report_desc(&report_size); |
| |
| if (data_size < report_size) { |
| return ZX_ERR_BUFFER_TOO_SMALL; |
| } |
| memcpy(out_data_buffer, report_descriptor, report_size); |
| *out_data_actual = report_size; |
| return ZX_OK; |
| } |
| |
| void HidMouse::ReceiveKeyEvent(virtio_input_event_t* event) { |
| ZX_DEBUG_ASSERT(event->type == VIRTIO_INPUT_EV_KEY); |
| uint16_t key_code = event->code; |
| uint32_t status = event->value; |
| |
| uint8_t button_idx = 0; |
| switch (key_code) { |
| case kKeyCodeBtnLeft: |
| button_idx = kButtonIndexLeft; |
| break; |
| case kKeyCodeBtnRight: |
| button_idx = kButtonIndexRight; |
| break; |
| case kKeyCodeBtnMiddle: |
| button_idx = kButtonIndexMid; |
| break; |
| default: |
| zxlogf(ERROR, "%s: key code %u not supported!", __func__, key_code); |
| return; |
| } |
| |
| if (status == VIRTIO_INPUT_EV_KEY_PRESSED) { |
| report_.button |= 1 << (button_idx - 1); |
| } else { |
| report_.button &= ~(1 << (button_idx - 1)); |
| } |
| } |
| |
| void HidMouse::ReceiveRelEvent(virtio_input_event_t* event) { |
| ZX_DEBUG_ASSERT(event->type == VIRTIO_INPUT_EV_REL); |
| switch (event->code) { |
| case VIRTIO_INPUT_EV_REL_X: |
| report_.rel_x = static_cast<int16_t>(event->value); |
| break; |
| case VIRTIO_INPUT_EV_REL_Y: |
| report_.rel_y = static_cast<int16_t>(event->value); |
| break; |
| case VIRTIO_INPUT_EV_REL_HWHEEL: |
| // TODO(65215): Support horizontal wheel scrolling. |
| break; |
| case VIRTIO_INPUT_EV_REL_WHEEL: |
| report_.rel_wheel = static_cast<int16_t>(event->value); |
| break; |
| default: |
| zxlogf(ERROR, "%s: event code %u not supported!", __func__, event->code); |
| return; |
| } |
| } |
| |
| void HidMouse::ReceiveEvent(virtio_input_event_t* event) { |
| switch (event->type) { |
| case VIRTIO_INPUT_EV_KEY: |
| ReceiveKeyEvent(event); |
| break; |
| case VIRTIO_INPUT_EV_REL: |
| ReceiveRelEvent(event); |
| break; |
| case VIRTIO_INPUT_EV_SYN: |
| // EV_SYN events will be handled by InputDevice directly after calling |
| // |ReceiveEvent|, so we ignore the SYN event here. |
| break; |
| default: |
| zxlogf(ERROR, "%s: unsupported event type %u!", __func__, event->type); |
| break; |
| } |
| } |
| |
| const uint8_t* HidMouse::GetReport(size_t* size) { |
| *size = sizeof(report_); |
| return reinterpret_cast<const uint8_t*>(&report_); |
| } |
| |
| } // namespace virtio |