| // 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 "src/ui/tools/print-input-report/devices.h" |
| |
| #include <fidl/fuchsia.input.report/cpp/wire.h> |
| #include <lib/ddk/device.h> |
| #include <lib/trace/event.h> |
| #include <zircon/status.h> |
| |
| namespace print_input_report { |
| |
| zx_status_t PrintFeatureReports(std::string filename, Printer* printer, |
| fidl::WireSharedClient<fuchsia_input_report::InputDevice> client, |
| fit::closure callback) { |
| client->GetFeatureReport().ThenExactlyOnce( |
| [filename = std::move(filename), printer, callback = std::move(callback), _ = client.Clone()]( |
| fidl::WireUnownedResult<fuchsia_input_report::InputDevice::GetFeatureReport>& |
| call_result) { |
| if (!call_result.ok()) { |
| return; |
| } |
| auto* result = call_result.Unwrap(); |
| if (result->is_error()) { |
| callback(); |
| return; |
| } |
| auto& report = result->value()->report; |
| |
| printer->SetIndent(0); |
| printer->Print("Feature Report from file: %s\n", filename.c_str()); |
| printer->IncreaseIndent(); |
| if (report.has_sensor()) { |
| printer->Print("Sensor Feature Report:\n"); |
| printer->IncreaseIndent(); |
| if (report.sensor().has_report_interval()) { |
| printer->Print("Report Interval: %ld\n", report.sensor().report_interval()); |
| } |
| if (report.sensor().has_reporting_state()) { |
| printer->Print("Reporting State: %u\n", report.sensor().reporting_state()); |
| } |
| if (report.sensor().has_sensitivity()) { |
| printer->Print("Sensitivity:\n"); |
| printer->IncreaseIndent(); |
| for (size_t i = 0; i < report.sensor().sensitivity().count(); i++) { |
| printer->Print("%ld ", report.sensor().sensitivity().data()[i]); |
| } |
| printer->Print("\n"); |
| printer->DecreaseIndent(); |
| } |
| if (report.sensor().has_threshold_high()) { |
| printer->Print("Threshold High:\n"); |
| printer->IncreaseIndent(); |
| for (size_t i = 0; i < report.sensor().threshold_high().count(); i++) { |
| printer->Print("%ld ", report.sensor().threshold_high().data()[i]); |
| } |
| printer->Print("\n"); |
| printer->DecreaseIndent(); |
| } |
| if (report.sensor().has_threshold_low()) { |
| printer->Print("Threshold Low:\n"); |
| printer->IncreaseIndent(); |
| for (size_t i = 0; i < report.sensor().threshold_low().count(); i++) { |
| printer->Print("%ld ", report.sensor().threshold_low().data()[i]); |
| } |
| printer->Print("\n"); |
| printer->DecreaseIndent(); |
| } |
| if (report.sensor().has_sampling_rate()) { |
| printer->Print("Sampling Rate: %u\n", report.sensor().sampling_rate()); |
| } |
| printer->DecreaseIndent(); |
| } |
| |
| if (report.has_touch()) { |
| printer->Print("Touch Feature Report:\n"); |
| printer->IncreaseIndent(); |
| if (report.touch().has_input_mode()) { |
| printer->Print("Input Mode: %u\n", report.touch().input_mode()); |
| } |
| if (report.touch().has_selective_reporting()) { |
| printer->Print("Selective Reporting:\n"); |
| printer->IncreaseIndent(); |
| if (report.touch().selective_reporting().has_surface_switch()) { |
| printer->Print("Surface Switch: %u\n", |
| report.touch().selective_reporting().surface_switch()); |
| } |
| if (report.touch().selective_reporting().has_button_switch()) { |
| printer->Print("Button Switch: %u\n", |
| report.touch().selective_reporting().button_switch()); |
| } |
| printer->DecreaseIndent(); |
| } |
| printer->DecreaseIndent(); |
| } |
| printer->DecreaseIndent(); |
| callback(); |
| }); |
| return ZX_OK; |
| } |
| |
| zx_status_t PrintInputDescriptor(std::string filename, Printer* printer, |
| fidl::WireSharedClient<fuchsia_input_report::InputDevice> client, |
| fit::closure callback) { |
| client->GetDescriptor().ThenExactlyOnce( |
| [filename = std::move(filename), printer, callback = std::move(callback), _ = client.Clone()]( |
| fidl::WireUnownedResult<fuchsia_input_report::InputDevice::GetDescriptor>& call_result) { |
| if (!call_result.ok()) { |
| return; |
| } |
| auto* result = call_result.Unwrap(); |
| printer->SetIndent(0); |
| printer->Print("Descriptor from file: %s\n", filename.c_str()); |
| if (result->descriptor.has_device_information()) { |
| PrintDeviceInfo(printer, result->descriptor.device_information()); |
| } |
| if (result->descriptor.has_mouse()) { |
| if (result->descriptor.mouse().has_input()) { |
| PrintMouseDesc(printer, result->descriptor.mouse().input()); |
| } |
| } |
| if (result->descriptor.has_sensor()) { |
| if (result->descriptor.sensor().has_input()) { |
| for (const auto& input : result->descriptor.sensor().input()) { |
| PrintSensorDesc(printer, input); |
| } |
| } |
| } |
| if (result->descriptor.has_touch()) { |
| PrintTouchDesc(printer, result->descriptor.touch()); |
| } |
| if (result->descriptor.has_keyboard()) { |
| PrintKeyboardDesc(printer, result->descriptor.keyboard()); |
| } |
| if (result->descriptor.has_consumer_control()) { |
| PrintConsumerControlDesc(printer, result->descriptor.consumer_control()); |
| } |
| callback(); |
| }); |
| return ZX_OK; |
| } |
| |
| void PrintDeviceInfo(Printer* printer, |
| const fuchsia_input_report::wire::DeviceInformation& device_info) { |
| printer->Print("Device Info:\n"); |
| printer->IncreaseIndent(); |
| |
| printer->Print("Vendor ID:\n"); |
| printer->IncreaseIndent(); |
| printer->Print("0x%x\n", device_info.vendor_id()); |
| printer->DecreaseIndent(); |
| |
| printer->Print("Product ID:\n"); |
| printer->IncreaseIndent(); |
| printer->Print("0x%x\n", device_info.product_id()); |
| printer->DecreaseIndent(); |
| |
| printer->Print("Version:\n"); |
| printer->IncreaseIndent(); |
| printer->Print("0x%x\n", device_info.version()); |
| printer->DecreaseIndent(); |
| |
| printer->Print("Polling Rate:\n"); |
| printer->IncreaseIndent(); |
| printer->Print("%lu usec\n", device_info.polling_rate()); |
| printer->DecreaseIndent(); |
| |
| printer->DecreaseIndent(); |
| } |
| |
| void PrintMouseDesc(Printer* printer, |
| const fuchsia_input_report::wire::MouseInputDescriptor& mouse_desc) { |
| printer->Print("Mouse Descriptor:\n"); |
| printer->IncreaseIndent(); |
| if (mouse_desc.has_movement_x()) { |
| printer->Print("Movement X:\n"); |
| printer->PrintAxisIndented(mouse_desc.movement_x()); |
| } |
| if (mouse_desc.has_movement_y()) { |
| printer->Print("Movement Y:\n"); |
| printer->PrintAxisIndented(mouse_desc.movement_y()); |
| } |
| if (mouse_desc.has_position_x()) { |
| printer->Print("Position X:\n"); |
| printer->PrintAxisIndented(mouse_desc.position_x()); |
| } |
| if (mouse_desc.has_position_y()) { |
| printer->Print("Position Y:\n"); |
| printer->PrintAxisIndented(mouse_desc.position_y()); |
| } |
| if (mouse_desc.has_buttons()) { |
| for (uint8_t button : mouse_desc.buttons()) { |
| printer->Print("Button: %d\n", button); |
| } |
| } |
| printer->DecreaseIndent(); |
| } |
| |
| void PrintSensorDesc(Printer* printer, |
| const fuchsia_input_report::wire::SensorInputDescriptor& sensor_desc) { |
| printer->Print("Sensor Descriptor:\n"); |
| if (!sensor_desc.has_values()) { |
| return; |
| } |
| |
| printer->IncreaseIndent(); |
| if (sensor_desc.has_report_id()) { |
| printer->Print("ReportID: %02d\n", sensor_desc.report_id()); |
| } |
| for (size_t i = 0; i < sensor_desc.values().count(); i++) { |
| printer->Print("Value %02d:\n", i); |
| printer->IncreaseIndent(); |
| printer->Print("SensorType: %s\n", Printer::SensorTypeToString(sensor_desc.values()[i].type)); |
| printer->PrintAxis(sensor_desc.values()[i].axis); |
| printer->DecreaseIndent(); |
| } |
| printer->DecreaseIndent(); |
| } |
| |
| void PrintTouchDesc(Printer* printer, |
| const fuchsia_input_report::wire::TouchDescriptor& touch_desc) { |
| printer->Print("Touch Descriptor:\n"); |
| printer->IncreaseIndent(); |
| if (touch_desc.has_input()) { |
| printer->Print("Input Report:\n"); |
| printer->IncreaseIndent(); |
| const auto& input = touch_desc.input(); |
| if (input.has_touch_type()) { |
| printer->Print("Touch Type: %s\n", Printer::TouchTypeToString(input.touch_type())); |
| } |
| if (input.has_max_contacts()) { |
| printer->Print("Max Contacts: %ld\n", input.max_contacts()); |
| } |
| if (input.has_contacts()) { |
| for (size_t i = 0; i < input.contacts().count(); i++) { |
| const fuchsia_input_report::wire::ContactInputDescriptor& contact = input.contacts()[i]; |
| |
| printer->Print("Contact: %02d\n", i); |
| printer->IncreaseIndent(); |
| |
| if (contact.has_position_x()) { |
| printer->Print("Position X:\n"); |
| printer->PrintAxisIndented(contact.position_x()); |
| } |
| if (contact.has_position_y()) { |
| printer->Print("Position Y:\n"); |
| printer->PrintAxisIndented(contact.position_y()); |
| } |
| if (contact.has_pressure()) { |
| printer->Print("Pressure:\n"); |
| printer->PrintAxisIndented(contact.pressure()); |
| } |
| if (contact.has_contact_width()) { |
| printer->Print("Contact Width:\n"); |
| printer->PrintAxisIndented(contact.contact_width()); |
| } |
| if (contact.has_contact_height()) { |
| printer->Print("Contact Height:\n"); |
| printer->PrintAxisIndented(contact.contact_height()); |
| } |
| |
| printer->DecreaseIndent(); |
| } |
| } |
| |
| printer->DecreaseIndent(); |
| } |
| |
| if (touch_desc.has_feature()) { |
| printer->Print("Feature Report:\n"); |
| printer->IncreaseIndent(); |
| const auto& feature = touch_desc.feature(); |
| printer->Print("Supports InputMode: %u\n", |
| feature.has_supports_input_mode() ? feature.supports_input_mode() : false); |
| printer->Print("Supports SelectiveReporting: %u\n", feature.has_supports_selective_reporting() |
| ? feature.supports_selective_reporting() |
| : false); |
| printer->DecreaseIndent(); |
| } |
| printer->DecreaseIndent(); |
| } |
| |
| void PrintKeyboardDesc(Printer* printer, |
| const fuchsia_input_report::wire::KeyboardDescriptor& keyboard_desc) { |
| printer->Print("Keyboard Descriptor:\n"); |
| |
| if (keyboard_desc.has_input()) { |
| const fuchsia_input_report::wire::KeyboardInputDescriptor& input = keyboard_desc.input(); |
| printer->Print("Input Report:\n"); |
| printer->IncreaseIndent(); |
| if (input.has_keys3()) { |
| for (size_t i = 0; i < input.keys3().count(); i++) { |
| printer->Print("Key: %8ld\n", input.keys3()[i]); |
| } |
| } |
| printer->DecreaseIndent(); |
| } |
| if (keyboard_desc.has_output()) { |
| const fuchsia_input_report::wire::KeyboardOutputDescriptor& output = keyboard_desc.output(); |
| printer->Print("Output Report:\n"); |
| printer->IncreaseIndent(); |
| if (output.has_leds()) { |
| for (size_t i = 0; i < output.leds().count(); i++) { |
| printer->Print("Led: %s\n", Printer::LedTypeToString(output.leds()[i])); |
| } |
| } |
| printer->DecreaseIndent(); |
| } |
| } |
| |
| void PrintConsumerControlDesc( |
| Printer* printer, const fuchsia_input_report::wire::ConsumerControlDescriptor& descriptor) { |
| printer->Print("ConsumerControl Descriptor:\n"); |
| |
| if (descriptor.has_input()) { |
| const fuchsia_input_report::wire::ConsumerControlInputDescriptor& input = descriptor.input(); |
| printer->Print("Input Report:\n"); |
| printer->IncreaseIndent(); |
| if (input.has_buttons()) { |
| for (size_t i = 0; i < input.buttons().count(); i++) { |
| printer->Print("Button: %16s\n", |
| Printer::ConsumerControlButtonToString(input.buttons()[i])); |
| } |
| } |
| printer->DecreaseIndent(); |
| } |
| } |
| |
| void PrintInputReports(std::string filename, Printer* printer, |
| fidl::WireSharedClient<fuchsia_input_report::InputReportsReader> reader, |
| size_t num_reads, fit::closure callback) { |
| if (num_reads == 0) { |
| callback(); |
| return; |
| } |
| // Read the reports. |
| // We need the ReadInputReport's callback to be mutable because the PrintInputReports callback is |
| // moved into the next ReadInputReport's call. |
| reader->ReadInputReports().ThenExactlyOnce( |
| [=, filename = std::move(filename), reader = reader.Clone(), callback = std::move(callback)]( |
| fidl::WireUnownedResult<fuchsia_input_report::InputReportsReader::ReadInputReports>& |
| call_result) mutable { |
| if (!call_result.ok()) { |
| return; |
| } |
| auto* result = call_result.Unwrap(); |
| size_t reads_left = num_reads; |
| if (result->is_error()) { |
| callback(); |
| return; |
| } |
| auto& reports = result->value()->reports; |
| TRACE_DURATION("input", "print-input-report ReadReports"); |
| for (auto& report : reports) { |
| if (reads_left == 0) { |
| callback(); |
| return; |
| } |
| reads_left -= 1; |
| printer->SetIndent(0); |
| printer->Print("Report from file: %s\n", filename.c_str()); |
| if (report.has_event_time()) { |
| printer->Print("EventTime: 0x%016lx\n", report.event_time()); |
| } |
| if (report.has_trace_id()) { |
| TRACE_FLOW_END("input", "input_report", report.trace_id()); |
| } |
| if (report.has_report_id()) { |
| printer->Print("ReportID: %02d\n", report.report_id()); |
| } |
| if (report.has_mouse()) { |
| auto& mouse = report.mouse(); |
| PrintMouseInputReport(printer, mouse); |
| } |
| if (report.has_sensor()) { |
| PrintSensorInputReport(printer, report.sensor()); |
| } |
| if (report.has_touch()) { |
| PrintTouchInputReport(printer, report.touch()); |
| } |
| if (report.has_keyboard()) { |
| PrintKeyboardInputReport(printer, report.keyboard()); |
| } |
| if (report.has_consumer_control()) { |
| PrintConsumerControlInputReport(printer, report.consumer_control()); |
| } |
| printer->Print("\n"); |
| } |
| PrintInputReports(filename, printer, std::move(reader), reads_left, std::move(callback)); |
| }); |
| } |
| |
| void GetAndPrintInputReport(std::string filename, |
| fuchsia_input_report::wire::DeviceType device_type, Printer* printer, |
| fidl::WireSharedClient<fuchsia_input_report::InputDevice> client, |
| fit::closure callback) { |
| client->GetInputReport(device_type) |
| .ThenExactlyOnce( |
| [=, filename = std::move(filename), callback = std::move(callback), _ = client.Clone()]( |
| fidl::WireUnownedResult<fuchsia_input_report::InputDevice::GetInputReport>& |
| call_result) { |
| if (!call_result.ok()) { |
| return; |
| } |
| auto* result = call_result.Unwrap(); |
| if (result->is_error()) { |
| callback(); |
| return; |
| } |
| auto& report = result->value()->report; |
| TRACE_DURATION("input", "print-input-report GetReport"); |
| printer->SetIndent(0); |
| printer->Print("Report from file: %s\n", filename.c_str()); |
| if (report.has_event_time()) { |
| printer->Print("EventTime: 0x%016lx\n", report.event_time()); |
| } |
| if (report.has_trace_id()) { |
| TRACE_FLOW_END("input", "input_report", report.trace_id()); |
| } |
| if (report.has_report_id()) { |
| printer->Print("ReportID: %02d\n", report.report_id()); |
| } |
| if (report.has_mouse()) { |
| auto& mouse = report.mouse(); |
| PrintMouseInputReport(printer, mouse); |
| } |
| if (report.has_sensor()) { |
| PrintSensorInputReport(printer, report.sensor()); |
| } |
| if (report.has_touch()) { |
| PrintTouchInputReport(printer, report.touch()); |
| } |
| if (report.has_keyboard()) { |
| PrintKeyboardInputReport(printer, report.keyboard()); |
| } |
| if (report.has_consumer_control()) { |
| PrintConsumerControlInputReport(printer, report.consumer_control()); |
| } |
| printer->Print("\n"); |
| callback(); |
| }); |
| } |
| |
| zx::result<fidl::WireSharedClient<fuchsia_input_report::InputReportsReader>> GetReaderClient( |
| fidl::WireSharedClient<fuchsia_input_report::InputDevice>* client, |
| async_dispatcher_t* dispatcher) { |
| fidl::ClientEnd<fuchsia_input_report::InputReportsReader> reader_client; |
| auto reader_server = fidl::CreateEndpoints(&reader_client); |
| if (reader_server.is_error()) { |
| return reader_server.take_error(); |
| } |
| auto result = (*client)->GetInputReportsReader(std::move(*reader_server)); |
| |
| if (result.status() != ZX_OK) { |
| return zx::error(result.status()); |
| } |
| |
| return zx::ok(fidl::WireSharedClient(std::move(reader_client), dispatcher)); |
| } |
| |
| void PrintMouseInputReport(Printer* printer, |
| const fuchsia_input_report::wire::MouseInputReport& mouse_report) { |
| if (mouse_report.has_movement_x()) { |
| printer->Print("Movement x: %08ld\n", mouse_report.movement_x()); |
| } |
| if (mouse_report.has_movement_y()) { |
| printer->Print("Movement y: %08ld\n", mouse_report.movement_y()); |
| } |
| if (mouse_report.has_position_x()) { |
| printer->Print("Position x: %08ld\n", mouse_report.position_x()); |
| } |
| if (mouse_report.has_position_y()) { |
| printer->Print("Position y: %08ld\n", mouse_report.position_y()); |
| } |
| if (mouse_report.has_scroll_v()) { |
| printer->Print("Scroll v: %08ld\n", mouse_report.scroll_v()); |
| } |
| if (mouse_report.has_pressed_buttons()) { |
| for (uint8_t button : mouse_report.pressed_buttons()) { |
| printer->Print("Button %02d pressed\n", button); |
| } |
| } |
| } |
| |
| void PrintSensorInputReport(Printer* printer, |
| const fuchsia_input_report::wire::SensorInputReport& sensor_report) { |
| if (!sensor_report.has_values()) { |
| return; |
| } |
| |
| for (size_t i = 0; i < sensor_report.values().count(); i++) { |
| printer->Print("Sensor[%02d]: %08d\n", i, sensor_report.values()[i]); |
| } |
| } |
| |
| void PrintTouchInputReport(Printer* printer, |
| const fuchsia_input_report::wire::TouchInputReport& touch_report) { |
| if (touch_report.has_contacts()) { |
| for (size_t i = 0; i < touch_report.contacts().count(); i++) { |
| const fuchsia_input_report::wire::ContactInputReport& contact = touch_report.contacts()[i]; |
| |
| if (contact.has_contact_id()) { |
| printer->Print("Contact ID: %2ld\n", contact.contact_id()); |
| } else { |
| printer->Print("Contact: %2d\n", i); |
| } |
| |
| printer->IncreaseIndent(); |
| if (contact.has_position_x()) { |
| printer->Print("Position X: %08ld\n", contact.position_x()); |
| } |
| if (contact.has_position_y()) { |
| printer->Print("Position Y: %08ld\n", contact.position_y()); |
| } |
| if (contact.has_pressure()) { |
| printer->Print("Pressure: %08ld\n", contact.pressure()); |
| } |
| if (contact.has_contact_width()) { |
| printer->Print("Contact Width: %08ld\n", contact.contact_width()); |
| } |
| if (contact.has_contact_height()) { |
| printer->Print("Contact Height: %08ld\n", contact.contact_height()); |
| } |
| if (contact.has_confidence()) { |
| printer->Print("Confidence: %d\n", contact.confidence()); |
| } |
| |
| printer->DecreaseIndent(); |
| } |
| } |
| } |
| |
| void PrintKeyboardInputReport( |
| Printer* printer, const fuchsia_input_report::wire::KeyboardInputReport& keyboard_report) { |
| printer->Print("Keyboard Report\n"); |
| printer->IncreaseIndent(); |
| if (keyboard_report.has_pressed_keys3()) { |
| for (size_t i = 0; i < keyboard_report.pressed_keys3().count(); i++) { |
| printer->Print("Key: %8ld\n", keyboard_report.pressed_keys3()[i]); |
| } |
| if (keyboard_report.pressed_keys3().count() == 0) { |
| printer->Print("No keys pressed\n"); |
| } |
| } |
| printer->DecreaseIndent(); |
| } |
| |
| void PrintConsumerControlInputReport( |
| Printer* printer, const fuchsia_input_report::wire::ConsumerControlInputReport& report) { |
| printer->Print("ConsumerControl Report\n"); |
| printer->IncreaseIndent(); |
| if (report.has_pressed_buttons()) { |
| for (size_t i = 0; i < report.pressed_buttons().count(); i++) { |
| printer->Print("Button: %16s\n", |
| Printer::ConsumerControlButtonToString(report.pressed_buttons()[i])); |
| } |
| } |
| printer->DecreaseIndent(); |
| } |
| |
| } // namespace print_input_report |