| // Copyright 2016 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 "garnet/bin/ui/input_reader/input_interpreter.h" |
| |
| #include <fcntl.h> |
| #include <hid/acer12.h> |
| #include <hid/hid.h> |
| #include <hid/paradise.h> |
| #include <hid/samsung.h> |
| #include <hid/usages.h> |
| #include <zircon/device/device.h> |
| #include <zircon/device/input.h> |
| #include <zircon/types.h> |
| #include <sys/types.h> |
| #include <sys/uio.h> |
| #include <unistd.h> |
| |
| #include <trace/event.h> |
| |
| #include "lib/ui/input/cpp/formatting.h" |
| #include "lib/ui/input/fidl/usages.fidl.h" |
| #include "lib/fxl/logging.h" |
| #include "lib/fxl/time/time_point.h" |
| |
| namespace { |
| int64_t InputEventTimestampNow() { |
| return fxl::TimePoint::Now().ToEpochDelta().ToNanoseconds(); |
| } |
| } // namespace |
| |
| namespace mozart { |
| namespace input { |
| |
| std::unique_ptr<InputInterpreter> InputInterpreter::Open( |
| int dirfd, |
| std::string filename, |
| mozart::InputDeviceRegistry* registry) { |
| int fd = openat(dirfd, filename.c_str(), O_RDONLY); |
| if (fd < 0) { |
| FXL_LOG(ERROR) << "Failed to open device " << filename; |
| return nullptr; |
| } |
| |
| std::unique_ptr<InputInterpreter> device( |
| new InputInterpreter(filename, fd, registry)); |
| if (!device->Initialize()) { |
| return nullptr; |
| } |
| |
| return device; |
| } |
| |
| InputInterpreter::InputInterpreter(std::string name, |
| int fd, |
| mozart::InputDeviceRegistry* registry) |
| : fd_(fd), name_(std::move(name)), registry_(registry) { |
| memset(acer12_touch_reports_, 0, 2 * sizeof(acer12_touch_t)); |
| } |
| |
| InputInterpreter::~InputInterpreter() {} |
| |
| bool InputInterpreter::Initialize() { |
| int protocol; |
| if (!GetProtocol(&protocol)) { |
| FXL_LOG(ERROR) << "Failed to retrieve HID protocol for " << name_; |
| return false; |
| } |
| |
| if (protocol == INPUT_PROTO_KBD) { |
| FXL_VLOG(2) << "Device " << name_ << " has keyboard"; |
| has_keyboard_ = true; |
| keyboard_descriptor_ = mozart::KeyboardDescriptor::New(); |
| keyboard_descriptor_->keys.resize(HID_USAGE_KEY_RIGHT_GUI - |
| HID_USAGE_KEY_A + 1); |
| for (size_t index = HID_USAGE_KEY_A; index <= HID_USAGE_KEY_RIGHT_GUI; |
| ++index) { |
| keyboard_descriptor_->keys[index - HID_USAGE_KEY_A] = index; |
| } |
| |
| keyboard_report_ = mozart::InputReport::New(); |
| keyboard_report_->keyboard = mozart::KeyboardReport::New(); |
| } else if (protocol == INPUT_PROTO_MOUSE) { |
| FXL_VLOG(2) << "Device " << name_ << " has mouse"; |
| has_mouse_ = true; |
| mouse_device_type_ = MouseDeviceType::BOOT; |
| |
| mouse_descriptor_ = mozart::MouseDescriptor::New(); |
| mouse_descriptor_->rel_x = mozart::Axis::New(); |
| mouse_descriptor_->rel_x->range = mozart::Range::New(); |
| mouse_descriptor_->rel_x->range->min = INT32_MIN; |
| mouse_descriptor_->rel_x->range->max = INT32_MAX; |
| mouse_descriptor_->rel_x->resolution = 1; |
| |
| mouse_descriptor_->rel_y = mozart::Axis::New(); |
| mouse_descriptor_->rel_y->range = mozart::Range::New(); |
| mouse_descriptor_->rel_y->range->min = INT32_MIN; |
| mouse_descriptor_->rel_y->range->max = INT32_MAX; |
| mouse_descriptor_->rel_y->resolution = 1; |
| |
| mouse_descriptor_->buttons |= kMouseButtonPrimary; |
| mouse_descriptor_->buttons |= kMouseButtonSecondary; |
| mouse_descriptor_->buttons |= kMouseButtonTertiary; |
| |
| mouse_report_ = mozart::InputReport::New(); |
| mouse_report_->mouse = mozart::MouseReport::New(); |
| } else if (protocol == INPUT_PROTO_NONE) { |
| size_t report_desc_len; |
| if (!GetReportDescriptionLength(&report_desc_len)) { |
| FXL_LOG(ERROR) << "Failed to retrieve HID description length for " |
| << name_; |
| return false; |
| } |
| |
| std::vector<uint8_t> desc(report_desc_len); |
| if (!GetReportDescription(desc.data(), desc.size())) { |
| FXL_LOG(ERROR) << "Failed to retrieve HID description for " << name_; |
| return false; |
| } |
| |
| if (is_acer12_touch_report_desc(desc.data(), desc.size())) { |
| zx_status_t setup_res = setup_acer12_touch(fd_); |
| if (setup_res != ZX_OK) { |
| FXL_LOG(ERROR) << "Failed to setup Acer12 touch (res " << setup_res |
| << ")"; |
| return false; |
| } |
| |
| FXL_VLOG(2) << "Device " << name_ << " has stylus"; |
| has_stylus_ = true; |
| stylus_descriptor_ = mozart::StylusDescriptor::New(); |
| stylus_descriptor_->x = mozart::Axis::New(); |
| stylus_descriptor_->x->range = mozart::Range::New(); |
| stylus_descriptor_->x->range->min = 0; |
| stylus_descriptor_->x->range->max = ACER12_STYLUS_X_MAX; |
| stylus_descriptor_->x->resolution = 1; |
| |
| stylus_descriptor_->y = mozart::Axis::New(); |
| stylus_descriptor_->y->range = mozart::Range::New(); |
| stylus_descriptor_->y->range->min = 0; |
| stylus_descriptor_->y->range->max = ACER12_STYLUS_Y_MAX; |
| stylus_descriptor_->y->resolution = 1; |
| |
| stylus_descriptor_->is_invertible = false; |
| |
| stylus_descriptor_->buttons |= kStylusBarrel; |
| |
| stylus_report_ = mozart::InputReport::New(); |
| stylus_report_->stylus = mozart::StylusReport::New(); |
| |
| FXL_VLOG(2) << "Device " << name_ << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = mozart::TouchscreenDescriptor::New(); |
| touchscreen_descriptor_->x = mozart::Axis::New(); |
| touchscreen_descriptor_->x->range = mozart::Range::New(); |
| touchscreen_descriptor_->x->range->min = 0; |
| touchscreen_descriptor_->x->range->max = ACER12_X_MAX; |
| touchscreen_descriptor_->x->resolution = 1; |
| |
| touchscreen_descriptor_->y = mozart::Axis::New(); |
| touchscreen_descriptor_->y->range = mozart::Range::New(); |
| touchscreen_descriptor_->y->range->min = 0; |
| touchscreen_descriptor_->y->range->max = ACER12_Y_MAX; |
| touchscreen_descriptor_->y->resolution = 1; |
| |
| // TODO(jpoichet) do not hardcode this |
| touchscreen_descriptor_->max_finger_id = 255; |
| |
| touchscreen_report_ = mozart::InputReport::New(); |
| touchscreen_report_->touchscreen = mozart::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::ACER12; |
| } else if (is_samsung_touch_report_desc(desc.data(), desc.size())) { |
| zx_status_t setup_res = setup_samsung_touch(fd_); |
| if (setup_res != ZX_OK) { |
| FXL_LOG(ERROR) << "Failed to setup Samsung touch (res " << setup_res |
| << ")"; |
| return false; |
| } |
| |
| FXL_VLOG(2) << "Device " << name_ << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = mozart::TouchscreenDescriptor::New(); |
| touchscreen_descriptor_->x = mozart::Axis::New(); |
| touchscreen_descriptor_->x->range = mozart::Range::New(); |
| touchscreen_descriptor_->x->range->min = 0; |
| touchscreen_descriptor_->x->range->max = SAMSUNG_X_MAX; |
| touchscreen_descriptor_->x->resolution = 1; |
| |
| touchscreen_descriptor_->y = mozart::Axis::New(); |
| touchscreen_descriptor_->y->range = mozart::Range::New(); |
| touchscreen_descriptor_->y->range->min = 0; |
| touchscreen_descriptor_->y->range->max = SAMSUNG_Y_MAX; |
| touchscreen_descriptor_->y->resolution = 1; |
| |
| // TODO(jpoichet) do not hardcode this |
| touchscreen_descriptor_->max_finger_id = 255; |
| |
| touchscreen_report_ = mozart::InputReport::New(); |
| touchscreen_report_->touchscreen = mozart::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::SAMSUNG; |
| } else if (is_paradise_touch_report_desc(desc.data(), desc.size())) { |
| zx_status_t setup_res = setup_paradise_touch(fd_); |
| if (setup_res != ZX_OK) { |
| FXL_LOG(ERROR) << "Failed to setup Paradise touch (res " << setup_res |
| << ")"; |
| return false; |
| } |
| |
| // TODO(cpu): Add support for stylus. |
| |
| FXL_VLOG(2) << "Device " << name_ << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = mozart::TouchscreenDescriptor::New(); |
| touchscreen_descriptor_->x = mozart::Axis::New(); |
| touchscreen_descriptor_->x->range = mozart::Range::New(); |
| touchscreen_descriptor_->x->range->min = 0; |
| touchscreen_descriptor_->x->range->max = PARADISE_X_MAX; |
| touchscreen_descriptor_->x->resolution = 1; |
| |
| touchscreen_descriptor_->y = mozart::Axis::New(); |
| touchscreen_descriptor_->y->range = mozart::Range::New(); |
| touchscreen_descriptor_->y->range->min = 0; |
| touchscreen_descriptor_->y->range->max = PARADISE_Y_MAX; |
| touchscreen_descriptor_->y->resolution = 1; |
| |
| // TODO(cpu) do not hardcode |max_finger_id|. |
| touchscreen_descriptor_->max_finger_id = 255; |
| |
| touchscreen_report_ = mozart::InputReport::New(); |
| touchscreen_report_->touchscreen = mozart::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::PARADISE; |
| } else if (is_paradise_touchpad_report_desc(desc.data(), desc.size())) { |
| zx_status_t setup_res = setup_paradise_touchpad(fd_); |
| if (setup_res != ZX_OK) { |
| FXL_LOG(ERROR) << "Failed to setup Paradise touchpad (res " |
| << setup_res << ")"; |
| return true; |
| } |
| |
| FXL_VLOG(2) << "Device " << name_ << " has touchpad"; |
| has_mouse_ = true; |
| mouse_device_type_ = MouseDeviceType::PARADISE; |
| |
| mouse_descriptor_ = mozart::MouseDescriptor::New(); |
| mouse_descriptor_->rel_x = mozart::Axis::New(); |
| mouse_descriptor_->rel_x->range = mozart::Range::New(); |
| mouse_descriptor_->rel_x->range->min = INT32_MIN; |
| mouse_descriptor_->rel_x->range->max = INT32_MAX; |
| mouse_descriptor_->rel_x->resolution = 1; |
| |
| mouse_descriptor_->rel_y = mozart::Axis::New(); |
| mouse_descriptor_->rel_y->range = mozart::Range::New(); |
| mouse_descriptor_->rel_y->range->min = INT32_MIN; |
| mouse_descriptor_->rel_y->range->max = INT32_MAX; |
| mouse_descriptor_->rel_y->resolution = 1; |
| |
| mouse_descriptor_->buttons |= kMouseButtonPrimary; |
| |
| mouse_report_ = mozart::InputReport::New(); |
| mouse_report_->mouse = mozart::MouseReport::New(); |
| } else { |
| FXL_VLOG(2) << "Device " << name_ << " has unsupported HID device"; |
| return false; |
| } |
| } else { |
| FXL_VLOG(2) << "Device " << name_ << " has unsupported HID protocol"; |
| return false; |
| } |
| |
| // Get event handle for file descriptor |
| zx_handle_t handle; |
| ssize_t rc = ioctl_device_get_event_handle(fd_, &handle); |
| if (rc < 0) { |
| FXL_LOG(ERROR) << "Could not convert file descriptor to handle"; |
| return false; |
| } |
| |
| event_.reset(handle); |
| |
| if (!GetMaxReportLength(&max_report_len_)) { |
| FXL_LOG(ERROR) << "Failed to retrieve maximum HID report length for " |
| << name_; |
| return false; |
| } |
| |
| report_.reserve(max_report_len_); |
| |
| NotifyRegistry(); |
| |
| return true; |
| } |
| |
| void InputInterpreter::NotifyRegistry() { |
| mozart::DeviceDescriptorPtr descriptor = mozart::DeviceDescriptor::New(); |
| if (has_keyboard_) { |
| descriptor->keyboard = keyboard_descriptor_.Clone(); |
| } |
| if (has_mouse_) { |
| descriptor->mouse = mouse_descriptor_.Clone(); |
| } |
| if (has_stylus_) { |
| descriptor->stylus = stylus_descriptor_.Clone(); |
| } |
| if (has_touchscreen_) { |
| descriptor->touchscreen = touchscreen_descriptor_.Clone(); |
| } |
| |
| registry_->RegisterDevice(std::move(descriptor), input_device_.NewRequest()); |
| } |
| |
| bool InputInterpreter::Read(bool discard) { |
| int rc = read(fd_, report_.data(), max_report_len_); |
| if (rc < 1) { |
| FXL_LOG(ERROR) << "Failed to read from input: " << rc; |
| // TODO(jpoichet) check whether the device was actually closed or not |
| return false; |
| } |
| |
| TRACE_DURATION("input", "Read"); |
| if (has_keyboard_) { |
| ParseKeyboardReport(report_.data(), rc); |
| if (!discard) { |
| input_device_->DispatchReport(keyboard_report_.Clone()); |
| } |
| } |
| |
| switch (mouse_device_type_) { |
| case MouseDeviceType::BOOT: |
| ParseMouseReport(report_.data(), rc); |
| if (!discard) { |
| input_device_->DispatchReport(mouse_report_.Clone()); |
| } |
| break; |
| case MouseDeviceType::PARADISE: |
| if (ParseParadiseTouchpadReport(report_.data(), rc)) { |
| if (!discard) { |
| input_device_->DispatchReport(mouse_report_.Clone()); |
| } |
| } |
| break; |
| case MouseDeviceType::NONE: |
| break; |
| } |
| |
| switch (touch_device_type_) { |
| case TouchDeviceType::ACER12: |
| if (report_[0] == ACER12_RPT_ID_STYLUS) { |
| if (ParseAcer12StylusReport(report_.data(), rc)) { |
| if (!discard) { |
| input_device_->DispatchReport(stylus_report_.Clone()); |
| } |
| } |
| } else if (report_[0] == ACER12_RPT_ID_TOUCH) { |
| if (ParseAcer12TouchscreenReport(report_.data(), rc)) { |
| if (!discard) { |
| input_device_->DispatchReport(touchscreen_report_.Clone()); |
| } |
| } |
| } |
| break; |
| |
| case TouchDeviceType::SAMSUNG: |
| if (report_[0] == SAMSUNG_RPT_ID_TOUCH) { |
| if (ParseSamsungTouchscreenReport(report_.data(), rc)) { |
| if (!discard) { |
| input_device_->DispatchReport(touchscreen_report_.Clone()); |
| } |
| } |
| } |
| break; |
| |
| case TouchDeviceType::PARADISE: |
| if (report_[0] == PARADISE_RPT_ID_TOUCH) { |
| if (ParseParadiseTouchscreenReport(report_.data(), rc)) { |
| if (!discard) { |
| input_device_->DispatchReport(touchscreen_report_.Clone()); |
| } |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| return true; |
| } |
| |
| void InputInterpreter::ParseKeyboardReport(uint8_t* report, size_t len) { |
| hid_keys_t key_state; |
| uint8_t keycode; |
| hid_kbd_parse_report(report, &key_state); |
| keyboard_report_->event_time = InputEventTimestampNow(); |
| |
| size_t index = 0; |
| keyboard_report_->keyboard->pressed_keys.resize(index); |
| hid_for_every_key(&key_state, keycode) { |
| keyboard_report_->keyboard->pressed_keys.resize(index + 1); |
| keyboard_report_->keyboard->pressed_keys[index] = keycode; |
| index++; |
| } |
| FXL_VLOG(2) << name_ << " parsed: " << *keyboard_report_; |
| } |
| |
| void InputInterpreter::ParseMouseReport(uint8_t* r, size_t len) { |
| auto report = reinterpret_cast<boot_mouse_report_t*>(r); |
| mouse_report_->event_time = InputEventTimestampNow(); |
| |
| mouse_report_->mouse->rel_x = report->rel_x; |
| mouse_report_->mouse->rel_y = report->rel_y; |
| mouse_report_->mouse->pressed_buttons = report->buttons; |
| FXL_VLOG(2) << name_ << " parsed: " << *mouse_report_; |
| } |
| |
| bool InputInterpreter::ParseAcer12StylusReport(uint8_t* r, size_t len) { |
| if (len != sizeof(acer12_stylus_t)) { |
| return false; |
| } |
| |
| auto report = reinterpret_cast<acer12_stylus_t*>(r); |
| stylus_report_->event_time = InputEventTimestampNow(); |
| |
| stylus_report_->stylus->x = report->x; |
| stylus_report_->stylus->y = report->y; |
| stylus_report_->stylus->pressure = report->pressure; |
| |
| stylus_report_->stylus->is_in_contact = |
| acer12_stylus_status_inrange(report->status) && |
| (acer12_stylus_status_tswitch(report->status) || |
| acer12_stylus_status_eraser(report->status)); |
| |
| stylus_report_->stylus->in_range = |
| acer12_stylus_status_inrange(report->status); |
| |
| if (acer12_stylus_status_invert(report->status) || |
| acer12_stylus_status_eraser(report->status)) { |
| stylus_report_->stylus->is_inverted = true; |
| } |
| |
| if (acer12_stylus_status_barrel(report->status)) { |
| stylus_report_->stylus->pressed_buttons |= kStylusBarrel; |
| } |
| FXL_VLOG(2) << name_ << " parsed: " << *stylus_report_; |
| |
| return true; |
| } |
| |
| bool InputInterpreter::ParseAcer12TouchscreenReport(uint8_t* r, size_t len) { |
| if (len != sizeof(acer12_touch_t)) { |
| return false; |
| } |
| |
| // Acer12 touch reports come in pairs when there are more than 5 fingers |
| // First report has the actual number of fingers stored in contact_count, |
| // second report will have a contact_count of 0. |
| auto report = reinterpret_cast<acer12_touch_t*>(r); |
| if (report->contact_count > 0) { |
| acer12_touch_reports_[0] = *report; |
| } else { |
| acer12_touch_reports_[1] = *report; |
| } |
| touchscreen_report_->event_time = InputEventTimestampNow(); |
| |
| size_t index = 0; |
| touchscreen_report_->touchscreen->touches.resize(index); |
| |
| for (uint8_t i = 0; i < 2; i++) { |
| // Only 5 touches per report |
| for (uint8_t c = 0; c < 5; c++) { |
| auto fid = acer12_touch_reports_[i].fingers[c].finger_id; |
| |
| if (!acer12_finger_id_tswitch(fid)) |
| continue; |
| mozart::TouchPtr touch = mozart::Touch::New(); |
| touch->finger_id = acer12_finger_id_contact(fid); |
| touch->x = acer12_touch_reports_[i].fingers[c].x; |
| touch->y = acer12_touch_reports_[i].fingers[c].y; |
| touch->width = acer12_touch_reports_[i].fingers[c].width; |
| touch->height = acer12_touch_reports_[i].fingers[c].height; |
| touchscreen_report_->touchscreen->touches.resize(index + 1); |
| touchscreen_report_->touchscreen->touches[index++] = std::move(touch); |
| } |
| } |
| FXL_VLOG(2) << name_ << " parsed: " << *touchscreen_report_; |
| return true; |
| } |
| |
| bool InputInterpreter::ParseSamsungTouchscreenReport(uint8_t* r, size_t len) { |
| if (len != sizeof(samsung_touch_t)) { |
| return false; |
| } |
| |
| const auto& report = *(reinterpret_cast<samsung_touch_t*>(r)); |
| touchscreen_report_->event_time = InputEventTimestampNow(); |
| |
| size_t index = 0; |
| touchscreen_report_->touchscreen->touches.resize(index); |
| |
| for (size_t i = 0; i < countof(report.fingers); ++i) { |
| auto fid = report.fingers[i].finger_id; |
| |
| if (!samsung_finger_id_tswitch(fid)) |
| continue; |
| |
| mozart::TouchPtr touch = mozart::Touch::New(); |
| touch->finger_id = samsung_finger_id_contact(fid); |
| touch->x = report.fingers[i].x; |
| touch->y = report.fingers[i].y; |
| touch->width = report.fingers[i].width; |
| touch->height = report.fingers[i].height; |
| touchscreen_report_->touchscreen->touches.resize(index + 1); |
| touchscreen_report_->touchscreen->touches[index++] = std::move(touch); |
| } |
| |
| return true; |
| } |
| |
| bool InputInterpreter::ParseParadiseTouchscreenReport(uint8_t* r, size_t len) { |
| if (len != sizeof(paradise_touch_t)) { |
| FXL_LOG(INFO) << "paradise wrong size " << len; |
| return false; |
| } |
| |
| const auto& report = *(reinterpret_cast<paradise_touch_t*>(r)); |
| touchscreen_report_->event_time = InputEventTimestampNow(); |
| |
| size_t index = 0; |
| touchscreen_report_->touchscreen->touches.resize(index); |
| |
| for (size_t i = 0; i < countof(report.fingers); ++i) { |
| if (!paradise_finger_flags_tswitch(report.fingers[i].flags)) |
| continue; |
| |
| mozart::TouchPtr touch = mozart::Touch::New(); |
| touch->finger_id = report.fingers[i].finger_id; |
| touch->x = report.fingers[i].x; |
| touch->y = report.fingers[i].y; |
| touch->width = 5; // TODO(cpu): Don't hardcode |width| or |height|. |
| touch->height = 5; |
| touchscreen_report_->touchscreen->touches.resize(index + 1); |
| touchscreen_report_->touchscreen->touches[index++] = std::move(touch); |
| } |
| |
| FXL_VLOG(2) << name_ << " parsed: " << *touchscreen_report_; |
| return true; |
| } |
| |
| bool InputInterpreter::ParseParadiseTouchpadReport(uint8_t* r, size_t len) { |
| if (len != sizeof(paradise_touchpad_t)) { |
| FXL_LOG(INFO) << "paradise wrong size " << len; |
| return false; |
| } |
| |
| mouse_report_->event_time = InputEventTimestampNow(); |
| |
| const auto& report = *(reinterpret_cast<paradise_touchpad_t*>(r)); |
| if (!report.fingers[0].tip_switch) { |
| mouse_report_->mouse->rel_x = 0; |
| mouse_report_->mouse->rel_y = 0; |
| mouse_report_->mouse->pressed_buttons = 0; |
| |
| mouse_abs_x_ = -1; |
| return true; |
| } |
| |
| // Each axis has a resolution of .00078125cm. 5/32 is a relatively arbitrary |
| // coefficient that gives decent sensitivity and a nice resolution of .005cm. |
| mouse_report_->mouse->rel_x = |
| mouse_abs_x_ != -1 ? 5 * (report.fingers[0].x - mouse_abs_x_) / 32 : 0; |
| mouse_report_->mouse->rel_y = |
| mouse_abs_x_ != -1 ? 5 * (report.fingers[0].y - mouse_abs_y_) / 32 : 0; |
| mouse_report_->mouse->pressed_buttons = |
| report.button ? kMouseButtonPrimary : 0; |
| |
| // Don't update the abs position if there was no relative change, so that |
| // we don't drop fractional relative deltas. |
| if (mouse_report_->mouse->rel_y || mouse_abs_x_ == -1) { |
| mouse_abs_y_ = report.fingers[0].y; |
| } |
| if (mouse_report_->mouse->rel_x || mouse_abs_x_ == -1) { |
| mouse_abs_x_ = report.fingers[0].x; |
| } |
| |
| return true; |
| } |
| |
| |
| zx_status_t InputInterpreter::GetProtocol(int* out_proto) { |
| ssize_t rc = ioctl_input_get_protocol(fd_, out_proto); |
| if (rc < 0) { |
| FXL_LOG(ERROR) << "hid: could not get protocol from " << name_ |
| << " (status=" << rc << ")"; |
| } |
| return rc; |
| } |
| |
| zx_status_t InputInterpreter::GetReportDescriptionLength( |
| size_t* out_report_desc_len) { |
| ssize_t rc = ioctl_input_get_report_desc_size(fd_, out_report_desc_len); |
| if (rc < 0) { |
| FXL_LOG(ERROR) << "hid: could not get report descriptor length from " |
| << name_ << " (status=" << rc << ")"; |
| } |
| return rc; |
| } |
| |
| zx_status_t InputInterpreter::GetReportDescription(uint8_t* out_buf, |
| size_t out_report_desc_len) { |
| ssize_t rc = ioctl_input_get_report_desc(fd_, out_buf, out_report_desc_len); |
| if (rc < 0) { |
| FXL_LOG(ERROR) << "hid: could not get report descriptor from " << name_ |
| << " (status=" << rc << ")"; |
| } |
| return rc; |
| } |
| |
| zx_status_t InputInterpreter::GetMaxReportLength( |
| input_report_size_t* out_max_report_len) { |
| ssize_t rc = ioctl_input_get_max_reportsize(fd_, out_max_report_len); |
| if (rc < 0) { |
| FXL_LOG(ERROR) << "hid: could not get max report size from " << name_ |
| << " (status=" << rc << ")"; |
| } |
| return rc; |
| } |
| |
| } // namespace input |
| } // namespace mozart |