blob: 650b1939853ed58013b44472a0ea412e671668a3 [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use super::constants::*;
use super::evdev::{grab_evdev, ungrab_evdev};
use super::InputError;
use super::Result;
use base::{warn, AsRawDescriptor, RawDescriptor};
use data_model::DataInit;
use linux_input_sys::{input_event, virtio_input_event, InputEventDecoder};
use std::collections::VecDeque;
use std::io::Read;
use std::io::Write;
/// Encapsulates a socket or device node into an abstract event source, providing a common
/// interface.
/// It supports read and write operations to provide and accept events just like an event device
/// node would, except that it handles virtio_input_event instead of input_event structures.
/// It's necessary to call receive_events() before events are available for read.
pub trait EventSource: AsRawDescriptor {
/// Perform any necessary initialization before receiving and sending events from/to the source.
fn init(&mut self) -> Result<()> {
Ok(())
}
/// Perform any necessary cleanup when the device will no longer be used.
fn finalize(&mut self) -> Result<()> {
Ok(())
}
/// Receive events from the source, filters them and stores them in a queue for future
/// consumption by reading from this object. Returns the number of new non filtered events
/// received. This function may block waiting for events to be available.
fn receive_events(&mut self) -> Result<usize>;
/// Returns the number of received events that have not been filtered or consumed yet.
fn available_events_count(&self) -> usize;
/// Returns the next available event
fn pop_available_event(&mut self) -> Option<virtio_input_event>;
/// Sends a status update event to the source
fn send_event(&mut self, vio_evt: &virtio_input_event) -> Result<()>;
}
/// Encapsulates implementation details common to all kinds of event sources.
pub struct EventSourceImpl<T> {
source: T,
queue: VecDeque<virtio_input_event>,
read_buffer: Vec<u8>,
read_idx: usize,
}
impl<T: AsRawDescriptor> EventSourceImpl<T> {
fn as_raw_descriptor(&self) -> RawDescriptor {
self.source.as_raw_descriptor()
}
}
impl<T> EventSourceImpl<T>
where
T: Read + Write,
{
// Receive events from the source and store them in a queue.
fn receive_events<E: InputEventDecoder>(&mut self) -> Result<usize> {
let read = self
.source
.read(&mut self.read_buffer[self.read_idx..])
.map_err(InputError::EventsReadError)?;
let buff_size = read + self.read_idx;
for evt_slice in self.read_buffer[..buff_size].chunks_exact(E::SIZE) {
self.queue.push_back(E::decode(evt_slice));
}
let remainder = buff_size % E::SIZE;
// If there is an incomplete event at the end of the buffer, it needs to be moved to the
// beginning and the next read operation must write right after it.
if remainder != 0 {
warn!("read incomplete event from source");
// The copy should only happen if there is at least one complete event in the buffer,
// otherwise source and destination would be the same.
if buff_size != remainder {
let (des, src) = self.read_buffer.split_at_mut(buff_size - remainder);
des[..remainder].copy_from_slice(&src[..remainder]);
}
}
self.read_idx = remainder;
let received_events = buff_size / E::SIZE;
Ok(received_events)
}
fn available_events(&self) -> usize {
self.queue.len()
}
fn pop_available_event(&mut self) -> Option<virtio_input_event> {
self.queue.pop_front()
}
fn send_event(&mut self, vio_evt: &virtio_input_event, encoding: EventType) -> Result<()> {
// Miscellaneous events produced by the device are sent back to it by the kernel input
// subsystem, but because these events are handled by the host kernel as well as the
// guest the device would get them twice. Which would prompt the device to send the
// event to the guest again entering an infinite loop.
if vio_evt.type_ != EV_MSC {
let evt;
let event_bytes = match encoding {
EventType::InputEvent => {
evt = input_event::from_virtio_input_event(vio_evt);
evt.as_slice()
}
EventType::VirtioInputEvent => vio_evt.as_slice(),
};
self.source
.write_all(event_bytes)
.map_err(InputError::EventsWriteError)?;
}
Ok(())
}
fn new(source: T, capacity: usize) -> EventSourceImpl<T> {
EventSourceImpl {
source,
queue: VecDeque::new(),
read_buffer: vec![0; capacity],
read_idx: 0,
}
}
}
enum EventType {
VirtioInputEvent,
InputEvent,
}
/// Encapsulates a (unix) socket as an event source.
pub struct SocketEventSource<T> {
evt_source_impl: EventSourceImpl<T>,
}
impl<T> SocketEventSource<T>
where
T: Read + Write + AsRawDescriptor,
{
pub fn new(source: T) -> SocketEventSource<T> {
SocketEventSource {
evt_source_impl: EventSourceImpl::new(source, 16 * virtio_input_event::SIZE),
}
}
}
impl<T: AsRawDescriptor> AsRawDescriptor for SocketEventSource<T> {
fn as_raw_descriptor(&self) -> RawDescriptor {
self.evt_source_impl.as_raw_descriptor()
}
}
impl<T> EventSource for SocketEventSource<T>
where
T: Read + Write + AsRawDescriptor,
{
fn init(&mut self) -> Result<()> {
Ok(())
}
fn finalize(&mut self) -> Result<()> {
Ok(())
}
fn receive_events(&mut self) -> Result<usize> {
self.evt_source_impl.receive_events::<virtio_input_event>()
}
fn available_events_count(&self) -> usize {
self.evt_source_impl.available_events()
}
fn pop_available_event(&mut self) -> Option<virtio_input_event> {
self.evt_source_impl.pop_available_event()
}
fn send_event(&mut self, vio_evt: &virtio_input_event) -> Result<()> {
self.evt_source_impl
.send_event(vio_evt, EventType::VirtioInputEvent)
}
}
/// Encapsulates an event device node as an event source
pub struct EvdevEventSource<T> {
evt_source_impl: EventSourceImpl<T>,
}
impl<T> EvdevEventSource<T>
where
T: Read + Write + AsRawDescriptor,
{
pub fn new(source: T) -> EvdevEventSource<T> {
EvdevEventSource {
evt_source_impl: EventSourceImpl::new(source, 16 * input_event::SIZE),
}
}
}
impl<T: AsRawDescriptor> AsRawDescriptor for EvdevEventSource<T> {
fn as_raw_descriptor(&self) -> RawDescriptor {
self.evt_source_impl.as_raw_descriptor()
}
}
impl<T> EventSource for EvdevEventSource<T>
where
T: Read + Write + AsRawDescriptor,
{
fn init(&mut self) -> Result<()> {
grab_evdev(self)
}
fn finalize(&mut self) -> Result<()> {
ungrab_evdev(self)
}
fn receive_events(&mut self) -> Result<usize> {
self.evt_source_impl.receive_events::<input_event>()
}
fn available_events_count(&self) -> usize {
self.evt_source_impl.available_events()
}
fn pop_available_event(&mut self) -> Option<virtio_input_event> {
self.evt_source_impl.pop_available_event()
}
fn send_event(&mut self, vio_evt: &virtio_input_event) -> Result<()> {
self.evt_source_impl
.send_event(vio_evt, EventType::InputEvent)
}
}
#[cfg(test)]
mod tests {
use std::cmp::min;
use std::io::{Read, Write};
use data_model::{DataInit, Le16, Le32};
use linux_input_sys::InputEventDecoder;
use crate::virtio::input::event_source::{input_event, virtio_input_event, EventSourceImpl};
struct SourceMock {
events: Vec<u8>,
}
impl SourceMock {
fn new(evts: &Vec<input_event>) -> SourceMock {
let mut events: Vec<u8> = vec![];
for evt in evts {
for byte in evt.as_slice() {
events.push(byte.clone());
}
}
SourceMock { events }
}
}
impl Read for SourceMock {
fn read(&mut self, buf: &mut [u8]) -> std::result::Result<usize, std::io::Error> {
let copy_size = min(buf.len(), self.events.len());
buf[..copy_size].copy_from_slice(&self.events[..copy_size]);
Ok(copy_size)
}
}
impl Write for SourceMock {
fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, std::io::Error> {
Ok(buf.len())
}
fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
Ok(())
}
}
#[test]
fn empty_new() {
let mut source = EventSourceImpl::new(SourceMock::new(&vec![]), 128);
assert_eq!(
source.available_events(),
0,
"zero events should be available"
);
assert_eq!(
source.pop_available_event().is_none(),
true,
"no events should be available"
);
}
#[test]
fn empty_receive() {
let mut source = EventSourceImpl::new(SourceMock::new(&vec![]), 128);
assert_eq!(
source.receive_events::<input_event>().unwrap(),
0,
"zero events should be received"
);
assert_eq!(
source.pop_available_event().is_none(),
true,
"no events should be available"
);
}
fn instantiate_input_events(count: usize) -> Vec<input_event> {
let mut ret: Vec<input_event> = Vec::with_capacity(count);
for idx in 0..count {
ret.push(input_event {
timestamp_fields: [0, 0],
type_: 3 * (idx as u16) + 1,
code: 3 * (idx as u16) + 2,
value: 3 * (idx as u32) + 3,
});
}
ret
}
fn assert_events_match(e1: &virtio_input_event, e2: &input_event) {
assert_eq!(e1.type_, Le16::from(e2.type_), "type should match");
assert_eq!(e1.code, Le16::from(e2.code), "code should match");
assert_eq!(e1.value, Le32::from(e2.value), "value should match");
}
#[test]
fn partial_pop() {
let evts = instantiate_input_events(4usize);
let mut source = EventSourceImpl::new(SourceMock::new(&evts), input_event::SIZE * 4);
assert_eq!(
source.receive_events::<input_event>().unwrap(),
evts.len(),
"should receive all events"
);
let evt_opt = source.pop_available_event();
assert_eq!(evt_opt.is_some(), true, "event should have been poped");
let evt = evt_opt.unwrap();
assert_events_match(&evt, &evts[0]);
}
#[test]
fn total_pop() {
const EVENT_COUNT: usize = 4;
let evts = instantiate_input_events(EVENT_COUNT);
let mut source = EventSourceImpl::new(SourceMock::new(&evts), input_event::SIZE * 4);
assert_eq!(
source.receive_events::<input_event>().unwrap(),
evts.len(),
"should receive all events"
);
for idx in 0..EVENT_COUNT {
let evt = source.pop_available_event().unwrap();
assert_events_match(&evt, &evts[idx]);
}
assert_eq!(
source.available_events(),
0,
"there should be no events left"
);
assert_eq!(
source.pop_available_event().is_none(),
true,
"no events should pop"
);
}
}