| // 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 "garnet/bin/ui/input_reader/hardcoded.h" |
| |
| #include <fuchsia/hardware/input/c/fidl.h> |
| #include <fuchsia/ui/input/cpp/fidl.h> |
| #include <hid-parser/parser.h> |
| #include <hid-parser/usages.h> |
| #include <hid/acer12.h> |
| #include <hid/ambient-light.h> |
| #include <hid/boot.h> |
| #include <hid/egalax.h> |
| #include <hid/eyoyo.h> |
| #include <hid/ft3x27.h> |
| #include <hid/hid.h> |
| #include <hid/paradise.h> |
| #include <hid/samsung.h> |
| #include <hid/usages.h> |
| #include <lib/ui/input/cpp/formatting.h> |
| #include <src/lib/fxl/arraysize.h> |
| #include <src/lib/fxl/logging.h> |
| #include <src/lib/fxl/time/time_point.h> |
| #include <sys/types.h> |
| #include <sys/uio.h> |
| #include <trace/event.h> |
| #include <zircon/errors.h> |
| #include <zircon/types.h> |
| |
| namespace { |
| |
| // Variable to quickly re-enable the hardcoded touchpad reports. |
| // TODO(ZX-3219): Remove this once touchpads are stable |
| bool USE_TOUCHPAD_HARDCODED_REPORTS = false; |
| bool USE_TOUCHSCREEN_HARDCODED_REPORTS = false; |
| |
| int64_t InputEventTimestampNow() { |
| return fxl::TimePoint::Now().ToEpochDelta().ToNanoseconds(); |
| } |
| |
| fuchsia::ui::input::InputReport CloneReport( |
| const fuchsia::ui::input::InputReport& report) { |
| fuchsia::ui::input::InputReport result; |
| fidl::Clone(report, &result); |
| return result; |
| } |
| |
| // Casting from unsigned to signed can change the bit pattern so |
| // we need to resort to this method. |
| int8_t signed_bit_cast(uint8_t src) { |
| int8_t dest; |
| memcpy(&dest, &src, sizeof(uint8_t)); |
| return dest; |
| } |
| |
| // Extracts up to 8 bits unsigned number from a byte array |v|. |
| // Both |begin| and |count| are in bits units. This function does not |
| // check for the array being long enough. |
| static uint8_t extract_uint8(const uint8_t* v, uint32_t begin, uint32_t count) { |
| uint8_t val = v[begin / 8u] >> (begin % 8u); |
| return (count < 8) ? (val & ~(1u << count)) : val; |
| } |
| |
| // Extracts a 16 bits unsigned number from a byte array |v|. |
| // |begin| is in bits units. This function does not check for the array |
| // being long enough. |
| static uint16_t extract_uint16(const uint8_t* v, uint32_t begin) { |
| return static_cast<uint16_t>(extract_uint8(v, begin, 8)) | |
| static_cast<uint16_t>(extract_uint8(v, begin + 8, 8)) << 8; |
| } |
| |
| // Extracts up to 8 bits sign extended to int32_t from a byte array |v|. |
| // Both |begin| and |count| are in bits units. This function does not |
| // check for the array being long enough. |
| static int32_t extract_int8_ext(const uint8_t* v, uint32_t begin, |
| uint32_t count) { |
| uint8_t val = extract_uint8(v, begin, count); |
| return signed_bit_cast(val); |
| } |
| |
| // TODO(SCN-473): Extract sensor IDs from HID. |
| const size_t kParadiseAccLid = 0; |
| const size_t kParadiseAccBase = 1; |
| const size_t kAmbientLight = 2; |
| |
| } // namespace |
| |
| namespace ui_input { |
| |
| bool Hardcoded::ParseGamepadDescriptor(const hid::ReportField* fields, |
| size_t count) { |
| // Need to recover the five fields as seen in HidGamepadSimple and put |
| // them into the decoder_ in the same order. |
| if (count < 5u) |
| return false; |
| |
| decoder_.resize(6u); |
| uint8_t offset = 0; |
| |
| if (fields[0].report_id != 0) { |
| // If exists, the first entry (8-bits) is always the report id and |
| // all items start after the first byte. |
| decoder_[0] = DataLocator{0u, 8u, fields[0].report_id}; |
| offset = 8u; |
| } |
| |
| // Needs to be kept in sync with HidGamepadSimple {}. |
| const uint16_t table[] = { |
| static_cast<uint16_t>(hid::usage::GenericDesktop::kX), // left X. |
| static_cast<uint16_t>(hid::usage::GenericDesktop::kY), // left Y. |
| static_cast<uint16_t>(hid::usage::GenericDesktop::kZ), // right X. |
| static_cast<uint16_t>(hid::usage::GenericDesktop::kRz), // right Y. |
| static_cast<uint16_t>(hid::usage::GenericDesktop::kHatSwitch) // buttons |
| }; |
| |
| uint32_t bit_count = 0; |
| |
| // Traverse each input report field and see if there is a match in the table. |
| // If so place the location in |decoder_| array. |
| for (size_t ix = 0; ix != count; ix++) { |
| if (fields[ix].type != hid::kInput) |
| continue; |
| |
| for (size_t iy = 0; iy != arraysize(table); iy++) { |
| if (fields[ix].attr.usage.usage == table[iy]) { |
| // Found a required usage. |
| decoder_[iy + 1] = |
| DataLocator{bit_count + offset, fields[ix].attr.bit_sz, 0}; |
| break; |
| } |
| } |
| |
| bit_count += fields[ix].attr.bit_sz; |
| } |
| |
| // Here |decoder_| should look like this: |
| // [rept_id][left X][left Y]....[hat_sw] |
| // With each box, the location in a report for each item, for example: |
| // [0, 0, 0][24, 0, 0][8, 0, 0][0, 0, 0]...[64, 4, 0] |
| return true; |
| } |
| |
| bool Hardcoded::ParseAmbientLightDescriptor(const hid::ReportField* fields, |
| size_t count) { |
| if (count == 0u) |
| return false; |
| |
| decoder_.resize(2u); |
| uint8_t offset = 0; |
| |
| if (fields[0].report_id != 0) { |
| // If exists, the first entry (8-bits) is always the report id and |
| // all items start after the first byte. |
| decoder_[0] = DataLocator{0u, 8u, fields[0].report_id}; |
| offset = 8u; |
| } |
| |
| uint32_t bit_count = 0; |
| |
| // Traverse each input report field and see if there is a match in the table. |
| // If so place the location in |decoder_| array. |
| for (size_t ix = 0; ix != count; ix++) { |
| if (fields[ix].type != hid::kInput) |
| continue; |
| |
| if (fields[ix].attr.usage.usage == hid::usage::Sensor::kLightIlluminance) { |
| decoder_[1] = DataLocator{bit_count + offset, fields[ix].attr.bit_sz, 0}; |
| // Found a required usage. |
| // Here |decoder_| should look like this: |
| // [rept_id][abs_light] |
| return true; |
| } |
| |
| bit_count += fields[ix].attr.bit_sz; |
| } |
| return false; |
| } |
| |
| bool Hardcoded::ParseKeyboardReport( |
| uint8_t* report, size_t len, |
| fuchsia::ui::input::InputReport* keyboard_report) { |
| hid_keys_t key_state; |
| uint8_t keycode; |
| hid_kbd_parse_report(report, &key_state); |
| keyboard_report->event_time = InputEventTimestampNow(); |
| keyboard_report->trace_id = TRACE_NONCE(); |
| |
| std::vector<uint32_t> pressed_keys; |
| hid_for_every_key(&key_state, keycode) { |
| if (keycode == HID_USAGE_KEY_ERROR_ROLLOVER) { |
| FXL_VLOG(2) << name() << " rollover error"; |
| return false; |
| } |
| pressed_keys.push_back(keycode); |
| } |
| pressed_keys.swap(keyboard_report->keyboard->pressed_keys); |
| FXL_VLOG(2) << name() << " parsed: " << *keyboard_report; |
| |
| return true; |
| } |
| |
| void Hardcoded::ParseMouseReport( |
| uint8_t* r, size_t len, fuchsia::ui::input::InputReport* mouse_report) { |
| auto report = reinterpret_cast<hid_boot_mouse_report_t*>(r); |
| mouse_report->event_time = InputEventTimestampNow(); |
| mouse_report->trace_id = TRACE_NONCE(); |
| |
| 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 Hardcoded::ParseReport(const uint8_t* report, size_t len, |
| HidGamepadSimple* gamepad) { |
| auto cur = &decoder_[0]; |
| if ((cur->match != 0) && (cur->count == 8u)) { |
| // The first byte is the report id. |
| if (report[0] != cur->match) { |
| // This is a normal condition. The device can generate reports |
| // for controls we don't yet handle. |
| *gamepad = {}; |
| return true; |
| } |
| ++cur; |
| } |
| |
| gamepad->left_x = extract_int8_ext(report, cur->begin, cur->count) / 2; |
| ++cur; |
| gamepad->left_y = extract_int8_ext(report, cur->begin, cur->count) / 2; |
| ++cur; |
| gamepad->right_x = extract_int8_ext(report, cur->begin, cur->count) / 2; |
| ++cur; |
| gamepad->right_y = extract_int8_ext(report, cur->begin, cur->count) / 2; |
| ++cur; |
| gamepad->hat_switch = extract_int8_ext(report, cur->begin, cur->count); |
| return true; |
| } |
| |
| bool Hardcoded::ParseGamepadMouseReport( |
| uint8_t* report, size_t len, |
| fuchsia::ui::input::InputReport* mouse_report) { |
| HidGamepadSimple gamepad = {}; |
| if (!ParseReport(report, len, &gamepad)) |
| return false; |
| mouse_report->event_time = InputEventTimestampNow(); |
| mouse_report->trace_id = TRACE_NONCE(); |
| |
| mouse_report->mouse->rel_x = gamepad.left_x; |
| mouse_report->mouse->rel_y = gamepad.left_y; |
| mouse_report->mouse->pressed_buttons = gamepad.hat_switch; |
| return true; |
| } |
| |
| bool Hardcoded::ParseAcer12TouchscreenReport( |
| uint8_t* r, size_t len, |
| fuchsia::ui::input::InputReport* touchscreen_report) { |
| 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(); |
| touchscreen_report->trace_id = TRACE_NONCE(); |
| |
| 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; |
| fuchsia::ui::input::Touch touch; |
| 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.at(index++) = std::move(touch); |
| } |
| } |
| FXL_VLOG(2) << name() << " parsed: " << *touchscreen_report; |
| return true; |
| } |
| |
| bool Hardcoded::ParseAcer12StylusReport( |
| uint8_t* r, size_t len, fuchsia::ui::input::InputReport* stylus_report) { |
| if (len != sizeof(acer12_stylus_t)) { |
| return false; |
| } |
| |
| auto report = reinterpret_cast<acer12_stylus_t*>(r); |
| stylus_report->event_time = InputEventTimestampNow(); |
| stylus_report->trace_id = TRACE_NONCE(); |
| |
| 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 |= fuchsia::ui::input::kStylusBarrel; |
| } |
| FXL_VLOG(2) << name() << " parsed: " << *stylus_report; |
| |
| return true; |
| } |
| |
| bool Hardcoded::ParseSamsungTouchscreenReport( |
| uint8_t* r, size_t len, |
| fuchsia::ui::input::InputReport* touchscreen_report) { |
| if (len != sizeof(samsung_touch_t)) { |
| return false; |
| } |
| |
| const auto& report = *(reinterpret_cast<samsung_touch_t*>(r)); |
| touchscreen_report->event_time = InputEventTimestampNow(); |
| touchscreen_report->trace_id = TRACE_NONCE(); |
| |
| size_t index = 0; |
| touchscreen_report->touchscreen->touches.resize(index); |
| |
| for (size_t i = 0; i < arraysize(report.fingers); ++i) { |
| auto fid = report.fingers[i].finger_id; |
| |
| if (!samsung_finger_id_tswitch(fid)) |
| continue; |
| |
| fuchsia::ui::input::Touch touch; |
| 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.at(index++) = std::move(touch); |
| } |
| |
| return true; |
| } |
| |
| bool Hardcoded::ParseParadiseTouchscreenReportV1( |
| uint8_t* r, size_t len, |
| fuchsia::ui::input::InputReport* touchscreen_report) { |
| return ParseParadiseTouchscreenReport<paradise_touch_t>(r, len, |
| touchscreen_report); |
| } |
| |
| bool Hardcoded::ParseParadiseTouchscreenReportV2( |
| uint8_t* r, size_t len, |
| fuchsia::ui::input::InputReport* touchscreen_report) { |
| return ParseParadiseTouchscreenReport<paradise_touch_v2_t>( |
| r, len, touchscreen_report); |
| } |
| |
| template <typename ReportT> |
| bool Hardcoded::ParseParadiseTouchscreenReport( |
| uint8_t* r, size_t len, |
| fuchsia::ui::input::InputReport* touchscreen_report) { |
| if (len != sizeof(ReportT)) { |
| FXL_LOG(INFO) << "paradise wrong size " << len; |
| return false; |
| } |
| |
| const auto& report = *(reinterpret_cast<ReportT*>(r)); |
| touchscreen_report->event_time = InputEventTimestampNow(); |
| touchscreen_report->trace_id = TRACE_NONCE(); |
| |
| size_t index = 0; |
| touchscreen_report->touchscreen->touches.resize(index); |
| |
| for (size_t i = 0; i < arraysize(report.fingers); ++i) { |
| if (!paradise_finger_flags_tswitch(report.fingers[i].flags)) |
| continue; |
| |
| fuchsia::ui::input::Touch touch; |
| 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.at(index++) = std::move(touch); |
| } |
| |
| FXL_VLOG(2) << name() << " parsed: " << *touchscreen_report; |
| return true; |
| } |
| |
| bool Hardcoded::ParseEGalaxTouchscreenReport( |
| uint8_t* r, size_t len, |
| fuchsia::ui::input::InputReport* touchscreen_report) { |
| if (len != sizeof(egalax_touch_t)) { |
| FXL_LOG(INFO) << "egalax wrong size " << len << " expected " |
| << sizeof(egalax_touch_t); |
| return false; |
| } |
| |
| const auto& report = *(reinterpret_cast<egalax_touch_t*>(r)); |
| touchscreen_report->event_time = InputEventTimestampNow(); |
| touchscreen_report->trace_id = TRACE_NONCE(); |
| if (egalax_pressed_flags(report.button_pad)) { |
| fuchsia::ui::input::Touch touch; |
| touch.finger_id = 0; |
| touch.x = report.x; |
| touch.y = report.y; |
| touch.width = 5; |
| touch.height = 5; |
| touchscreen_report->touchscreen->touches.resize(1); |
| touchscreen_report->touchscreen->touches.at(0) = std::move(touch); |
| } else { |
| // if the button isn't pressed, send an empty report, this will terminate |
| // the finger session |
| touchscreen_report->touchscreen->touches.resize(0); |
| } |
| |
| FXL_VLOG(2) << name() << " parsed: " << *touchscreen_report; |
| return true; |
| } |
| |
| bool Hardcoded::ParseParadiseTouchpadReportV1( |
| uint8_t* r, size_t len, fuchsia::ui::input::InputReport* touchpad_report) { |
| return ParseParadiseTouchpadReport<paradise_touchpad_v1_t>(r, len, |
| touchpad_report); |
| } |
| |
| bool Hardcoded::ParseParadiseTouchpadReportV2( |
| uint8_t* r, size_t len, fuchsia::ui::input::InputReport* touchpad_report) { |
| return ParseParadiseTouchpadReport<paradise_touchpad_v1_t>(r, len, |
| touchpad_report); |
| } |
| |
| template <typename ReportT> |
| bool Hardcoded::ParseParadiseTouchpadReport( |
| uint8_t* r, size_t len, fuchsia::ui::input::InputReport* mouse_report) { |
| if (len != sizeof(ReportT)) { |
| FXL_LOG(INFO) << "paradise wrong size " << len; |
| return false; |
| } |
| |
| mouse_report->event_time = InputEventTimestampNow(); |
| mouse_report->trace_id = TRACE_NONCE(); |
| |
| const auto& report = *(reinterpret_cast<ReportT*>(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 ? fuchsia::ui::input::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; |
| } |
| |
| bool Hardcoded::ParseParadiseStylusReport( |
| uint8_t* r, size_t len, fuchsia::ui::input::InputReport* stylus_report) { |
| if (len != sizeof(paradise_stylus_t)) { |
| FXL_LOG(INFO) << "paradise wrong stylus report size " << len; |
| return false; |
| } |
| |
| auto report = reinterpret_cast<paradise_stylus_t*>(r); |
| stylus_report->event_time = InputEventTimestampNow(); |
| stylus_report->trace_id = TRACE_NONCE(); |
| |
| stylus_report->stylus->x = report->x; |
| stylus_report->stylus->y = report->y; |
| stylus_report->stylus->pressure = report->pressure; |
| |
| stylus_report->stylus->is_in_contact = |
| paradise_stylus_status_inrange(report->status) && |
| (paradise_stylus_status_tswitch(report->status) || |
| paradise_stylus_status_eraser(report->status)); |
| |
| stylus_report->stylus->in_range = |
| paradise_stylus_status_inrange(report->status); |
| |
| if (paradise_stylus_status_invert(report->status) || |
| paradise_stylus_status_eraser(report->status)) { |
| stylus_report->stylus->is_inverted = true; |
| } |
| |
| if (paradise_stylus_status_barrel(report->status)) { |
| stylus_report->stylus->pressed_buttons |= fuchsia::ui::input::kStylusBarrel; |
| } |
| FXL_VLOG(2) << name() << " parsed: " << *stylus_report; |
| |
| return true; |
| } |
| |
| bool Hardcoded::ParseEyoyoTouchscreenReport( |
| uint8_t* r, size_t len, |
| fuchsia::ui::input::InputReport* touchscreen_report) { |
| if (len != sizeof(eyoyo_touch_t)) { |
| return false; |
| } |
| |
| const auto& report = *(reinterpret_cast<eyoyo_touch_t*>(r)); |
| touchscreen_report->event_time = InputEventTimestampNow(); |
| touchscreen_report->trace_id = TRACE_NONCE(); |
| |
| size_t index = 0; |
| touchscreen_report->touchscreen->touches.resize(index); |
| |
| for (size_t i = 0; i < arraysize(report.fingers); ++i) { |
| auto fid = report.fingers[i].finger_id; |
| |
| if (!eyoyo_finger_id_tswitch(fid)) |
| continue; |
| |
| fuchsia::ui::input::Touch touch; |
| touch.finger_id = eyoyo_finger_id_contact(fid); |
| touch.x = report.fingers[i].x; |
| touch.y = report.fingers[i].y; |
| // Panel does not support touch width/height. |
| touch.width = 5; |
| touch.height = 5; |
| touchscreen_report->touchscreen->touches.resize(index + 1); |
| touchscreen_report->touchscreen->touches.at(index++) = std::move(touch); |
| } |
| |
| return true; |
| } |
| |
| bool Hardcoded::ParseFt3x27TouchscreenReport( |
| uint8_t* r, size_t len, |
| fuchsia::ui::input::InputReport* touchscreen_report) { |
| if (len != sizeof(ft3x27_touch_t)) { |
| return false; |
| } |
| |
| const auto& report = *(reinterpret_cast<ft3x27_touch_t*>(r)); |
| touchscreen_report->event_time = InputEventTimestampNow(); |
| touchscreen_report->trace_id = TRACE_NONCE(); |
| |
| size_t index = 0; |
| touchscreen_report->touchscreen->touches.resize(index); |
| |
| for (size_t i = 0; i < arraysize(report.fingers); ++i) { |
| auto fid = report.fingers[i].finger_id; |
| |
| if (!ft3x27_finger_id_tswitch(fid)) |
| continue; |
| |
| fuchsia::ui::input::Touch touch; |
| touch.finger_id = ft3x27_finger_id_contact(fid); |
| touch.x = report.fingers[i].x; |
| touch.y = report.fingers[i].y; |
| touch.width = 5; |
| touch.height = 5; |
| touchscreen_report->touchscreen->touches.resize(index + 1); |
| touchscreen_report->touchscreen->touches.at(index++) = std::move(touch); |
| FXL_VLOG(2) << name() |
| << " parsed (sensor=" << static_cast<uint16_t>(touch.finger_id) |
| << ") x=" << touch.x << ", y=" << touch.y; |
| } |
| |
| return true; |
| } |
| |
| bool Hardcoded::ParseParadiseSensorReport( |
| uint8_t* r, size_t len, uint8_t* sensor_idx, |
| fuchsia::ui::input::InputReport* sensor_report) { |
| if (len != sizeof(paradise_sensor_vector_data_t) && |
| len != sizeof(paradise_sensor_scalar_data_t)) { |
| FXL_LOG(INFO) << "paradise sensor data: wrong size " << len << ", expected " |
| << sizeof(paradise_sensor_vector_data_t) << " or " |
| << sizeof(paradise_sensor_scalar_data_t); |
| return false; |
| } |
| |
| sensor_report->event_time = InputEventTimestampNow(); |
| sensor_report->trace_id = TRACE_NONCE(); |
| *sensor_idx = r[0]; // We know sensor structs start with sensor ID. |
| switch (*sensor_idx) { |
| case kParadiseAccLid: |
| case kParadiseAccBase: { |
| const auto& report = |
| *(reinterpret_cast<paradise_sensor_vector_data_t*>(r)); |
| std::array<int16_t, 3> data; |
| data[0] = report.vector[0]; |
| data[1] = report.vector[1]; |
| data[2] = report.vector[2]; |
| sensor_report->sensor->set_vector(std::move(data)); |
| } break; |
| case 2: |
| case 3: |
| case 4: |
| // TODO(SCN-626): Expose other sensors. |
| return false; |
| default: |
| FXL_LOG(ERROR) << "paradise sensor unrecognized: " << *sensor_idx; |
| return false; |
| } |
| |
| FXL_VLOG(3) << name() |
| << " parsed (sensor=" << static_cast<uint16_t>(*sensor_idx) |
| << "): " << *sensor_report; |
| return true; |
| } |
| |
| bool Hardcoded::ParseReport(const uint8_t* report, size_t len, |
| HidAmbientLightSimple* data) { |
| auto cur = &decoder_[0]; |
| if ((cur->match != 0) && (cur->count == 8u)) { |
| // The first byte is the report id. |
| if (report[0] != cur->match) { |
| // This is a normal condition. The device can generate reports |
| // for controls we don't yet handle. |
| *data = {}; |
| return true; |
| } |
| ++cur; |
| } |
| if (cur->count != 16u) { |
| FXL_LOG(ERROR) << "Unexpected count in report from ambient light:" |
| << cur->count; |
| return false; |
| } |
| data->illuminance = extract_uint16(report, cur->begin); |
| return true; |
| } |
| |
| bool Hardcoded::ParseAmbientLightSensorReport( |
| const uint8_t* report, size_t len, uint8_t* sensor_idx, |
| fuchsia::ui::input::InputReport* sensor_report) { |
| HidAmbientLightSimple data; |
| if (!ParseReport(report, len, &data)) { |
| FXL_LOG(ERROR) << " failed reading from ambient light sensor"; |
| return false; |
| } |
| sensor_report->sensor->set_scalar(data.illuminance); |
| sensor_report->event_time = InputEventTimestampNow(); |
| sensor_report->trace_id = TRACE_NONCE(); |
| *sensor_idx = kAmbientLight; |
| |
| FXL_VLOG(2) << name() |
| << " parsed (sensor=" << static_cast<uint16_t>(*sensor_idx) |
| << "): " << *sensor_report; |
| return true; |
| } |
| |
| Protocol Hardcoded::MatchProtocol(const std::vector<uint8_t> desc, |
| HidDecoder* hid_decoder) { |
| if (USE_TOUCHSCREEN_HARDCODED_REPORTS) { |
| FXL_VLOG(2) << name() << " Using Hardcoded Touchscreen descriptors"; |
| if (is_acer12_touch_report_desc(desc.data(), desc.size())) { |
| return Protocol::Acer12Touch; |
| } |
| if (is_samsung_touch_report_desc(desc.data(), desc.size())) { |
| hid_decoder->SetupDevice(HidDecoder::Device::SAMSUNG); |
| return Protocol::SamsungTouch; |
| } |
| if (is_paradise_touch_report_desc(desc.data(), desc.size())) { |
| return Protocol::ParadiseV1Touch; |
| } |
| if (is_paradise_touch_v2_report_desc(desc.data(), desc.size())) { |
| return Protocol::ParadiseV2Touch; |
| } |
| if (is_paradise_touch_v3_report_desc(desc.data(), desc.size())) { |
| return Protocol::ParadiseV3Touch; |
| } |
| if (is_egalax_touchscreen_report_desc(desc.data(), desc.size())) { |
| return Protocol::EgalaxTouch; |
| } |
| if (is_eyoyo_touch_report_desc(desc.data(), desc.size())) { |
| hid_decoder->SetupDevice(HidDecoder::Device::EYOYO); |
| return Protocol::EyoyoTouch; |
| } |
| if (is_ft3x27_touch_report_desc(desc.data(), desc.size())) { |
| hid_decoder->SetupDevice(HidDecoder::Device::FT3X27); |
| return Protocol::Ft3x27Touch; |
| } |
| } |
| if (USE_TOUCHPAD_HARDCODED_REPORTS) { |
| FXL_VLOG(2) << name() << " Using Hardcoded Touchpad descriptors"; |
| if (is_paradise_touchpad_v1_report_desc(desc.data(), desc.size())) { |
| return Protocol::ParadiseV1TouchPad; |
| } |
| if (is_paradise_touchpad_v2_report_desc(desc.data(), desc.size())) { |
| return Protocol::ParadiseV2TouchPad; |
| } |
| } |
| if (is_paradise_sensor_report_desc(desc.data(), desc.size())) { |
| return Protocol::ParadiseSensor; |
| } |
| return Protocol::Other; |
| } |
| |
| void Hardcoded::Initialize(Protocol protocol) { |
| protocol_ = protocol; |
| if (protocol == Protocol::Keyboard) { |
| FXL_VLOG(2) << "Device " << name() << " has keyboard"; |
| has_keyboard_ = true; |
| keyboard_descriptor_ = fuchsia::ui::input::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.at(index - HID_USAGE_KEY_A) = index; |
| } |
| |
| keyboard_report_ = fuchsia::ui::input::InputReport::New(); |
| keyboard_report_->keyboard = fuchsia::ui::input::KeyboardReport::New(); |
| } else if (protocol == Protocol::BootMouse || protocol == Protocol::Gamepad) { |
| FXL_VLOG(2) << "Device " << name() << " has mouse"; |
| has_mouse_ = true; |
| mouse_device_type_ = (protocol == Protocol::BootMouse) |
| ? MouseDeviceType::BOOT |
| : MouseDeviceType::GAMEPAD; |
| |
| mouse_descriptor_ = fuchsia::ui::input::MouseDescriptor::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.range.min = INT32_MIN; |
| mouse_descriptor_->rel_y.range.max = INT32_MAX; |
| mouse_descriptor_->rel_y.resolution = 1; |
| |
| mouse_descriptor_->buttons |= fuchsia::ui::input::kMouseButtonPrimary; |
| mouse_descriptor_->buttons |= fuchsia::ui::input::kMouseButtonSecondary; |
| mouse_descriptor_->buttons |= fuchsia::ui::input::kMouseButtonTertiary; |
| |
| mouse_report_ = fuchsia::ui::input::InputReport::New(); |
| mouse_report_->mouse = fuchsia::ui::input::MouseReport::New(); |
| } else if (protocol == Protocol::Acer12Touch) { |
| FXL_VLOG(2) << "Device " << name() << " has stylus"; |
| has_stylus_ = true; |
| stylus_descriptor_ = fuchsia::ui::input::StylusDescriptor::New(); |
| |
| stylus_descriptor_->x.range.min = 0; |
| stylus_descriptor_->x.range.max = ACER12_STYLUS_X_MAX; |
| stylus_descriptor_->x.resolution = 1; |
| |
| 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 |= fuchsia::ui::input::kStylusBarrel; |
| |
| stylus_report_ = fuchsia::ui::input::InputReport::New(); |
| stylus_report_->stylus = fuchsia::ui::input::StylusReport::New(); |
| |
| FXL_VLOG(2) << "Device " << name() << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = ACER12_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| |
| 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_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::ACER12; |
| } else if (protocol == Protocol::SamsungTouch) { |
| FXL_VLOG(2) << "Device " << name() << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = SAMSUNG_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| |
| 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_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::SAMSUNG; |
| } else if (protocol == Protocol::ParadiseV1Touch) { |
| // TODO(cpu): Add support for stylus. |
| FXL_VLOG(2) << "Device " << name() << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = PARADISE_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| |
| 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_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::PARADISEv1; |
| } else if (protocol == Protocol::ParadiseV2Touch) { |
| FXL_VLOG(2) << "Device " << name() << " has stylus"; |
| has_stylus_ = true; |
| stylus_descriptor_ = fuchsia::ui::input::StylusDescriptor::New(); |
| |
| stylus_descriptor_->x.range.min = 0; |
| stylus_descriptor_->x.range.max = PARADISE_STYLUS_X_MAX; |
| stylus_descriptor_->x.resolution = 1; |
| |
| stylus_descriptor_->y.range.min = 0; |
| stylus_descriptor_->y.range.max = PARADISE_STYLUS_Y_MAX; |
| stylus_descriptor_->y.resolution = 1; |
| |
| stylus_descriptor_->is_invertible = false; |
| |
| stylus_descriptor_->buttons |= fuchsia::ui::input::kStylusBarrel; |
| |
| stylus_report_ = fuchsia::ui::input::InputReport::New(); |
| stylus_report_->stylus = fuchsia::ui::input::StylusReport::New(); |
| |
| FXL_VLOG(2) << "Device " << name() << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = PARADISE_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| |
| 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_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::PARADISEv2; |
| } else if (protocol == Protocol::ParadiseV3Touch) { |
| FXL_VLOG(2) << "Device " << name() << " has stylus"; |
| has_stylus_ = true; |
| stylus_descriptor_ = fuchsia::ui::input::StylusDescriptor::New(); |
| |
| stylus_descriptor_->x.range.min = 0; |
| stylus_descriptor_->x.range.max = PARADISE_STYLUS_X_MAX; |
| stylus_descriptor_->x.resolution = 1; |
| |
| stylus_descriptor_->y.range.min = 0; |
| stylus_descriptor_->y.range.max = PARADISE_STYLUS_Y_MAX; |
| stylus_descriptor_->y.resolution = 1; |
| |
| stylus_descriptor_->is_invertible = false; |
| |
| stylus_descriptor_->buttons |= fuchsia::ui::input::kStylusBarrel; |
| |
| stylus_report_ = fuchsia::ui::input::InputReport::New(); |
| stylus_report_->stylus = fuchsia::ui::input::StylusReport::New(); |
| |
| FXL_VLOG(2) << "Device " << name() << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = PARADISE_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| |
| 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_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::PARADISEv3; |
| } else if (protocol == Protocol::ParadiseV1TouchPad) { |
| FXL_VLOG(2) << "Device " << name() << " has touchpad"; |
| has_mouse_ = true; |
| mouse_device_type_ = MouseDeviceType::PARADISEv1; |
| |
| mouse_descriptor_ = fuchsia::ui::input::MouseDescriptor::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.range.min = INT32_MIN; |
| mouse_descriptor_->rel_y.range.max = INT32_MAX; |
| mouse_descriptor_->rel_y.resolution = 1; |
| |
| mouse_descriptor_->buttons |= fuchsia::ui::input::kMouseButtonPrimary; |
| |
| mouse_report_ = fuchsia::ui::input::InputReport::New(); |
| mouse_report_->mouse = fuchsia::ui::input::MouseReport::New(); |
| } else if (protocol == Protocol::ParadiseV2TouchPad) { |
| FXL_VLOG(2) << "Device " << name() << " has touchpad"; |
| has_mouse_ = true; |
| mouse_device_type_ = MouseDeviceType::PARADISEv2; |
| |
| mouse_descriptor_ = fuchsia::ui::input::MouseDescriptor::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.range.min = INT32_MIN; |
| mouse_descriptor_->rel_y.range.max = INT32_MAX; |
| mouse_descriptor_->rel_y.resolution = 1; |
| |
| mouse_descriptor_->buttons |= fuchsia::ui::input::kMouseButtonPrimary; |
| |
| mouse_report_ = fuchsia::ui::input::InputReport::New(); |
| mouse_report_->mouse = fuchsia::ui::input::MouseReport::New(); |
| } else if (protocol == Protocol::EgalaxTouch) { |
| FXL_VLOG(2) << "Device " << name() << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = EGALAX_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| |
| touchscreen_descriptor_->y.range.min = 0; |
| touchscreen_descriptor_->y.range.max = EGALAX_Y_MAX; |
| touchscreen_descriptor_->y.resolution = 1; |
| |
| touchscreen_descriptor_->max_finger_id = 1; |
| |
| touchscreen_report_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::EGALAX; |
| } else if (protocol == Protocol::ParadiseSensor) { |
| FXL_VLOG(2) << "Device " << name() << " has motion sensors"; |
| sensor_device_type_ = SensorDeviceType::PARADISE; |
| has_sensors_ = true; |
| |
| fuchsia::ui::input::SensorDescriptorPtr acc_base = |
| fuchsia::ui::input::SensorDescriptor::New(); |
| acc_base->type = fuchsia::ui::input::SensorType::ACCELEROMETER; |
| acc_base->loc = fuchsia::ui::input::SensorLocation::BASE; |
| sensor_descriptors_[kParadiseAccBase] = std::move(acc_base); |
| |
| fuchsia::ui::input::SensorDescriptorPtr acc_lid = |
| fuchsia::ui::input::SensorDescriptor::New(); |
| acc_lid->type = fuchsia::ui::input::SensorType::ACCELEROMETER; |
| acc_lid->loc = fuchsia::ui::input::SensorLocation::LID; |
| sensor_descriptors_[kParadiseAccLid] = std::move(acc_lid); |
| |
| sensor_report_ = fuchsia::ui::input::InputReport::New(); |
| sensor_report_->sensor = fuchsia::ui::input::SensorReport::New(); |
| } else if (protocol == Protocol::EyoyoTouch) { |
| FXL_VLOG(2) << "Device " << name() << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = EYOYO_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| |
| touchscreen_descriptor_->y.range.min = 0; |
| touchscreen_descriptor_->y.range.max = EYOYO_Y_MAX; |
| touchscreen_descriptor_->y.resolution = 1; |
| |
| // TODO(jpoichet) do not hardcode this |
| touchscreen_descriptor_->max_finger_id = 255; |
| |
| touchscreen_report_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::EYOYO; |
| } else if (protocol == Protocol::LightSensor) { |
| FXL_VLOG(2) << "Device " << name() << " has an ambient light sensor"; |
| sensor_device_type_ = SensorDeviceType::AMBIENT_LIGHT; |
| has_sensors_ = true; |
| |
| fuchsia::ui::input::SensorDescriptorPtr desc = |
| fuchsia::ui::input::SensorDescriptor::New(); |
| desc->type = fuchsia::ui::input::SensorType::LIGHTMETER; |
| desc->loc = fuchsia::ui::input::SensorLocation::UNKNOWN; |
| sensor_descriptors_[kAmbientLight] = std::move(desc); |
| |
| sensor_report_ = fuchsia::ui::input::InputReport::New(); |
| sensor_report_->sensor = fuchsia::ui::input::SensorReport::New(); |
| } else if (protocol == Protocol::EyoyoTouch) { |
| FXL_VLOG(2) << "Device " << name() << " has touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = EYOYO_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| |
| touchscreen_descriptor_->y.range.min = 0; |
| touchscreen_descriptor_->y.range.max = EYOYO_Y_MAX; |
| touchscreen_descriptor_->y.resolution = 1; |
| |
| // TODO(jpoichet) do not hardcode this |
| touchscreen_descriptor_->max_finger_id = 255; |
| |
| touchscreen_report_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::EYOYO; |
| } else if (protocol == Protocol::Ft3x27Touch) { |
| FXL_VLOG(2) << "Device " << name() << " has a touchscreen"; |
| has_touchscreen_ = true; |
| touchscreen_descriptor_ = fuchsia::ui::input::TouchscreenDescriptor::New(); |
| touchscreen_descriptor_->x.range.min = 0; |
| touchscreen_descriptor_->x.range.max = FT3X27_X_MAX; |
| touchscreen_descriptor_->x.resolution = 1; |
| touchscreen_descriptor_->y.range.min = 0; |
| touchscreen_descriptor_->y.range.max = FT3X27_Y_MAX; |
| touchscreen_descriptor_->y.resolution = 1; |
| |
| // TODO(SCN-867) Use HID parsing for all touch devices |
| // will remove the need for this hardcoding |
| touchscreen_descriptor_->max_finger_id = 255; |
| |
| touchscreen_report_ = fuchsia::ui::input::InputReport::New(); |
| touchscreen_report_->touchscreen = |
| fuchsia::ui::input::TouchscreenReport::New(); |
| |
| touch_device_type_ = TouchDeviceType::FT3X27; |
| } |
| } |
| |
| void Hardcoded::NotifyRegistry( |
| fuchsia::ui::input::InputDeviceRegistry* registry) { |
| if (has_sensors_) { |
| FXL_DCHECK(kMaxSensorCount == sensor_descriptors_.size()); |
| FXL_DCHECK(kMaxSensorCount == sensor_devices_.size()); |
| for (size_t i = 0; i < kMaxSensorCount; ++i) { |
| if (sensor_descriptors_[i]) { |
| fuchsia::ui::input::DeviceDescriptor descriptor; |
| zx_status_t status = |
| fidl::Clone(sensor_descriptors_[i], &descriptor.sensor); |
| FXL_DCHECK(status == ZX_OK) |
| << "Sensor descriptor: clone failed (status=" << status << ")"; |
| registry->RegisterDevice(std::move(descriptor), |
| sensor_devices_[i].NewRequest()); |
| } |
| } |
| // Sensor devices can't be anything else, so don't bother with other types. |
| return; |
| } |
| |
| // Register the hardcoded device's descriptors. |
| { |
| fuchsia::ui::input::DeviceDescriptor descriptor; |
| if (has_keyboard_) { |
| fidl::Clone(keyboard_descriptor_, &descriptor.keyboard); |
| } |
| if (has_mouse_) { |
| fidl::Clone(mouse_descriptor_, &descriptor.mouse); |
| } |
| if (has_stylus_) { |
| fidl::Clone(stylus_descriptor_, &descriptor.stylus); |
| } |
| if (has_touchscreen_) { |
| fidl::Clone(touchscreen_descriptor_, &descriptor.touchscreen); |
| } |
| registry->RegisterDevice(std::move(descriptor), input_device_.NewRequest()); |
| } |
| } |
| |
| void Hardcoded::Read(std::vector<uint8_t> report, int report_len, |
| bool discard) { |
| if (has_keyboard_) { |
| bool parsed = ParseKeyboardReport(report.data(), report_len, keyboard_report_.get()); |
| if (!discard && parsed) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| keyboard_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*keyboard_report_)); |
| } |
| } |
| |
| switch (mouse_device_type_) { |
| case MouseDeviceType::BOOT: |
| ParseMouseReport(report.data(), report_len, mouse_report_.get()); |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| mouse_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*mouse_report_)); |
| } |
| break; |
| case MouseDeviceType::PARADISEv1: |
| if (ParseParadiseTouchpadReportV1(report.data(), report_len, |
| mouse_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| mouse_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*mouse_report_)); |
| } |
| } |
| break; |
| case MouseDeviceType::PARADISEv2: |
| if (ParseParadiseTouchpadReportV2(report.data(), report_len, |
| mouse_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| mouse_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*mouse_report_)); |
| } |
| } |
| break; |
| case MouseDeviceType::GAMEPAD: |
| // TODO(cpu): remove this once we have a good way to test gamepad. |
| if (ParseGamepadMouseReport(report.data(), report_len, |
| mouse_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| mouse_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*mouse_report_)); |
| } |
| } |
| break; |
| case MouseDeviceType::NONE: |
| break; |
| default: |
| break; |
| } |
| |
| switch (touch_device_type_) { |
| case TouchDeviceType::ACER12: |
| if (report[0] == ACER12_RPT_ID_STYLUS) { |
| if (ParseAcer12StylusReport(report.data(), report_len, |
| stylus_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| stylus_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*stylus_report_)); |
| } |
| } |
| } else if (report[0] == ACER12_RPT_ID_TOUCH) { |
| if (ParseAcer12TouchscreenReport(report.data(), report_len, |
| touchscreen_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| touchscreen_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*touchscreen_report_)); |
| } |
| } |
| } |
| break; |
| case TouchDeviceType::SAMSUNG: |
| if (report[0] == SAMSUNG_RPT_ID_TOUCH) { |
| if (ParseSamsungTouchscreenReport(report.data(), report_len, |
| touchscreen_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| touchscreen_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*touchscreen_report_)); |
| } |
| } |
| } |
| break; |
| |
| case TouchDeviceType::PARADISEv1: |
| if (report[0] == PARADISE_RPT_ID_TOUCH) { |
| if (ParseParadiseTouchscreenReportV1(report.data(), report_len, |
| touchscreen_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| touchscreen_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*touchscreen_report_)); |
| } |
| } |
| } |
| break; |
| case TouchDeviceType::PARADISEv2: |
| if (report[0] == PARADISE_RPT_ID_TOUCH) { |
| if (ParseParadiseTouchscreenReportV2(report.data(), report_len, |
| touchscreen_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| touchscreen_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*touchscreen_report_)); |
| } |
| } |
| } else if (report[0] == PARADISE_RPT_ID_STYLUS) { |
| if (ParseParadiseStylusReport(report.data(), report_len, |
| stylus_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| stylus_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*stylus_report_)); |
| } |
| } |
| } |
| break; |
| case TouchDeviceType::PARADISEv3: |
| if (report[0] == PARADISE_RPT_ID_TOUCH) { |
| // Paradise V3 uses the same touchscreen report as v1. |
| if (ParseParadiseTouchscreenReportV1(report.data(), report_len, |
| touchscreen_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| touchscreen_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*touchscreen_report_)); |
| } |
| } |
| } else if (report[0] == PARADISE_RPT_ID_STYLUS) { |
| if (ParseParadiseStylusReport(report.data(), report_len, |
| stylus_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| stylus_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*stylus_report_)); |
| } |
| } |
| } |
| break; |
| case TouchDeviceType::EGALAX: |
| if (report[0] == EGALAX_RPT_ID_TOUCH) { |
| if (ParseEGalaxTouchscreenReport(report.data(), report_len, |
| touchscreen_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| touchscreen_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*touchscreen_report_)); |
| } |
| } |
| } |
| break; |
| |
| case TouchDeviceType::EYOYO: |
| if (report[0] == EYOYO_RPT_ID_TOUCH) { |
| if (ParseEyoyoTouchscreenReport(report.data(), report_len, |
| touchscreen_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| touchscreen_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*touchscreen_report_)); |
| } |
| } |
| } |
| break; |
| case TouchDeviceType::FT3X27: |
| if (report[0] == FT3X27_RPT_ID_TOUCH) { |
| if (ParseFt3x27TouchscreenReport(report.data(), report_len, |
| touchscreen_report_.get())) { |
| if (!discard) { |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| touchscreen_report_->trace_id); |
| input_device_->DispatchReport(CloneReport(*touchscreen_report_)); |
| } |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| switch (sensor_device_type_) { |
| case SensorDeviceType::PARADISE: |
| if (ParseParadiseSensorReport(report.data(), report_len, &sensor_idx_, |
| sensor_report_.get())) { |
| if (!discard) { |
| FXL_DCHECK(sensor_idx_ < kMaxSensorCount); |
| FXL_DCHECK(sensor_devices_[sensor_idx_]); |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| sensor_report_->trace_id); |
| sensor_devices_[sensor_idx_]->DispatchReport( |
| CloneReport(*sensor_report_)); |
| } |
| } |
| break; |
| case SensorDeviceType::AMBIENT_LIGHT: |
| if (ParseAmbientLightSensorReport(report.data(), report_len, &sensor_idx_, |
| sensor_report_.get())) { |
| if (!discard) { |
| FXL_DCHECK(sensor_idx_ < kMaxSensorCount); |
| FXL_DCHECK(sensor_devices_[sensor_idx_]); |
| TRACE_FLOW_BEGIN("input", "hid_read_to_listener", |
| sensor_report_->trace_id); |
| sensor_devices_[sensor_idx_]->DispatchReport( |
| CloneReport(*sensor_report_)); |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| } // namespace ui_input |