| // Copyright 2017 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. | |
| #ifndef SRC_UI_INPUT_DRIVERS_VIRTIO_CPP_INPUT_H_ | |
| #define SRC_UI_INPUT_DRIVERS_VIRTIO_CPP_INPUT_H_ | |
| #include <fidl/fuchsia.input.report/cpp/wire.h> | |
| #include <lib/ddk/debug.h> | |
| #include <lib/ddk/io-buffer.h> | |
| #include <lib/inspect/cpp/inspect.h> | |
| #include <lib/virtio/device.h> | |
| #include <lib/virtio/ring.h> | |
| #include <ddktl/device.h> | |
| #include <fbl/mutex.h> | |
| #include <virtio/input.h> | |
| #include "src/ui/input/drivers/virtio/cpp/input_device.h" | |
| namespace virtio { | |
| class InputDevice | |
| : public Device, | |
| public ddk::Device<InputDevice, ddk::Messageable<fuchsia_input_report::InputDevice>::Mixin> { | |
| public: | |
| // Max unacknowledged report count allowed for 1/2 second. | |
| // VirtIO input devices are event-driven via VirtQueue interrupt notifications. | |
| // Assuming a standard max event rate of 120 Hz yields 60 reports per 1/2 second (120 Hz / 2). | |
| static constexpr uint16_t kMaxReportsPerHalfSecond = 60; | |
| InputDevice(zx_device_t* device, zx::bti bti, std::unique_ptr<Backend> backend); | |
| virtual ~InputDevice(); | |
| zx_status_t Init() override; | |
| void IrqRingUpdate() override; | |
| void IrqConfigChange() override; | |
| const char* tag() const override { return "virtio-input"; } | |
| // DDK driver hooks | |
| void DdkRelease(); | |
| // fuchsia_input_report::InputDevice required methods | |
| void GetInputReportsReader(GetInputReportsReaderRequestView request, | |
| GetInputReportsReaderCompleter::Sync& completer) override { | |
| ZX_PANIC("GetInputReportsReader (v1) is no longer supported; use GetInputReportsReaderV2"); | |
| } | |
| void GetInputReportsReaderV2(GetInputReportsReaderV2RequestView request, | |
| GetInputReportsReaderV2Completer::Sync& completer) override; | |
| void GetDescriptor(GetDescriptorCompleter::Sync& completer) override { | |
| fidl::Arena<kFeatureAndDescriptorBufferSize> allocator; | |
| completer.Reply(hid_device_->GetDescriptor(allocator)); | |
| } | |
| void SendOutputReport(SendOutputReportRequestView request, | |
| SendOutputReportCompleter::Sync& completer) override { | |
| completer.ReplyError(ZX_ERR_NOT_SUPPORTED); | |
| } | |
| void GetFeatureReport(GetFeatureReportCompleter::Sync& completer) override { | |
| completer.ReplyError(ZX_ERR_NOT_SUPPORTED); | |
| } | |
| void SetFeatureReport(SetFeatureReportRequestView request, | |
| SetFeatureReportCompleter::Sync& completer) override { | |
| completer.ReplyError(ZX_ERR_NOT_SUPPORTED); | |
| } | |
| void GetInputReport(GetInputReportRequestView request, | |
| GetInputReportCompleter::Sync& completer) override { | |
| completer.ReplyError(ZX_ERR_NOT_SUPPORTED); | |
| } | |
| void handle_unknown_method( | |
| fidl::UnknownMethodMetadata<fuchsia_input_report::InputDevice> metadata, | |
| fidl::UnknownMethodCompleter::Sync& completer) override { | |
| zxlogf(WARNING, "Unexpected fidl method invoked: %ld", metadata.method_ordinal); | |
| } | |
| private: | |
| static constexpr size_t kFeatureAndDescriptorBufferSize = 512; | |
| static constexpr size_t kEventCount = 64; | |
| // We don't currently send status events to the device, so we use the | |
| // smallest value that is a power of 2, as required by virtio::Ring::Init(); | |
| static constexpr size_t kStatusCount = 2; | |
| void ReceiveEvent(virtio_input_event_t* event); | |
| void SelectConfig(uint8_t select, uint8_t subsel); | |
| virtio_input_config_t config_; | |
| io_buffer_t eventq_buffers_[kEventCount]; | |
| io_buffer_t statusq_buffers_[kStatusCount]; | |
| fbl::Mutex lock_; | |
| std::unique_ptr<HidDeviceBase> hid_device_; | |
| // The input device's event virtqueue, or `eventq`. | |
| // | |
| // Defined in the VIRTIO spec Section 5.8.2 "Input Device" > "Virtqueues". | |
| Ring eventq_vring_{this}; | |
| // The input device's status virtqueue, or `statusq`. | |
| // | |
| // Defined in the VIRTIO spec Section 5.8.2 "Input Device" > "Virtqueues". | |
| Ring statusq_vring_{this}; | |
| inspect::Inspector inspector_; | |
| inspect::Node metrics_root_; | |
| inspect::UintProperty total_report_count_; | |
| inspect::UintProperty last_event_timestamp_; | |
| fidl::ServerBindingGroup<fuchsia_input_report::InputDevice> bindings_; | |
| }; | |
| } // namespace virtio | |
| #endif // SRC_UI_INPUT_DRIVERS_VIRTIO_CPP_INPUT_H_ |