xref: /aosp_15_r20/external/crosvm/gpu_display/src/event_device.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::VecDeque;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::iter::ExactSizeIterator;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::ReadNotifier;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::StreamChannel;
16*bb4ee6a4SAndroid Build Coastguard Worker use linux_input_sys::virtio_input_event;
17*bb4ee6a4SAndroid Build Coastguard Worker use linux_input_sys::InputEventDecoder;
18*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
19*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
20*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
21*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker const EVENT_SIZE: usize = virtio_input_event::SIZE;
24*bb4ee6a4SAndroid Build Coastguard Worker const EVENT_BUFFER_LEN_MAX: usize = 64 * EVENT_SIZE;
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
27*bb4ee6a4SAndroid Build Coastguard Worker pub enum EventDeviceKind {
28*bb4ee6a4SAndroid Build Coastguard Worker     /// Produces relative mouse motions, wheel, and button clicks while the real mouse is captured.
29*bb4ee6a4SAndroid Build Coastguard Worker     Mouse,
30*bb4ee6a4SAndroid Build Coastguard Worker     /// Produces absolute motion and touch events from the display window's events.
31*bb4ee6a4SAndroid Build Coastguard Worker     Touchscreen,
32*bb4ee6a4SAndroid Build Coastguard Worker     /// Produces key events while the display window has focus.
33*bb4ee6a4SAndroid Build Coastguard Worker     Keyboard,
34*bb4ee6a4SAndroid Build Coastguard Worker }
35*bb4ee6a4SAndroid Build Coastguard Worker 
36*bb4ee6a4SAndroid Build Coastguard Worker /// Encapsulates a virtual event device, such as a mouse or keyboard
37*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, Serialize)]
38*bb4ee6a4SAndroid Build Coastguard Worker pub struct EventDevice {
39*bb4ee6a4SAndroid Build Coastguard Worker     kind: EventDeviceKind,
40*bb4ee6a4SAndroid Build Coastguard Worker     event_buffer: VecDeque<u8>,
41*bb4ee6a4SAndroid Build Coastguard Worker     event_socket: StreamChannel,
42*bb4ee6a4SAndroid Build Coastguard Worker }
43*bb4ee6a4SAndroid Build Coastguard Worker 
44*bb4ee6a4SAndroid Build Coastguard Worker impl EventDevice {
new(kind: EventDeviceKind, mut event_socket: StreamChannel) -> EventDevice45*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(kind: EventDeviceKind, mut event_socket: StreamChannel) -> EventDevice {
46*bb4ee6a4SAndroid Build Coastguard Worker         let _ = event_socket.set_nonblocking(true);
47*bb4ee6a4SAndroid Build Coastguard Worker         EventDevice {
48*bb4ee6a4SAndroid Build Coastguard Worker             kind,
49*bb4ee6a4SAndroid Build Coastguard Worker             event_buffer: Default::default(),
50*bb4ee6a4SAndroid Build Coastguard Worker             event_socket,
51*bb4ee6a4SAndroid Build Coastguard Worker         }
52*bb4ee6a4SAndroid Build Coastguard Worker     }
53*bb4ee6a4SAndroid Build Coastguard Worker 
54*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
mouse(event_socket: StreamChannel) -> EventDevice55*bb4ee6a4SAndroid Build Coastguard Worker     pub fn mouse(event_socket: StreamChannel) -> EventDevice {
56*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(EventDeviceKind::Mouse, event_socket)
57*bb4ee6a4SAndroid Build Coastguard Worker     }
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
touchscreen(event_socket: StreamChannel) -> EventDevice60*bb4ee6a4SAndroid Build Coastguard Worker     pub fn touchscreen(event_socket: StreamChannel) -> EventDevice {
61*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(EventDeviceKind::Touchscreen, event_socket)
62*bb4ee6a4SAndroid Build Coastguard Worker     }
63*bb4ee6a4SAndroid Build Coastguard Worker 
64*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
keyboard(event_socket: StreamChannel) -> EventDevice65*bb4ee6a4SAndroid Build Coastguard Worker     pub fn keyboard(event_socket: StreamChannel) -> EventDevice {
66*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(EventDeviceKind::Keyboard, event_socket)
67*bb4ee6a4SAndroid Build Coastguard Worker     }
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
kind(&self) -> EventDeviceKind70*bb4ee6a4SAndroid Build Coastguard Worker     pub fn kind(&self) -> EventDeviceKind {
71*bb4ee6a4SAndroid Build Coastguard Worker         self.kind
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker 
74*bb4ee6a4SAndroid Build Coastguard Worker     /// Flushes the buffered events that did not fit into the underlying transport, if any.
75*bb4ee6a4SAndroid Build Coastguard Worker     ///
76*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns `Ok(true)` if, after this function returns, there all the buffer of events is
77*bb4ee6a4SAndroid Build Coastguard Worker     /// empty.
flush_buffered_events(&mut self) -> io::Result<bool>78*bb4ee6a4SAndroid Build Coastguard Worker     pub fn flush_buffered_events(&mut self) -> io::Result<bool> {
79*bb4ee6a4SAndroid Build Coastguard Worker         while !self.event_buffer.is_empty() {
80*bb4ee6a4SAndroid Build Coastguard Worker             let written = self.event_socket.write(self.event_buffer.as_slices().0)?;
81*bb4ee6a4SAndroid Build Coastguard Worker             if written == 0 {
82*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(false);
83*bb4ee6a4SAndroid Build Coastguard Worker             }
84*bb4ee6a4SAndroid Build Coastguard Worker             self.event_buffer.drain(..written);
85*bb4ee6a4SAndroid Build Coastguard Worker         }
86*bb4ee6a4SAndroid Build Coastguard Worker         Ok(true)
87*bb4ee6a4SAndroid Build Coastguard Worker     }
88*bb4ee6a4SAndroid Build Coastguard Worker 
is_buffered_events_empty(&self) -> bool89*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_buffered_events_empty(&self) -> bool {
90*bb4ee6a4SAndroid Build Coastguard Worker         self.event_buffer.is_empty()
91*bb4ee6a4SAndroid Build Coastguard Worker     }
92*bb4ee6a4SAndroid Build Coastguard Worker 
93*bb4ee6a4SAndroid Build Coastguard Worker     /// Determines if there is space in the event buffer for the given number
94*bb4ee6a4SAndroid Build Coastguard Worker     /// of events. The buffer is capped at `EVENT_BUFFER_LEN_MAX`.
95*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
can_buffer_events(&self, num_events: usize) -> bool96*bb4ee6a4SAndroid Build Coastguard Worker     fn can_buffer_events(&self, num_events: usize) -> bool {
97*bb4ee6a4SAndroid Build Coastguard Worker         let event_bytes = match EVENT_SIZE.checked_mul(num_events) {
98*bb4ee6a4SAndroid Build Coastguard Worker             Some(bytes) => bytes,
99*bb4ee6a4SAndroid Build Coastguard Worker             None => return false,
100*bb4ee6a4SAndroid Build Coastguard Worker         };
101*bb4ee6a4SAndroid Build Coastguard Worker         let free_bytes = EVENT_BUFFER_LEN_MAX.saturating_sub(self.event_buffer.len());
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker         free_bytes >= event_bytes
104*bb4ee6a4SAndroid Build Coastguard Worker     }
105*bb4ee6a4SAndroid Build Coastguard Worker 
send_report<E: IntoIterator<Item = virtio_input_event>>( &mut self, events: E, ) -> io::Result<bool> where E::IntoIter: ExactSizeIterator,106*bb4ee6a4SAndroid Build Coastguard Worker     pub fn send_report<E: IntoIterator<Item = virtio_input_event>>(
107*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
108*bb4ee6a4SAndroid Build Coastguard Worker         events: E,
109*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<bool>
110*bb4ee6a4SAndroid Build Coastguard Worker     where
111*bb4ee6a4SAndroid Build Coastguard Worker         E::IntoIter: ExactSizeIterator,
112*bb4ee6a4SAndroid Build Coastguard Worker     {
113*bb4ee6a4SAndroid Build Coastguard Worker         let it = events.into_iter();
114*bb4ee6a4SAndroid Build Coastguard Worker 
115*bb4ee6a4SAndroid Build Coastguard Worker         if !self.can_buffer_events(it.len() + 1) {
116*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(false);
117*bb4ee6a4SAndroid Build Coastguard Worker         }
118*bb4ee6a4SAndroid Build Coastguard Worker 
119*bb4ee6a4SAndroid Build Coastguard Worker         for event in it {
120*bb4ee6a4SAndroid Build Coastguard Worker             let bytes = event.as_bytes();
121*bb4ee6a4SAndroid Build Coastguard Worker             self.event_buffer.extend(bytes.iter());
122*bb4ee6a4SAndroid Build Coastguard Worker         }
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker         self.event_buffer
125*bb4ee6a4SAndroid Build Coastguard Worker             .extend(virtio_input_event::syn().as_bytes().iter());
126*bb4ee6a4SAndroid Build Coastguard Worker 
127*bb4ee6a4SAndroid Build Coastguard Worker         self.flush_buffered_events()
128*bb4ee6a4SAndroid Build Coastguard Worker     }
129*bb4ee6a4SAndroid Build Coastguard Worker 
130*bb4ee6a4SAndroid Build Coastguard Worker     /// Sends the given `event`, returning `Ok(true)` if, after this function returns, there are no
131*bb4ee6a4SAndroid Build Coastguard Worker     /// buffered events remaining.
send_event_encoded(&mut self, event: virtio_input_event) -> io::Result<bool>132*bb4ee6a4SAndroid Build Coastguard Worker     pub fn send_event_encoded(&mut self, event: virtio_input_event) -> io::Result<bool> {
133*bb4ee6a4SAndroid Build Coastguard Worker         if !self.flush_buffered_events()? {
134*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(false);
135*bb4ee6a4SAndroid Build Coastguard Worker         }
136*bb4ee6a4SAndroid Build Coastguard Worker 
137*bb4ee6a4SAndroid Build Coastguard Worker         let bytes = event.as_bytes();
138*bb4ee6a4SAndroid Build Coastguard Worker         let written = self.event_socket.write(bytes)?;
139*bb4ee6a4SAndroid Build Coastguard Worker 
140*bb4ee6a4SAndroid Build Coastguard Worker         if written == bytes.len() {
141*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(true);
142*bb4ee6a4SAndroid Build Coastguard Worker         }
143*bb4ee6a4SAndroid Build Coastguard Worker 
144*bb4ee6a4SAndroid Build Coastguard Worker         if self.can_buffer_events(1) {
145*bb4ee6a4SAndroid Build Coastguard Worker             self.event_buffer.extend(bytes[written..].iter());
146*bb4ee6a4SAndroid Build Coastguard Worker         }
147*bb4ee6a4SAndroid Build Coastguard Worker 
148*bb4ee6a4SAndroid Build Coastguard Worker         Ok(false)
149*bb4ee6a4SAndroid Build Coastguard Worker     }
150*bb4ee6a4SAndroid Build Coastguard Worker 
recv_event_encoded(&self) -> io::Result<virtio_input_event>151*bb4ee6a4SAndroid Build Coastguard Worker     pub fn recv_event_encoded(&self) -> io::Result<virtio_input_event> {
152*bb4ee6a4SAndroid Build Coastguard Worker         let mut event = virtio_input_event::new_zeroed();
153*bb4ee6a4SAndroid Build Coastguard Worker         (&self.event_socket).read_exact(event.as_bytes_mut())?;
154*bb4ee6a4SAndroid Build Coastguard Worker         Ok(event)
155*bb4ee6a4SAndroid Build Coastguard Worker     }
156*bb4ee6a4SAndroid Build Coastguard Worker }
157*bb4ee6a4SAndroid Build Coastguard Worker 
158*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for EventDevice {
as_raw_descriptor(&self) -> RawDescriptor159*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
160*bb4ee6a4SAndroid Build Coastguard Worker         self.event_socket.as_raw_descriptor()
161*bb4ee6a4SAndroid Build Coastguard Worker     }
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker impl ReadNotifier for EventDevice {
get_read_notifier(&self) -> &dyn AsRawDescriptor165*bb4ee6a4SAndroid Build Coastguard Worker     fn get_read_notifier(&self) -> &dyn AsRawDescriptor {
166*bb4ee6a4SAndroid Build Coastguard Worker         self.event_socket.get_read_notifier()
167*bb4ee6a4SAndroid Build Coastguard Worker     }
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker 
170*bb4ee6a4SAndroid Build Coastguard Worker impl fmt::Debug for EventDevice {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result171*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172*bb4ee6a4SAndroid Build Coastguard Worker         write!(f, "Event device ({:?})", self.kind)
173*bb4ee6a4SAndroid Build Coastguard Worker     }
174*bb4ee6a4SAndroid Build Coastguard Worker }
175